[Bf-blender-cvs] [aa3fc89] master: Fix T44611: 'make_links_data' modifiers would fail and crash with multires modifier.

Bastien Montagne noreply at git.blender.org
Thu May 7 15:21:28 CEST 2015


Commit: aa3fc89257f839260e7577881f399011a709badf
Author: Bastien Montagne
Date:   Thu May 7 15:16:10 2015 +0200
Branches: master
https://developer.blender.org/rBaa3fc89257f839260e7577881f399011a709badf

Fix T44611: 'make_links_data' modifiers would fail and crash with multires modifier.

Since it was not ensuring dest has valid mdisp data matching new multires modifier subdiv level...

Also, fixed a bug in `multires_subdivide()`, which would crash when trying to
increase from level 0 (aka no subdiv) to > 1 (wrong check, trying to interpolate
when it should not). And added a few sanity checks.

===================================================================

M	source/blender/blenkernel/BKE_multires.h
M	source/blender/blenkernel/intern/multires.c
M	source/blender/blenkernel/intern/object.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 627b8d6..a8242a5 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -79,8 +79,9 @@ struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifier
                                     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);
+void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple);
+void multiresModifier_sync_levels_ex(
+        struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst);
 int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd,
                              struct Object *dst, struct Object *src);
 int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd,
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index e4bf05c..0c984c3 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -882,18 +882,20 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
 {
 	Mesh *me = ob->data;
 	MDisps *mdisps;
-	int lvl = mmd->totlvl;
+	const int lvl = mmd->totlvl;
 
 	if ((totlvl > multires_max_levels) || (me->totpoly == 0))
 		return;
 
+	BLI_assert(totlvl > lvl);
+
 	multires_force_update(ob);
 
 	mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
 	if (!mdisps)
 		mdisps = multires_mdisps_initialize_hidden(me, totlvl);
 
-	if (mdisps->disps && !updateblock && totlvl > 1) {
+	if (mdisps->disps && !updateblock && lvl != 0) {
 		/* upsample */
 		DerivedMesh *lowdm, *cddm, *highdm;
 		CCGElem **highGridData, **lowGridData, **subGridData;
@@ -910,6 +912,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
 
 		/* create multires DM from original mesh at low level */
 		lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask);
+		BLI_assert(lowdm != cddm);
 		cddm->release(cddm);
 
 		/* copy subsurf grids and replace them with low displaced grids */
@@ -2137,27 +2140,38 @@ void multires_load_old(Object *ob, Mesh *me)
 	me->mr = NULL;
 }
 
-/* If 'ob' and 'to_ob' both have multires modifiers, synchronize them
- * such that 'ob' has the same total number of levels as 'to_ob'. */
-static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
+/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
+ * such that 'ob_dst' has the same total number of levels as 'ob_src'. */
+void multiresModifier_sync_levels_ex(Object *ob_dst, MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst)
 {
-	MultiresModifierData *mmd = get_multires_modifier(scene, ob, 1);
-	MultiresModifierData *to_mmd = get_multires_modifier(scene, to_ob, 1);
+	if (mmd_src->totlvl == mmd_dst->totlvl) {
+		return;
+	}
+
+	if (mmd_src->totlvl > mmd_dst->totlvl) {
+		multires_subdivide(mmd_dst, ob_dst, mmd_src->totlvl, false, mmd_dst->simple);
+	}
+	else {
+		multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
+	}
+}
 
-	if (!mmd) {
+static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+	MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true);
+	MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true);
+
+	if (!mmd_src) {
 		/* 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) */
 
-		multires_customdata_delete(ob->data);
+		multires_customdata_delete(ob_src->data);
 	}
 
-	if (mmd && to_mmd) {
-		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);
+	if (mmd_src && mmd_dst) {
+		multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
 	}
 }
 
@@ -2276,7 +2290,7 @@ void multiresModifier_scale_disp(Scene *scene, Object *ob)
 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);
+	multires_sync_levels(scene, to_ob, ob);
 
 	/* construct scale matrix for displacement */
 	BKE_object_scale_to_mat3(to_ob, tmat);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index bd0b727..5b29187 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -96,6 +96,7 @@
 #include "BKE_editmesh.h"
 #include "BKE_mball.h"
 #include "BKE_modifier.h"
+#include "BKE_multires.h"
 #include "BKE_node.h"
 #include "BKE_object.h"
 #include "BKE_paint.h"
@@ -280,6 +281,12 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
 
 		nmd = modifier_new(md->type);
 		BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
+
+		if (md->type == eModifierType_Multires) {
+			/* Has to be done after mod creation, but *before* we actually copy its settings! */
+			multiresModifier_sync_levels_ex(ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd);
+		}
+
 		modifier_copyData(md, nmd);
 		BLI_addtail(&ob_dst->modifiers, nmd);
 		modifier_unique_name(&ob_dst->modifiers, nmd);




More information about the Bf-blender-cvs mailing list