[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [50525] trunk/blender/source/blender/ blenkernel: fix [#29616] Crash/ infinite loop from missing cyclic check in group/dupligroups (unlikely/ intentional)

Campbell Barton ideasman42 at gmail.com
Tue Sep 11 12:18:46 CEST 2012


Revision: 50525
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=50525
Author:   campbellbarton
Date:     2012-09-11 10:18:45 +0000 (Tue, 11 Sep 2012)
Log Message:
-----------
fix [#29616] Crash/infinite loop from missing cyclic check in group/dupligroups (unlikely/intentional)

calling BKE_ptcache_ids_from_object() could recursively call BKE_object_handle_update(), when there is no reason to update object transforms at all. Add option not to do any updates and just return an object list.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_anim.h
    trunk/blender/source/blender/blenkernel/intern/anim.c
    trunk/blender/source/blender/blenkernel/intern/pointcache.c

Modified: trunk/blender/source/blender/blenkernel/BKE_anim.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_anim.h	2012-09-11 09:39:37 UTC (rev 50524)
+++ trunk/blender/source/blender/blenkernel/BKE_anim.h	2012-09-11 10:18:45 UTC (rev 50525)
@@ -65,6 +65,7 @@
 /* ---------------------------------------------------- */
 /* Dupli-Geometry */
 
+struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update);
 struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob);
 void free_object_duplilist(struct ListBase *lb);
 int count_duplilist(struct Object *ob);

Modified: trunk/blender/source/blender/blenkernel/intern/anim.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/anim.c	2012-09-11 09:39:37 UTC (rev 50524)
+++ trunk/blender/source/blender/blenkernel/intern/anim.c	2012-09-11 10:18:45 UTC (rev 50525)
@@ -74,7 +74,8 @@
 /* --------------------- */
 /* forward declarations */
 
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated);
+static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
+                                       int level, short animated, short update);
 
 /* ******************************************************************** */
 /* Animation Visualization */
@@ -717,7 +718,8 @@
 	return dob;
 }
 
-static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated)
+static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index,
+                            int level, short animated, short update)
 {
 	DupliObject *dob;
 	Group *group;
@@ -731,8 +733,14 @@
 	if (level > MAX_DUPLI_RECUR) return;
 	
 	/* handles animated groups, and */
+
 	/* we need to check update for objects that are not in scene... */
-	group_handle_recalc_and_update(scene, ob, group);
+	if (update) {
+		/* note: update is optional because we don't always need object
+		 * transformations to be correct. Also fixes bug [#29616]. */
+		group_handle_recalc_and_update(scene, ob, group);
+	}
+
 	animated = animated || group_is_animated(ob, group);
 	
 	for (go = group->gobject.first; go; go = go->next) {
@@ -764,7 +772,7 @@
 
 			if (go->ob->transflag & OB_DUPLI) {
 				copy_m4_m4(dob->ob->obmat, dob->mat);
-				object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated);
+				object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated, update);
 				copy_m4_m4(dob->ob->obmat, dob->omat);
 			}
 		}
@@ -844,6 +852,7 @@
 	ID *id; /* scene or group, for recursive loops */
 	int level;
 	int animated;
+	int update;
 	ListBase *lb;
 	float pmat[4][4];
 	float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */
@@ -899,12 +908,13 @@
 		float tmpmat[4][4];
 		copy_m4_m4(tmpmat, vdd->ob->obmat);
 		copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
-		object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated);
+		object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated, vdd->update);
 		copy_m4_m4(vdd->ob->obmat, tmpmat);
 	}
 }
 
-static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated)
+static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
+                             int level, short animated, short update)
 {
 	Object *ob, *ob_iter;
 	Mesh *me = par->data;
@@ -983,6 +993,7 @@
 					vdd.id = id;
 					vdd.level = level;
 					vdd.animated = animated;
+					vdd.update = update;
 					vdd.lb = lb;
 					vdd.ob = ob;
 					vdd.scene = scene;
@@ -1027,7 +1038,8 @@
 	dm->release(dm);
 }
 
-static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated)
+static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
+                           int level, short animated, short update)
 {
 	Object *ob, *ob_iter;
 	Base *base = NULL;
@@ -1197,7 +1209,7 @@
 							float tmpmat[4][4];
 							copy_m4_m4(tmpmat, ob->obmat);
 							copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
-							object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated);
+							object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated, update);
 							copy_m4_m4(ob->obmat, tmpmat);
 						}
 					}
@@ -1217,7 +1229,8 @@
 	dm->release(dm);
 }
 
-static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, int level, int animated)
+static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys,
+                                   int level, short animated, short update)
 {
 	GroupObject *go;
 	Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
@@ -1300,7 +1313,9 @@
 
 		/* gather list of objects or single object */
 		if (part->ren_as == PART_DRAW_GR) {
-			group_handle_recalc_and_update(scene, par, part->dup_group);
+			if (update) {
+				group_handle_recalc_and_update(scene, par, part->dup_group);
+			}
 
 			if (part->draw & PART_DRAW_COUNT_GR) {
 				for (dw = part->dupliweights.first; dw; dw = dw->next)
@@ -1603,7 +1618,8 @@
 
 /* ------------- */
 
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated)
+static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
+                                       int level, short animated, short update)
 {	
 	if ((ob->transflag & OB_DUPLI) == 0)
 		return;
@@ -1623,11 +1639,11 @@
 	if (ob->transflag & OB_DUPLIPARTS) {
 		ParticleSystem *psys = ob->particlesystem.first;
 		for (; psys; psys = psys->next)
-			new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated);
+			new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated, update);
 	}
 	else if (ob->transflag & OB_DUPLIVERTS) {
 		if (ob->type == OB_MESH) {
-			vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated);
+			vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update);
 		}
 		else if (ob->type == OB_FONT) {
 			if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
@@ -1637,7 +1653,7 @@
 	}
 	else if (ob->transflag & OB_DUPLIFACES) {
 		if (ob->type == OB_MESH)
-			face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated);
+			face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update);
 	}
 	else if (ob->transflag & OB_DUPLIFRAMES) {
 		if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
@@ -1647,7 +1663,7 @@
 	else if (ob->transflag & OB_DUPLIGROUP) {
 		DupliObject *dob;
 		
-		group_duplilist(duplilist, scene, ob, par_index, level + 1, animated); /* now recursive */
+		group_duplilist(duplilist, scene, ob, par_index, level + 1, animated, update); /* now recursive */
 
 		if (level == 0) {
 			for (dob = duplilist->first; dob; dob = dob->next)
@@ -1659,14 +1675,22 @@
 
 /* Returns a list of DupliObject
  * note; group dupli's already set transform matrix. see note in group_duplilist() */
-ListBase *object_duplilist(Scene *sce, Object *ob)
+ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update)
 {
 	ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
 	duplilist->first = duplilist->last = NULL;
-	object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0);
+	object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0, update);
 	return duplilist;
 }
 
+/* note: previously updating was always done, this is why it defaults to be on
+ * but there are likely places it can be called without updating */
+ListBase *object_duplilist(Scene *sce, Object *ob)
+{
+	return object_duplilist_ex(sce, ob, TRUE);
+}
+
+
 void free_object_duplilist(ListBase *lb)
 {
 	DupliObject *dob;

Modified: trunk/blender/source/blender/blenkernel/intern/pointcache.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/pointcache.c	2012-09-11 09:39:37 UTC (rev 50524)
+++ trunk/blender/source/blender/blenkernel/intern/pointcache.c	2012-09-11 10:18:45 UTC (rev 50525)
@@ -1029,7 +1029,8 @@
 	if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
 		ListBase *lb_dupli_ob;
 
-		if ((lb_dupli_ob=object_duplilist(scene, ob))) {
+		/* don't update the dupli groups, we only wan't their pid's */
+		if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE))) {
 			DupliObject *dob;
 			for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
 				if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */




More information about the Bf-blender-cvs mailing list