[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