From 9dd1bcfdfb3e32b57aee6ee7c1e2f0f5d2446da9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 21 Jan 2008 22:10:14 +0000 Subject: Render instancing can now also handle the same object in multiple, non-animated dupligroups. --- .../blender/render/intern/include/render_types.h | 8 +- .../blender/render/intern/source/convertblender.c | 104 +++++++++++++++++---- source/blender/render/intern/source/occlusion.c | 21 ++++- 3 files changed, 108 insertions(+), 25 deletions(-) (limited to 'source/blender/render/intern') diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 6124870d63e..b400014d1bf 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -244,7 +244,7 @@ typedef struct ObjectRen { struct ObjectRen *next, *prev; struct Object *ob, *par; struct Scene *sce; - int index, psysindex; + int index, psysindex, flag; int totvert, totvlak, totstrand, tothalo; int vertnodeslen, vlaknodeslen, strandnodeslen, blohalen; @@ -257,6 +257,8 @@ typedef struct ObjectRen { char (*mtface)[32]; char (*mcol)[32]; int actmtface, actmcol; + + float obmat[4][4]; /* only used in convertblender.c, for instancing */ } ObjectRen; typedef struct ObjectInstanceRen { @@ -487,10 +489,14 @@ typedef struct LampRen { #define R_STRAND_BSPLINE 1 #define R_STRAND_B_UNITS 2 +/* objectren->flag */ +#define R_INSTANCEABLE 1 + /* objectinstance->flag */ #define R_DUPLI_TRANSFORMED 1 #define R_ENV_TRANSFORMED 2 #define R_TRANSFORMED (1|2) +#define R_DUPLI_ELEM 4 #endif /* RENDER_TYPES_H */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index ff227b1c670..845fda22816 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3896,7 +3896,7 @@ static void find_dupli_instances(Render *re, ObjectRen *obr) float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; int first = 1; - Mat4MulMat4(obmat, obr->ob->obmat, re->viewmat); + Mat4MulMat4(obmat, obr->obmat, re->viewmat); Mat4Invert(imat, obmat); for(obi=re->instancetable.last; obi; obi=obi->prev) { @@ -3923,6 +3923,40 @@ static void find_dupli_instances(Render *re, ObjectRen *obr) } } +static void assign_dupligroup_dupli(Render *re, ObjectInstanceRen *obi, ObjectRen *obr) +{ + float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; + + Mat4MulMat4(obmat, obr->obmat, re->viewmat); + Mat4Invert(imat, obmat); + + obi->obr= obr; + + /* compute difference between object matrix and + * object matrix with dupli transform, in viewspace */ + Mat4CpyMat4(obimat, obi->mat); + Mat4MulMat4(obi->mat, imat, obimat); + + Mat3CpyMat4(nmat, obi->mat); + Mat3Inv(obi->imat, nmat); + + re->totvert += obr->totvert; + re->totvlak += obr->totvlak; + re->tothalo += obr->tothalo; + re->totstrand += obr->totstrand; +} + +static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex) +{ + ObjectRen *obr; + + for(obr=re->objecttable.first; obr; obr=obr->next) + if(obr->ob == ob && obr->psysindex == psysindex && (obr->flag & R_INSTANCEABLE)) + return obr; + + return NULL; +} + static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) { Object *ob= obr->ob; @@ -3962,7 +3996,7 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) re->totstrand += obr->totstrand; } -static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts) +static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable) { ObjectRen *obr; ParticleSystem *psys; @@ -3985,6 +4019,10 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in /* one render object for the data itself */ if(allow_render) { obr= RE_addRenderObject(re, ob, par, index, 0); + if(instanceable) { + obr->flag |= R_INSTANCEABLE; + Mat4CpyMat4(obr->obmat, ob->obmat); + } init_render_object_data(re, obr, only_verts); /* only add instance for objects that have not been used for dupli */ @@ -3999,6 +4037,10 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in psysindex= 1; for(psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) { obr= RE_addRenderObject(re, ob, par, index, psysindex); + if(instanceable) { + obr->flag |= R_INSTANCEABLE; + Mat4CpyMat4(obr->obmat, ob->obmat); + } init_render_object_data(re, obr, only_verts); psys_render_restore(ob, psys); @@ -4013,7 +4055,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in /* par = pointer to duplicator parent, needed for object lookup table */ /* index = when duplicater copies same object (particle), the counter */ -static void init_render_object(Render *re, Object *ob, Object *par, int index, int only_verts) +static void init_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable) { static double lasttime= 0.0; double time; @@ -4022,7 +4064,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i if(ob->type==OB_LAMP) add_render_lamp(re, ob); else if(render_object_type(ob->type)) - add_render_object(re, ob, par, index, only_verts); + add_render_object(re, ob, par, index, only_verts, instanceable); else { MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); MTC_Mat4Invert(ob->imat, mat); @@ -4151,7 +4193,7 @@ static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object static int allow_render_dupli_instance(Render *re, DupliObject *dob, Object *obd) { return (render_object_type(obd->type) && - (!(dob->type == OB_DUPLIGROUP)) && + (!(dob->type == OB_DUPLIGROUP) || !dob->animated) && !(re->r.mode & R_RADIO)); } @@ -4224,7 +4266,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int 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, only_verts); + init_render_object(re, ob, NULL, 0, only_verts, 1); } else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) { @@ -4255,38 +4297,60 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int if(allow_render_dupli_instance(re, dob, obd)) { ParticleSystem *psys; + ObjectRen *obr = NULL; int psysindex; float mat[4][4]; - Mat4MulMat4(mat, dob->mat, re->viewmat); - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat); - VECCOPY(obi->dupliorco, dob->orco); - obi->dupliuv[0]= dob->uv[0]; - obi->dupliuv[1]= dob->uv[1]; + 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); + + if(dob->type != OB_DUPLIGROUP) { + VECCOPY(obi->dupliorco, dob->orco); + obi->dupliuv[0]= dob->uv[0]; + obi->dupliuv[1]= dob->uv[1]; + obi->flag |= R_DUPLI_ELEM; + } + else + assign_dupligroup_dupli(re, obi, obr); + } + else + init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); psysindex= 1; for(psys=obd->particlesystem.first; psys; psys=psys->next) { - RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat); - VECCOPY(obi->dupliorco, dob->orco); - obi->dupliuv[0]= dob->uv[0]; - obi->dupliuv[1]= dob->uv[1]; + if(dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, ob, psysindex))) { + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat); + if(dob->type != OB_DUPLIGROUP) { + VECCOPY(obi->dupliorco, dob->orco); + obi->dupliuv[0]= dob->uv[0]; + obi->dupliuv[1]= dob->uv[1]; + obi->flag |= R_DUPLI_ELEM; + } + else + assign_dupligroup_dupli(re, obi, obr); + } + else + init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); } - obd->flag |= OB_DONE; - obd->transflag |= OB_RENDER_DUPLI; + if(dob->type != OB_DUPLIGROUP) { + obd->flag |= OB_DONE; + obd->transflag |= OB_RENDER_DUPLI; + } } else - init_render_object(re, obd, ob, dob->index, only_verts); + init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); if(re->test_break()) break; } free_object_duplilist(lb); if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts); + init_render_object(re, ob, NULL, 0, only_verts, 0); } else if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts); + init_render_object(re, ob, NULL, 0, only_verts, 0); } if(re->test_break()) break; diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index bcd6ed3aa0d..0744aa95c45 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -297,6 +297,7 @@ static void occ_face(const OccFace *face, float *co, float *normal, float *area) { ObjectInstanceRen *obi; VlakRen *vlr; + float v1[3], v2[3], v3[3], v4[3]; obi= &R.objectinstance[face->obi]; vlr= RE_findOrAddVlak(obi->obr, face->facenr); @@ -330,11 +331,23 @@ static void occ_face(const OccFace *face, float *co, float *normal, float *area) } if(area) { + VECCOPY(v1, vlr->v1->co); + VECCOPY(v3, vlr->v2->co); + VECCOPY(v3, vlr->v3->co); + if(vlr->v4) VECCOPY(v4, vlr->v4->co); + + if(obi->flag & R_TRANSFORMED) { + Mat4MulVecfl(obi->mat, v1); + Mat4MulVecfl(obi->mat, v2); + Mat4MulVecfl(obi->mat, v3); + if(vlr->v4) Mat4MulVecfl(obi->mat, v4); + } + /* todo: correct area for instances */ if(vlr->v4) - *area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); + *area= AreaQ3Dfl(v1, v2, v3, v4); else - *area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co); + *area= AreaT3Dfl(v1, v2, v3); } } @@ -576,7 +589,7 @@ static OcclusionTree *occ_tree_build(Render *re) /* count */ totface= 0; for(obi=re->instancetable.first; obi; obi=obi->next) { - if(obi->flag & R_TRANSFORMED) + if(obi->flag & R_DUPLI_ELEM) continue; obr= obi->obr; @@ -612,7 +625,7 @@ static OcclusionTree *occ_tree_build(Render *re) /* make array of face pointers */ for(b=0, c=0, obi=re->instancetable.first; obi; obi=obi->next, c++) { - if(obi->flag & R_TRANSFORMED) + if(obi->flag & R_DUPLI_ELEM) continue; /* temporary to avoid slow renders with loads of duplis */ obr= obi->obr; -- cgit v1.2.3