[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [13887] trunk/blender/source/blender/ render/intern/source/convertblender.c:

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Feb 27 12:50:20 CET 2008


Revision: 13887
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=13887
Author:   blendix
Date:     2008-02-27 12:50:20 +0100 (Wed, 27 Feb 2008)

Log Message:
-----------

Fix for dupli rendering bug, with a duplicating particle system using
groups that were not in the scene. Also commented the code better.

Modified Paths:
--------------
    trunk/blender/source/blender/render/intern/source/convertblender.c

Modified: trunk/blender/source/blender/render/intern/source/convertblender.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/convertblender.c	2008-02-27 11:47:07 UTC (rev 13886)
+++ trunk/blender/source/blender/render/intern/source/convertblender.c	2008-02-27 11:50:20 UTC (rev 13887)
@@ -4036,6 +4036,9 @@
 	Mat4MulMat4(obmat, obr->obmat, re->viewmat);
 	Mat4Invert(imat, obmat);
 
+	/* for objects instanced by dupliverts/faces/particles, we go over the
+	 * list of instances to find ones that instance obr, and setup their
+	 * matrices and obr pointer */
 	for(obi=re->instancetable.last; obi; obi=obi->prev) {
 		if(!obi->obr && obi->ob == obr->ob && obi->psysindex == obr->psysindex) {
 			obi->obr= obr;
@@ -4087,9 +4090,13 @@
 {
 	ObjectRen *obr;
 
+	/* if the object is itself instanced, we don't want to create an instance
+	 * for it */
 	if(ob->transflag & OB_RENDER_DUPLI)
 		return NULL;
 
+	/* try to find an object that was already created so we can reuse it
+	 * and save memory */
 	for(obr=re->objecttable.first; obr; obr=obr->next)
 		if(obr->ob == ob && obr->psysindex == psysindex && (obr->flag & R_INSTANCEABLE))
 			return obr;
@@ -4471,16 +4478,47 @@
 	return lay;
 }
 
+static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, int onlyselected, Object *actob, int timeoffset, int vectorlay, int level)
+{
+	GroupObject *go;
+	Object *ob;
+
+	/* simple preventing of too deep nested groups */
+	if(level>MAX_DUPLI_RECUR) return;
+
+	/* recursively go into dupligroups to find objects with OB_RENDER_DUPLI
+	 * that were not created yet */
+	for(go= group->gobject.first; go; go= go->next) {
+		ob= go->ob;
+
+		if(ob->flag & OB_DONE) {
+			if(ob->transflag & OB_RENDER_DUPLI) {
+				if(allow_render_object(ob, nolamps, onlyselected, actob)) {
+					init_render_object(re, ob, NULL, 0, timeoffset, vectorlay);
+					ob->transflag &= ~OB_RENDER_DUPLI;
+
+					if(ob->dup_group)
+						add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, vectorlay, level+1);
+				}
+			}
+		}
+	}
+}
+
 static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset)
 {
 	Base *base;
 	Object *ob;
+	Group *group;
 	ObjectInstanceRen *obi;
 	Scene *sce;
 	float mat[4][4];
 	int lay, vectorlay, redoimat= 0;
 
-	set_dupli_tex_mat(NULL, NULL, NULL); /* init */
+	/* for duplis we need the Object texture mapping to work as if
+	 * untransformed, set_dupli_tex_mat sets the matrix to allow that
+	 * NULL is just for init */
+	set_dupli_tex_mat(NULL, NULL, NULL);
 
 	for(SETLOOPER(re->scene, base)) {
 		ob= base->object;
@@ -4495,6 +4533,9 @@
 	for(SETLOOPER(re->scene, base)) {
 		ob= base->object;
 
+		/* in the prev/next pass for making speed vectors, avoid creating
+		 * objects that are not on a renderlayer with a vector pass, can
+		 * save a lot of time in complex scenes */
 		vectorlay= get_vector_renderlayers(sce);
 		lay= (timeoffset)? renderlay & vectorlay: renderlay;
 
@@ -4503,9 +4544,14 @@
 
 		/* OB_DONE means the object itself got duplicated, so was already converted */
 		if(ob->flag & OB_DONE) {
-			if(ob->transflag & OB_RENDER_DUPLI)
-				if(allow_render_object(ob, nolamps, onlyselected, actob))
+			/* OB_RENDER_DUPLI means instances for it were already created, now
+			 * it still needs to create the ObjectRen containing the data */
+			if(ob->transflag & OB_RENDER_DUPLI) {
+				if(allow_render_object(ob, nolamps, onlyselected, actob)) {
 					init_render_object(re, ob, NULL, 0, timeoffset, vectorlay);
+					ob->transflag &= ~OB_RENDER_DUPLI;
+				}
+			}
 		}
 		else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) {
 			if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
@@ -4514,6 +4560,8 @@
 
 				redoimat= 1;
 
+				/* create list of duplis generated by this object, particle
+				 * system need to have render settings set for dupli particles */
 				dupli_render_particle_set(re, ob, timeoffset, 0, 1);
 				lb= object_duplilist(sce, ob);
 				dupli_render_particle_set(re, ob, timeoffset, 0, 0);
@@ -4542,29 +4590,42 @@
 						int psysindex;
 						float mat[4][4];
 
+						/* instances instead of the actual object are added in two cases, either
+						 * this is a duplivert/face/particle, or it is a non-animated object in
+						 * a dupligroup that has already been created before */
 						if(dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) {
 							Mat4MulMat4(mat, dob->mat, re->viewmat);
 							obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat);
+
+							/* fill in instance variables for texturing */
 							set_dupli_tex_mat(re, obi, dob);
-
 							if(dob->type != OB_DUPLIGROUP) {
 								VECCOPY(obi->dupliorco, dob->orco);
 								obi->dupliuv[0]= dob->uv[0];
 								obi->dupliuv[1]= dob->uv[1];
 							}
 							else {
+								/* for the second case, setup instance to point to the already
+								 * created object, and possibly setup instances if this object
+								 * itself was duplicated. for the first case find_dupli_instances
+								 * will be called later. */
 								assign_dupligroup_dupli(re, obi, obr);
 								if(obd->transflag & OB_RENDER_DUPLI)
 									find_dupli_instances(re, obr);
 							}
 						}
 						else
+							/* can't instance, just create the object */
 							init_render_object(re, obd, ob, dob, timeoffset, vectorlay);
 
+						/* same logic for particles, each particle system has it's own object, so
+						 * need to go over them separately */
 						psysindex= 1;
 						for(psys=obd->particlesystem.first; psys; psys=psys->next) {
 							if(dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, ob, psysindex))) {
 								obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat);
+
+								set_dupli_tex_mat(re, obi, dob);
 								if(dob->type != OB_DUPLIGROUP) {
 									VECCOPY(obi->dupliorco, dob->orco);
 									obi->dupliuv[0]= dob->uv[0];
@@ -4575,8 +4636,6 @@
 									if(obd->transflag & OB_RENDER_DUPLI)
 										find_dupli_instances(re, obr);
 								}
-
-								set_dupli_tex_mat(re, obi, dob);
 							}
 						}
 						
@@ -4602,6 +4661,11 @@
 		if(re->test_break()) break;
 	}
 
+	/* objects in groups with OB_RENDER_DUPLI set still need to be created,
+	 * since they may not be part of the scene */
+	for(group= G.main->group.first; group; group=group->id.next)
+		add_group_render_dupli_obs(re, group, nolamps, onlyselected, actob, timeoffset, renderlay, 0);
+
 	/* imat objects has to be done again, since groups can mess it up */
 	if(redoimat) {
 		for(SETLOOPER(re->scene, base)) {





More information about the Bf-blender-cvs mailing list