diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2014-02-24 21:53:35 +0400 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2014-02-24 22:00:44 +0400 |
commit | 188f8d093504aa3dcf28efc404c395ad43fc633f (patch) | |
tree | 3aa201070829aac12757a13ef9d3f50124632072 /source/blender | |
parent | 036d35dd2471bc490c266cf4f7d4aba10080cb10 (diff) |
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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 57fb42cf20a..3e9e1b1c5e5 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); |