[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [32698] trunk/blender/source/blender: Fix #24255: Multires object gets modified when joining it to another multires object.

Sergey Sharybin g.ulairi at gmail.com
Mon Oct 25 10:03:05 CEST 2010


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++)





More information about the Bf-blender-cvs mailing list