[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [34162] trunk/blender: Fix for bug [#21534 ] Multires modifier strange deformations

Nicholas Bishop nicholasbishop at gmail.com
Fri Jan 7 22:12:48 CET 2011


Revision: 34162
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=34162
Author:   nicholasbishop
Date:     2011-01-07 21:12:47 +0000 (Fri, 07 Jan 2011)
Log Message:
-----------
Fix for bug [#21534] Multires modifier strange deformations

This adds the "Apply Base" feature from my gsoc2010 branch.

Apply Base partially applies the modifier, in that the mesh is
reshaped to more closely match the deformed mesh. The upper-level
displacements are recalculated so that the highest multires level
appears unchanged.

Multires does not currently deal well with too large displacements.
An easy-to-reproduce example: create any mesh type, add multires,
subdivide a few times, then use the sculpt grab brush to drag the
entire mesh over a few units. At the highest level, and at level 0,
the mesh looks fine, but all of the intervening levels will have ugly
spikes on them.

This patch doesn't help with situations where you can't modify the
base mesh, but otherwise works around the problem fairly well (albeit
with a heuristic, not an exact solution.)

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_data_modifier.py
    trunk/blender/source/blender/blenkernel/BKE_multires.h
    trunk/blender/source/blender/blenkernel/intern/multires.c
    trunk/blender/source/blender/editors/object/object_intern.h
    trunk/blender/source/blender/editors/object/object_modifier.c
    trunk/blender/source/blender/editors/object/object_ops.c

Modified: trunk/blender/release/scripts/ui/properties_data_modifier.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_data_modifier.py	2011-01-07 20:02:56 UTC (rev 34161)
+++ trunk/blender/release/scripts/ui/properties_data_modifier.py	2011-01-07 21:12:47 UTC (rev 34162)
@@ -401,6 +401,7 @@
         col.operator("object.multires_subdivide", text="Subdivide")
         col.operator("object.multires_higher_levels_delete", text="Delete Higher")
         col.operator("object.multires_reshape", text="Reshape")
+        col.operator("object.multires_base_apply", text="Apply Base")
         col.prop(md, "show_only_control_edges")
 
         layout.separator()

Modified: trunk/blender/source/blender/blenkernel/BKE_multires.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_multires.h	2011-01-07 20:02:56 UTC (rev 34161)
+++ trunk/blender/source/blender/blenkernel/BKE_multires.h	2011-01-07 21:12:47 UTC (rev 34162)
@@ -56,6 +56,7 @@
 struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifierData *mmd,
 				struct Object *ob);
 void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
+void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob);
 void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob,
 				int updateblock, int simple);
 int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd,

Modified: trunk/blender/source/blender/blenkernel/intern/multires.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/multires.c	2011-01-07 20:02:56 UTC (rev 34161)
+++ trunk/blender/source/blender/blenkernel/intern/multires.c	2011-01-07 21:12:47 UTC (rev 34162)
@@ -472,6 +472,128 @@
 	return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0);
 }
 
+
+
+/* assumes no is normalized; return value's sign is negative if v is on
+   the other side of the plane */
+static float v3_dist_from_plane(float v[3], float center[3], float no[3])
+{
+	float s[3];
+	sub_v3_v3v3(s, v, center);
+	return dot_v3v3(s, no);
+}
+
+void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob)
+{
+	DerivedMesh *cddm, *dispdm, *origdm;
+	Mesh *me;
+	ListBase *fmap;
+	float (*origco)[3];
+	int i, j, offset, totlvl;
+
+	multires_force_update(ob);
+
+	me = get_mesh(ob);
+	totlvl = mmd->totlvl;
+
+	/* nothing to do */
+	if(!totlvl)
+		return;
+
+	/* XXX - probably not necessary to regenerate the cddm so much? */
+
+	/* generate highest level with displacements */
+	cddm = CDDM_from_mesh(me, NULL);
+	DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+	dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0);
+	cddm->release(cddm);
+
+	/* copy the new locations of the base verts into the mesh */
+	offset = dispdm->getNumVerts(dispdm) - me->totvert;
+	for(i = 0; i < me->totvert; ++i) {
+		dispdm->getVertCo(dispdm, offset + i, me->mvert[i].co);
+	}
+
+	/* heuristic to produce a better-fitting base mesh */
+
+	cddm = CDDM_from_mesh(me, NULL);
+	fmap = cddm->getFaceMap(ob, cddm);
+	origco = MEM_callocN(sizeof(float)*3*me->totvert, "multires apply base origco");
+	for(i = 0; i < me->totvert ;++i)
+		copy_v3_v3(origco[i], me->mvert[i].co);
+
+	for(i = 0; i < me->totvert; ++i) {
+		IndexNode *n;
+		float avg_no[3] = {0,0,0}, center[3] = {0,0,0}, push[3];
+		float dist;
+		int tot;
+
+		/* don't adjust verts not used by at least one face */
+		if(!fmap[i].first)
+			continue;
+
+		/* find center */
+		for(n = fmap[i].first, tot = 0; n; n = n->next) {
+			MFace *f = &me->mface[n->index];
+			int S = f->v4 ? 4 : 3;
+			
+			/* this double counts, not sure if that's bad or good */
+			for(j = 0; j < S; ++j) {
+				int vndx = (&f->v1)[j];
+				if(vndx != i) {
+					add_v3_v3(center, origco[vndx]);
+					++tot;
+				}
+			}
+		}
+		mul_v3_fl(center, 1.0f / tot);
+
+		/* find normal */
+		for(n = fmap[i].first; n; n = n->next) {
+			MFace *f = &me->mface[n->index];
+			int S = f->v4 ? 4 : 3;
+			float v[4][3], no[3];
+			
+			for(j = 0; j < S; ++j) {
+				int vndx = (&f->v1)[j];
+				if(vndx == i)
+					copy_v3_v3(v[j], center);
+				else
+					copy_v3_v3(v[j], origco[vndx]);
+			}
+			
+			if(S == 4)
+				normal_quad_v3(no, v[0], v[1], v[2], v[3]);
+			else
+				normal_tri_v3(no, v[0], v[1], v[2]);
+			add_v3_v3(avg_no, no);
+		}
+		normalize_v3(avg_no);
+
+		/* push vertex away from the plane */
+		dist = v3_dist_from_plane(me->mvert[i].co, center, avg_no);
+		copy_v3_v3(push, avg_no);
+		mul_v3_fl(push, dist);
+		add_v3_v3(me->mvert[i].co, push);
+		
+	}
+
+	MEM_freeN(origco);
+	cddm->release(cddm);
+
+	/* subdivide the mesh to highest level without displacements */
+	cddm = CDDM_from_mesh(me, NULL);
+	DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+	origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0);
+	cddm->release(cddm);
+
+	/* calc disps */
+	multiresModifier_disp_run(dispdm, me, 1, 0, origdm->getGridData(origdm), totlvl);
+
+	origdm->release(origdm);
+	dispdm->release(dispdm);
+}
+
 void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple)
 {
 	Mesh *me = ob->data;

Modified: trunk/blender/source/blender/editors/object/object_intern.h
===================================================================
--- trunk/blender/source/blender/editors/object/object_intern.h	2011-01-07 20:02:56 UTC (rev 34161)
+++ trunk/blender/source/blender/editors/object/object_intern.h	2011-01-07 21:12:47 UTC (rev 34162)
@@ -151,6 +151,7 @@
 void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
 void OBJECT_OT_multires_reshape(struct wmOperatorType *ot);
 void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot);
+void OBJECT_OT_multires_base_apply(struct wmOperatorType *ot);
 void OBJECT_OT_multires_external_save(struct wmOperatorType *ot);
 void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
 void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);

Modified: trunk/blender/source/blender/editors/object/object_modifier.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_modifier.c	2011-01-07 20:02:56 UTC (rev 34161)
+++ trunk/blender/source/blender/editors/object/object_modifier.c	2011-01-07 21:12:47 UTC (rev 34162)
@@ -1177,6 +1177,48 @@
 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/********************* multires apply base ***********************/
+static int multires_base_apply_exec(bContext *C, wmOperator *op)
+{
+	Object *ob = ED_object_active_context(C);
+	MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+	
+	if (!mmd)
+		return OPERATOR_CANCELLED;
+	
+	multiresModifier_base_apply(mmd, ob);
+
+	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+	if (edit_modifier_invoke_properties(C, op))
+		return multires_base_apply_exec(C, op);
+	else
+		return OPERATOR_CANCELLED;
+}
+
+
+void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
+{
+	ot->name= "Multires Apply Base";
+	ot->description= "Modify the base mesh to conform to the displaced mesh";
+	ot->idname= "OBJECT_OT_multires_base_apply";
+
+	ot->poll= multires_poll;
+	ot->invoke= multires_base_apply_invoke;
+	ot->exec= multires_base_apply_exec;
+	
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+	edit_modifier_properties(ot);
+}
+
+
 /************************ mdef bind operator *********************/
 
 static int meshdeform_poll(bContext *C)

Modified: trunk/blender/source/blender/editors/object/object_ops.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_ops.c	2011-01-07 20:02:56 UTC (rev 34161)
+++ trunk/blender/source/blender/editors/object/object_ops.c	2011-01-07 21:12:47 UTC (rev 34162)
@@ -134,6 +134,7 @@
 	WM_operatortype_append(OBJECT_OT_multires_subdivide);
 	WM_operatortype_append(OBJECT_OT_multires_reshape);
 	WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete);
+	WM_operatortype_append(OBJECT_OT_multires_base_apply);
 	WM_operatortype_append(OBJECT_OT_multires_external_save);
 	WM_operatortype_append(OBJECT_OT_multires_external_pack);
 	WM_operatortype_append(OBJECT_OT_meshdeform_bind);




More information about the Bf-blender-cvs mailing list