Render instancing can now also handle the same object in multiple,
non-animated dupligroups.
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user