Revision: 32698
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32698
Author:   nazgul
Date:     2010-10-25 10:03:05 +0200 (Mon, 25 Oct 2010)

Log Message:
-----------
Fix #24255: Multires object gets modified when joining it to another multires 
object.
Fix #22018: joining objects with different multires levels loses levesl from 
the higher multires object

- Synchronyze mulires subdivision level when joining objects
- Apply scale on MDISP layer when applying scale
- Re-calculate MDISP when joining scaled objects

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_multires.h
    trunk/blender/source/blender/blenkernel/intern/multires.c
    trunk/blender/source/blender/editors/mesh/meshtools.c
    trunk/blender/source/blender/editors/object/object_transform.c

Modified: trunk/blender/source/blender/blenkernel/BKE_multires.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_multires.h      2010-10-25 
07:36:14 UTC (rev 32697)
+++ trunk/blender/source/blender/blenkernel/BKE_multires.h      2010-10-25 
08:03:05 UTC (rev 32698)
@@ -71,5 +71,8 @@
 void multires_load_old(struct Object *ob, struct Mesh *me);
 void multires_load_old_250(struct Mesh *);
 
+void multiresModifier_scale_disp(struct Scene *scene, struct Object *ob);
+void multiresModifier_prepare_join(struct Scene *scene, struct Object *ob, 
struct Object *to_ob);
+
 #endif
 

Modified: trunk/blender/source/blender/blenkernel/intern/multires.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/multires.c   2010-10-25 
07:36:14 UTC (rev 32697)
+++ trunk/blender/source/blender/blenkernel/intern/multires.c   2010-10-25 
08:03:05 UTC (rev 32698)
@@ -46,6 +46,7 @@
 #include "BKE_scene.h"
 #include "BKE_subsurf.h"
 #include "BKE_utildefines.h"
+#include "BKE_object.h"
 
 #include "CCGSubSurf.h"
 
@@ -89,6 +90,34 @@
        return NULL;
 }
 
+/* used for applying scale on mdisps layer and syncing subdivide levels when 
joining objects */
+static MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob)
+{
+       ModifierData *md;
+       MultiresModifierData *mmd= NULL, *firstmmd= NULL;
+
+       /* find first active multires modifier */
+       for(md = ob->modifiers.first; md; md = md->next) {
+               if(md->type == eModifierType_Multires) {
+                       if(!firstmmd)
+                               firstmmd= (MultiresModifierData*)md;
+
+                       if (modifier_isEnabled(scene, md, 
eModifierMode_Realtime)) {
+                               mmd= (MultiresModifierData*)md;
+                               break;
+                       }
+               }
+       }
+
+       if(!mmd) {
+               /* active multires have not been found
+                  try to use first one */
+               return firstmmd;
+       }
+
+       return mmd;
+}
+
 static int multires_get_level(Object *ob, MultiresModifierData *mmd, int 
render)
 {
        if(render)
@@ -389,11 +418,9 @@
        }
 }
 
-/* direction=1 for delete higher, direction=0 for lower (not implemented yet) 
*/
-void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int 
direction)
+static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
 {
-       Mesh *me = get_mesh(ob);
-       int lvl = multires_get_level(ob, mmd, 0);
+       Mesh *me = (Mesh*)ob->data;
        int levels = mmd->totlvl - lvl;
        MDisps *mdisps;
 
@@ -403,7 +430,7 @@
 
        multires_force_update(ob);
 
-       if(mdisps && levels > 0 && direction == 1) {
+       if(mdisps && levels > 0) {
                if(lvl > 0) {
                        int nsize = multires_side_tot[lvl];
                        int hsize = multires_side_tot[mmd->totlvl];
@@ -442,6 +469,27 @@
        multires_set_tot_level(ob, mmd, lvl);
 }
 
+/* direction=1 for delete higher, direction=0 for lower (not implemented yet) 
*/
+void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int 
direction)
+{
+       Mesh *me = get_mesh(ob);
+       int lvl = multires_get_level(ob, mmd, 0);
+       int levels = mmd->totlvl - lvl;
+       MDisps *mdisps;
+
+       multires_set_tot_mdisps(me, mmd->totlvl);
+       CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, 
me->totface);
+       mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+       multires_force_update(ob);
+
+       if(mdisps && levels > 0 && direction == 1) {
+               multires_del_higher(mmd, ob, lvl);
+       }
+
+       multires_set_tot_level(ob, mmd, lvl);
+}
+
 static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int 
lvl, int totlvl, int simple)
 {
        MultiresModifierData mmd;
@@ -471,12 +519,11 @@
        return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0);
 }
 
-void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int 
updateblock, int simple)
+void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int 
updateblock, int simple)
 {
        Mesh *me = ob->data;
        MDisps *mdisps;
        int lvl= mmd->totlvl;
-       int totlvl= mmd->totlvl+1;
 
        if(totlvl > multires_max_levels)
                return;
@@ -549,6 +596,11 @@
        multires_set_tot_level(ob, mmd, totlvl);
 }
 
+void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int 
updateblock, int simple)
+{
+       multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple);
+}
+
 static void grid_tangent(int gridSize, int index, int x, int y, int axis, 
DMGridData **gridData, float t[3])
 {
        if(axis == 0) {
@@ -1386,3 +1438,141 @@
        me->mr= NULL;
 }
 
+static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
+{
+       MultiresModifierData *mmd= get_multires_modifier(scene, ob);
+       MultiresModifierData *to_mmd= get_multires_modifier(scene, to_ob);
+
+       if(!mmd) {
+               /* object could have MDISP even when there is no multires 
modifier
+                  this could lead to troubles due to i've got no idea how 
mdisp could be
+                  upsampled correct without modifier data.
+                  just remove mdisps if no multires present (nazgul) */
+
+               Mesh *me= (Mesh*)ob->data;
+
+               CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, 
me->totface);
+               CustomData_free_layer_active(&me->fdata, CD_MDISPS, 
me->totface);
+       }
+
+       if(!mmd || !to_mmd) return;
+
+       if(mmd->totlvl>to_mmd->totlvl) multires_del_higher(mmd, ob, 
to_mmd->totlvl);
+       else multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple);
+}
+
+void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
+{
+       DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL;
+       DMGridData **gridData, **subGridData;
+       Mesh *me= (Mesh*)ob->data;
+       MFace *mface= me->mface;
+       MVert *mvert= NULL;
+       MDisps *mdisps;
+       int *gridOffset;
+       int i, numGrids, gridSize, dGridSize, dSkip, totvert;
+       float (*vertCos)[3] = NULL;
+       MultiresModifierData *mmd= get_multires_modifier(scene, ob);
+
+       CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, 
me->totface);
+       mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+       if(!mdisps || !mmd) return;
+
+
+       /* unscaled multires with applied displacement */
+       subdm= get_multires_dm(scene, mmd, ob);
+
+       /* prepare scaled CDDM to create ccgDN */
+       cddm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+
+       totvert= cddm->getNumVerts(cddm);
+       vertCos= MEM_mallocN(sizeof(*vertCos) * totvert, "multiresScale 
vertCos");
+       cddm->getVertCos(cddm, vertCos);
+       for(i=0; i<totvert; i++)
+               mul_m3_v3(smat, vertCos[i]);
+       CDDM_apply_vert_coords(cddm, vertCos);
+       MEM_freeN(vertCos);
+
+       mvert= cddm->getVertArray(cddm);
+
+       /* scaled ccgDM for tangent space of object with applied scale */
+       dm= subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0);
+       cddm->release(cddm);
+
+       numGrids= dm->getNumGrids(dm);
+       gridSize= dm->getGridSize(dm);
+       gridData= dm->getGridData(dm);
+       gridOffset= dm->getGridOffset(dm);
+       subGridData= subdm->getGridData(subdm);
+
+       dGridSize= multires_side_tot[mmd->totlvl];
+       dSkip= (dGridSize-1)/(gridSize-1);
+
+       #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 
>= CCG_OMP_LIMIT)
+       for(i = 0; i < me->totface; ++i) {
+               const int numVerts= mface[i].v4 ? 4 : 3;
+               MDisps *mdisp= &mdisps[i];
+               int S, x, y, gIndex = gridOffset[i];
+
+               for(S = 0; S < numVerts; ++S, ++gIndex) {
+                       DMGridData *grid= gridData[gIndex];
+                       DMGridData *subgrid= subGridData[gIndex];
+                       float (*dispgrid)[3]= 
&mdisp->disps[S*dGridSize*dGridSize];
+
+                       for(y = 0; y < gridSize; y++) {
+                               for(x = 0; x < gridSize; x++) {
+                                       float *co= grid[x + y*gridSize].co;
+                                       float *sco= subgrid[x + y*gridSize].co;
+                                       float *no= grid[x + y*gridSize].no;
+                                       float *data= dispgrid[dGridSize*y*dSkip 
+ x*dSkip];
+                                       float mat[3][3], tx[3], ty[3], disp[3];
+
+                                       /* construct tangent space matrix */
+                                       grid_tangent(gridSize, gIndex, x, y, 0, 
gridData, tx);
+                                       normalize_v3(tx);
+
+                                       grid_tangent(gridSize, gIndex, x, y, 1, 
gridData, ty);
+                                       normalize_v3(ty);
+
+                                       column_vectors_to_mat3(mat, tx, ty, no);
+
+                                       /* scale subgrid coord and calculate 
displacement */
+                                       mul_m3_v3(smat, sco);
+                                       sub_v3_v3v3(disp, sco, co);
+
+                                       /* convert difference to tangent space 
*/
+                                       invert_m3(mat);
+                                       mul_v3_m3v3(data, mat, disp);
+                               }
+                       }
+               }
+       }
+
+       dm->release(dm);
+       subdm->release(subdm);
+}
+
+void multiresModifier_scale_disp(Scene *scene, Object *ob)
+{
+       float smat[3][3];
+
+       /* object's scale matrix */
+       object_scale_to_mat3(ob, smat);
+
+       multires_apply_smat(scene, ob, smat);
+}
+
+void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
+{
+       float smat[3][3], tmat[3][3], mat[3][3];
+       multires_sync_levels(scene, ob, to_ob);
+
+       /* construct scale matrix for displacement */
+       object_scale_to_mat3(to_ob, tmat);
+       invert_m3(tmat);
+       object_scale_to_mat3(ob, smat);
+       mul_m3_m3m3(mat, smat, tmat);
+
+       multires_apply_smat(scene, ob, mat);
+}

Modified: trunk/blender/source/blender/editors/mesh/meshtools.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/meshtools.c       2010-10-25 
07:36:14 UTC (rev 32697)
+++ trunk/blender/source/blender/editors/mesh/meshtools.c       2010-10-25 
08:03:05 UTC (rev 32698)
@@ -63,6 +63,7 @@
 #include "BKE_mesh.h"
 #include "BKE_material.h"
 #include "BKE_report.h"
+#include "BKE_multires.h"
 
 #include "BLO_sys_types.h" // for intptr_t support
 
@@ -396,6 +397,9 @@
                                        }
                                }
                                
+                               if(base->object!=ob)
+                                       multiresModifier_prepare_join(scene, 
base->object, ob);
+
                                CustomData_merge(&me->fdata, &fdata, 
CD_MASK_MESH, CD_DEFAULT, totface);
                                CustomData_copy_data(&me->fdata, &fdata, 0, 
faceofs, me->totface);
                                

Modified: trunk/blender/source/blender/editors/object/object_transform.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_transform.c      
2010-10-25 07:36:14 UTC (rev 32697)
+++ trunk/blender/source/blender/editors/object/object_transform.c      
2010-10-25 08:03:05 UTC (rev 32698)
@@ -47,6 +47,7 @@
 #include "BKE_mesh.h"
 #include "BKE_object.h"
 #include "BKE_report.h"
+#include "BKE_multires.h"
 
 #include "RNA_define.h"
 #include "RNA_access.h"
@@ -491,6 +492,8 @@
                if(ob->type==OB_MESH) {
                        me= ob->data;
                        
+                       multiresModifier_scale_disp(scene, ob);
+                       
                        /* adjust data */
                        mvert= me->mvert;
                        for(a=0; a<me->totvert; a++, mvert++)


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to