[Bf-blender-cvs] [188f8d0] master: Fix T38801: Dupli objects with modifiers exhibit bad transform artifacts in Blender Internal renderer.

Lukas Tönne noreply at git.blender.org
Mon Feb 24 19:05:55 CET 2014


Commit: 188f8d093504aa3dcf28efc404c395ad43fc633f
Author: Lukas Tönne
Date:   Mon Feb 24 18:53:35 2014 +0100
https://developer.blender.org/rB188f8d093504aa3dcf28efc404c395ad43fc633f

Fix T38801: Dupli objects with modifiers exhibit bad transform artifacts
in Blender Internal renderer.

The BI renderer applies modifiers //after// changing the obmat of the
respective object (for the first instance it encounters). Before
rB6940bf0 the original obmat (omat) was stored inside dupli object data,
which was removed in favor of local omat variables due to hackishness
and redundancy. Problem with BI is that all the obmats have to be
overridden in relation to each other to produce the correct modifier
results (here: offset object for the array modifier).

The patch restores the old (messy) behavior for BI by first overriding
**all** the obmats at once from duplis, then creating render instances,
then cleaning up.

A better solution would be to avoid these modifier hacks in BI
altogether and properly evaluate them in the original object space, but
that requires far greater changes to the old code base, and is out of
scope for bugfixing.

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

M	source/blender/render/intern/source/convertblender.c

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

diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 57fb42c..3e9e1b1 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4930,6 +4930,13 @@ static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, in
 	}
 }
 
+/* additional data for dupli objects outside
+ * of the main dupli list
+ */
+typedef struct DupliObjectExtra {
+	float omat[4][4];
+} DupliObjectExtra;
+
 static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset)
 {
 	Base *base;
@@ -4988,20 +4995,28 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
 		else if ((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->lay)) ) {
 			if ((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
 				DupliObject *dob;
-				ListBase *lb;
+				ListBase *duplilist;
+				DupliObjectExtra *duplilist_extra = NULL;
+				int totdob, i;
 
 				/* 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(re->eval_ctx, re->scene, ob);
+				duplilist = object_duplilist(re->eval_ctx, re->scene, ob);
+				totdob = BLI_countlist(duplilist);
+				if (totdob > 0)
+					duplilist_extra = MEM_mallocN(sizeof(DupliObjectExtra) * totdob, "DupliObject extra data");
 				dupli_render_particle_set(re, ob, timeoffset, 0, 0);
 
-				for (dob= lb->first; dob; dob= dob->next) {
+				/* set dupli obmats */
+				for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
+					copy_m4_m4(duplilist_extra[i].omat, dob->ob->obmat);
+					copy_m4_m4(dob->ob->obmat, dob->mat);
+				}
+
+				for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
+					DupliObjectExtra *dob_extra = &duplilist_extra[i];
 					Object *obd= dob->ob;
-					float omat[4][4];
-					
-					copy_m4_m4(omat, obd->obmat);
-					copy_m4_m4(obd->obmat, dob->mat);
 
 					/* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
 					if (!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw)
@@ -5033,7 +5048,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
 							obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay); 
 
 							/* fill in instance variables for texturing */
-							set_dupli_tex_mat(re, obi, dob, omat);
+							set_dupli_tex_mat(re, obi, dob, dob_extra->omat);
 							if (dob->type != OB_DUPLIGROUP) {
 								copy_v3_v3(obi->dupliorco, dob->orco);
 								obi->dupliuv[0]= dob->uv[0];
@@ -5059,7 +5074,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
 									mul_m4_m4m4(mat, re->viewmat, dob->mat);
 								obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay);
 
-								set_dupli_tex_mat(re, obi, dob, omat);
+								set_dupli_tex_mat(re, obi, dob, dob_extra->omat);
 								if (dob->type != OB_DUPLIGROUP) {
 									copy_v3_v3(obi->dupliorco, dob->orco);
 									obi->dupliuv[0]= dob->uv[0];
@@ -5075,7 +5090,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
 
 						if (obi==NULL)
 							/* can't instance, just create the object */
-							init_render_object(re, obd, ob, dob, omat, timeoffset);
+							init_render_object(re, obd, ob, dob, dob_extra->omat, timeoffset);
 						
 						if (dob->type != OB_DUPLIGROUP) {
 							obd->flag |= OB_DONE;
@@ -5083,13 +5098,19 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
 						}
 					}
 					else
-						init_render_object(re, obd, ob, dob, omat, timeoffset);
-					
-					copy_m4_m4(obd->obmat, omat);
+						init_render_object(re, obd, ob, dob, dob_extra->omat, timeoffset);
 					
 					if (re->test_break(re->tbh)) break;
 				}
-				free_object_duplilist(lb);
+				
+				/* restore obmats */
+				for (dob= duplilist->first, i = 0; dob; dob= dob->next, ++i) {
+					copy_m4_m4(dob->ob->obmat, duplilist_extra[i].omat);
+				}
+				
+				free_object_duplilist(duplilist);
+				if (duplilist_extra)
+					MEM_freeN(duplilist_extra);
 
 				if (allow_render_object(re, ob, nolamps, onlyselected, actob))
 					init_render_object(re, ob, NULL, NULL, NULL, timeoffset);




More information about the Bf-blender-cvs mailing list