[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48897] trunk/blender/source/blender/ blenkernel/intern/multires.c: Fix [#32013] Crash loading a 2.49b model

Bastien Montagne montagne29 at wanadoo.fr
Fri Jul 13 22:50:33 CEST 2012


Revision: 48897
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48897
Author:   mont29
Date:     2012-07-13 20:50:32 +0000 (Fri, 13 Jul 2012)
Log Message:
-----------
Fix [#32013] Crash loading a 2.49b model

Problems were in the old multires loading system.

Actually, the sigsev itself was the easy part of the job (simply had to convert from tesselated data to polys/loops), but after that I was getting a horrible bunch of wild stray faces...

It finally turned out it was a mismatch in two different subsurf structs used while computing a mdisps layer from the multires DM, leading to getting complete random normals (null ones, NAN ones...), leading to complete dummy tangent space matrix, leading to absurds mdisps values...

Note: I also moved the copy of first layer's vertex and face data from old me->mr to mesh's v/fdata earlier in multire_load_old(), to be able to use general face_to_poly conversion function (later on we would have to do it by hand, the general function would erase our newly computed mdisps layer...).

Took me the whole week (something like 20h) to track this down: multires + subsurf = C nightmare!

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/multires.c

Modified: trunk/blender/source/blender/blenkernel/intern/multires.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/multires.c	2012-07-13 19:59:38 UTC (rev 48896)
+++ trunk/blender/source/blender/blenkernel/intern/multires.c	2012-07-13 20:50:32 UTC (rev 48897)
@@ -992,6 +992,9 @@
 	copy_v3_v3(mat[2], CCG_grid_elem_no(key, grid, x, y));
 }
 
+/* XXX WARNING: subsurf elements from dm and oldGridData *must* be of the same format (size),
+ *              because this code uses CCGKey's info from dm to access oldGridData's normals
+ *              (through the call to grid_tangent_matrix())! */
 static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl)
 {
 	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -2069,6 +2072,21 @@
 		me->mface[i].mat_nr = lvl->faces[i].mat_nr;
 	}
 
+	/* Copy the first-level data to the mesh */
+	/* XXX We must do this before converting tessfaces to polys/lopps! */
+	for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; ++i, ++l)
+		CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
+	for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l)
+		CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
+	memset(&me->mr->vdata, 0, sizeof(CustomData));
+	memset(&me->mr->fdata, 0, sizeof(CustomData));
+
+	multires_load_old_vcols(me);
+	multires_load_old_face_flags(me);
+
+	/* multiresModifier_subdivide (actually, multires_subdivide) expects polys, not tessfaces! */
+	BKE_mesh_convert_mfaces_to_mpolys(me);
+
 	/* Add a multires modifier to the object */
 	md = ob->modifiers.first;
 	while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
@@ -2081,25 +2099,19 @@
 
 	mmd->lvl = mmd->totlvl;
 	orig = CDDM_from_mesh(me, NULL);
-	dm = multires_make_derived_from_derived(orig, mmd, ob, 0);
-					   
+	/* XXX We *must* alloc paint mask here, else we have some kind of mismatch in
+	 *     multires_modifier_update_mdisps() (called by dm->release(dm)), which always creates the
+	 *     reference subsurfed dm with this option, before calling multiresModifier_disp_run(),
+	 *     which implitely expects both subsurfs from its first dm and oldGridData parameters to
+	 *     be of the same "format"! */
+	dm = multires_make_derived_from_derived(orig, mmd, ob, MULTIRES_ALLOC_PAINT_MASK);
+
 	multires_load_old_dm(dm, me, mmd->totlvl + 1);
 
 	multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED);
 	dm->release(dm);
 	orig->release(orig);
 
-	/* Copy the first-level data to the mesh */
-	for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; ++i, ++l)
-		CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
-	for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l)
-		CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
-	memset(&me->mr->vdata, 0, sizeof(CustomData));
-	memset(&me->mr->fdata, 0, sizeof(CustomData));
-
-	multires_load_old_vcols(me);
-	multires_load_old_face_flags(me);
-
 	/* Remove the old multires */
 	multires_free(me->mr);
 	me->mr = NULL;




More information about the Bf-blender-cvs mailing list