Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/intern/anim.c10
-rw-r--r--source/blender/makesdna/DNA_object_types.h1
-rw-r--r--source/blender/nodes/intern/SHD_nodes/SHD_geom.c2
-rw-r--r--source/blender/radiosity/intern/source/radfactors.c4
-rw-r--r--source/blender/radiosity/intern/source/radrender.c295
-rw-r--r--source/blender/render/extern/include/RE_raytrace.h26
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h8
-rw-r--r--source/blender/render/intern/include/render_types.h77
-rw-r--r--source/blender/render/intern/include/rendercore.h3
-rw-r--r--source/blender/render/intern/include/renderdatabase.h85
-rw-r--r--source/blender/render/intern/include/shadbuf.h5
-rw-r--r--source/blender/render/intern/include/shading.h6
-rw-r--r--source/blender/render/intern/include/strand.h100
-rw-r--r--source/blender/render/intern/include/zbuf.h35
-rw-r--r--source/blender/render/intern/source/convertblender.c3306
-rw-r--r--source/blender/render/intern/source/envmap.c136
-rw-r--r--source/blender/render/intern/source/imagetexture.c1
-rw-r--r--source/blender/render/intern/source/rayshade.c166
-rw-r--r--source/blender/render/intern/source/raytrace.c181
-rw-r--r--source/blender/render/intern/source/rendercore.c328
-rw-r--r--source/blender/render/intern/source/renderdatabase.c785
-rw-r--r--source/blender/render/intern/source/shadbuf.c300
-rw-r--r--source/blender/render/intern/source/shadeinput.c315
-rw-r--r--source/blender/render/intern/source/shadeoutput.c2
-rw-r--r--source/blender/render/intern/source/strand.c343
-rw-r--r--source/blender/render/intern/source/texture.c67
-rw-r--r--source/blender/render/intern/source/zbuf.c1004
-rw-r--r--source/blender/src/meshlaplacian.c4
-rw-r--r--source/blender/yafray/YafRay_Api.h2
-rw-r--r--source/blender/yafray/intern/api.cpp2
-rw-r--r--source/blender/yafray/intern/export_File.cpp10
-rw-r--r--source/blender/yafray/intern/export_Plugin.cpp16
-rw-r--r--source/blender/yafray/intern/yafray_Render.cpp142
-rw-r--r--source/blender/yafray/intern/yafray_Render.h2
34 files changed, 3926 insertions, 3843 deletions
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 4aebd099885..1eb7e232382 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -292,14 +292,6 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i
dob->index= index;
ob->lay= lay;
- /* allowing duplicators for particle systems... a bit silly still */
- {
- PartEff *paf= give_parteff(ob);
- if(paf) {
- Mat4Invert(ob->imat, ob->obmat);
- Mat4CpyMat4(paf->imat, ob->imat);
- }
- }
return dob;
}
@@ -809,7 +801,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob)
group_duplilist(duplilist, ob, 0); /* now recursive */
- /* make copy already, because in group dupli's deform displists can be makde, requiring parent matrices */
+ /* make copy already, because in group dupli's deform displists can be made, requiring parent matrices */
for(dob= duplilist->first; dob; dob= dob->next)
Mat4CpyMat4(dob->ob->obmat, dob->mat);
}
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 8e15f6b1684..16ecc4b88f0 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -279,6 +279,7 @@ extern Object workob;
#define OB_DUPLIFACES 512
#define OB_DUPLIFACES_SCALE 1024
#define OB_DUPLIPARTS 2048
+#define OB_RENDER_DUPLI 4096
/* (short) ipoflag */
#define OB_DRAWKEY 1
diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
index b15aa6802f3..24395059c60 100644
--- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
+++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c
@@ -51,7 +51,7 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **in, bNod
if(data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
NodeGeometry *ngeo= (NodeGeometry*)node->storage;
- ShadeInputUV *suv= &shi->uv[0];
+ ShadeInputUV *suv= &shi->uv[shi->actuv];
static float defaultvcol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
static float front= 0.0;
int i;
diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c
index 46fb6b2c910..b6411522179 100644
--- a/source/blender/radiosity/intern/source/radfactors.c
+++ b/source/blender/radiosity/intern/source/radfactors.c
@@ -912,8 +912,8 @@ void inithemiwindows()
memset(vw, 0, sizeof(RadView));
vw->rectx= RG.hemires;
vw->recty= RG.hemires;
- vw->rectz= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows");
- vw->rect= MEM_mallocN(4*vw->rectx*vw->recty, "initwindows");
+ vw->rectz= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows");
+ vw->rect= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows");
vw->mynear= RG.maxsize/2000.0;
vw->myfar= 2.0*RG.maxsize;
vw->wx1= -vw->mynear;
diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c
index 42c7fa58da5..ee52956bbd2 100644
--- a/source/blender/radiosity/intern/source/radrender.c
+++ b/source/blender/radiosity/intern/source/radrender.c
@@ -87,6 +87,7 @@ static float maxenergy;
static VlakRen *findshoot_rr(Render *re)
{
RadFace *rf;
+ ObjectRen *obr;
VlakRen *vlr=NULL, *shoot;
float energy;
int a;
@@ -94,19 +95,21 @@ static VlakRen *findshoot_rr(Render *re)
shoot= NULL;
maxenergy= 0.0;
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
- if(vlr->radface) {
- rf= vlr->radface;
- rf->flag &= ~RAD_SHOOT;
-
- energy= rf->unshot[0]*rf->area;
- energy+= rf->unshot[1]*rf->area;
- energy+= rf->unshot[2]*rf->area;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+ if(vlr->radface) {
+ rf= vlr->radface;
+ rf->flag &= ~RAD_SHOOT;
+
+ energy= rf->unshot[0]*rf->area;
+ energy+= rf->unshot[1]*rf->area;
+ energy+= rf->unshot[2]*rf->area;
- if(energy>maxenergy) {
- shoot= vlr;
- maxenergy= energy;
+ if(energy>maxenergy) {
+ shoot= vlr;
+ maxenergy= energy;
+ }
}
}
}
@@ -122,22 +125,22 @@ static VlakRen *findshoot_rr(Render *re)
static void backface_test_rr(Render *re, VlakRen *shoot)
{
+ ObjectRen *obr;
VlakRen *vlr=NULL;
RadFace *rf;
float tvec[3];
int a;
/* backface testing */
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
- if(vlr->radface) {
- if(vlr!=shoot) {
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+ if(vlr->radface && vlr!=shoot) {
rf= vlr->radface;
VecSubf(tvec, shoot->radface->cent, rf->cent);
- if( tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0) {
+ if(tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0)
rf->flag |= RAD_BACKFACE;
- }
}
}
}
@@ -145,17 +148,20 @@ static void backface_test_rr(Render *re, VlakRen *shoot)
static void clear_backface_test_rr(Render *re)
{
+ ObjectRen *obr;
VlakRen *vlr=NULL;
RadFace *rf;
int a;
/* backface flag clear */
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->radface) {
- rf= vlr->radface;
- rf->flag &= ~RAD_BACKFACE;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->radface) {
+ rf= vlr->radface;
+ rf->flag &= ~RAD_BACKFACE;
+ }
}
}
}
@@ -165,6 +171,7 @@ extern RadView hemitop, hemiside; // radfactors.c
/* hemi-zbuffering, delivers formfactors array */
static void makeformfactors_rr(Render *re, VlakRen *shoot)
{
+ ObjectRen *obr;
VlakRen *vlr=NULL;
RadFace *rf;
float len, vec[3], up[3], side[3], tar[5][3], *fp;
@@ -207,16 +214,18 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot)
/* convert factors to real radiosity */
fp= RG.formfactors;
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->radface) {
- rf= vlr->radface;
- if(*fp!=0.0 && rf->area!=0.0) {
- *fp *= shoot->radface->area/rf->area;
- if(*fp>1.0) *fp= 1.0001;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->radface) {
+ rf= vlr->radface;
+ if(*fp!=0.0 && rf->area!=0.0) {
+ *fp *= shoot->radface->area/rf->area;
+ if(*fp>1.0) *fp= 1.0001;
+ }
+ fp++;
}
- fp++;
}
}
}
@@ -224,6 +233,7 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot)
/* based at RG.formfactors array, distribute shoot energy over other faces */
static void applyformfactors_rr(Render *re, VlakRen *shoot)
{
+ ObjectRen *obr;
VlakRen *vlr=NULL;
RadFace *rf;
float *fp, *ref, unr, ung, unb, r, g, b;
@@ -235,30 +245,32 @@ static void applyformfactors_rr(Render *re, VlakRen *shoot)
fp= RG.formfactors;
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->radface) {
- rf= vlr->radface;
- if(*fp!= 0.0) {
-
- ref= &(vlr->mat->r);
-
- r= (*fp)*unr*ref[0];
- g= (*fp)*ung*ref[1];
- b= (*fp)*unb*ref[2];
-
- // if(rf->flag & RAD_BACKFACE) {
-
- rf->totrad[0]+= r;
- rf->totrad[1]+= g;
- rf->totrad[2]+= b;
-
- rf->unshot[0]+= r;
- rf->unshot[1]+= g;
- rf->unshot[2]+= b;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->radface) {
+ rf= vlr->radface;
+ if(*fp!= 0.0) {
+
+ ref= &(vlr->mat->r);
+
+ r= (*fp)*unr*ref[0];
+ g= (*fp)*ung*ref[1];
+ b= (*fp)*unb*ref[2];
+
+ // if(rf->flag & RAD_BACKFACE) {
+
+ rf->totrad[0]+= r;
+ rf->totrad[1]+= g;
+ rf->totrad[2]+= b;
+
+ rf->unshot[0]+= r;
+ rf->unshot[1]+= g;
+ rf->unshot[2]+= b;
+ }
+ fp++;
}
- fp++;
}
}
/* shoot energy has been shot */
@@ -313,6 +325,7 @@ static RadFace *radfaces=NULL;
static void initradfaces(Render *re)
{
+ ObjectRen *obr;
VlakRen *vlr= NULL;
RadFace *rf;
int a, b;
@@ -326,58 +339,62 @@ static void initradfaces(Render *re)
RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20;
/* count first for fast malloc */
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->mat->mode & MA_RADIO) {
- if(vlr->mat->emit > 0.0) {
- RG.totpatch++;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->mat->mode & MA_RADIO) {
+ if(vlr->mat->emit > 0.0) {
+ RG.totpatch++;
+ }
+ RG.totelem++;
}
- RG.totelem++;
}
}
-
+
printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch);
if(RG.totelem==0 || RG.totpatch==0) return;
/* make/init radfaces */
rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces");
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->mat->mode & MA_RADIO) {
-
- /* during render, vlr->n gets flipped/corrected, we cannot have that */
- if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm);
- else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm);
-
- rf->totrad[0]= vlr->mat->emit*vlr->mat->r;
- rf->totrad[1]= vlr->mat->emit*vlr->mat->g;
- rf->totrad[2]= vlr->mat->emit*vlr->mat->b;
- VECCOPY(rf->unshot, rf->totrad);
-
- if(vlr->v4) {
- rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
- CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
- }
- else {
- rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co);
- CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co);
- }
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
- RG.totenergy+= rf->unshot[0]*rf->area;
- RG.totenergy+= rf->unshot[1]*rf->area;
- RG.totenergy+= rf->unshot[2]*rf->area;
-
- for(b=0; b<3; b++) {
- RG.min[b]= MIN2(RG.min[b], rf->cent[b]);
- RG.max[b]= MAX2(RG.max[b], rf->cent[b]);
- }
+ if(vlr->mat->mode & MA_RADIO) {
+
+ /* during render, vlr->n gets flipped/corrected, we cannot have that */
+ if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm);
+ else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm);
+
+ rf->totrad[0]= vlr->mat->emit*vlr->mat->r;
+ rf->totrad[1]= vlr->mat->emit*vlr->mat->g;
+ rf->totrad[2]= vlr->mat->emit*vlr->mat->b;
+ VECCOPY(rf->unshot, rf->totrad);
+
+ if(vlr->v4) {
+ rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+ CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+ }
+ else {
+ rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co);
+ CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co);
+ }
+
+ RG.totenergy+= rf->unshot[0]*rf->area;
+ RG.totenergy+= rf->unshot[1]*rf->area;
+ RG.totenergy+= rf->unshot[2]*rf->area;
+
+ for(b=0; b<3; b++) {
+ RG.min[b]= MIN2(RG.min[b], rf->cent[b]);
+ RG.max[b]= MAX2(RG.max[b], rf->cent[b]);
+ }
-// uncommented; this isnt satisfying, but i leave it in the code for now (ton)
-// if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED;
-
- vlr->radface= rf++;
+ // uncommented; this isnt satisfying, but i leave it in the code for now (ton)
+ // if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED;
+
+ vlr->radface= rf++;
+ }
}
}
RG.size[0]= (RG.max[0]- RG.min[0]);
@@ -408,6 +425,7 @@ static void vecaddfac(float *vec, float *v1, float *v2, float fac)
static void make_vertex_rad_values(Render *re)
{
+ ObjectRen *obr;
VertRen *v1=NULL;
VlakRen *vlr=NULL;
RadFace *rf;
@@ -418,54 +436,55 @@ static void make_vertex_rad_values(Render *re)
RG.radfactor= RG.radfac*pow(64*64, RG.igamma)/128.0; /* compatible with radio-tool */
/* accumulate vertexcolors */
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->radface) {
- rf= vlr->radface;
-
- /* apply correction */
- rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma);
- rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma);
- rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma);
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
- /* correct rf->rad values for color */
- if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r;
- if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g;
- if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b;
-
- col= RE_vertren_get_rad(re, vlr->v1, 1);
- vecaddfac(col, col, rf->totrad, rf->area);
- col[3]+= rf->area;
-
- col= RE_vertren_get_rad(re, vlr->v2, 1);
- vecaddfac(col, col, rf->totrad, rf->area);
- col[3]+= rf->area;
-
- col= RE_vertren_get_rad(re, vlr->v3, 1);
- vecaddfac(col, col, rf->totrad, rf->area);
- col[3]+= rf->area;
-
- if(vlr->v4) {
- col= RE_vertren_get_rad(re, vlr->v4, 1);
+ if(vlr->radface) {
+ rf= vlr->radface;
+
+ /* apply correction */
+ rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma);
+ rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma);
+ rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma);
+
+ /* correct rf->rad values for color */
+ if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r;
+ if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g;
+ if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b;
+
+ col= RE_vertren_get_rad(obr, vlr->v1, 1);
vecaddfac(col, col, rf->totrad, rf->area);
col[3]+= rf->area;
+
+ col= RE_vertren_get_rad(obr, vlr->v2, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+
+ col= RE_vertren_get_rad(obr, vlr->v3, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+
+ if(vlr->v4) {
+ col= RE_vertren_get_rad(obr, vlr->v4, 1);
+ vecaddfac(col, col, rf->totrad, rf->area);
+ col[3]+= rf->area;
+ }
}
}
- }
- /* make vertex colors */
- for(a=0; a<re->totvert; a++) {
- if((a & 255)==0) v1= RE_findOrAddVert(re, a); else v1++;
-
- col= RE_vertren_get_rad(re, v1, 0);
- if(col && col[3]>0.0) {
- col[0]/= col[3];
- col[1]/= col[3];
- col[2]/= col[3];
+ /* make vertex colors */
+ for(a=0; a<obr->totvert; a++) {
+ if((a & 255)==0) v1= RE_findOrAddVert(obr, a); else v1++;
+
+ col= RE_vertren_get_rad(obr, v1, 0);
+ if(col && col[3]>0.0) {
+ col[0]/= col[3];
+ col[1]/= col[3];
+ col[2]/= col[3];
+ }
}
}
-
}
/* main call, extern */
diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h
index d20e3130fa4..39bf2be4256 100644
--- a/source/blender/render/extern/include/RE_raytrace.h
+++ b/source/blender/render/extern/include/RE_raytrace.h
@@ -41,6 +41,19 @@ typedef void RayTree;
/* abstraction of face type */
typedef void RayFace;
+/* object numbers above this are transformed */
+#define RE_RAY_TRANSFORM_OFFS 0x8000000
+
+/* convert from pointer to index in array and back, with offset if the
+ * instance is transformed */
+#define RAY_OBJECT_SET(re, obi) \
+ ((obi == NULL)? 0: \
+ ((obi - (re)->objectinstance) + ((obi->flag & R_TRANSFORMED)? RE_RAY_TRANSFORM_OFFS: 0)))
+
+#define RAY_OBJECT_GET(re, i) \
+ ((re)->objectinstance + ((i >= RE_RAY_TRANSFORM_OFFS)? i-RE_RAY_TRANSFORM_OFFS: i))
+
+
/* struct for intersection data */
typedef struct Isect {
float start[3]; /* start+vec = end, in ray_tree_intersect */
@@ -50,8 +63,11 @@ typedef struct Isect {
float labda, u, v; /* distance to hitpoint, uv weights */
RayFace *face; /* face is where to intersect with */
+ int ob;
RayFace *faceorig; /* start face */
+ int oborig;
RayFace *face_last; /* for shadow optimize, last intersected face */
+ int ob_last;
short isect; /* which half of quad */
short mode; /* RE_RAYSHADOW, RE_RAYMIRROR, RE_RAYSHADOW_TRA */
@@ -62,6 +78,7 @@ typedef struct Isect {
/* octree only */
RayFace *facecontr;
+ int obcontr;
float ddalabda;
short faceisect; /* flag if facecontr was done or not */
@@ -73,18 +90,21 @@ typedef struct Isect {
typedef void (*RayCoordsFunc)(RayFace *face,
float **v1, float **v2, float **v3, float **v4);
typedef int (*RayCheckFunc)(Isect *is, RayFace *face);
+typedef float *(*RayObjectTransformFunc)(void *userdata, int ob);
/* tree building and freeing */
RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max,
- RayCoordsFunc coordfunc, RayCheckFunc checkfunc);
-void RE_ray_tree_add_face(RayTree *tree, RayFace *face);
+ RayCoordsFunc coordfunc, RayCheckFunc checkfunc,
+ RayObjectTransformFunc transformfunc, void *userdata);
+void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face);
void RE_ray_tree_done(RayTree *tree);
void RE_ray_tree_free(RayTree *tree);
/* intersection with full tree and single face */
int RE_ray_tree_intersect(RayTree *tree, Isect *is);
int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc check);
-int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc);
+int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc,
+ RayCoordsFunc coordsfunc);
/* retrieve the diameter of the tree structure, for setting intersection
end distance */
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 8a4f6bb2ec8..5b81052f5d2 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -64,8 +64,11 @@ struct ShadeInputCopy {
struct Material *mat;
struct VlakRen *vlr;
+ struct ObjectInstanceRen *obi;
+ struct ObjectRen *obr;
int facenr;
float facenor[3]; /* copy from face */
+ short flippednor; /* is facenor flipped? */
struct VertRen *v1, *v2, *v3; /* vertices can be in any order for quads... */
short i1, i2, i3; /* original vertex indices */
short puno;
@@ -93,8 +96,11 @@ typedef struct ShadeInput
struct Material *mat;
struct VlakRen *vlr;
+ struct ObjectInstanceRen *obi;
+ struct ObjectRen *obr;
int facenr;
float facenor[3]; /* copy from face */
+ short flippednor; /* is facenor flipped? */
struct VertRen *v1, *v2, *v3; /* vertices can be in any order for quads... */
short i1, i2, i3; /* original vertex indices */
short puno;
@@ -130,7 +136,7 @@ typedef struct ShadeInput
ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */
ShadeInputCol col[8]; /* 8 = MAX_MCOL */
- int totuv, totcol;
+ int totuv, totcol, actuv, actcol;
/* dx/dy OSA coordinates */
float dxco[3], dyco[3];
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index f7f2222e98d..84230bd4f6d 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -49,6 +49,7 @@ struct VertTableNode;
struct VlakTableNode;
struct GHash;
struct RenderBuckets;
+struct ObjectInstanceRen;
#define TABLEINITSIZE 1024
#define LAMPINITSIZE 256
@@ -81,13 +82,15 @@ typedef struct RenderPart
/* result of part rendering */
RenderResult *result;
+ int *recto; /* object table for objects */
int *rectp; /* polygon index table */
int *rectz; /* zbuffer */
long *rectdaps; /* delta acum buffer for pixel structs */
+ int *rectbacko; /* object table for backside sss */
int *rectbackp; /* polygon index table for backside sss */
int *rectbackz; /* zbuffer for backside sss */
long *rectall; /* buffer for all faces for sss */
-
+
rcti disprect; /* part coordinates within total picture */
int rectx, recty; /* the size */
short crop, ready; /* crop is amount of pixels we crop, for filter */
@@ -161,21 +164,19 @@ struct Render
/* render database */
int totvlak, totvert, tothalo, totstrand, totlamp;
+ struct HaloRen **sortedhalos;
+
ListBase lights; /* GroupObject pointers */
ListBase lampren; /* storage, for free */
- int vertnodeslen;
- struct VertTableNode *vertnodes;
- int vlaknodeslen;
- struct VlakTableNode *vlaknodes;
- int strandnodeslen;
- struct StrandTableNode *strandnodes;
- int blohalen;
- struct HaloRen **bloha;
ListBase objecttable;
- ListBase strandbufs;
struct RenderBuckets *strandbuckets;
+ struct ObjectInstanceRen *objectinstance;
+ ListBase instancetable;
+ struct GHash *objecthash;
+ int totinstance;
+
struct Image *backbuf, *bakebuf;
struct GHash *orco_hash;
@@ -235,23 +236,48 @@ typedef struct ShadBuf {
} ShadBuf;
/* ------------------------------------------------------------------------- */
-/* lookup of objects in database */
+
typedef struct ObjectRen {
struct ObjectRen *next, *prev;
struct Object *ob, *par;
- int index, startvert, endvert, startface, endface, startstrand, endstrand;
- float *vectors;
+ struct Scene *sce;
+ int index, psysindex;
+
+ int totvert, totvlak, totstrand, tothalo;
+ int vertnodeslen, vlaknodeslen, strandnodeslen, blohalen;
+ struct VertTableNode *vertnodes;
+ struct VlakTableNode *vlaknodes;
+ struct StrandTableNode *strandnodes;
+ struct HaloRen **bloha;
+ ListBase strandbufs;
+
+ char (*mtface)[32];
+ char (*mcol)[32];
+ int actmtface, actmcol;
} ObjectRen;
+typedef struct ObjectInstanceRen {
+ struct ObjectInstanceRen *next, *prev;
+
+ ObjectRen *obr;
+ Object *ob, *par;
+ int index, psysindex;
+
+ float mat[4][4], imat[3][3];
+ short flag;
+
+ float *vectors;
+ int totvector;
+} ObjectInstanceRen;
+
/* ------------------------------------------------------------------------- */
typedef struct VertRen
{
float co[3];
float n[3];
- float ho[4];
float *orco;
- short clip;
+ short clip;
unsigned short flag; /* in use for clipping zbuffer parts, temp setting stuff in convertblender.c */
float accum; /* accum for radio weighting, and for strand texco static particles */
int index; /* index allows extending vertren with any property */
@@ -279,10 +305,10 @@ typedef struct VlakRen {
unsigned int lay;
float n[3];
struct Material *mat;
- char noflag, puno;
+ char puno;
char flag, ec;
RadFace *radface;
- Object *ob;
+ ObjectRen *obr;
int index;
} VlakRen;
@@ -312,7 +338,7 @@ typedef struct StrandBuffer {
struct StrandVert *vert;
int totvert;
- struct Object *ob;
+ struct ObjectRen *obr;
struct Material *ma;
unsigned int lay;
int overrideuv;
@@ -393,7 +419,7 @@ typedef struct LampRen {
short xold[BLENDER_MAX_THREADS], yold[BLENDER_MAX_THREADS]; /* last jitter table for area lights */
float area_size, area_sizey, area_sizez;
float adapt_thresh;
-
+
struct ShadBuf *shb;
float *jitter;
QMCSampler *qsa;
@@ -417,6 +443,7 @@ typedef struct LampRen {
/* ray optim */
VlakRen *vlr_last[BLENDER_MAX_THREADS];
+ ObjectInstanceRen *obi_last[BLENDER_MAX_THREADS];
struct MTex *mtex[MAX_MTEX];
} LampRen;
@@ -435,7 +462,7 @@ typedef struct LampRen {
/* vlakren->flag (vlak = face in dutch) char!!! */
#define R_SMOOTH 1
-#define R_VISIBLE 2
+#define R_HIDDEN 2
/* strand flag, means special handling */
#define R_STRAND 4
#define R_NOPUNOFLIP 8
@@ -446,16 +473,14 @@ typedef struct LampRen {
/* vertex normals are tangent or view-corrected vector, for hair strands */
#define R_TANGENT 128
-/* vlakren->noflag (char) */
-#define R_SNPROJ_X 1
-#define R_SNPROJ_Y 2
-#define R_SNPROJ_Z 4
-#define R_FLIPPED_NO 8
-
/* strandbuffer->flag */
#define R_STRAND_BSPLINE 1
#define R_STRAND_B_UNITS 2
+/* objectinstance->flag */
+#define R_DUPLI_TRANSFORMED 1
+#define R_ENV_TRANSFORMED 2
+#define R_TRANSFORMED (1|2)
#endif /* RENDER_TYPES_H */
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 0d807d56180..600ece8ad50 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -49,13 +49,14 @@ struct ShadeResult;
struct World;
struct RenderPart;
struct RenderLayer;
+struct ObjectRen;
/* ------------------------------------------------------------------------- */
typedef struct PixStr
{
struct PixStr *next;
- int facenr, z;
+ int obi, facenr, z;
unsigned short mask;
short shadfac;
} PixStr;
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index febf90d9d6e..0346f2d6413 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -41,6 +41,7 @@ struct MTFace;
struct CustomData;
struct StrandBuffer;
struct StrandRen;
+struct ObjectInstanceRen;
#define RE_QUAD_MASK 0x7FFFFFF
#define RE_QUAD_OFFS 0x8000000
@@ -58,71 +59,65 @@ typedef struct VertTableNode {
typedef struct VlakTableNode {
struct VlakRen *vlak;
- struct MTFace **mtface;
- struct MCol **mcol;
+ struct MTFace *mtface;
+ struct MCol *mcol;
int totmtface, totmcol;
float *surfnor;
- struct CustomDataNames **names;
} VlakTableNode;
typedef struct StrandTableNode {
struct StrandRen *strand;
float *winspeed;
float *surfnor;
- struct MCol **mcol;
- float **uv;
+ struct MCol *mcol;
+ float *uv;
int totuv, totmcol;
- struct CustomDataNames **names;
} StrandTableNode;
-typedef struct CustomDataNames{
- struct CustomDataNames *next, *prev;
-
- char (*mtface)[32];
- char (*mcol)[32];
-} CustomDataNames;
-
/* renderdatabase.c */
void free_renderdata_tables(struct Render *re);
void free_renderdata_vertnodes(struct VertTableNode *vertnodes);
void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes);
-void set_normalflags(Render *re);
+void set_normalflags(struct Render *re, struct ObjectRen *obr);
void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets);
/* functions are not exported... so wrong names */
-struct VlakRen *RE_findOrAddVlak(struct Render *re, int nr);
-struct VertRen *RE_findOrAddVert(struct Render *re, int nr);
-struct StrandRen *RE_findOrAddStrand(struct Render *re, int nr);
-struct HaloRen *RE_findOrAddHalo(struct Render *re, int nr);
-struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize,
- float vectsize, int seed);
-struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1,
- float *orco, float *uvco, float hasize, float vectsize, int seed);
-void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est);
-struct StrandBuffer *RE_addStrandBuffer(struct Render *re, struct Object *ob, int totvert);
-
-float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_stress(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_rad(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_strand(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_tangent(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verify);
-
-struct MTFace *RE_vlakren_get_tface(struct Render *re, VlakRen *ren, int n, char **name, int verify);
-struct MCol *RE_vlakren_get_mcol(struct Render *re, VlakRen *ren, int n, char **name, int verify);
-float *RE_vlakren_get_surfnor(struct Render *re, VlakRen *ren, int verify);
-
-float *RE_strandren_get_winspeed(struct Render *re, struct StrandRen *strand, int verify);
-float *RE_strandren_get_surfnor(struct Render *re, struct StrandRen *strand, int verify);
-float *RE_strandren_get_uv(struct Render *re, struct StrandRen *strand, int n, char **name, int verify);
-struct MCol *RE_strandren_get_mcol(struct Render *re, struct StrandRen *strand, int n, char **name, int verify);
-
-struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver);
-struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr);
-
-void RE_vlakren_set_customdata_names(struct Render *re, struct CustomData *data);
+struct VlakRen *RE_findOrAddVlak(struct ObjectRen *obr, int nr);
+struct VertRen *RE_findOrAddVert(struct ObjectRen *obr, int nr);
+struct StrandRen *RE_findOrAddStrand(struct ObjectRen *obr, int nr);
+struct HaloRen *RE_findOrAddHalo(struct ObjectRen *obr, int nr);
+struct HaloRen *RE_inithalo(struct Render *re, struct ObjectRen *obr, struct Material *ma, float *vec, float *vec1, float *orco, float hasize, float vectsize, int seed);
+struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, struct Material *ma, float *vec, float *vec1, float *orco, float *uvco, float hasize, float vectsize, int seed);
+struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert);
+
+struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex);
+void RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]);
+void RE_makeRenderInstances(struct Render *re);
+void RE_instanceTransformNormal(struct ObjectInstanceRen *obi, float *nor, float *tnor);
+
+float *RE_vertren_get_sticky(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_stress(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify);
+
+struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
+struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
+float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
+int RE_vlakren_get_normal(struct Render *re, struct ObjectInstanceRen *obi, struct VlakRen *vlr, float *nor);
+
+float *RE_strandren_get_surfnor(struct ObjectRen *obr, struct StrandRen *strand, int verify);
+float *RE_strandren_get_uv(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify);
+struct MCol *RE_strandren_get_mcol(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify);
+float *RE_strandren_get_winspeed(struct ObjectInstanceRen *obi, struct StrandRen *strand, int verify);
+
+struct VertRen *RE_vertren_copy(struct ObjectRen *obr, struct VertRen *ver);
+struct VlakRen *RE_vlakren_copy(struct ObjectRen *obr, struct VlakRen *vlr);
+
+void RE_set_customdata_names(struct ObjectRen *obr, struct CustomData *data);
/* haloren->type: flags */
#define HA_ONLYSKY 1
diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h
index 8b786c6e098..b4f196a89fa 100644
--- a/source/blender/render/intern/include/shadbuf.h
+++ b/source/blender/render/intern/include/shadbuf.h
@@ -37,6 +37,8 @@
#include "render_types.h"
+struct ObjectRen;
+
/**
* Calculates shadowbuffers for a vector of shadow-giving lamps
* @param lar The vector of lamps
@@ -80,6 +82,7 @@ float ISB_getshadow(ShadeInput *shi, ShadBuf *shb);
typedef struct ISBSample {
float zco[3]; /* coordinate in lampview projection */
short *shadfac; /* initialized zero = full lighted */
+ int obi; /* object for face lookup */
int facenr; /* index in faces list */
} ISBSample;
@@ -87,6 +90,7 @@ typedef struct ISBSample {
typedef struct ISBSampleA {
float zco[3]; /* coordinate in lampview projection */
short *shadfac; /* NULL = full lighted */
+ int obi; /* object for face lookup */
int facenr; /* index in faces list */
struct ISBSampleA *next; /* in end, we want the first items to align with ISBSample */
} ISBSampleA;
@@ -94,6 +98,7 @@ typedef struct ISBSampleA {
/* used for transparent storage only */
typedef struct ISBShadfacA {
struct ISBShadfacA *next;
+ int obi;
int facenr;
float shadfac;
} ISBShadfacA;
diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h
index 3390c32ebfe..6ca63a2976d 100644
--- a/source/blender/render/intern/include/shading.h
+++ b/source/blender/render/intern/include/shading.h
@@ -32,6 +32,7 @@ struct LampRen;
struct VlakRen;
struct StrandSegment;
struct StrandPoint;
+struct ObjectInstanceRen obi;
/* shadeinput.c */
@@ -52,12 +53,13 @@ typedef struct ShadeSample {
/* also the node shader callback */
void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr);
-void shade_input_set_triangle_i(struct ShadeInput *shi, struct VlakRen *vlr, short i1, short i2, short i3);
-void shade_input_set_triangle(struct ShadeInput *shi, volatile int facenr, int normal_flip);
+void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3);
+void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip);
void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from);
void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float z);
void shade_input_set_uv(struct ShadeInput *shi);
void shade_input_set_normals(struct ShadeInput *shi);
+void shade_input_flip_normals(struct ShadeInput *shi);
void shade_input_set_shade_texco(struct ShadeInput *shi);
void shade_input_set_strand(struct ShadeInput *shi, struct StrandRen *strand, struct StrandPoint *spoint);
void shade_input_set_strand_texco(struct ShadeInput *shi, struct StrandRen *strand, struct StrandVert *svert, struct StrandPoint *spoint);
diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h
index 55c789de764..7f37317d4d5 100644
--- a/source/blender/render/intern/include/strand.h
+++ b/source/blender/render/intern/include/strand.h
@@ -43,6 +43,7 @@ struct RenderPart;
struct RenderBuckets;
struct RenderPrimitiveIterator;
struct ZSpan;
+struct ObjectInstanceRen;
typedef struct StrandPoint {
/* position within segment */
@@ -73,6 +74,7 @@ typedef struct StrandSegment {
struct StrandVert *v[4];
struct StrandRen *strand;
struct StrandBuffer *buffer;
+ struct ObjectInstanceRen *obi;
float sqadaptcos;
StrandPoint point1, point2;
@@ -80,103 +82,7 @@ typedef struct StrandSegment {
} StrandSegment;
void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint);
-void render_strand_segment(struct Render *re, struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg);
-void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets);
-
-struct RenderBuckets *init_buckets(struct Render *re);
-void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim);
-void free_buckets(struct RenderBuckets *buckets);
-void project_hoco_to_bucket(struct RenderBuckets *buckets, float *hoco, float *bucketco);
-
-struct RenderPrimitiveIterator *init_primitive_iterator(struct Render *re, struct RenderBuckets *buckets, struct RenderPart *pa);
-void *next_primitive_iterator(struct RenderPrimitiveIterator *iter);
-void free_primitive_iterator(struct RenderPrimitiveIterator *iter);
-
-#endif
-
-/*
- * $Id$
- *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License. See http://www.blender.org/BL/ for information
- * about this.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: none of this file.
- *
- * Contributor(s): Brecht Van Lommel.
- *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
- */
-
-#ifndef STRAND_H
-#define STRAND_H
-
-struct StrandVert;
-struct StrandRen;
-struct StrandBuffer;
-struct ShadeSample;
-struct StrandPart;
-struct Render;
-struct RenderPart;
-struct RenderBuckets;
-struct RenderPrimitiveIterator;
-struct ZSpan;
-
-typedef struct StrandPoint {
- /* position within segment */
- float t;
-
- /* camera space */
- float co[3];
- float nor[3];
- float tan[3];
- float strandco;
- float width;
-
- /* derivatives */
- float dtco[3], dsco[3];
- float dtstrandco;
-
- /* outer points */
- float co1[3], co2[3];
- float hoco1[4], hoco2[4];
- float zco1[3], zco2[3];
-
- /* screen space */
- float hoco[4];
- float x, y;
-} StrandPoint;
-
-typedef struct StrandSegment {
- struct StrandVert *v[4];
- struct StrandRen *strand;
- struct StrandBuffer *buffer;
- float sqadaptcos;
-
- StrandPoint point1, point2;
- int shaded;
-} StrandSegment;
-
-void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint);
-void render_strand_segment(struct Render *re, struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg);
+void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg);
void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets);
struct RenderBuckets *init_buckets(struct Render *re);
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
index 0d88d40e7ac..5f1aa5679bf 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -35,6 +35,7 @@ struct RenderLayer;
struct LampRen;
struct VlakRen;
struct ListBase;
+struct ZSpan;
void fillrect(int *rect, int x, int y, int val);
@@ -46,19 +47,20 @@ void projectvert(float *v1, float winmat[][4], float *adr);
void projectverto(float *v1, float winmat[][4], float *adr);
int testclip(float *v);
-void set_part_zbuf_clipflag(struct RenderPart *pa);
-void zbuffer_shadow(struct Render *re, struct LampRen *lar, int *rectz, int size, float jitx, float jity);
-void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag);
+void zbuffer_shadow(struct Render *re, float winmat[][4], struct LampRen *lar, int *rectz, int size, float jitx, float jity);
+void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data);
+
unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass);
unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass);
void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl);
-void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int));
+void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int));
typedef struct APixstr {
- unsigned short mask[4]; /* jitter mask */
- int z[4]; /* distance */
- int p[4]; /* index */
- short shadfac[4]; /* optimize storage for irregular shadow */
+ unsigned short mask[4]; /* jitter mask */
+ int z[4]; /* distance */
+ int p[4]; /* index */
+ int obi[4]; /* object instance */
+ short shadfac[4]; /* optimize storage for irregular shadow */
struct APixstr *next;
} APixstr;
@@ -81,6 +83,7 @@ typedef struct ZSpan {
int *rectz, *arectz; /* zbuffers, arectz is for transparant */
int *rectz1; /* seconday z buffer for shadowbuffer (2nd closest z) */
int *rectp; /* polygon index buffer */
+ int *recto; /* object buffer */
APixstr *apixbuf, *curpstr; /* apixbuf for transparent */
struct ListBase *apsmbase;
@@ -89,24 +92,28 @@ typedef struct ZSpan {
int mask, apsmcounter; /* in use by apixbuf */
void *sss_handle; /* used by sss */
- void (*sss_func)(void *, int, int, int, int);
+ void (*sss_func)(void *, int, int, int, int, int);
- void (*zbuffunc)(struct ZSpan *, int, float *, float *, float *, float *);
- void (*zbuflinefunc)(struct ZSpan *, int, float *, float *);
+ void (*zbuffunc)(struct ZSpan *, int, int, float *, float *, float *, float *);
+ void (*zbuflinefunc)(struct ZSpan *, int, int, float *, float *);
} ZSpan;
/* exported to shadbuf.c */
-void zbufclip4(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4);
+void zbufclip4(struct ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4);
void zbuf_free_span(struct ZSpan *zspan);
/* to rendercore.c */
void zspan_scanconvert(struct ZSpan *zpan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) );
/* exported to edge render... */
-void zbufclip(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3);
+void zbufclip(struct ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3);
void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty);
-void zbufclipwire(struct ZSpan *zspan, int zvlnr, struct VlakRen *vlr);
+void zbufclipwire(struct ZSpan *zspan, int obi, int zvlnr, int ec, float *ho1, float *ho2, float *ho3, float *ho4, int c1, int c2, int c3, int c4);
+
+/* exported to shadeinput.c */
+void zbuf_make_winmat(Render *re, float duplimat[][4], float winmat[][4]);
+void zbuf_render_project(float winmat[][4], float *co, float *ho);
#endif
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 9280b457a4c..4b683441833 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -119,23 +119,15 @@
* Same is true for lamp coords & vec.
* Duplicated data objects & dupliframe/duplivert objects are only stored once,
* only the matrix is stored for all others, in yafray these objects are instances of the original.
- * The main changes are in RE_rotateBlenderScene().
+ * The main changes are in RE_Database_FromScene().
*/
#endif /* disable yafray */
-/* ------------------------------------------------------------------------- */
-/* Local functions */
-/* ------------------------------------------------------------------------- */
-static short test_for_displace(Render *re, Object *ob);
-static void do_displacement(Render *re, Object *ob, int startface, int numface, int startvert, int numvert );
-static int vlakren_customdata_layer_num(int n, int active);
-
/* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
/* or for checking vertex normal flips */
#define FLT_EPSILON10 1.19209290e-06F
-
/* ------------------------------------------------------------------------- */
/* Stuff for stars. This sits here because it uses gl-things. Part of
@@ -143,14 +135,14 @@ this code may move down to the converter. */
/* ------------------------------------------------------------------------- */
/* this is a bad beast, since it is misused by the 3d view drawing as well. */
-static HaloRen *initstar(Render *re, float *vec, float hasize)
+static HaloRen *initstar(Render *re, ObjectRen *obr, float *vec, float hasize)
{
HaloRen *har;
float hoco[4];
projectverto(vec, re->winmat, hoco);
- har= RE_findOrAddHalo(re, re->tothalo++);
+ har= RE_findOrAddHalo(obr, obr->tothalo++);
/* projectvert is done in function zbufvlaggen again, because of parts */
VECCOPY(har->co, vec);
@@ -171,6 +163,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
void (*vertexfunc)(float*), void (*termfunc)(void))
{
extern unsigned char hash[512];
+ ObjectRen *obr= NULL;
World *wrld= NULL;
HaloRen *har;
Scene *scene;
@@ -234,11 +227,14 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
if (initfunc) {
initfunc();
}
+
+ if(re) /* add render object for stars */
+ obr= RE_addRenderObject(re, NULL, NULL, 0, 0);
for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) {
for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) {
for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) {
-
+
BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8));
vec[0] = fx + (hlfrand * BLI_drand()) - dblrand;
vec[1] = fy + (hlfrand * BLI_drand()) - dblrand;
@@ -281,7 +277,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
if (alpha != 0.0) {
fac = force * BLI_drand();
- har = initstar(re, vec, fac);
+ har = initstar(re, obr, vec, fac);
if (har) {
har->alfa = sqrt(sqrt(alpha));
@@ -305,6 +301,9 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
}
}
if (termfunc) termfunc();
+
+ if(obr)
+ re->tothalo += obr->tothalo;
}
@@ -328,35 +327,35 @@ u | | F1 | F2 |
/* ------------------------------------------------------------------------- */
-static void split_v_renderfaces(Render *re, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv)
+static void split_v_renderfaces(ObjectRen *obr, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv)
{
int vLen = vsize-1+(!!cyclv);
int v;
for (v=0; v<vLen; v++) {
- VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v);
- VertRen *vert = RE_vertren_copy(re, vlr->v2);
+ VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v);
+ VertRen *vert = RE_vertren_copy(obr, vlr->v2);
if (cyclv) {
vlr->v2 = vert;
if (v==vLen-1) {
- VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + 0);
+ VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0);
vlr->v1 = vert;
} else {
- VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v+1);
+ VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
vlr->v1 = vert;
}
} else {
vlr->v2 = vert;
if (v<vLen-1) {
- VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v+1);
+ VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
vlr->v1 = vert;
}
if (v==0) {
- vlr->v1 = RE_vertren_copy(re, vlr->v1);
+ vlr->v1 = RE_vertren_copy(obr, vlr->v1);
}
}
}
@@ -374,6 +373,8 @@ static int check_vnormal(float *n, float *veno)
}
/* ------------------------------------------------------------------------- */
+/* Stress, tangents and normals */
+/* ------------------------------------------------------------------------- */
static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2)
{
@@ -389,20 +390,20 @@ static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2)
acc[1]+= 1.0f;
}
-static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
+static void calc_edge_stress(Render *re, ObjectRen *obr, Mesh *me)
{
float loc[3], size[3], *accum, *acc, *accumoffs, *stress;
int a;
- if(startvert==re->totvert) return;
+ if(obr->totvert==0) return;
mesh_get_texspace(me, loc, NULL, size);
- accum= MEM_callocN(2*sizeof(float)*(re->totvert-startvert), "temp accum for stress");
+ accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress");
/* de-normalize orco */
- for(a=startvert; a<re->totvert; a++) {
- VertRen *ver= RE_findOrAddVert(re, a);
+ for(a=0; a<obr->totvert; a++) {
+ VertRen *ver= RE_findOrAddVert(obr, a);
if(ver->orco) {
ver->orco[0]= ver->orco[0]*size[0] +loc[0];
ver->orco[1]= ver->orco[1]*size[1] +loc[1];
@@ -411,9 +412,9 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
}
/* add stress values */
- accumoffs= accum - 2*startvert; /* so we can use vertex index */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
+ accumoffs= accum; /* so we can use vertex index */
+ for(a=0; a<obr->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(obr, a);
if(vlr->v1->orco && vlr->v4) {
calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2);
@@ -427,14 +428,14 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
}
}
- for(a=startvert; a<re->totvert; a++) {
- VertRen *ver= RE_findOrAddVert(re, a);
+ for(a=0; a<obr->totvert; a++) {
+ VertRen *ver= RE_findOrAddVert(obr, a);
if(ver->orco) {
/* find stress value */
acc= accumoffs + 2*ver->index;
if(acc[1]!=0.0f)
acc[0]/= acc[1];
- stress= RE_vertren_get_stress(re, ver, 1);
+ stress= RE_vertren_get_stress(obr, ver, 1);
*stress= *acc;
/* restore orcos */
@@ -474,9 +475,9 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2,
}
/* gets tangent from tface or orco */
-static void calc_tangent_vector(Render *re, VlakRen *vlr)
+static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr)
{
- MTFace *tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0);
+ MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
float tang[3], *tav;
float *uv1, *uv2, *uv3, *uv4;
@@ -500,40 +501,40 @@ static void calc_tangent_vector(Render *re, VlakRen *vlr)
tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang);
- tav= RE_vertren_get_tangent(re, v1, 1);
+ tav= RE_vertren_get_tangent(obr, v1, 1);
VECADD(tav, tav, tang);
- tav= RE_vertren_get_tangent(re, v2, 1);
+ tav= RE_vertren_get_tangent(obr, v2, 1);
VECADD(tav, tav, tang);
- tav= RE_vertren_get_tangent(re, v3, 1);
+ tav= RE_vertren_get_tangent(obr, v3, 1);
VECADD(tav, tav, tang);
if(v4) {
tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang);
- tav= RE_vertren_get_tangent(re, v1, 1);
+ tav= RE_vertren_get_tangent(obr, v1, 1);
VECADD(tav, tav, tang);
- tav= RE_vertren_get_tangent(re, v3, 1);
+ tav= RE_vertren_get_tangent(obr, v3, 1);
VECADD(tav, tav, tang);
- tav= RE_vertren_get_tangent(re, v4, 1);
+ tav= RE_vertren_get_tangent(obr, v4, 1);
VECADD(tav, tav, tang);
}
}
-static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_tangent)
+static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent)
{
int a;
/* clear all vertex normals */
- for(a=startvert; a<re->totvert; a++) {
- VertRen *ver= RE_findOrAddVert(re, a);
+ for(a=0; a<obr->totvert; a++) {
+ VertRen *ver= RE_findOrAddVert(obr, a);
ver->n[0]=ver->n[1]=ver->n[2]= 0.0f;
}
/* calculate cos of angles and point-masses, use as weight factor to
add face normal to vertex */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
+ for(a=0; a<obr->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(obr, a);
if(vlr->flag & ME_SMOOTH) {
VertRen *v1= vlr->v1;
VertRen *v2= vlr->v2;
@@ -599,13 +600,13 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
if(do_tangent) {
/* tangents still need to be calculated for flat faces too */
/* weighting removed, they are not vertexnormals */
- calc_tangent_vector(re, vlr);
+ calc_tangent_vector(obr, vlr);
}
}
/* do solid faces */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
+ for(a=0; a<obr->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(obr, a);
if((vlr->flag & ME_SMOOTH)==0) {
float *f1= vlr->v1->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
@@ -621,11 +622,11 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
}
/* normalize vertex normals */
- for(a=startvert; a<re->totvert; a++) {
- VertRen *ver= RE_findOrAddVert(re, a);
+ for(a=0; a<obr->totvert; a++) {
+ VertRen *ver= RE_findOrAddVert(obr, a);
Normalize(ver->n);
if(do_tangent) {
- float *tav= RE_vertren_get_tangent(re, ver, 0);
+ float *tav= RE_vertren_get_tangent(obr, ver, 0);
if (tav) {
/* orthonorm. */
float tdn = tav[0]*ver->n[0] + tav[1]*ver->n[1] + tav[2]*ver->n[2];
@@ -636,40 +637,20 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
}
}
}
-
- /* vertex normal (puno) switch flags for during render */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
-
- if((vlr->flag & R_NOPUNOFLIP)==0) {
- float *v1= vlr->v1->n;
- float *v2= vlr->v2->n;
- float *v3= vlr->v3->n;
- float *v4= vlr->v4?vlr->v4->n:NULL;
- float *nor= vlr->n;
- vlr->puno &= ~15;
- if ((nor[0]*v1[0] + nor[1]*v1[1] + nor[2]*v1[2]) < -FLT_EPSILON10) vlr->puno= 1;
- if ((nor[0]*v2[0] + nor[1]*v2[1] + nor[2]*v2[2]) < -FLT_EPSILON10) vlr->puno+= 2;
- if ((nor[0]*v3[0] + nor[1]*v3[1] + nor[2]*v3[2]) < -FLT_EPSILON10) vlr->puno+= 4;
- if(v4) {
- if((nor[0]*v4[0] + nor[1]*v4[1] + nor[2]*v4[2]) < -FLT_EPSILON10 ) vlr->puno+= 8;
- }
- }
- }
}
// NT same as calc_vertexnormals, but dont modify the existing vertex normals
// only recalculate other render data. If this is at some point used for other things than fluidsim,
// this could be made on option for the normal calc_vertexnormals
-static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int do_tangent)
+static void calc_fluidsimnormals(Render *re, ObjectRen *obr, int do_tangent)
{
int a;
/* dont clear vertex normals here */
- // OFF for(a=startvert; a<re->totvert; a++) { VertRen *ver= RE_findOrAddVert(re, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; }
+ // OFF for(a=0; a<obr->totvert; a++) { VertRen *ver= RE_findOrAddVert(obr, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; }
/* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
+ for(a=0; a<obr->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(obr, a);
if(vlr->flag & ME_SMOOTH) {
VertRen *v1= vlr->v1;
VertRen *v2= vlr->v2;
@@ -709,18 +690,18 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d
}
//if(do_tangent)
- // calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
+ // calc_tangent_vector(obr, vlr, fac1, fac2, fac3, fac4);
}
if(do_tangent) {
/* tangents still need to be calculated for flat faces too */
/* weighting removed, they are not vertexnormals */
- calc_tangent_vector(re, vlr);
+ calc_tangent_vector(obr, vlr);
}
}
/* do solid faces */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
+ for(a=0; a<obr->totvlak; a++) {
+ VlakRen *vlr= RE_findOrAddVlak(obr, a);
if((vlr->flag & ME_SMOOTH)==0) {
float *f1= vlr->v1->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
@@ -736,32 +717,14 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d
}
/* normalize vertex normals */
- for(a=startvert; a<re->totvert; a++) {
- VertRen *ver= RE_findOrAddVert(re, a);
+ for(a=0; a<obr->totvert; a++) {
+ VertRen *ver= RE_findOrAddVert(obr, a);
Normalize(ver->n);
if(do_tangent) {
- float *tav= RE_vertren_get_tangent(re, ver, 0);
+ float *tav= RE_vertren_get_tangent(obr, ver, 0);
if(tav) Normalize(tav);
}
}
-
- /* vertex normal (puno) switch flags for during render */
- for(a=startvlak; a<re->totvlak; a++) {
- VlakRen *vlr= RE_findOrAddVlak(re, a);
- if((vlr->flag & R_NOPUNOFLIP)==0) {
- VertRen *v1= vlr->v1;
- VertRen *v2= vlr->v2;
- VertRen *v3= vlr->v3;
- VertRen *v4= vlr->v4;
- vlr->puno &= ~15;
- if ((vlr->n[0]*v1->n[0]+vlr->n[1]*v1->n[1]+vlr->n[2]*v1->n[2])<0.0) vlr->puno= 1;
- if ((vlr->n[0]*v2->n[0]+vlr->n[1]*v2->n[1]+vlr->n[2]*v2->n[2])<0.0) vlr->puno+= 2;
- if ((vlr->n[0]*v3->n[0]+vlr->n[1]*v3->n[1]+vlr->n[2]*v3->n[2])<0.0) vlr->puno+= 4;
- if(v4) {
- if((vlr->n[0]*v4->n[0]+vlr->n[1]*v4->n[1]+vlr->n[2]*v4->n[2])<0.0) vlr->puno+= 8;
- }
- }
- }
}
/* ------------------------------------------------------------------------- */
@@ -860,18 +823,17 @@ static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thr
/* note; autosmooth happens in object space still, after applying autosmooth we rotate */
/* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */
-static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, int degr)
+static void autosmooth(Render *re, ObjectRen *obr, float mat[][4], int degr)
{
- ASvert *asv, *asverts, *asvertoffs;
+ ASvert *asv, *asverts;
ASface *asf;
VertRen *ver, *v1;
VlakRen *vlr;
float thresh;
int a, b, totvert;
- if(startvert==re->totvert) return;
- asverts= MEM_callocN(sizeof(ASvert)*(re->totvert-startvert), "all smooth verts");
- asvertoffs= asverts-startvert; /* se we can use indices */
+ if(obr->totvert==0) return;
+ asverts= MEM_callocN(sizeof(ASvert)*obr->totvert, "all smooth verts");
thresh= cos( M_PI*(0.5f+(float)degr)/180.0 );
@@ -879,24 +841,24 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
/* step one: construct listbase of all vertices and pointers to faces */
- for(a=startvlak; a<re->totvlak; a++) {
- vlr= RE_findOrAddVlak(re, a);
+ for(a=0; a<obr->totvlak; a++) {
+ vlr= RE_findOrAddVlak(obr, a);
/* skip wire faces */
if(vlr->v2 != vlr->v3) {
- as_addvert(asvertoffs+vlr->v1->index, vlr->v1, vlr);
- as_addvert(asvertoffs+vlr->v2->index, vlr->v2, vlr);
- as_addvert(asvertoffs+vlr->v3->index, vlr->v3, vlr);
+ as_addvert(asverts+vlr->v1->index, vlr->v1, vlr);
+ as_addvert(asverts+vlr->v2->index, vlr->v2, vlr);
+ as_addvert(asverts+vlr->v3->index, vlr->v3, vlr);
if(vlr->v4)
- as_addvert(asvertoffs+vlr->v4->index, vlr->v4, vlr);
+ as_addvert(asverts+vlr->v4->index, vlr->v4, vlr);
}
}
+ totvert= obr->totvert;
/* we now test all vertices, when faces have a normal too much different: they get a new vertex */
- totvert= re->totvert;
- for(a=startvert, asv=asverts; a<totvert; a++, asv++) {
+ for(a=0, asv=asverts; a<totvert; a++, asv++) {
if(asv && asv->totface>1) {
- ver= RE_findOrAddVert(re, a);
-
+ ver= RE_findOrAddVert(obr, a);
+
asf= asv->faces.first;
while(asf) {
for(b=0; b<4; b++) {
@@ -909,7 +871,7 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
v1= as_findvertex(vlr, ver, asv, thresh);
if(v1==NULL) {
/* make a new vertex */
- v1= RE_vertren_copy(re, ver);
+ v1= RE_vertren_copy(obr, ver);
}
asf->nver[b]= v1;
if(vlr->v1==ver) vlr->v1= v1;
@@ -924,18 +886,18 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
}
/* free */
- for(a=0; a<totvert-startvert; a++) {
+ for(a=0; a<totvert; a++) {
BLI_freelistN(&asverts[a].faces);
}
MEM_freeN(asverts);
/* rotate vertices and calculate normal of faces */
- for(a=startvert; a<re->totvert; a++) {
- ver= RE_findOrAddVert(re, a);
+ for(a=0; a<obr->totvert; a++) {
+ ver= RE_findOrAddVert(obr, a);
MTC_Mat4MulVecfl(mat, ver->co);
}
- for(a=startvlak; a<re->totvlak; a++) {
- vlr= RE_findOrAddVlak(re, a);
+ for(a=0; a<obr->totvlak; a++) {
+ vlr= RE_findOrAddVlak(obr, a);
/* skip wire faces */
if(vlr->v2 != vlr->v3) {
@@ -948,14 +910,9 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
}
/* ------------------------------------------------------------------------- */
-/* End of autosmoothing: */
+/* Orco hash and Materials */
/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* Orco hash */
-/* ------------------------------------------------------------------------- */
-
-
static float *get_object_orco(Render *re, Object *ob)
{
float *orco;
@@ -995,59 +952,6 @@ static void free_mesh_orco_hash(Render *re)
}
}
-/* ******************** END ORCO HASH ***************** */
-
-
-static void make_render_halos(Render *re, Object *ob, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco)
-{
- HaloRen *har;
- float xn, yn, zn, nor[3], view[3];
- float vec[3], hasize, mat[4][4], imat[3][3];
- int a, ok, seed= ma->seed1;
-
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat3CpyMat4(imat, ob->imat);
-
- re->flag |= R_HALO;
-
- for(a=0; a<totvert; a++, mvert++) {
- ok= 1;
-
- if(ok) {
- hasize= ma->hasize;
-
- VECCOPY(vec, mvert->co);
- MTC_Mat4MulVecfl(mat, vec);
-
- if(ma->mode & MA_HALOPUNO) {
- xn= mvert->no[0];
- yn= mvert->no[1];
- zn= mvert->no[2];
-
- /* transpose ! */
- nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
- nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
- nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
- Normalize(nor);
-
- VECCOPY(view, vec);
- Normalize(view);
-
- zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
- if(zn>=0.0) hasize= 0.0;
- else hasize*= zn*zn*zn*zn;
- }
-
- if(orco) har= RE_inithalo(re, ma, vec, NULL, orco, hasize, 0.0, seed);
- else har= RE_inithalo(re, ma, vec, NULL, mvert->co, hasize, 0.0, seed);
- if(har) har->lay= ob->lay;
- }
- if(orco) orco+= 3;
- seed++;
- }
-}
-
-/* ------------------------------------------------------------------------- */
static Material *give_render_material(Render *re, Object *ob, int nr)
{
extern Material defmaterial; /* material.c */
@@ -1068,158 +972,12 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
return ma;
}
-
-
-static void render_particle_system(Render *re, Object *ob, Object *par, PartEff *paf)
-{
- Particle *pa=0;
- HaloRen *har=0;
- Material *ma=0;
- float xn, yn, zn, imat[3][3], tmat[4][4], mat[4][4], hasize, stime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
- float haloScale = 1.0; //NT scale halos
- float iniAlpha = 0.0; // restore material alpha
- int a, mat_nr=1, seed;
- int useFluidsimParticles = 0; // FSPARTICLE
-
- ma= give_render_material(re, ob, paf->omat);
-
- if( (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) {
- useFluidsimParticles = 1;
- iniAlpha = ma->alpha;
- }
-
- pa= paf->keys;
- if(pa==NULL || paf->disp!=100 || useFluidsimParticles) {
- build_particle_system(ob);
- pa= paf->keys;
- if(pa==NULL) return;
- }
-
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat); /* this is correct, for imat texture */
-
- /* enable duplicators to work */
- if(par) {
- Mat4MulMat4(tmat, paf->imat, ob->obmat);
- MTC_Mat4MulMat4(mat, tmat, re->viewmat);
-
- MTC_Mat4Invert(tmat, mat);
- MTC_Mat3CpyMat4(imat, tmat);
- }
- else {
- MTC_Mat4CpyMat4(mat, re->viewmat);
-
- MTC_Mat4Invert(tmat, re->viewmat);
- MTC_Mat3CpyMat4(imat, tmat);
-
- }
-
- re->flag |= R_HALO;
-
- if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
- else ptime= 0.0;
- ctime= bsystem_time(ob, (float)re->scene->r.cfra, ptime);
- seed= ma->seed1;
-
- for(a=0; a<paf->totpart; a++, pa+=paf->totkey, seed++) {
-
- /* offset time for calculating normal */
- stime= ctime;
- ptime= ctime+1.0f;
- if(ctime < pa->time) {
- if(paf->flag & PAF_UNBORN)
- ptime= pa->time+1.0f;
- else
- continue;
- }
- if(ctime > pa->time+pa->lifetime) {
- if(paf->flag & PAF_DIED)
- stime= pa->time+pa->lifetime-1.0f;
- else
- continue;
- }
-
- /* watch it: also calculate the normal of a particle */
- if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
- where_is_particle(paf, pa, stime, vec);
- MTC_Mat4MulVecfl(mat, vec);
- where_is_particle(paf, pa, ptime, vec1);
- MTC_Mat4MulVecfl(mat, vec1);
- }
- else {
- where_is_particle(paf, pa, ctime, vec);
- MTC_Mat4MulVecfl(mat, vec);
- }
-
- if(pa->mat_nr != mat_nr) {
- mat_nr= pa->mat_nr;
- ma= give_render_material(re, ob, mat_nr);
- }
-
- if(ma->ipo) {
- /* correction for lifetime */
- ptime= 100.0*(ctime-pa->time)/pa->lifetime;
- calc_ipo(ma->ipo, ptime);
- execute_ipo((ID *)ma, ma->ipo);
- }
-
- //NT scale halos FSPARTICLE
- if(useFluidsimParticles) {
- // rescale to 1.0-10.0, then div by 5 afterwards, gives values in range 0.2-2.0
- double fspsize = ((double)pa->rt / 1000.0f) / 5.0 ;
- haloScale = 1.0/(float)pow(fspsize, (double)ob->fluidsimSettings->particleInfSize);
- ma->alpha = iniAlpha / (float)pow( fspsize, (double)ob->fluidsimSettings->particleInfAlpha);
- if(ma->alpha>1.) ma->alpha = 1.;
- }
-
- hasize= ma->hasize * haloScale;
-
- if(ma->mode & MA_HALOPUNO) {
- xn= pa->no[0];
- yn= pa->no[1];
- zn= pa->no[2];
-
- /* transpose ! */
- nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
- nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
- nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
- Normalize(nor);
-
- VECCOPY(view, vec);
- Normalize(view);
-
- zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
- if(zn>=0.0) hasize= 0.0;
- else hasize*= zn*zn*zn*zn;
- }
-
- if(paf->stype==PAF_VECT) har= RE_inithalo(re, ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
- else {
- har= RE_inithalo(re, ma, vec, NULL, pa->co, hasize, 0.0, seed);
- if(har && ma->mode & MA_HALO_SHADE) {
- VecSubf(har->no, vec, vec1);
- Normalize(har->no);
- }
- }
- if(har) har->lay= ob->lay;
- }
-
- /* restore material */
- for(a=1; a<=ob->totcol; a++) {
- ma= give_render_material(re, ob, a);
- if(ma) do_mat_ipo(ma);
- }
-
- if(paf->disp!=100) {
- MEM_freeN(paf->keys);
- paf->keys= NULL;
- }
-
- if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore...
-}
+/* ------------------------------------------------------------------------- */
+/* Particles */
+/* ------------------------------------------------------------------------- */
/* future thread problem... */
-static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *surfnor,
+static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, float *orco, float *surfnor,
float *uvco, int totuv, float *vec, float *vec1, float ctime,
int first, int line, int adapt, float adapt_angle, float adapt_pix, int override_uv)
{
@@ -1280,13 +1038,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
/* single face line */
if(line) {
- vlr= RE_findOrAddVlak(re, re->totvlak++);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->flag= flag;
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, re->totvert++);
- vlr->v2= RE_findOrAddVert(re, re->totvert++);
- vlr->v3= RE_findOrAddVert(re, re->totvert++);
- vlr->v4= RE_findOrAddVert(re, re->totvert++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
VECCOPY(vlr->v1->co, vec);
VecAddf(vlr->v1->co, vlr->v1->co, cross);
@@ -1316,17 +1074,17 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
vlr->mat= ma;
vlr->ec= ME_V2V3;
- vlr->lay= ob->lay;
+ vlr->lay= obr->ob->lay;
if(surfnor) {
- float *snor= RE_vlakren_get_surfnor(re, vlr, 1);
+ float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
VECCOPY(snor, surfnor);
}
if(uvco){
for(i=0; i<totuv; i++){
MTFace *mtf;
- mtf=RE_vlakren_get_tface(re,vlr,i,NULL,1);
+ mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1);
mtf->uv[0][0]=mtf->uv[1][0]=
mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0];
mtf->uv[0][1]=mtf->uv[1][1]=
@@ -1334,7 +1092,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
}
if(override_uv>=0){
MTFace *mtf;
- mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0);
+ mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0);
mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
@@ -1352,8 +1110,8 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
second=1;
}
- v1= RE_findOrAddVert(re, re->totvert++);
- v2= RE_findOrAddVert(re, re->totvert++);
+ v1= RE_findOrAddVert(obr, obr->totvert++);
+ v2= RE_findOrAddVert(obr, obr->totvert++);
VECCOPY(v1->co, vec);
VecAddf(v1->co, v1->co, cross);
@@ -1370,13 +1128,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
/* more vertices & faces to strand */
else {
if(adapt==0 || second){
- vlr= RE_findOrAddVlak(re, re->totvlak++);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->flag= flag;
- vlr->ob= ob;
+ vlr->obr= obr;
vlr->v1= v1;
vlr->v2= v2;
- vlr->v3= RE_findOrAddVert(re, re->totvert++);
- vlr->v4= RE_findOrAddVert(re, re->totvert++);
+ vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
v1= vlr->v4; // cycle
v2= vlr->v3; // cycle
@@ -1400,13 +1158,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
dy= re->winy*dvec[1]*re->winmat[1][1]/w;
w= sqrt(dx*dx + dy*dy);
if(Inpf(anor,nor)<adapt_angle && w>adapt_pix){
- vlr= RE_findOrAddVlak(re, re->totvlak++);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->flag= flag;
- vlr->ob= ob;
+ vlr->obr= obr;
vlr->v1= v1;
vlr->v2= v2;
- vlr->v3= RE_findOrAddVert(re, re->totvert++);
- vlr->v4= RE_findOrAddVert(re, re->totvert++);
+ vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
v1= vlr->v4; // cycle
v2= vlr->v3; // cycle
@@ -1415,7 +1173,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
VECCOPY(avec,vec);
}
else{
- vlr= RE_findOrAddVlak(re, re->totvlak-1);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak-1);
}
}
@@ -1435,17 +1193,17 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
vlr->mat= ma;
vlr->ec= ME_V2V3;
- vlr->lay= ob->lay;
+ vlr->lay= obr->ob->lay;
if(surfnor) {
- float *snor= RE_vlakren_get_surfnor(re, vlr, 1);
+ float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
VECCOPY(snor, surfnor);
}
if(uvco){
for(i=0; i<totuv; i++){
MTFace *mtf;
- mtf=RE_vlakren_get_tface(re,vlr,i,NULL,1);
+ mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1);
mtf->uv[0][0]=mtf->uv[1][0]=
mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0];
mtf->uv[0][1]=mtf->uv[1][1]=
@@ -1453,7 +1211,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
}
if(override_uv>=0){
MTFace *mtf;
- mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0);
+ mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0);
mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
@@ -1465,16 +1223,16 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
}
}
-static void static_particle_wire(Render *re, Object *ob, Material *ma, float *vec, float *vec1, int first, int line)
+static void static_particle_wire(ObjectRen *obr, Material *ma, float *vec, float *vec1, int first, int line)
{
VlakRen *vlr;
static VertRen *v1;
if(line) {
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, re->totvert++);
- vlr->v2= RE_findOrAddVert(re, re->totvert++);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
vlr->v3= vlr->v2;
vlr->v4= NULL;
@@ -1488,18 +1246,18 @@ static void static_particle_wire(Render *re, Object *ob, Material *ma, float *ve
vlr->mat= ma;
vlr->ec= ME_V1V2;
- vlr->lay= ob->lay;
+ vlr->lay= obr->ob->lay;
}
else if(first) {
- v1= RE_findOrAddVert(re, re->totvert++);
+ v1= RE_findOrAddVert(obr, obr->totvert++);
VECCOPY(v1->co, vec);
}
else {
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
vlr->v1= v1;
- vlr->v2= RE_findOrAddVert(re, re->totvert++);
+ vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
vlr->v3= vlr->v2;
vlr->v4= NULL;
@@ -1512,11 +1270,11 @@ static void static_particle_wire(Render *re, Object *ob, Material *ma, float *ve
vlr->mat= ma;
vlr->ec= ME_V1V2;
- vlr->lay= ob->lay;
+ vlr->lay= obr->ob->lay;
}
}
-static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align,
+static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align,
int lock, int p, int totpart, short uv_split, short anim, short split_offset, float random, float pa_time, float offset[2], int uv[3])
{
VlakRen *vlr;
@@ -1528,12 +1286,12 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
if(align<PART_BB_VIEW)
onevec[align]=1.0f;
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, re->totvert++);
- vlr->v2= RE_findOrAddVert(re, re->totvert++);
- vlr->v3= RE_findOrAddVert(re, re->totvert++);
- vlr->v4= RE_findOrAddVert(re, re->totvert++);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+ vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
if(lock && align==PART_BB_VIEW){
VECCOPY(xvec,bb_ob->obmat[0]);
@@ -1612,7 +1370,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
vlr->mat= ma;
vlr->ec= ME_V2V3;
- vlr->lay= ob->lay;
+ vlr->lay= obr->ob->lay;
if(uv_split>1){
uvdx=uvdy=1.0f/(float)uv_split;
@@ -1665,7 +1423,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
/* normal UVs */
if(uv[0]>=0){
- mtf=RE_vlakren_get_tface(re,vlr,uv[0],NULL,1);
+ mtf=RE_vlakren_get_tface(obr,vlr,uv[0],NULL,1);
mtf->uv[0][0]=1.0f;
mtf->uv[0][1]=1.0f;
mtf->uv[1][0]=0.0f;
@@ -1678,14 +1436,14 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
/* time-index UVs */
if(uv[1]>=0){
- mtf=RE_vlakren_get_tface(re,vlr,uv[1],NULL,1);
+ mtf=RE_vlakren_get_tface(obr,vlr,uv[1],NULL,1);
mtf->uv[0][0]=mtf->uv[1][0]=mtf->uv[2][0]=mtf->uv[3][0]=pa_time;
mtf->uv[0][1]=mtf->uv[1][1]=mtf->uv[2][1]=mtf->uv[3][1]=(float)p/(float)totpart;
}
/* split UVs */
if(uv_split>1 && uv[2]>=0){
- mtf=RE_vlakren_get_tface(re,vlr,uv[2],NULL,1);
+ mtf=RE_vlakren_get_tface(obr,vlr,uv[2],NULL,1);
mtf->uv[0][0]=uvx+uvdx;
mtf->uv[0][1]=uvy+uvdy;
mtf->uv[1][0]=uvx;
@@ -1696,28 +1454,29 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
mtf->uv[3][1]=uvy;
}
}
-static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line,
+static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, int path, int first, int line,
float time, float *loc, float *loc1, float *orco, float *surfnor, int totuv, float *uvco,
float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix)
{
HaloRen *har=0;
if(path){
if(ma->mode&MA_WIRE)
- static_particle_wire(re, ob, ma, loc, loc1, first, line);
+ static_particle_wire(obr, ma, loc, loc1, first, line);
else if(ma->mode & MA_HALO){
- har= RE_inithalo_particle(re, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed);
- if(har) har->lay= ob->lay;
+ har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed);
+ if(har) har->lay= obr->ob->lay;
}
else
- static_particle_strand(re, ob, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
+ static_particle_strand(re, obr, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
}
else{
- har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
- if(har) har->lay= ob->lay;
+ har= RE_inithalo_particle(re, obr, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
+ if(har) har->lay= obr->ob->lay;
}
}
-static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *psys)
+static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys)
{
+ Object *ob= obr->ob;
Object *tob=0, *bb_ob=re->scene->camera;
Material *ma=0;
CustomDataLayer *layer;
@@ -1737,7 +1496,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f;
float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random;
- int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1;
+ int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1;
int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild;
int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0};
char **uv_name=0;
@@ -1785,7 +1544,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
execute_ipo((ID *)ma, ma->ipo);
}
- RE_vlakren_set_customdata_names(re, &psmd->dm->faceData);
+ RE_set_customdata_names(obr, &psmd->dm->faceData);
totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE);
if(ma->texco & TEXCO_UV && totuv) {
@@ -1845,9 +1604,6 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
Mat3CpyMat4(nmat, ob->imat);
Mat3Transp(nmat);
- totvlako= re->totvlak;
- totverto= re->totvert;
-
totpart=psys->totpart;
mesh_get_texspace(ob->data, loc_tex, NULL, size_tex);
@@ -1877,7 +1633,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
}
if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) {
- strandbuf= RE_addStrandBuffer(re, ob, (totpart+totchild)*(path_nbr+1));
+ strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
strandbuf->ma= ma;
strandbuf->lay= ob->lay;
Mat4CpyMat4(strandbuf->winmat, re->winmat);
@@ -1944,15 +1700,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
for(i=0; i<totuv; i++){
- int n;
MFace *mface=psmd->dm->getFaceData(psmd->dm,pa->num,CD_MFACE);
mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
mtface+=pa->num;
- n= vlakren_customdata_layer_num(i, layer->active);
-
- psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n);
+ psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i);
}
}
@@ -2000,15 +1753,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
for(i=0; i<totuv; i++){
if(part->childtype==PART_CHILD_FACES){
- int n;
MFace *mface=psmd->dm->getFaceData(psmd->dm,cpa->num,CD_MFACE);
mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
mtface+=cpa->num;
- n= vlakren_customdata_layer_num(i, layer->active);
-
- psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*n);
+ psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*i);
}
else{
uvco[2*i]=uvco[2*i+1]=0.0f;
@@ -2018,15 +1768,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
else if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
for(i=0; i<totuv; i++){
ParticleData *parent = psys->particles+cpa->parent;
- int n;
MFace *mface=psmd->dm->getFaceData(psmd->dm,parent->num,CD_MFACE);
mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
mtface+=parent->num;
- n= vlakren_customdata_layer_num(i, layer->active);
-
- psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*n);
+ psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*i);
}
}
}
@@ -2053,20 +1800,20 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
/* strand render setup */
if(strandbuf) {
- strand= RE_findOrAddStrand(re, re->totstrand++);
+ strand= RE_findOrAddStrand(obr, obr->totstrand++);
strand->buffer= strandbuf;
strand->vert= svert;
VECCOPY(strand->orco, orco);
if(surfnor) {
- float *snor= RE_strandren_get_surfnor(re, strand, 1);
+ float *snor= RE_strandren_get_surfnor(obr, strand, 1);
VECCOPY(snor, surfnor);
}
if(uvco){
for(i=0; i<totuv; i++){
if(i != override_uv) {
- float *uv= RE_strandren_get_uv(re, strand, i, NULL, 1);
+ float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
uv[0]= uvco[2*i];
uv[1]= uvco[2*i+1];
@@ -2121,13 +1868,13 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
VECADDFAC(loc1,loc,vel,part->draw_line[1]);
- render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
+ render_new_particle(re,obr,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
orco,surfnor,totuv,uvco,hasize,seed,override_uv,0,0,0);
}
else if(part->draw_as==PART_DRAW_BB) {
VECCOPY(vel,state.vel);
//MTC_Mat4Mul3Vecfl(re->viewmat,vel);
- particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt),
+ particle_billboard(re,obr,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt),
part->bb_align,part->draw&PART_DRAW_BB_LOCK,
a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv);
}
@@ -2141,13 +1888,13 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
if(k==1){
VECSUB(loc0,loc1,loc);
VECADD(loc0,loc1,loc0);
- render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
+ render_new_particle(re,obr,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
orco,surfnor,totuv,uvco,hasize,seed,override_uv,
adapt,adapt_angle,adapt_pix);
}
if(path_nbr==0 || k)
- render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1,
+ render_new_particle(re,obr,psmd->dm,ma,path,0,0,time,loc,loc1,
orco,surfnor,totuv,uvco,hasize,seed,override_uv,
adapt,adapt_angle,adapt_pix);
@@ -2187,249 +1934,278 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
}
if(path && (ma->mode_l & MA_TANGENT_STR)==0)
- calc_vertexnormals(re, totverto, totvlako, 0);
+ calc_vertexnormals(re, obr, 0);
return 1;
}
-static void render_static_particle_system(Render *re, Object *ob, PartEff *paf)
-{
- Particle *pa=0;
- HaloRen *har=0;
- Material *ma=0;
- VertRen *v1= NULL;
- VlakRen *vlr;
- float xn, yn, zn, imat[3][3], mat[4][4], hasize;
- float mtime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
- float *orco= NULL, loc_tex[3], size_tex[3];
- int a, mat_nr=1, seed, totvlako, totverto, first;
-
- pa= paf->keys;
- if(pa==NULL || (paf->flag & PAF_ANIMATED) || paf->disp!=100) {
- build_particle_system(ob);
- pa= paf->keys;
- if(pa==NULL) return;
- }
+/* ------------------------------------------------------------------------- */
+/* Halo's */
+/* ------------------------------------------------------------------------- */
- totvlako= re->totvlak;
- totverto= re->totvert;
-
- ma= give_render_material(re, ob, paf->omat);
- if(ma->mode & MA_HALO)
- re->flag |= R_HALO;
+static void make_render_halos(Render *re, ObjectRen *obr, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco)
+{
+ Object *ob= obr->ob;
+ HaloRen *har;
+ float xn, yn, zn, nor[3], view[3];
+ float vec[3], hasize, mat[4][4], imat[3][3];
+ int a, ok, seed= ma->seed1;
MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat); /* need to be that way, for imat texture */
-
MTC_Mat3CpyMat4(imat, ob->imat);
-
- /* orcos */
- if(!(ma->mode & (MA_HALO|MA_WIRE))) {
- orco= MEM_mallocN(3*sizeof(float)*paf->totpart, "static particle orcos");
- set_object_orco(re, paf, orco);
- }
-
- mesh_get_texspace(ob->data, loc_tex, NULL, size_tex);
-
- if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
- else ptime= 0.0;
- ctime= bsystem_time(ob, (float)re->scene->r.cfra, ptime);
- seed= ma->seed1;
- for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
-
- where_is_particle(paf, pa, pa->time, vec1);
- if(orco) {
- orco[0] = (vec1[0]-loc_tex[0])/size_tex[0];
- orco[1] = (vec1[1]-loc_tex[1])/size_tex[1];
- orco[2] = (vec1[2]-loc_tex[2])/size_tex[2];
- }
- MTC_Mat4MulVecfl(mat, vec1);
- mtime= pa->time+pa->lifetime+paf->staticstep-1;
-
- first= 1;
- for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
-
- /* make sure hair grows until the end.. */
- if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
-
- /* watch it: also calc the normal of a particle */
- if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
- where_is_particle(paf, pa, ctime+1.0, vec);
- MTC_Mat4MulVecfl(mat, vec);
- }
- else {
- where_is_particle(paf, pa, ctime, vec);
- MTC_Mat4MulVecfl(mat, vec);
- }
+ re->flag |= R_HALO;
- if(pa->mat_nr != mat_nr) {
- mat_nr= pa->mat_nr;
- ma= give_render_material(re, ob, mat_nr);
- }
-
- /* wires */
- if(ma->mode & MA_WIRE) {
- if(ctime == pa->time) {
- v1= RE_findOrAddVert(re, re->totvert++);
- VECCOPY(v1->co, vec);
- }
- else {
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= v1;
- vlr->v2= RE_findOrAddVert(re, re->totvert++);
- vlr->v3= vlr->v2;
- vlr->v4= NULL;
-
- v1= vlr->v2; // cycle
- VECCOPY(v1->co, vec);
-
- VecSubf(vlr->n, vec, vec1);
- Normalize(vlr->n);
- VECCOPY(v1->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V1V2;
- vlr->lay= ob->lay;
- }
- }
- else {
- if(ma->ipo) {
- /* correction for lifetime */
- ptime= 100.0*(ctime-pa->time)/pa->lifetime;
- calc_ipo(ma->ipo, ptime);
- execute_ipo((ID *)ma, ma->ipo);
- }
-
- if(ma->mode & MA_HALO) {
- hasize= ma->hasize;
+ for(a=0; a<totvert; a++, mvert++) {
+ ok= 1;
- if(ma->mode & MA_HALOPUNO) {
- xn= pa->no[0];
- yn= pa->no[1];
- zn= pa->no[2];
+ if(ok) {
+ hasize= ma->hasize;
- /* transpose ! */
- nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
- nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
- nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
- Normalize(nor);
+ VECCOPY(vec, mvert->co);
+ MTC_Mat4MulVecfl(mat, vec);
- VECCOPY(view, vec);
- Normalize(view);
+ if(ma->mode & MA_HALOPUNO) {
+ xn= mvert->no[0];
+ yn= mvert->no[1];
+ zn= mvert->no[2];
- zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
- if(zn>=0.0) hasize= 0.0;
- else hasize*= zn*zn*zn*zn;
- }
+ /* transpose ! */
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalize(nor);
- if(paf->stype==PAF_VECT) har= RE_inithalo(re, ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
- else {
- har= RE_inithalo(re, ma, vec, NULL, pa->co, hasize, 0.0, seed);
- if(har && (ma->mode & MA_HALO_SHADE)) {
- VecSubf(har->no, vec, vec1);
- Normalize(har->no);
- har->lay= ob->lay;
- }
- }
- if(har) har->lay= ob->lay;
- }
- else { /* generate pixel sized hair strand */
- float strandco= 1.0f;
-
- /* last strand, texco to end */
- if(ctime + paf->staticstep < mtime)
- strandco= (ctime-pa->time)/(mtime-pa->time);
-
- static_particle_strand(re, ob, ma, orco, 0, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1);
- }
+ VECCOPY(view, vec);
+ Normalize(view);
+
+ zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
+ if(zn>=0.0) hasize= 0.0;
+ else hasize*= zn*zn*zn*zn;
}
-
- VECCOPY(vec1, vec);
- first= 0;
+
+ if(orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed);
+ else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed);
+ if(har) har->lay= ob->lay;
}
-
+ if(orco) orco+= 3;
seed++;
- if(orco) orco+=3;
}
+}
+
+static int verghalo(const void *a1, const void *a2)
+{
+ const HaloRen *har1= a1, *har2= a2;
+
+ if(har1->zs < har2->zs) return 1;
+ else if(har1->zs > har2->zs) return -1;
+ return 0;
+}
+
+static void sort_halos(Render *re, int totsort)
+{
+ ObjectRen *obr;
+ HaloRen *har= NULL, **haso;
+ int a;
+
+ if(re->tothalo==0) return;
+
+ re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos");
+ haso= re->sortedhalos;
+
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->tothalo; a++) {
+ if((a & 255)==0) har= obr->bloha[a>>8];
+ else har++;
- if(paf->disp!=100) {
- MEM_freeN(paf->keys);
- paf->keys= NULL;
+ *(haso++)= har;
+ }
}
- if((ma->mode & MA_TANGENT_STR)==0)
- calc_vertexnormals(re, totverto, totvlako, 0);
+ qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo);
}
-
+/* ------------------------------------------------------------------------- */
+/* Displacement Mapping */
/* ------------------------------------------------------------------------- */
-static int verghalo(const void *a1, const void *a2)
+static short test_for_displace(Render *re, Object *ob)
{
- const struct halosort *x1=a1, *x2=a2;
+ /* return 1 when this object uses displacement textures. */
+ Material *ma;
+ int i;
- if( x1->z < x2->z ) return 1;
- else if( x1->z > x2->z) return -1;
+ for (i=1; i<=ob->totcol; i++) {
+ ma=give_render_material(re, ob, i);
+ /* ma->mapto is ORed total of all mapto channels */
+ if(ma && (ma->mapto & MAP_DISPLACE)) return 1;
+ }
return 0;
}
-/* ------------------------------------------------------------------------- */
-static void sort_halos(Render *re)
+static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale)
{
- struct halosort *hablock, *haso;
- HaloRen *har = NULL, **bloha;
- int a;
+ MTFace *tface;
+ short texco= shi->mat->texco;
+ float sample=0;
+ char *name;
+ int i;
- if(re->tothalo==0) return;
+ /* shi->co is current render coord, just make sure at least some vector is here */
+ VECCOPY(shi->co, vr->co);
+ /* vertex normal is used for textures type 'col' and 'var' */
+ VECCOPY(shi->vn, vr->n);
+
+ if (texco & TEXCO_UV) {
+ shi->totuv= 0;
+ shi->actuv= obr->actmtface;
- /* make datablock with halo pointers, sort */
- haso= hablock= MEM_mallocN(sizeof(struct halosort)*re->tothalo, "hablock");
+ for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) {
+ ShadeInputUV *suv= &shi->uv[i];
- for(a=0; a<re->tothalo; a++) {
- if((a & 255)==0) har= re->bloha[a>>8];
- else har++;
- haso->har= har;
- haso->z= har->zs;
- haso++;
+ /* shi.uv needs scale correction from tface uv */
+ suv->uv[0]= 2*tface->uv[vindex][0]-1.0f;
+ suv->uv[1]= 2*tface->uv[vindex][1]-1.0f;
+ suv->uv[2]= 0.0f;
+ suv->name= name;
+ shi->totuv++;
+ }
}
- qsort(hablock, re->tothalo, sizeof(struct halosort), verghalo);
+ /* set all rendercoords, 'texco' is an ORed value for all textures needed */
+ if ((texco & TEXCO_ORCO) && (vr->orco)) {
+ VECCOPY(shi->lo, vr->orco);
+ }
+ if (texco & TEXCO_STICKY) {
+ float *sticky= RE_vertren_get_sticky(obr, vr, 0);
+ if(sticky) {
+ shi->sticky[0]= sticky[0];
+ shi->sticky[1]= sticky[1];
+ shi->sticky[2]= 0.0f;
+ }
+ }
+ if (texco & TEXCO_GLOB) {
+ VECCOPY(shi->gl, shi->co);
+ MTC_Mat4MulVecfl(re->viewinv, shi->gl);
+ }
+ if (texco & TEXCO_NORM) {
+ VECCOPY(shi->orn, shi->vn);
+ }
+ if(texco & TEXCO_REFL) {
+ /* not (yet?) */
+ }
+
+ shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
+
+ do_material_tex(shi);
+
+ //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2],
+ //vr->co[0], vr->co[1], vr->co[2]);
+
+ /* 0.5 could become button once? */
+ vr->co[0] += shi->displace[0] * scale[0] ;
+ vr->co[1] += shi->displace[1] * scale[1] ;
+ vr->co[2] += shi->displace[2] * scale[2] ;
+
+ //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]);
+
+ /* we just don't do this vertex again, bad luck for other face using same vertex with
+ different material... */
+ vr->flag |= 1;
+
+ /* Pass sample back so displace_face can decide which way to split the quad */
+ sample = shi->displace[0]*shi->displace[0];
+ sample += shi->displace[1]*shi->displace[1];
+ sample += shi->displace[2]*shi->displace[2];
+
+ vr->accum=sample;
+ /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */
+ return;
+}
- /* re-assamble re->bloha */
+static void displace_render_face(Render *re, VlakRen *vlr, float *scale)
+{
+ ShadeInput shi;
- bloha= re->bloha;
- re->bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(re->blohalen),"Bloha");
+ /* set up shadeinput struct for multitex() */
+ shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */
+ shi.vlr= vlr; /* current render face */
+ shi.mat= vlr->mat; /* current input material */
+
+ /* Displace the verts, flag is set when done */
+ if (!vlr->v1->flag)
+ displace_render_vert(re, vlr->obr, &shi, vlr->v1,0, scale);
+
+ if (!vlr->v2->flag)
+ displace_render_vert(re, vlr->obr, &shi, vlr->v2, 1, scale);
- haso= hablock;
- for(a=0; a<re->tothalo; a++) {
- har= RE_findOrAddHalo(re, a);
- *har= *(haso->har);
+ if (!vlr->v3->flag)
+ displace_render_vert(re, vlr->obr, &shi, vlr->v3, 2, scale);
- haso++;
+ if (vlr->v4) {
+ if (!vlr->v4->flag)
+ displace_render_vert(re, vlr->obr, &shi, vlr->v4, 3, scale);
+
+ /* closest in displace value. This will help smooth edges. */
+ if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum))
+ vlr->flag |= R_DIVIDE_24;
+ else vlr->flag &= ~R_DIVIDE_24;
}
+
+ /* Recalculate the face normal - if flipped before, flip now */
+ if(vlr->v4) {
+ CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+ }
+ else {
+ CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+ }
+}
- /* free */
- a= 0;
- while(bloha[a]) {
- MEM_freeN(bloha[a]);
- a++;
+static void do_displacement(Render *re, ObjectRen *obr)
+{
+ VertRen *vr;
+ VlakRen *vlr;
+// float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30};
+ float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn
+ int i; //, texflag=0;
+ Object *obt;
+
+ /* Object Size with parenting */
+ obt=obr->ob;
+ while(obt){
+ VecAddf(temp, obt->size, obt->dsize);
+ scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2];
+ obt=obt->parent;
+ }
+
+ /* Clear all flags */
+ for(i=0; i<obr->totvert; i++){
+ vr= RE_findOrAddVert(obr, i);
+ vr->flag= 0;
}
- MEM_freeN(bloha);
- MEM_freeN(hablock);
+ for(i=0; i<obr->totvlak; i++){
+ vlr=RE_findOrAddVlak(obr, i);
+ displace_render_face(re, vlr, scale);
+ }
+
+ /* Recalc vertex normals */
+ calc_vertexnormals(re, obr, 0);
}
/* ------------------------------------------------------------------------- */
-static void init_render_mball(Render *re, Object *ob)
+/* Metaball */
+/* ------------------------------------------------------------------------- */
+
+static void init_render_mball(Render *re, ObjectRen *obr)
{
+ Object *ob= obr->ob;
DispList *dl;
VertRen *ver;
VlakRen *vlr, *vlr1;
Material *ma;
float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn;
- int a, need_orco, startvert, *index;
+ int a, need_orco, *index;
if (ob!=find_basis_mball(ob))
return;
@@ -2449,19 +2225,19 @@ static void init_render_mball(Render *re, Object *ob)
dl= ob->disp.first;
if(dl==0) return;
- startvert= re->totvert;
data= dl->verts;
nors= dl->nors;
for(a=0; a<dl->nr; a++, data+=3, nors+=3) {
- ver= RE_findOrAddVert(re, re->totvert++);
+ ver= RE_findOrAddVert(obr, obr->totvert++);
VECCOPY(ver->co, data);
MTC_Mat4MulVecfl(mat, ver->co);
- xn= nors[0];
- yn= nors[1];
- zn= nors[2];
+ /* render normals are inverted */
+ xn= -nors[0];
+ yn= -nors[1];
+ zn= -nors[2];
/* transpose ! */
ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
@@ -2476,11 +2252,11 @@ static void init_render_mball(Render *re, Object *ob)
index= dl->index;
for(a=0; a<dl->parts; a++, index+=4) {
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, startvert+index[0]);
- vlr->v2= RE_findOrAddVert(re, startvert+index[1]);
- vlr->v3= RE_findOrAddVert(re, startvert+index[2]);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, index[0]);
+ vlr->v2= RE_findOrAddVert(obr, index[1]);
+ vlr->v3= RE_findOrAddVert(obr, index[2]);
vlr->v4= 0;
if(ob->transflag & OB_NEG_SCALE)
@@ -2495,10 +2271,10 @@ static void init_render_mball(Render *re, Object *ob)
/* mball -too bad- always has triangles, because quads can be non-planar */
if(index[3] && index[3]!=index[2]) {
- vlr1= RE_findOrAddVlak(re, re->totvlak++);
+ vlr1= RE_findOrAddVlak(obr, obr->totvlak++);
*vlr1= *vlr;
vlr1->v2= vlr1->v3;
- vlr1->v3= RE_findOrAddVert(re, startvert+index[3]);
+ vlr1->v3= RE_findOrAddVert(obr, index[3]);
if(ob->transflag & OB_NEG_SCALE)
CalcNormFloat(vlr1->v1->co, vlr1->v2->co, vlr1->v3->co, vlr1->n);
else
@@ -2518,17 +2294,450 @@ static void init_render_mball(Render *re, Object *ob)
/* this enforces remake for real, orco displist is small (in scale) */
ob->recalc |= OB_RECALC_DATA;
}
+
+/* ------------------------------------------------------------------------- */
+/* Surfaces and Curves */
/* ------------------------------------------------------------------------- */
-/* convert */
-static int vlakren_customdata_layer_num(int n, int active)
+/* returns amount of vertices added for orco */
+static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4])
{
- /* make the active layer the first */
- if (n == active) return 0;
- else if (n < active) return n+1;
- else return n;
+ Object *ob= obr->ob;
+ VertRen *v1, *v2, *v3, *v4, *ver;
+ VlakRen *vlr, *vlr1, *vlr2, *vlr3;
+ Curve *cu= ob->data;
+ float *data, n1[3], flen;
+ int u, v, orcoret= 0;
+ int p1, p2, p3, p4, a;
+ int sizeu, nsizeu, sizev, nsizev;
+ int startvert, startvlak;
+
+ startvert= obr->totvert;
+ nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr;
+
+ data= dl->verts;
+ for (u = 0; u < sizeu; u++) {
+ v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */
+ VECCOPY(v1->co, data); data += 3;
+ if(orco) {
+ v1->orco= orco; orco+= 3; orcoret++;
+ }
+ MTC_Mat4MulVecfl(mat, v1->co);
+
+ for (v = 1; v < sizev; v++) {
+ ver= RE_findOrAddVert(obr, obr->totvert++);
+ VECCOPY(ver->co, data); data += 3;
+ if(orco) {
+ ver->orco= orco; orco+= 3; orcoret++;
+ }
+ MTC_Mat4MulVecfl(mat, ver->co);
+ }
+ /* if V-cyclic, add extra vertices at end of the row */
+ if (dl->flag & DL_CYCL_U) {
+ ver= RE_findOrAddVert(obr, obr->totvert++);
+ VECCOPY(ver->co, v1->co);
+ if(orco) {
+ ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0);
+ }
+ }
+ }
+
+ /* Done before next loop to get corner vert */
+ if (dl->flag & DL_CYCL_U) nsizev++;
+ if (dl->flag & DL_CYCL_V) nsizeu++;
+
+ /* if U cyclic, add extra row at end of column */
+ if (dl->flag & DL_CYCL_V) {
+ for (v = 0; v < nsizev; v++) {
+ v1= RE_findOrAddVert(obr, startvert + v);
+ ver= RE_findOrAddVert(obr, obr->totvert++);
+ VECCOPY(ver->co, v1->co);
+ if(orco) {
+ ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v);
+ }
+ }
+ }
+
+ sizeu = nsizeu;
+ sizev = nsizev;
+
+ startvlak= obr->totvlak;
+
+ for(u = 0; u < sizeu - 1; u++) {
+ p1 = startvert + u * sizev; /* walk through face list */
+ p2 = p1 + 1;
+ p3 = p2 + sizev;
+ p4 = p3 - 1;
+
+ for(v = 0; v < sizev - 1; v++) {
+ v1= RE_findOrAddVert(obr, p1);
+ v2= RE_findOrAddVert(obr, p2);
+ v3= RE_findOrAddVert(obr, p3);
+ v4= RE_findOrAddVert(obr, p4);
+
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
+
+ flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
+ VECCOPY(vlr->n, n1);
+
+ vlr->lay= ob->lay;
+ vlr->mat= matar[ dl->col];
+ vlr->ec= ME_V1V2+ME_V2V3;
+ vlr->flag= dl->rt;
+ if( (cu->flag & CU_NOPUNOFLIP) ) {
+ vlr->flag |= R_NOPUNOFLIP;
+ }
+
+ VecAddf(v1->n, v1->n, n1);
+ VecAddf(v2->n, v2->n, n1);
+ VecAddf(v3->n, v3->n, n1);
+ VecAddf(v4->n, v4->n, n1);
+
+ p1++; p2++; p3++; p4++;
+ }
+ }
+ /* fix normals for U resp. V cyclic faces */
+ sizeu--; sizev--; /* dec size for face array */
+ if (dl->flag & DL_CYCL_V) {
+
+ for (v = 0; v < sizev; v++)
+ {
+ /* optimize! :*/
+ vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v));
+ vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v));
+ VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
+ VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
+ VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
+ VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
+ }
+ }
+ if (dl->flag & DL_CYCL_U) {
+
+ for (u = 0; u < sizeu; u++)
+ {
+ /* optimize! :*/
+ vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0));
+ vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1));
+ VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
+ VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
+ VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
+ VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
+ }
+ }
+ /* last vertex is an extra case:
+
+ ^ ()----()----()----()
+ | | | || |
+ u | |(0,n)||(0,0)|
+ | | || |
+ ()====()====[]====()
+ | | || |
+ | |(m,n)||(m,0)|
+ | | || |
+ ()----()----()----()
+ v ->
+
+ vertex [] is no longer shared, therefore distribute
+ normals of the surrounding faces to all of the duplicates of []
+ */
+
+ if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U))
+ {
+ vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
+ vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0,0)); /* (0,0) */
+ VecAddf(n1, vlr->n, vlr1->n);
+ vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0,n) */
+ VecAddf(n1, n1, vlr2->n);
+ vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m,0) */
+ VecAddf(n1, n1, vlr3->n);
+ VECCOPY(vlr->v3->n, n1);
+ VECCOPY(vlr1->v1->n, n1);
+ VECCOPY(vlr2->v2->n, n1);
+ VECCOPY(vlr3->v4->n, n1);
+ }
+ for(a = startvert; a < obr->totvert; a++) {
+ ver= RE_findOrAddVert(obr, a);
+ Normalize(ver->n);
+ }
+
+
+ return orcoret;
+}
+
+static void init_render_surf(Render *re, ObjectRen *obr)
+{
+ Object *ob= obr->ob;
+ Nurb *nu=0;
+ Curve *cu;
+ ListBase displist;
+ DispList *dl;
+ Material *matar[32];
+ float *orco=NULL, *orcobase=NULL, mat[4][4];
+ int a, need_orco=0;
+
+ cu= ob->data;
+ nu= cu->nurb.first;
+ if(nu==0) return;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+
+ /* material array */
+ memset(matar, 0, 4*32);
+ matar[0]= give_render_material(re, ob, 0);
+ for(a=0; a<ob->totcol; a++) {
+ matar[a]= give_render_material(re, ob, a+1);
+ if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ }
+ }
+
+ if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
+
+ if(need_orco) orcobase= orco= get_object_orco(re, ob);
+
+ displist.first= displist.last= 0;
+ makeDispListSurf(ob, &displist, 1);
+
+ dl= displist.first;
+ /* walk along displaylist and create rendervertices/-faces */
+ while(dl) {
+ /* watch out: u ^= y, v ^= x !! */
+ if(dl->type==DL_SURF) {
+ orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
+ }
+
+ dl= dl->next;
+ }
+ freedisplist(&displist);
+}
+
+static void init_render_curve(Render *re, ObjectRen *obr, int only_verts)
+{
+ Object *ob= obr->ob;
+ Curve *cu;
+ VertRen *ver;
+ VlakRen *vlr;
+ DispList *dl;
+ ListBase olddl={NULL, NULL};
+ Material *matar[32];
+ float len, *data, *fp, *orco=NULL, *orcobase= NULL;
+ float n[3], mat[4][4];
+ int nr, startvert, startvlak, a, b;
+ int frontside, need_orco=0;
+
+ cu= ob->data;
+ if(cu->nurb.first==NULL) return;
+
+ /* no modifier call here, is in makedisp */
+
+ if(cu->resolu_ren)
+ SWAP(ListBase, olddl, cu->disp);
+
+ /* test displist */
+ if(cu->disp.first==NULL)
+ makeDispListCurveTypes(ob, 0);
+ dl= cu->disp.first;
+ if(cu->disp.first==NULL) return;
+
+ MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+
+ /* material array */
+ memset(matar, 0, 4*32);
+ matar[0]= give_render_material(re, ob, 0);
+ for(a=0; a<ob->totcol; a++) {
+ matar[a]= give_render_material(re, ob, a+1);
+ if(matar[a]->texco & TEXCO_ORCO) {
+ need_orco= 1;
+ }
+ }
+
+ if(need_orco) orcobase=orco= get_object_orco(re, ob);
+
+ dl= cu->disp.first;
+ while(dl) {
+ if(dl->type==DL_INDEX3) {
+ int *index;
+
+ startvert= obr->totvert;
+ data= dl->verts;
+
+ n[0]= ob->imat[0][2];
+ n[1]= ob->imat[1][2];
+ n[2]= ob->imat[2][2];
+ Normalize(n);
+
+ for(a=0; a<dl->nr; a++, data+=3) {
+ ver= RE_findOrAddVert(obr, obr->totvert++);
+ VECCOPY(ver->co, data);
+
+ /* flip normal if face is backfacing, also used in face loop below */
+ if(ver->co[2] < 0.0) {
+ VECCOPY(ver->n, n);
+ ver->flag = 1;
+ }
+ else {
+ ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
+ ver->flag = 0;
+ }
+
+ MTC_Mat4MulVecfl(mat, ver->co);
+
+ if (orco) {
+ ver->orco = orco;
+ orco += 3;
+ }
+ }
+
+ if(only_verts==0) {
+ startvlak= obr->totvlak;
+ index= dl->index;
+ for(a=0; a<dl->parts; a++, index+=3) {
+
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr = obr;
+ vlr->v1= RE_findOrAddVert(obr, startvert+index[0]);
+ vlr->v2= RE_findOrAddVert(obr, startvert+index[1]);
+ vlr->v3= RE_findOrAddVert(obr, startvert+index[2]);
+ vlr->v4= NULL;
+
+ if(vlr->v1->flag) {
+ VECCOPY(vlr->n, n);
+ }
+ else {
+ vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
+ }
+
+ vlr->mat= matar[ dl->col ];
+ vlr->flag= 0;
+ if( (cu->flag & CU_NOPUNOFLIP) ) {
+ vlr->flag |= R_NOPUNOFLIP;
+ }
+ vlr->ec= 0;
+ vlr->lay= ob->lay;
+ }
+ }
+ }
+ else if (dl->type==DL_SURF) {
+
+ /* cyclic U means an extruded full circular curve, we skip bevel splitting then */
+ if (dl->flag & DL_CYCL_U) {
+ orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
+ }
+ else {
+ int p1,p2,p3,p4;
+
+ fp= dl->verts;
+ startvert= obr->totvert;
+ nr= dl->nr*dl->parts;
+
+ while(nr--) {
+ ver= RE_findOrAddVert(obr, obr->totvert++);
+
+ VECCOPY(ver->co, fp);
+ MTC_Mat4MulVecfl(mat, ver->co);
+ fp+= 3;
+
+ if (orco) {
+ ver->orco = orco;
+ orco += 3;
+ }
+ }
+
+ if(dl->bevelSplitFlag || only_verts==0) {
+ startvlak= obr->totvlak;
+
+ for(a=0; a<dl->parts; a++) {
+
+ frontside= (a >= dl->nr/2);
+
+ DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
+ p1+= startvert;
+ p2+= startvert;
+ p3+= startvert;
+ p4+= startvert;
+
+ for(; b<dl->nr; b++) {
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, p2);
+ vlr->v2= RE_findOrAddVert(obr, p1);
+ vlr->v3= RE_findOrAddVert(obr, p3);
+ vlr->v4= RE_findOrAddVert(obr, p4);
+ vlr->ec= ME_V2V3+ME_V3V4;
+ if(a==0) vlr->ec+= ME_V1V2;
+
+ vlr->flag= dl->rt;
+ vlr->lay= ob->lay;
+
+ /* this is not really scientific: the vertices
+ * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
+ * front and backside treated different!!
+ */
+
+ if(frontside)
+ CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
+ else
+ CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
+
+ vlr->mat= matar[ dl->col ];
+
+ p4= p3;
+ p3++;
+ p2= p1;
+ p1++;
+ }
+ }
+
+ if (dl->bevelSplitFlag) {
+ for(a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
+ if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
+ split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
+ }
+
+ /* vertex normals */
+ for(a= startvlak; a<obr->totvlak; a++) {
+ vlr= RE_findOrAddVlak(obr, a);
+
+ VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
+ VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
+ VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
+ VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
+ }
+ for(a=startvert; a<obr->totvert; a++) {
+ ver= RE_findOrAddVert(obr, a);
+ len= Normalize(ver->n);
+ if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */
+ else ver->flag= 0;
+ }
+ for(a= startvlak; a<obr->totvlak; a++) {
+ vlr= RE_findOrAddVlak(obr, a);
+ if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n);
+ if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n);
+ if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n);
+ if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n);
+ }
+ }
+ }
+ }
+
+ dl= dl->next;
+ }
+
+ /* not very elegant... but we want original displist in UI */
+ if(cu->resolu_ren) {
+ freedisplist(&cu->disp);
+ SWAP(ListBase, olddl, cu->disp);
+ }
}
+/* ------------------------------------------------------------------------- */
+/* Mesh */
+/* ------------------------------------------------------------------------- */
+
struct edgesort {
int v1, v2;
int f;
@@ -2606,13 +2815,13 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
return edsort;
}
-static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge)
+static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge)
{
struct edgesort ed, *edp;
CustomDataLayer *layer;
MTFace *mtface, *mtf;
MCol *mcol, *mc;
- int index, mtfn, mcn, n;
+ int index, mtfn, mcn;
char *name;
if(medge->v1 < medge->v2) {
@@ -2636,8 +2845,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
mtface= &((MTFace*)layer->data)[edp->f];
- n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd);
- mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
+ mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1);
*mtf= *mtface;
@@ -2648,8 +2856,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak
}
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
mcol= &((MCol*)layer->data)[edp->f*4];
- n= vlakren_customdata_layer_num(mcn++, layer->active_rnd);
- mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
+ mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1);
mc[0]= mcol[edp->i1];
mc[1]= mc[2]= mc[3]= mcol[edp->i2];
@@ -2658,8 +2865,9 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak
}
}
-static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts)
+static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts)
{
+ Object *ob= obr->ob;
Mesh *me;
MVert *mvert = NULL;
MFace *mface;
@@ -2667,36 +2875,23 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
VertRen *ver;
Material *ma;
MSticky *ms = NULL;
- PartEff *paf;
DerivedMesh *dm;
CustomDataMask mask;
float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3],
float *orco=0;
- int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs;
+ int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, vertofs;
int end, do_autosmooth=0, totvert = 0;
int useFluidmeshNormals= 0; // NT fluidsim, use smoothed normals?
int use_original_normals= 0;
me= ob->data;
- paf = give_parteff(ob);
- if(paf) {
- /* warning; build_particle_system does modifier calls itself */
- if(paf->flag & PAF_STATIC) render_static_particle_system(re, ob, paf);
- else render_particle_system(re, ob, par, paf);
- if((paf->flag & PAF_SHOWE)==0) return;
- }
-
MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
MTC_Mat4Invert(ob->imat, mat);
MTC_Mat3CpyMat4(imat, ob->imat);
- if(me->totvert==0) {
+ if(me->totvert==0)
return;
- }
-
- totvlako= re->totvlak;
- totverto= re->totvert;
need_orco= 0;
for(a=1; a<=ob->totcol; a++) {
@@ -2767,16 +2962,16 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
ma= give_render_material(re, ob, 1);
if(ma->mode & MA_HALO) {
- make_render_halos(re, ob, me, totvert, mvert, ma, orco);
+ make_render_halos(re, obr, me, totvert, mvert, ma, orco);
}
else {
for(a=0; a<totvert; a++, mvert++) {
- ver= RE_findOrAddVert(re, re->totvert++);
+ ver= RE_findOrAddVert(obr, obr->totvert++);
VECCOPY(ver->co, mvert->co);
if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */
MTC_Mat4MulVecfl(mat, ver->co);
-
+
if(useFluidmeshNormals) {
/* normals are inverted in render */
xn = -mvert->no[0]/ 32767.0;
@@ -2793,7 +2988,7 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
orco+=3;
}
if(ms) {
- float *sticky= RE_vertren_get_sticky(re, ver, 1);
+ float *sticky= RE_vertren_get_sticky(obr, ver, 1);
sticky[0]= ms->co[0];
sticky[1]= ms->co[1];
ms++;
@@ -2802,12 +2997,12 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
if(!only_verts) {
/* store customdata names, because DerivedMesh is freed */
- RE_vlakren_set_customdata_names(re, &dm->faceData);
+ RE_set_customdata_names(obr, &dm->faceData);
/* still to do for keys: the correct local texture coordinate */
/* faces in order of color blocks */
- vertofs= re->totvert - totvert;
+ vertofs= obr->totvert - totvert;
for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
ma= give_render_material(re, ob, a1+1);
@@ -2845,13 +3040,13 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
v3= mface->v3;
v4= mface->v4;
flag= mface->flag & ME_SMOOTH;
-
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, vertofs+v1);
- vlr->v2= RE_findOrAddVert(re, vertofs+v2);
- vlr->v3= RE_findOrAddVert(re, vertofs+v3);
- if(v4) vlr->v4= RE_findOrAddVert(re, vertofs+v4);
+
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
+ vlr->v2= RE_findOrAddVert(obr, vertofs+v2);
+ vlr->v3= RE_findOrAddVert(obr, vertofs+v3);
+ if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4);
else vlr->v4= 0;
/* render normals are inverted in render */
@@ -2879,12 +3074,12 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
vlr->ec= 0; /* mesh edges rendered separately */
vlr->lay= ob->lay;
- if(len==0) re->totvlak--;
+ if(len==0) obr->totvlak--;
else {
CustomDataLayer *layer;
MTFace *mtface, *mtf;
MCol *mcol, *mc;
- int index, mtfn= 0, mcn= 0, n;
+ int index, mtfn= 0, mcn= 0;
char *name;
for(index=0; index<dm->faceData.totlayer; index++) {
@@ -2892,14 +3087,12 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
name= layer->name;
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
- n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd);
- mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
+ mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1);
mtface= (MTFace*)layer->data;
*mtf= mtface[a];
}
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
- n= vlakren_customdata_layer_num(mcn++, layer->active_rnd);
- mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
+ mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1);
mcol= (MCol*)layer->data;
memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
}
@@ -2929,16 +3122,15 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
MVert *v0 = &mvert[medge->v1];
MVert *v1 = &mvert[medge->v2];
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, vertofs+medge->v1);
- vlr->v2= RE_findOrAddVert(re, vertofs+medge->v2);
+ vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+ vlr->obr= obr;
+ vlr->v1= RE_findOrAddVert(obr, vertofs+medge->v1);
+ vlr->v2= RE_findOrAddVert(obr, vertofs+medge->v2);
vlr->v3= vlr->v2;
vlr->v4= NULL;
- if(edgetable) {
- use_mesh_edge_lookup(re, dm, medge, vlr, edgetable, totedge);
- }
+ if(edgetable)
+ use_mesh_edge_lookup(obr, dm, medge, vlr, edgetable, totedge);
xn= -(v0->no[0]+v1->no[0]);
yn= -(v0->no[1]+v1->no[1]);
@@ -2963,29 +3155,31 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts
if(!only_verts) {
if (test_for_displace(re, ob ) ) {
- calc_vertexnormals(re, totverto, totvlako, 0);
- do_displacement(re, ob, totvlako, re->totvlak-totvlako, totverto, re->totvert-totverto);
+ calc_vertexnormals(re, obr, 0);
+ do_displacement(re, obr);
}
if(do_autosmooth) {
- autosmooth(re, mat, totverto, totvlako, me->smoothresh);
+ autosmooth(re, obr, mat, me->smoothresh);
}
if(useFluidmeshNormals) {
// do not recalculate, only init render data
- calc_fluidsimnormals(re, totverto, totvlako, need_tangent);
+ calc_fluidsimnormals(re, obr, need_tangent);
} else {
- calc_vertexnormals(re, totverto, totvlako, need_tangent);
+ calc_vertexnormals(re, obr, need_tangent);
}
if(need_stress)
- calc_edge_stress(re, me, totverto, totvlako);
+ calc_edge_stress(re, obr, me);
}
dm->release(dm);
}
/* ------------------------------------------------------------------------- */
+/* Lamps and Shadowbuffers */
+/* ------------------------------------------------------------------------- */
static void initshadowbuf(Render *re, LampRen *lar, float mat[][4])
{
@@ -3039,7 +3233,6 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4])
}
-
static void area_lamp_vectors(LampRen *lar)
{
float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
@@ -3317,442 +3510,118 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
return go;
}
-/* ------------------------------------------------------------------------- */
-
-/* returns amount of vertices added for orco */
-static int dl_surf_to_renderdata(Render *re, Object *ob, DispList *dl, Material **matar, float *orco, float mat[4][4])
+/* layflag: allows material group to ignore layerflag */
+static void add_lightgroup(Render *re, Group *group, int exclusive)
{
- VertRen *v1, *v2, *v3, *v4, *ver;
- VlakRen *vlr, *vlr1, *vlr2, *vlr3;
- Curve *cu= ob->data;
- float *data, n1[3], flen;
- int u, v, orcoret= 0;
- int p1, p2, p3, p4, a;
- int sizeu, nsizeu, sizev, nsizev;
- int startvert, startvlak;
-
- startvert= re->totvert;
- nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr;
+ GroupObject *go, *gol;
- data= dl->verts;
- for (u = 0; u < sizeu; u++) {
- v1 = RE_findOrAddVert(re, re->totvert++); /* save this for possible V wrapping */
- VECCOPY(v1->co, data); data += 3;
- if(orco) {
- v1->orco= orco; orco+= 3; orcoret++;
- }
- MTC_Mat4MulVecfl(mat, v1->co);
+ group->id.flag &= ~LIB_DOIT;
+
+ /* it's a bit too many loops in loops... but will survive */
+ /* note that 'exclusive' will remove it from the global list */
+ for(go= group->gobject.first; go; go= go->next) {
+ go->lampren= NULL;
- for (v = 1; v < sizev; v++) {
- ver= RE_findOrAddVert(re, re->totvert++);
- VECCOPY(ver->co, data); data += 3;
- if(orco) {
- ver->orco= orco; orco+= 3; orcoret++;
- }
- MTC_Mat4MulVecfl(mat, ver->co);
- }
- /* if V-cyclic, add extra vertices at end of the row */
- if (dl->flag & DL_CYCL_U) {
- ver= RE_findOrAddVert(re, re->totvert++);
- VECCOPY(ver->co, v1->co);
- if(orco) {
- ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0);
- }
- }
- }
-
- /* Done before next loop to get corner vert */
- if (dl->flag & DL_CYCL_U) nsizev++;
- if (dl->flag & DL_CYCL_V) nsizeu++;
-
- /* if U cyclic, add extra row at end of column */
- if (dl->flag & DL_CYCL_V) {
- for (v = 0; v < nsizev; v++) {
- v1= RE_findOrAddVert(re, startvert + v);
- ver= RE_findOrAddVert(re, re->totvert++);
- VECCOPY(ver->co, v1->co);
- if(orco) {
- ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v);
+ if(go->ob->lay & re->scene->lay) {
+ if(go->ob && go->ob->type==OB_LAMP) {
+ for(gol= re->lights.first; gol; gol= gol->next) {
+ if(gol->ob==go->ob) {
+ go->lampren= gol->lampren;
+ break;
+ }
+ }
+ if(go->lampren==NULL)
+ gol= add_render_lamp(re, go->ob);
+ if(gol && exclusive) {
+ BLI_remlink(&re->lights, gol);
+ MEM_freeN(gol);
+ }
}
}
}
+}
+
+static void set_material_lightgroups(Render *re)
+{
+ Group *group;
+ Material *ma;
- sizeu = nsizeu;
- sizev = nsizev;
-
- startvlak= re->totvlak;
+ /* not for preview render */
+ if(re->scene->r.scemode & R_PREVIEWBUTS)
+ return;
- for(u = 0; u < sizeu - 1; u++) {
- p1 = startvert + u * sizev; /* walk through face list */
- p2 = p1 + 1;
- p3 = p2 + sizev;
- p4 = p3 - 1;
-
- for(v = 0; v < sizev - 1; v++) {
- v1= RE_findOrAddVert(re, p1);
- v2= RE_findOrAddVert(re, p2);
- v3= RE_findOrAddVert(re, p3);
- v4= RE_findOrAddVert(re, p4);
-
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
-
- flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
- VECCOPY(vlr->n, n1);
-
- vlr->lay= ob->lay;
- vlr->mat= matar[ dl->col];
- vlr->ec= ME_V1V2+ME_V2V3;
- vlr->flag= dl->rt;
- if( (cu->flag & CU_NOPUNOFLIP) ) {
- vlr->flag |= R_NOPUNOFLIP;
- }
-
- VecAddf(v1->n, v1->n, n1);
- VecAddf(v2->n, v2->n, n1);
- VecAddf(v3->n, v3->n, n1);
- VecAddf(v4->n, v4->n, n1);
-
- p1++; p2++; p3++; p4++;
- }
- }
- /* fix normals for U resp. V cyclic faces */
- sizeu--; sizev--; /* dec size for face array */
- if (dl->flag & DL_CYCL_V) {
-
- for (v = 0; v < sizev; v++)
- {
- /* optimize! :*/
- vlr= RE_findOrAddVlak(re, UVTOINDEX(sizeu - 1, v));
- vlr1= RE_findOrAddVlak(re, UVTOINDEX(0, v));
- VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
- VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
- VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
- VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
- }
- }
- if (dl->flag & DL_CYCL_U) {
-
- for (u = 0; u < sizeu; u++)
- {
- /* optimize! :*/
- vlr= RE_findOrAddVlak(re, UVTOINDEX(u, 0));
- vlr1= RE_findOrAddVlak(re, UVTOINDEX(u, sizev-1));
- VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
- VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
- VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
- VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
- }
- }
- /* last vertex is an extra case:
-
- ^ ()----()----()----()
- | | | || |
- u | |(0,n)||(0,0)|
- | | || |
- ()====()====[]====()
- | | || |
- | |(m,n)||(m,0)|
- | | || |
- ()----()----()----()
- v ->
-
- vertex [] is no longer shared, therefore distribute
- normals of the surrounding faces to all of the duplicates of []
- */
+ for(group= G.main->group.first; group; group=group->id.next)
+ group->id.flag |= LIB_DOIT;
- if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U))
- {
- vlr= RE_findOrAddVlak(re, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
- vlr1= RE_findOrAddVlak(re, UVTOINDEX(0,0)); /* (0,0) */
- VecAddf(n1, vlr->n, vlr1->n);
- vlr2= RE_findOrAddVlak(re, UVTOINDEX(0, sizev-1)); /* (0,n) */
- VecAddf(n1, n1, vlr2->n);
- vlr3= RE_findOrAddVlak(re, UVTOINDEX(sizeu-1, 0)); /* (m,0) */
- VecAddf(n1, n1, vlr3->n);
- VECCOPY(vlr->v3->n, n1);
- VECCOPY(vlr1->v1->n, n1);
- VECCOPY(vlr2->v2->n, n1);
- VECCOPY(vlr3->v4->n, n1);
- }
- for(a = startvert; a < re->totvert; a++) {
- ver= RE_findOrAddVert(re, a);
- Normalize(ver->n);
+ /* it's a bit too many loops in loops... but will survive */
+ /* hola! materials not in use...? */
+ for(ma= G.main->mat.first; ma; ma=ma->id.next) {
+ if(ma->group && (ma->group->id.flag & LIB_DOIT))
+ add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY);
}
-
-
- return orcoret;
}
-static void init_render_surf(Render *re, Object *ob)
+static void set_renderlayer_lightgroups(Render *re, Scene *sce)
{
- Nurb *nu=0;
- Curve *cu;
- ListBase displist;
- DispList *dl;
- Material *matar[32];
- float *orco=NULL, *orcobase=NULL, mat[4][4];
- int a, need_orco=0;
-
- cu= ob->data;
- nu= cu->nurb.first;
- if(nu==0) return;
-
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat);
-
- /* material array */
- memset(matar, 0, 4*32);
- matar[0]= give_render_material(re, ob, 0);
- for(a=0; a<ob->totcol; a++) {
- matar[a]= give_render_material(re, ob, a+1);
- if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
- need_orco= 1;
- }
- }
-
- if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
-
- if(need_orco) orcobase= orco= get_object_orco(re, ob);
-
- displist.first= displist.last= 0;
- makeDispListSurf(ob, &displist, 1);
-
- dl= displist.first;
- /* walk along displaylist and create rendervertices/-faces */
- while(dl) {
- /* watch out: u ^= y, v ^= x !! */
- if(dl->type==DL_SURF) {
- orco+= 3*dl_surf_to_renderdata(re, ob, dl, matar, orco, mat);
- }
-
- dl= dl->next;
+ SceneRenderLayer *srl;
+
+ for(srl= sce->r.layers.first; srl; srl= srl->next) {
+ if(srl->light_override)
+ add_lightgroup(re, srl->light_override, 0);
}
- freedisplist(&displist);
}
-static void init_render_curve(Render *re, Object *ob, int only_verts)
-{
- Curve *cu;
- VertRen *ver;
- VlakRen *vlr;
- DispList *dl;
- ListBase olddl={NULL, NULL};
- Material *matar[32];
- float len, *data, *fp, *orco=NULL, *orcobase= NULL;
- float n[3], mat[4][4];
- int nr, startvert, startvlak, a, b;
- int frontside, need_orco=0;
-
- cu= ob->data;
- if(cu->nurb.first==NULL) return;
-
- /* no modifier call here, is in makedisp */
+/* ------------------------------------------------------------------------- */
+/* World */
+/* ------------------------------------------------------------------------- */
- if(cu->resolu_ren)
- SWAP(ListBase, olddl, cu->disp);
-
- /* test displist */
- if(cu->disp.first==NULL)
- makeDispListCurveTypes(ob, 0);
- dl= cu->disp.first;
- if(cu->disp.first==NULL) return;
+void init_render_world(Render *re)
+{
+ int a;
+ char *cp;
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat);
-
- /* material array */
- memset(matar, 0, 4*32);
- matar[0]= give_render_material(re, ob, 0);
- for(a=0; a<ob->totcol; a++) {
- matar[a]= give_render_material(re, ob, a+1);
- if(matar[a]->texco & TEXCO_ORCO) {
- need_orco= 1;
- }
+ if(re->scene && re->scene->world) {
+ re->wrld= *(re->scene->world);
+
+ cp= (char *)&re->wrld.fastcol;
+
+ cp[0]= 255.0*re->wrld.horr;
+ cp[1]= 255.0*re->wrld.horg;
+ cp[2]= 255.0*re->wrld.horb;
+ cp[3]= 1;
+
+ VECCOPY(re->grvec, re->viewmat[2]);
+ Normalize(re->grvec);
+ Mat3CpyMat4(re->imat, re->viewinv);
+
+ for(a=0; a<MAX_MTEX; a++)
+ if(re->wrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX;
+
+ /* AO samples should be OSA minimum */
+ if(re->osa)
+ while(re->wrld.aosamp*re->wrld.aosamp < re->osa)
+ re->wrld.aosamp++;
+ if(!(re->r.mode & R_RAYTRACE))
+ re->wrld.mode &= ~WO_AMB_OCC;
}
-
- if(need_orco) orcobase=orco= get_object_orco(re, ob);
-
- dl= cu->disp.first;
- while(dl) {
- if(dl->type==DL_INDEX3) {
- int *index;
-
- startvert= re->totvert;
- data= dl->verts;
-
- n[0]= ob->imat[0][2];
- n[1]= ob->imat[1][2];
- n[2]= ob->imat[2][2];
- Normalize(n);
-
- for(a=0; a<dl->nr; a++, data+=3) {
- ver= RE_findOrAddVert(re, re->totvert++);
- VECCOPY(ver->co, data);
-
- /* flip normal if face is backfacing, also used in face loop below */
- if(ver->co[2] < 0.0) {
- VECCOPY(ver->n, n);
- ver->flag = 1;
- }
- else {
- ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
- ver->flag = 0;
- }
-
- MTC_Mat4MulVecfl(mat, ver->co);
-
- if (orco) {
- ver->orco = orco;
- orco += 3;
- }
- }
-
- if(only_verts==0) {
- startvlak= re->totvlak;
- index= dl->index;
- for(a=0; a<dl->parts; a++, index+=3) {
-
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob = ob;
- vlr->v1= RE_findOrAddVert(re, startvert+index[0]);
- vlr->v2= RE_findOrAddVert(re, startvert+index[1]);
- vlr->v3= RE_findOrAddVert(re, startvert+index[2]);
- vlr->v4= NULL;
-
- if(vlr->v1->flag) {
- VECCOPY(vlr->n, n);
- }
- else {
- vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
- }
-
- vlr->mat= matar[ dl->col ];
- vlr->flag= 0;
- if( (cu->flag & CU_NOPUNOFLIP) ) {
- vlr->flag |= R_NOPUNOFLIP;
- }
- vlr->ec= 0;
- vlr->lay= ob->lay;
- }
- }
- }
- else if (dl->type==DL_SURF) {
-
- /* cyclic U means an extruded full circular curve, we skip bevel splitting then */
- if (dl->flag & DL_CYCL_U) {
- orco+= 3*dl_surf_to_renderdata(re, ob, dl, matar, orco, mat);
- }
- else {
- int p1,p2,p3,p4;
-
- fp= dl->verts;
- startvert= re->totvert;
- nr= dl->nr*dl->parts;
-
- while(nr--) {
- ver= RE_findOrAddVert(re, re->totvert++);
-
- VECCOPY(ver->co, fp);
- MTC_Mat4MulVecfl(mat, ver->co);
- fp+= 3;
-
- if (orco) {
- ver->orco = orco;
- orco += 3;
- }
- }
-
- if(dl->bevelSplitFlag || only_verts==0) {
- startvlak= re->totvlak;
-
- for(a=0; a<dl->parts; a++) {
-
- frontside= (a >= dl->nr/2);
-
- DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
- p1+= startvert;
- p2+= startvert;
- p3+= startvert;
- p4+= startvert;
-
- for(; b<dl->nr; b++) {
- vlr= RE_findOrAddVlak(re, re->totvlak++);
- vlr->ob= ob;
- vlr->v1= RE_findOrAddVert(re, p2);
- vlr->v2= RE_findOrAddVert(re, p1);
- vlr->v3= RE_findOrAddVert(re, p3);
- vlr->v4= RE_findOrAddVert(re, p4);
- vlr->ec= ME_V2V3+ME_V3V4;
- if(a==0) vlr->ec+= ME_V1V2;
-
- vlr->flag= dl->rt;
- vlr->lay= ob->lay;
-
- /* this is not really scientific: the vertices
- * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
- * front and backside treated different!!
- */
-
- if(frontside)
- CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
- else
- CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
-
- vlr->mat= matar[ dl->col ];
-
- p4= p3;
- p3++;
- p2= p1;
- p1++;
- }
- }
-
- if (dl->bevelSplitFlag) {
- for(a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
- if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
- split_v_renderfaces(re, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
- }
-
- /* vertex normals */
- for(a= startvlak; a<re->totvlak; a++) {
- vlr= RE_findOrAddVlak(re, a);
-
- VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
- VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
- VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
- VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
- }
- for(a=startvert; a<re->totvert; a++) {
- ver= RE_findOrAddVert(re, a);
- len= Normalize(ver->n);
- if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */
- else ver->flag= 0;
- }
- for(a= startvlak; a<re->totvlak; a++) {
- vlr= RE_findOrAddVlak(re, a);
- if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n);
- if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n);
- if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n);
- if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n);
- }
- }
- }
- }
-
- dl= dl->next;
+ else {
+ memset(&re->wrld, 0, sizeof(World));
+ re->wrld.exp= 0.0;
+ re->wrld.range= 1.0;
}
- /* not very elegant... but we want original displist in UI */
- if(cu->resolu_ren) {
- freedisplist(&cu->disp);
- SWAP(ListBase, olddl, cu->disp);
- }
+ re->wrld.linfac= 1.0 + pow((2.0*re->wrld.exp + 0.5), -10);
+ re->wrld.logfac= log( (re->wrld.linfac-1.0)/re->wrld.linfac )/re->wrld.range;
}
+
+
+/* ------------------------------------------------------------------------- */
+/* Object Finalization */
+/* ------------------------------------------------------------------------- */
+
/* prevent phong interpolation for giving ray shadow errors (terminator problem) */
-static void set_phong_threshold(Render *re, Object *ob, int startface, int numface, int startvert, int numvert )
+static void set_phong_threshold(ObjectRen *obr)
{
// VertRen *ver;
VlakRen *vlr;
@@ -3763,8 +3632,8 @@ static void set_phong_threshold(Render *re, Object *ob, int startface, int numfa
are taken into account. This threshold is meant to work on smooth geometry, not
for extreme cases (ton) */
- for(i=startface; i<startface+numface; i++) {
- vlr= RE_findOrAddVlak(re, i);
+ for(i=0; i<obr->totvlak; i++) {
+ vlr= RE_findOrAddVlak(obr, i);
if(vlr->flag & R_SMOOTH) {
dot= INPR(vlr->n, vlr->v1->n);
dot= ABS(dot);
@@ -3795,175 +3664,13 @@ static void set_phong_threshold(Render *re, Object *ob, int startface, int numfa
if(tot) {
thresh/= (float)tot;
- ob->smoothresh= cos(0.5*M_PI-saacos(thresh));
- }
-}
-
-/* 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 double lasttime= 0.0;
- double time;
- float mat[4][4];
- int startface, startvert, startstrand, allow_render=1;
-
- startface=re->totvlak;
- startvert=re->totvert;
- startstrand=re->totstrand;
-
- ob->flag |= OB_DONE;
-
- /* the emitter has to be processed first (render levels of modifiers) */
- /* so here we only check if the emitter should be rendered */
- if(ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
- int showe = 0;
- for(; psys; psys=psys->next)
- showe += psys->part->draw & PART_DRAW_EMITTER;
-
- /* if no psys has "show emitter" selected don't render emitter */
- if(showe==0) allow_render = 0;
- }
-
- if(allow_render) {
- if(ob->type==OB_LAMP)
- add_render_lamp(re, ob);
- else if ELEM(ob->type, OB_FONT, OB_CURVE)
- init_render_curve(re, ob, only_verts);
- else if(ob->type==OB_SURF)
- init_render_surf(re, ob);
- else if(ob->type==OB_MESH)
- init_render_mesh(re, ob, par, only_verts);
- else if(ob->type==OB_MBALL)
- init_render_mball(re, ob);
- else {
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat);
- }
- }
-
- if(ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
- DerivedMesh *dm = 0;
-
- /* the emitter mesh wasn't rendered so the modifier stack wasn't evaluated with render settings */
- if(allow_render==0 && ob->type==OB_MESH)
- dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
-
- for(; psys; psys=psys->next) {
- render_new_particle_system(re, ob, psys);
- psys_free_render_memory(ob, psys);
- }
-
- if(dm)
- dm->release(dm);
- }
-
- /* generic post process here */
- if(startvert!=re->totvert || startstrand!=re->totstrand)
- RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak, startstrand, re->totstrand);
-
- if(startvert!=re->totvert) {
- /* the exception below is because displace code now is in init_render_mesh call,
- I will look at means to have autosmooth enabled for all object types
- and have it as general postprocess, like displace */
- if (ob->type!=OB_MESH && test_for_displace(re, ob ) )
- do_displacement(re, ob, startface, re->totvlak-startface, startvert, re->totvert-startvert);
-
- /* phong normal interpolation can cause error in tracing (terminator prob) */
- ob->smoothresh= 0.0;
- if( (re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW) )
- set_phong_threshold(re, ob, startface, re->totvlak-startface, startvert, re->totvert-startvert);
- }
-
- time= PIL_check_seconds_timer();
- if(time - lasttime > 1.0) {
- lasttime= time;
- /* clumsy copying still */
- re->i.totvert= re->totvert;
- re->i.totface= re->totvlak;
- re->i.totstrand= re->totstrand;
- re->i.tothalo= re->tothalo;
- re->i.totlamp= re->totlamp;
- re->stats_draw(&re->i);
- }
-}
-
-void RE_Database_Free(Render *re)
-{
- Object *ob = NULL;
- LampRen *lar;
-
- /* FREE */
-
- for(lar= re->lampren.first; lar; lar= lar->next) {
- freeshadowbuf(lar);
- if(lar->jitter) MEM_freeN(lar->jitter);
- if(lar->shadsamp) MEM_freeN(lar->shadsamp);
- if(lar->qsa) free_lamp_qmcsampler(lar);
- curvemapping_free(lar->curfalloff);
- }
-
- BLI_freelistN(&re->lampren);
- BLI_freelistN(&re->lights);
-
- free_renderdata_tables(re);
-
- /* free orco. check all objects because of duplis and sets */
- ob= G.main->object.first;
- while(ob) {
- if(ob->type==OB_MBALL) {
- if(ob->disp.first && ob->disp.first!=ob->disp.last) {
- DispList *dl= ob->disp.first;
- BLI_remlink(&ob->disp, dl);
- freedisplist(&ob->disp);
- BLI_addtail(&ob->disp, dl);
- }
- }
- ob= ob->id.next;
- }
-
- free_mesh_orco_hash(re);
-
- end_radio_render();
- end_render_materials();
-
- if(re->wrld.aosphere) {
- MEM_freeN(re->wrld.aosphere);
- re->wrld.aosphere= NULL;
- re->scene->world->aosphere= NULL;
- }
- if(re->wrld.aotables) {
- MEM_freeN(re->wrld.aotables);
- re->wrld.aotables= NULL;
- re->scene->world->aotables= NULL;
- }
- if((re->r.mode & R_RAYTRACE) && (re->wrld.mode & WO_AMB_OCC) &&
- (re->wrld.ao_samp_method == WO_AOSAMP_HAMMERSLEY) && (re->qsa))
- free_render_qmcsampler(re);
-
- if(re->r.mode & R_RAYTRACE) freeraytree(re);
-
- free_sss(re);
-
- re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
- re->i.convertdone= 0;
-
- if(re->scene)
- if(re->scene->r.scemode & R_FREE_IMAGE)
- if((re->r.scemode & R_PREVIEWBUTS)==0)
- BKE_image_free_all_textures();
-
- if(re->memArena) {
- BLI_memarena_free(re->memArena);
- re->memArena = NULL;
+ obr->ob->smoothresh= cos(0.5*M_PI-saacos(thresh));
}
}
/* per face check if all samples should be taken.
if raytrace, do always for raytraced material, or when material full_osa set */
-static void set_fullsample_flag(Render *re)
+static void set_fullsample_flag(Render *re, ObjectRen *obr)
{
VlakRen *vlr;
int a, trace;
@@ -3973,8 +3680,8 @@ static void set_fullsample_flag(Render *re)
trace= re->r.mode & R_RAYTRACE;
- for(a=re->totvlak-1; a>=0; a--) {
- vlr= RE_findOrAddVlak(re, a);
+ for(a=obr->totvlak-1; a>=0; a--) {
+ vlr= RE_findOrAddVlak(obr, a);
if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA;
else if(trace) {
@@ -3988,15 +3695,15 @@ static void set_fullsample_flag(Render *re)
}
}
-static void check_non_flat_quads(Render *re)
+static void check_non_flat_quads(ObjectRen *obr)
{
VlakRen *vlr, *vlr1;
VertRen *v1, *v2, *v3, *v4;
float nor[3], xn, flen;
int a;
- for(a=re->totvlak-1; a>=0; a--) {
- vlr= RE_findOrAddVlak(re, a);
+ for(a=obr->totvlak-1; a>=0; a--) {
+ vlr= RE_findOrAddVlak(obr, a);
/* test if rendering as a quad or triangle, skip wire */
if(vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->mode & MA_WIRE)==0) {
@@ -4052,7 +3759,7 @@ static void check_non_flat_quads(Render *re)
if(ABS(xn) < 0.999995 ) { // checked on noisy fractal grid
float d1, d2;
- vlr1= RE_vlakren_copy(re, vlr);
+ vlr1= RE_vlakren_copy(obr, vlr);
vlr1->flag |= R_FACE_SPLIT;
/* split direction based on vnorms */
@@ -4095,112 +3802,362 @@ static void check_non_flat_quads(Render *re)
}
}
-/* layflag: allows material group to ignore layerflag */
-static void add_lightgroup(Render *re, Group *group, int exclusive)
+static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts)
{
- GroupObject *go, *gol;
-
- group->id.flag &= ~LIB_DOIT;
+ Object *ob= obr->ob;
- /* it's a bit too many loops in loops... but will survive */
- /* note that 'exclusive' will remove it from the global list */
- for(go= group->gobject.first; go; go= go->next) {
- go->lampren= NULL;
-
- if(go->ob->lay & re->scene->lay) {
- if(go->ob && go->ob->type==OB_LAMP) {
- for(gol= re->lights.first; gol; gol= gol->next) {
- if(gol->ob==go->ob) {
- go->lampren= gol->lampren;
- break;
- }
- }
- if(go->lampren==NULL)
- gol= add_render_lamp(re, go->ob);
- if(gol && exclusive) {
- BLI_remlink(&re->lights, gol);
- MEM_freeN(gol);
- }
- }
+ if(obr->totvert || obr->totvlak || obr->tothalo || obr->totstrand) {
+ /* the exception below is because displace code now is in init_render_mesh call,
+ I will look at means to have autosmooth enabled for all object types
+ and have it as general postprocess, like displace */
+ if(ob->type!=OB_MESH && test_for_displace(re, ob))
+ do_displacement(re, obr);
+
+ if(!only_verts) {
+ /* phong normal interpolation can cause error in tracing
+ * (terminator problem) */
+ ob->smoothresh= 0.0;
+ if((re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW))
+ set_phong_threshold(obr);
+
+ check_non_flat_quads(obr);
+ set_fullsample_flag(re, obr);
}
}
}
-static void set_material_lightgroups(Render *re)
+/* ------------------------------------------------------------------------- */
+/* Database */
+/* ------------------------------------------------------------------------- */
+
+static int render_object_type(int type)
{
- Group *group;
- Material *ma;
-
- /* not for preview render */
- if(re->scene->r.scemode & R_PREVIEWBUTS)
- return;
-
- for(group= G.main->group.first; group; group=group->id.next)
- group->id.flag |= LIB_DOIT;
+ return ELEM5(type, OB_FONT, OB_CURVE, OB_SURF, OB_MESH, OB_MBALL);
+}
+
+static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts)
+{
+ Object *ob= obr->ob;
+ ParticleSystem *psys;
+ int i;
+
+ if(obr->psysindex) {
+ if((!obr->prev || obr->prev->ob != ob) && ob->type==OB_MESH) {
+ /* the emitter mesh wasn't rendered so the modifier stack wasn't
+ * evaluated with render settings */
+ DerivedMesh *dm;
+ dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+ dm->release(dm);
+ }
+
+ for(psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++)
+ psys= psys->next;
+
+ render_new_particle_system(re, obr, psys);
+ psys_free_render_memory(ob, psys);
+ }
+ else {
+ if ELEM(ob->type, OB_FONT, OB_CURVE)
+ init_render_curve(re, obr, only_verts);
+ else if(ob->type==OB_SURF)
+ init_render_surf(re, obr);
+ else if(ob->type==OB_MESH)
+ init_render_mesh(re, obr, only_verts);
+ else if(ob->type==OB_MBALL)
+ init_render_mball(re, obr);
+ }
+
+ finalize_render_object(re, obr, only_verts);
- /* it's a bit too many loops in loops... but will survive */
- /* hola! materials not in use...? */
- for(ma= G.main->mat.first; ma; ma=ma->id.next) {
- if(ma->group && (ma->group->id.flag & LIB_DOIT))
- add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY);
+ re->totvert += obr->totvert;
+ re->totvlak += obr->totvlak;
+ re->tothalo += obr->tothalo;
+ re->totstrand += obr->totstrand;
+}
+
+static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts)
+{
+ ObjectRen *obr;
+ ParticleSystem *psys;
+ int show_emitter, allow_render= 1, psysindex;
+
+ /* the emitter has to be processed first (render levels of modifiers) */
+ /* so here we only check if the emitter should be rendered */
+ if(ob->particlesystem.first) {
+ show_emitter= 0;
+ for(psys=ob->particlesystem.first; psys; psys=psys->next)
+ show_emitter += psys->part->draw & PART_DRAW_EMITTER;
+
+ /* if no psys has "show emitter" selected don't render emitter */
+ if(show_emitter == 0)
+ allow_render= 0;
+ }
+
+ /* one render object for the data itself */
+ if(allow_render) {
+ obr= RE_addRenderObject(re, ob, par, index, 0);
+ init_render_object_data(re, obr, only_verts);
+
+ /* only add instance for objects that have not been used for dupli */
+ if(!(ob->transflag & OB_RENDER_DUPLI))
+ RE_addRenderInstance(re, obr, ob, par, index, 0, NULL);
+ }
+
+ /* and one render object per particle system */
+ if(ob->particlesystem.first) {
+ psysindex= 1;
+ for(psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
+ obr= RE_addRenderObject(re, ob, par, index, psysindex);
+ init_render_object_data(re, obr, only_verts);
+
+ /* only add instance for objects that have not been used for dupli */
+ if(!(ob->transflag & OB_RENDER_DUPLI))
+ RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL);
+ }
}
}
-static void set_renderlayer_lightgroups(Render *re, Scene *sce)
+/* 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)
{
- SceneRenderLayer *srl;
+ static double lasttime= 0.0;
+ double time;
+ float mat[4][4];
+
+ 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);
+ else {
+ MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ }
- for(srl= sce->r.layers.first; srl; srl= srl->next) {
- if(srl->light_override)
- add_lightgroup(re, srl->light_override, 0);
+ time= PIL_check_seconds_timer();
+ if(time - lasttime > 1.0) {
+ lasttime= time;
+ /* clumsy copying still */
+ re->i.totvert= re->totvert;
+ re->i.totface= re->totvlak;
+ re->i.totstrand= re->totstrand;
+ re->i.tothalo= re->tothalo;
+ re->i.totlamp= re->totlamp;
+ re->stats_draw(&re->i);
}
+
+ ob->flag |= OB_DONE;
}
-void init_render_world(Render *re)
+void RE_Database_Free(Render *re)
{
- int a;
- char *cp;
+ Object *ob = NULL;
+ LampRen *lar;
+
+ /* FREE */
- if(re->scene && re->scene->world) {
- re->wrld= *(re->scene->world);
-
- cp= (char *)&re->wrld.fastcol;
-
- cp[0]= 255.0*re->wrld.horr;
- cp[1]= 255.0*re->wrld.horg;
- cp[2]= 255.0*re->wrld.horb;
- cp[3]= 1;
-
- VECCOPY(re->grvec, re->viewmat[2]);
- Normalize(re->grvec);
- Mat3CpyMat4(re->imat, re->viewinv);
-
- for(a=0; a<MAX_MTEX; a++)
- if(re->wrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX;
-
- /* AO samples should be OSA minimum */
- if(re->osa)
- while(re->wrld.aosamp*re->wrld.aosamp < re->osa)
- re->wrld.aosamp++;
- if(!(re->r.mode & R_RAYTRACE))
- re->wrld.mode &= ~WO_AMB_OCC;
+ for(lar= re->lampren.first; lar; lar= lar->next) {
+ freeshadowbuf(lar);
+ if(lar->jitter) MEM_freeN(lar->jitter);
+ if(lar->shadsamp) MEM_freeN(lar->shadsamp);
+ if(lar->qsa) free_lamp_qmcsampler(lar);
+ curvemapping_free(lar->curfalloff);
}
- else {
- memset(&re->wrld, 0, sizeof(World));
- re->wrld.exp= 0.0;
- re->wrld.range= 1.0;
+
+ BLI_freelistN(&re->lampren);
+ BLI_freelistN(&re->lights);
+
+ free_renderdata_tables(re);
+
+ /* free orco. check all objects because of duplis and sets */
+ ob= G.main->object.first;
+ while(ob) {
+ if(ob->type==OB_MBALL) {
+ if(ob->disp.first && ob->disp.first!=ob->disp.last) {
+ DispList *dl= ob->disp.first;
+ BLI_remlink(&ob->disp, dl);
+ freedisplist(&ob->disp);
+ BLI_addtail(&ob->disp, dl);
+ }
+ }
+ ob= ob->id.next;
+ }
+
+ free_mesh_orco_hash(re);
+
+ end_radio_render();
+ end_render_materials();
+
+ if(re->wrld.aosphere) {
+ MEM_freeN(re->wrld.aosphere);
+ re->wrld.aosphere= NULL;
+ re->scene->world->aosphere= NULL;
}
+ if(re->wrld.aotables) {
+ MEM_freeN(re->wrld.aotables);
+ re->wrld.aotables= NULL;
+ re->scene->world->aotables= NULL;
+ }
+ if((re->r.mode & R_RAYTRACE) && (re->wrld.mode & WO_AMB_OCC) &&
+ (re->wrld.ao_samp_method == WO_AOSAMP_HAMMERSLEY) && (re->qsa))
+ free_render_qmcsampler(re);
- re->wrld.linfac= 1.0 + pow((2.0*re->wrld.exp + 0.5), -10);
- re->wrld.logfac= log( (re->wrld.linfac-1.0)/re->wrld.linfac )/re->wrld.range;
+ if(re->r.mode & R_RAYTRACE) freeraytree(re);
+
+ free_sss(re);
+
+ re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
+ re->i.convertdone= 0;
+
+ if(re->scene)
+ if(re->scene->r.scemode & R_FREE_IMAGE)
+ if((re->r.scemode & R_PREVIEWBUTS)==0)
+ BKE_image_free_all_textures();
+
+ if(re->memArena) {
+ BLI_memarena_free(re->memArena);
+ re->memArena = NULL;
+ }
+}
+
+static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object *actob)
+{
+ /* override not showing object when duplis are used with particles */
+ if(ob->transflag & OB_DUPLIPARTS){
+ int allow= 0;
+
+ if(ob->particlesystem.first) {
+ ParticleSystem *psys;
+ ParticleSettings *part;
+
+ for(psys=ob->particlesystem.first; psys; psys=psys->next){
+ part=psys->part;
+
+ if((part->draw_as==PART_DRAW_OB && part->dup_ob) || (part->draw_as==PART_DRAW_GR && part->dup_group))
+ if(part->draw & PART_DRAW_EMITTER)
+ allow= 1;
+ }
+ }
+
+ if(!allow)
+ return 0;
+ }
+ else if(ob->transflag & OB_DUPLI)
+ return 0;
+
+ if(nolamps && (ob->type==OB_LAMP))
+ return 0;
+
+ if(onlyselected && (ob!=actob && !(ob->flag & SELECT)))
+ return 0;
+
+ return 1;
+}
+
+static int allow_render_dupli_instance(Render *re, Object *ob, Object *obd)
+{
+ return (render_object_type(obd->type) &&
+ (!(ob->transflag & OB_DUPLIGROUP)) &&
+ !(re->r.mode & R_RADIO));
+}
+
+static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int only_verts)
+{
+ Base *base;
+ Object *ob;
+ Scene *sce;
+ float mat[4][4];
+
+ for(SETLOOPER(re->scene, base)) {
+ ob= base->object;
+ /* imat objects has to be done here, since displace can have texture using Object map-input */
+ MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+ MTC_Mat4Invert(ob->imat, mat);
+ /* each object should only be rendered once */
+ ob->flag &= ~OB_DONE;
+ ob->transflag &= ~OB_RENDER_DUPLI;
+ }
+
+ for(SETLOOPER(re->scene, base)) {
+ ob= base->object;
+
+ /* if the object has been restricted from rendering in the outliner, ignore it */
+ if(ob->restrictflag & OB_RESTRICT_RENDER) continue;
+
+ /* 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))
+ init_render_object(re, ob, NULL, 0, only_verts);
+ }
+ else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) {
+ if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
+ DupliObject *dob;
+ ListBase *lb;
+
+ lb= object_duplilist(sce, ob);
+ for(dob= lb->first; dob; dob= dob->next) {
+ Object *obd= dob->ob;
+
+ Mat4CpyMat4(obd->obmat, dob->mat);
+
+ /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
+ if(dob->no_draw)
+ continue;
+
+ if(obd->restrictflag & OB_RESTRICT_RENDER)
+ continue;
+
+ if(obd->type==OB_MBALL)
+ continue;
+
+ if(!allow_render_object(obd, nolamps, onlyselected, actob))
+ continue;
+
+ if(allow_render_dupli_instance(re, ob, obd)) {
+ ParticleSystem *psys;
+ int psysindex;
+ float imat[4][4], mat[4][4];
+
+ /* compute difference between object matrix and
+ * object matrix with dupli transform, in viewspace */
+ Mat4Invert(imat, dob->omat);
+ MTC_Mat4MulSerie(mat, re->viewmat, dob->mat, imat, re->viewinv, 0, 0, 0, 0);
+
+ RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat);
+
+ psysindex= 1;
+ for(psys=obd->particlesystem.first; psys; psys=psys->next)
+ RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat);
+
+ obd->flag |= OB_DONE;
+ obd->transflag |= OB_RENDER_DUPLI;
+ }
+ else
+ init_render_object(re, obd, ob, dob->index, only_verts);
+
+ 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);
+ }
+ else if(allow_render_object(ob, nolamps, onlyselected, actob))
+ init_render_object(re, ob, NULL, 0, only_verts);
+ }
+
+ if(re->test_break()) break;
+ }
+
+ if(!re->test_break())
+ RE_makeRenderInstances(re);
}
/* used to be 'rotate scene' */
void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
{
extern int slurph_opt; /* key.c */
- Base *base;
- Object *ob;
Scene *sce;
float mat[4][4];
unsigned int lay;
@@ -4248,166 +4205,13 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
init_render_materials(re->r.mode, &re->wrld.ambr);
set_node_shader_lamp_loop(shade_material_loop);
- for(SETLOOPER(re->scene, base)) {
- ob= base->object;
- /* imat objects has to be done here, since displace can have texture using Object map-input */
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat);
- /* each object should only be rendered once */
- ob->flag &= ~OB_DONE;
- }
-
/* MAKE RENDER DATA */
-
- for(SETLOOPER(re->scene, base)) {
- ob= base->object;
-
- /* if the object has been restricted from rendering in the outliner, ignore it */
- if (ob->restrictflag & OB_RESTRICT_RENDER) continue;
-
- /* OB_DONE means the object itself got duplicated, so was already converted */
- if (ob->flag & OB_DONE) {
-#ifndef DISABLE_YAFRAY
- /* yafray: for some reason this part was removed, but yafray really needs it...
- Dupliverts objects are treated as instances of an original 'sourceobject',
- which needs to be included in the renderlist here.
- exception: lamps, lattices, armatures & camera's */
- if ((re->r.renderer==R_YAFRAY) && ((ob->type!=OB_LATTICE) && (ob->type!=OB_ARMATURE) &&
- (ob->type!=OB_LAMP) && (ob->type!=OB_CAMERA)))
- {
- printf("Duplivert object %s, adding to renderlist\n", ob->id.name);
- ob->flag &= ~OB_DONE;
- init_render_object(re, ob, NULL, 0, 0);
- ob->flag |= OB_DONE;
- }
-#endif /* disable yafray */
- }
- else if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) {
- int pdup=0;
- if(ob->transflag & OB_DUPLI) {
-
- /* exception: mballs! */
-#ifndef DISABLE_YAFRAY
- /* yafray: except for mballs, include at least one copy of a dupliframe object in the renderlist. */
- if (re->r.renderer==R_YAFRAY) {
- if ((ob->type!=OB_MBALL) && ((ob->transflag & OB_DUPLIFRAMES)!=0)) {
- printf("Dupliframe Object %s, adding to renderlist\n", ob->id.name);
- init_render_object(re, ob, NULL, 0, 0);
- }
- }
-#endif /* disable yafray */
- /* before make duplis, update particle for current frame */
- if(ob->transflag & OB_DUPLIVERTS) {
- PartEff *paf= give_parteff(ob);
- if(paf) {
- if(paf->flag & PAF_ANIMATED) build_particle_system(ob);
- }
- }
- if(ob->transflag & OB_DUPLIPARTS){
- if(ob->particlesystem.first){
- ParticleSystem *psys = ob->particlesystem.first;
- ParticleSettings *part;
-
- for(; psys; psys=psys->next){
- part=psys->part;
+ database_init_objects(re, lay, 0, 0, 0, 0);
- if((part->draw_as==PART_DRAW_OB && part->dup_ob) || (part->draw_as==PART_DRAW_GR && part->dup_group))
- if(part->draw & PART_DRAW_EMITTER)
- pdup++;
- }
- }
- }
-
- if(ob->type==OB_MBALL) {
- init_render_object(re, ob, NULL, 0, 0);
- }
- else {
- DupliObject *dob;
- ListBase *lb= object_duplilist(sce, ob);
-
- for(dob= lb->first; dob; dob= dob->next) {
- Object *obd= dob->ob;
-
- if (obd->restrictflag & OB_RESTRICT_RENDER) continue;
-
- Mat4CpyMat4(obd->obmat, dob->mat);
-
- /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */
- if(dob->no_draw)
- continue;
-
- if(obd->type!=OB_MBALL) {
-#ifndef DISABLE_YAFRAY
- /* yafray: special case handling of duplivert/dupligroup objects.
- Only one copy included in renderlist(see above), all others treated as instance of that.
- So only need to store name and matrix. Exception are lamps. lattices, armatures and camera's */
- if (re->r.renderer==R_YAFRAY) {
- /* dupligroup obs are included directly */
- if (obd->flag & OB_FROMGROUP) {
- printf("Dupligroup object %s, adding to renderlist\n", obd->id.name);
- init_render_object(re, obd, ob, dob->index, 0);
- }
- else if ((obd->type!=OB_LATTICE) && (obd->type!=OB_ARMATURE) &&
- (obd->type!=OB_LAMP) && (obd->type!=OB_CAMERA))
- {
- printf("Adding dupli matrix for object %s\n", obd->id.name);
- YAF_addDupliMtx(obd);
- }
- else init_render_object(re, obd, ob, dob->index, 0);
- }
- else init_render_object(re, obd, ob, dob->index, 0);
-#else
- init_render_object(re, obd, ob, dob->index, 0);
-#endif /* disable yafray */
- }
-
- if(re->test_break()) break;
- }
- free_object_duplilist(lb);
- }
- }
- else {
-#ifndef DISABLE_YAFRAY
- /* yafray: linked data objects treated similarly to dupliverts,
- If object not known yet (not in renderlist), include in the renderlist,
- otherwise treat as instance of it, so only name and matrix are stored
- Exception: objects which have materials linked to object instead of mesh */
- if ((re->r.renderer==R_YAFRAY) && (ob->colbits==0))
- {
- /* Special case, parent object dupli's: ignore if object itself is lamp or parent is lattice or empty */
- if (ob->parent) {
- if ((ob->type!=OB_LAMP) && (ob->parent->type!=OB_EMPTY) &&
- (ob->parent->type!=OB_LATTICE) && YAF_objectKnownData(ob))
- printf("From parent: Added dupli matrix for linked data object %s\n", ob->id.name);
- else
- init_render_object(re, ob, NULL, 0, 0);
- }
- else if ((ob->type!=OB_EMPTY) && (ob->type!=OB_LAMP) &&
- (ob->type!=OB_ARMATURE) && YAF_objectKnownData(ob))
- printf("Added dupli matrix for linked data object %s\n", ob->id.name);
- else
- init_render_object(re, ob, NULL, 0, 0);
- }
- else init_render_object(re, ob, NULL, 0, 0);
-#else
- init_render_object(re, ob, NULL, 0, 0);
-#endif /* disable yafray */
- }
-
- /* override not showing object when duplis are used with particles */
- if(pdup)
- init_render_object(re, ob, NULL, 0, 0);
- }
-
- if(re->test_break()) break;
- }
-
-
if(!re->test_break()) {
LampRen *lar;
-
- sort_halos(re);
-
+ int tothalo;
+
set_material_lightgroups(re);
for(sce= re->scene; sce; sce= sce->set)
set_renderlayer_lightgroups(re, sce);
@@ -4422,13 +4226,12 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
re->i.totlamp= re->totlamp;
re->stats_draw(&re->i);
- set_fullsample_flag(re);
- check_non_flat_quads(re);
- set_normalflags(re);
-
+ /* don't sort stars */
+ tothalo= re->tothalo;
if(!re->test_break())
- if(re->wrld.mode & WO_STARS)
+ if(re->wrld.mode & WO_STARS)
RE_make_stars(re, NULL, NULL, NULL);
+ sort_halos(re, tothalo);
re->i.infostr= "Creating Shadowbuffers";
re->stats_draw(&re->i);
@@ -4478,12 +4281,24 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
re->stats_draw(&re->i);
}
+/* exported call to recalculate hoco for vertices, when winmat changed */
+void RE_DataBase_ApplyWindow(Render *re)
+{
+ project_renderdata(re, projectverto, 0, 0, 0);
+}
+
+void RE_DataBase_GetView(Render *re, float mat[][4])
+{
+ Mat4CpyMat4(mat, re->viewmat);
+}
+
+/* ------------------------------------------------------------------------- */
+/* Speed Vectors */
+/* ------------------------------------------------------------------------- */
+
static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset)
{
extern int slurph_opt; /* key.c */
- Base *base;
- Object *ob;
- Scene *sce;
float mat[4][4];
unsigned int lay;
@@ -4513,62 +4328,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset)
RE_SetView(re, mat);
}
- for(SETLOOPER(re->scene, base)) {
- ob= base->object;
- /* imat objects has to be done here, since displace can have texture using Object map-input */
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat);
- /* each object should only be rendered once */
- ob->flag &= ~OB_DONE;
- }
-
/* MAKE RENDER DATA */
-
- for(SETLOOPER(re->scene, base)) {
- ob= base->object;
-
- if (ob->restrictflag & OB_RESTRICT_RENDER) continue;
-
- /* OB_DONE means the object itself got duplicated, so was already converted */
- if(ob->flag & OB_DONE);
- else if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) {
- if(ob->transflag & OB_DUPLI) {
-
- /* before make duplis, update particle for current frame */
- if(ob->transflag & OB_DUPLIVERTS) {
- PartEff *paf= give_parteff(ob);
- if(paf) {
- if(paf->flag & PAF_ANIMATED) build_particle_system(ob);
- }
- }
-
- if(ob->type==OB_MBALL) {
- init_render_object(re, ob, NULL, 0, 1);
- }
- else {
- DupliObject *dob;
- ListBase *lb= object_duplilist(sce, ob);
-
- for(dob= lb->first; dob; dob= dob->next) {
- Object *obd= dob->ob;
-
- if (obd->restrictflag & OB_RESTRICT_RENDER) continue;
-
- Mat4CpyMat4(obd->obmat, dob->mat);
-
- if(obd->type!=OB_MBALL) {
- init_render_object(re, obd, ob, dob->index, 1);
- }
- }
- free_object_duplilist(lb);
- }
- }
- else {
- init_render_object(re, ob, NULL, 0, 1);
- }
- }
- if(re->test_break()) break;
- }
+ database_init_objects(re, lay, 0, 0, 0, 1);
if(!re->test_break())
project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
@@ -4663,58 +4424,54 @@ static void calculate_speedvector(float *vectors, int step, float winsq, float w
}
}
-static void calculate_speedvectors(Render *re, ObjectRen *obren, float *vectors, int step)
+static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step)
{
+ ObjectRen *obr= obi->obr;
VertRen *ver= NULL;
StrandRen *strand= NULL;
- float *speed, ho[4];
+ float *speed, ho[4], winmat[4][4];
float winsq= re->winx*re->winy, winroot= sqrt(winsq);
- int a, startvert, endvert, startstrand, endstrand;
+ int a;
- startvert= obren->startvert;
- endvert= obren->endvert;
- startstrand= obren->startstrand;
- endstrand= obren->endstrand;
-
- if(re->vertnodes) {
- /* set first vertex OK */
- a= startvert-1;
- ver= re->vertnodes[a>>8].vert + (a & 255);
-
- for(a=startvert; a<endvert; a++, vectors+=2) {
- if((a & 255)==0) ver= re->vertnodes[a>>8].vert;
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(winmat, obi->mat, re->winmat);
+ else
+ Mat4CpyMat4(winmat, re->winmat);
+
+ if(obr->vertnodes) {
+ for(a=0; a<obr->totvert; a++, vectors+=2) {
+ if((a & 255)==0) ver= obr->vertnodes[a>>8].vert;
else ver++;
- speed= RE_vertren_get_winspeed(re, ver, 1);
- calculate_speedvector(vectors, step, winsq, winroot, ver->co, ver->ho, speed);
+ speed= RE_vertren_get_winspeed(obi, ver, 1);
+ projectvert(ver->co, winmat, ho);
+ calculate_speedvector(vectors, step, winsq, winroot, ver->co, ho, speed);
}
}
- if(re->strandnodes) {
- /* set first strand OK */
- a= startstrand-1;
- strand= re->strandnodes[a>>8].strand + (a & 255);
-
- for(a=startstrand; a<endstrand; a++, vectors+=2) {
- if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
+ if(obr->strandnodes) {
+ for(a=0; a<obr->totstrand; a++, vectors+=2) {
+ if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
else strand++;
- speed= RE_strandren_get_winspeed(re, strand, 1);
- projectverto(strand->vert->co, re->winmat, ho);
+ speed= RE_strandren_get_winspeed(obi, strand, 1);
+ projectvert(strand->vert->co, winmat, ho);
calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed);
}
}
}
-static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, int endvert, int step, Object *fsob)
+static int load_fluidsimspeedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step)
{
+ ObjectRen *obr= obi->obr;
+ Object *fsob= obr->ob;
VertRen *ver= NULL;
float *speed, div, zco[2];
float zmulx= re->winx/2, zmuly= re->winy/2, len;
float winsq= re->winx*re->winy, winroot= sqrt(winsq);
int a, j;
- float hoco[4], fsvec[4], camco[4];
- float mat[4][4];
+ float hoco[4], ho[4], fsvec[4], camco[4];
+ float mat[4][4], winmat[4][4];
float imat[4][4];
MVert *vverts;
@@ -4725,28 +4482,30 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert,
MTC_Mat4Invert(imat, mat);
/* set first vertex OK */
- a= startvert-1;
- ver= re->vertnodes[a>>8].vert + (a & 255);
-
if( (!fsob->fluidsimSettings) || (!fsob->fluidsimSettings->meshSurfNormals) ) return 0;
vverts = fsob->fluidsimSettings->meshSurfNormals;
//fprintf(stderr, "GZ_VEL obj '%s', calc load_fluidsimspeedvectors\n",fsob->id.name); // NT DEBUG
- if( endvert-startvert != fsob->fluidsimSettings->meshSurface->totvert ) {
- //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", endvert-startvert , fsob->fluidsimSettings->meshSurface->totvert); // DEBUG
+ if( obr->totvert != fsob->fluidsimSettings->meshSurface->totvert ) {
+ //fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", obr->totvert, fsob->fluidsimSettings->meshSurface->totvert); // DEBUG
return 0;
}
+
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(winmat, obi->mat, re->winmat);
+ else
+ Mat4CpyMat4(winmat, re->winmat);
- for(a=startvert; a<endvert; a++, vectors+=2) {
+ for(a=0; a<obr->totvert; a++, vectors+=2) {
if((a & 255)==0)
- ver= re->vertnodes[a>>8].vert;
+ ver= obr->vertnodes[a>>8].vert;
else
ver++;
// get fluid velocity
fsvec[3] = 0.;
//fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.; fsvec[2] = 2.; // NT fixed test
- for(j=0;j<3;j++) fsvec[j] = vverts[a-startvert].co[j];
+ for(j=0;j<3;j++) fsvec[j] = vverts[a].co[j];
// transform (=rotate) to cam space
camco[0]= imat[0][0]*fsvec[0] + imat[0][1]*fsvec[1] + imat[0][2]*fsvec[2];
@@ -4754,12 +4513,13 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert,
camco[2]= imat[2][0]*fsvec[0] + imat[2][1]*fsvec[1] + imat[2][2]*fsvec[2];
// get homogenous coordinates
- projectverto(camco, re->winmat, hoco);
+ projectvert(camco, winmat, hoco);
+ projectvert(ver->co, winmat, ho);
/* now map hocos to screenspace, uses very primitive clip still */
// use ho[3] of original vertex, xy component of vel. direction
- if(ver->ho[3]<0.1f) div= 10.0f;
- else div= 1.0f/ver->ho[3];
+ if(ho[3]<0.1f) div= 10.0f;
+ else div= 1.0f/ho[3];
zco[0]= zmulx*hoco[0]*div;
zco[1]= zmuly*hoco[1]*div;
@@ -4770,7 +4530,7 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert,
zco[0]*= len; zco[1]*= len;
}
- speed= RE_vertren_get_winspeed(re, ver, 1);
+ speed= RE_vertren_get_winspeed(obi, ver, 1);
// set both to the same value
speed[0]= speed[2]= zco[0];
speed[1]= speed[3]= zco[1];
@@ -4784,47 +4544,44 @@ static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert,
/* result should be that we can free entire database */
static void copy_dbase_object_vectors(Render *re, ListBase *lb)
{
- ObjectRen *obren, *obrenlb;
- VertRen *ver;
- StrandRen *strand;
- float *vec, ho[4];
+ ObjectInstanceRen *obi, *obilb;
+ ObjectRen *obr;
+ VertRen *ver= NULL;
+ StrandRen *strand= NULL;
+ float *vec, ho[4], winmat[4][4];
int a, totvector;
- for(obren= re->objecttable.first; obren; obren= obren->next) {
- obrenlb= MEM_dupallocN(obren);
- BLI_addtail(lb, obrenlb);
+ for(obi= re->instancetable.first; obi; obi= obi->next) {
+ obr= obi->obr;
+
+ obilb= MEM_mallocN(sizeof(ObjectInstanceRen), "ObInstanceVector");
+ memcpy(obilb, obi, sizeof(ObjectInstanceRen));
+ BLI_addtail(lb, obilb);
- totvector= obren->endvert - obren->startvert;
- totvector+= obren->endstrand - obren->startstrand;
+ obilb->totvector= totvector= obr->totvert + obr->totstrand;
if(totvector > 0) {
- vec= obrenlb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array");
+ vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array");
- if(obren->endvert > obren->startvert) {
- /* first vertex */
- a= obren->startvert-1;
- ver= re->vertnodes[a>>8].vert + (a & 255);
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(winmat, obi->mat, re->winmat);
+ else
+ Mat4CpyMat4(winmat, re->winmat);
- for(a=obren->startvert; a<obren->endvert; a++, vec+=2) {
- if((a & 255)==0) ver= re->vertnodes[a>>8].vert;
- else ver++;
-
- speedvector_project(NULL, vec, ver->co, ver->ho);
- }
+ for(a=0; a<obr->totvert; a++, vec+=2) {
+ if((a & 255)==0) ver= obr->vertnodes[a>>8].vert;
+ else ver++;
+
+ projectvert(ver->co, winmat, ho);
+ speedvector_project(NULL, vec, ver->co, ho);
}
- if(obren->endstrand > obren->startstrand) {
- /* first strand */
- a= obren->startstrand-1;
- strand= re->strandnodes[a>>8].strand + (a & 255);
-
- for(a=obren->startstrand; a<obren->endstrand; a++, vec+=2) {
- if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
- else strand++;
-
- projectverto(strand->vert->co, re->winmat, ho);
- speedvector_project(NULL, vec, strand->vert->co, ho);
- }
+ for(a=0; a<obr->totstrand; a++, vec+=2) {
+ if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
+ else strand++;
+
+ projectvert(strand->vert->co, winmat, ho);
+ speedvector_project(NULL, vec, strand->vert->co, ho);
}
}
}
@@ -4832,17 +4589,17 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb)
static void free_dbase_object_vectors(ListBase *lb)
{
- ObjectRen *obren;
+ ObjectInstanceRen *obi;
- for(obren= lb->first; obren; obren= obren->next)
- if(obren->vectors)
- MEM_freeN(obren->vectors);
+ for(obi= lb->first; obi; obi= obi->next)
+ if(obi->vectors)
+ MEM_freeN(obi->vectors);
BLI_freelistN(lb);
}
void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
{
- ObjectRen *obren, *oldobren;
+ ObjectInstanceRen *obi, *oldobi;
ListBase *table;
ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL};
int step;
@@ -4884,40 +4641,41 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
else
table= &oldtable;
- oldobren= table->first;
- for(obren= re->objecttable.first; obren && oldobren; obren= obren->next, oldobren= oldobren->next) {
+ oldobi= table->first;
+ for(obi= re->instancetable.first; obi && oldobi; obi= obi->next, oldobi= oldobi->next) {
int ok= 1;
+ obi->totvector= obi->obr->totvert + obi->obr->totstrand;
+
/* find matching object in old table */
- if(oldobren->ob!=obren->ob || oldobren->par!=obren->par || oldobren->index!=obren->index) {
+ if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) {
ok= 0;
- for(oldobren= table->first; oldobren; oldobren= oldobren->next)
- if(oldobren->ob==obren->ob && oldobren->par==obren->par && oldobren->index==obren->index)
+ for(oldobi= table->first; oldobi; oldobi= oldobi->next)
+ if(oldobi->ob==obi->ob && oldobi->par==obi->par && oldobi->index==obi->index && oldobi->psysindex==obi->psysindex)
break;
- if(oldobren==NULL)
- oldobren= table->first;
+ if(oldobi==NULL)
+ oldobi= table->first;
else
ok= 1;
}
if(ok==0) {
- printf("speed table: missing object %s\n", obren->ob->id.name+2);
+ printf("speed table: missing object %s\n", obi->ob->id.name+2);
continue;
}
// NT check for fluidsim special treatment
- if((obren->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obren->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) {
+ if((obi->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obi->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) {
// use preloaded per vertex simulation data , only does calculation for step=1
// NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls...
- load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob);
+ load_fluidsimspeedvectors(re, obi, oldobi->vectors, step);
} else {
/* check if both have same amounts of vertices */
- if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert ||
- obren->endstrand-obren->startstrand != oldobren->endstrand-oldobren->startstrand) {
- printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
+ if(obi->totvector!=oldobi->totvector) {
+ printf("Warning: object %s has different amount of vertices on other frame\n", obi->ob->id.name+2);
continue;
}
- calculate_speedvectors(re, obren, oldobren->vectors, step);
+ calculate_speedvectors(re, obi, oldobi->vectors, step);
} // not fluidsim
}
}
@@ -4931,11 +4689,9 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
}
-/* exported call to recalculate hoco for vertices, when winmat changed */
-void RE_DataBase_ApplyWindow(Render *re)
-{
- project_renderdata(re, projectverto, 0, 0, 0);
-}
+/* ------------------------------------------------------------------------- */
+/* Baking */
+/* ------------------------------------------------------------------------- */
/* setup for shaded view or bake, so only lamps and materials are initialized */
/* type:
@@ -4947,11 +4703,9 @@ void RE_DataBase_ApplyWindow(Render *re)
*/
void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
{
- Base *base;
- Object *ob;
- Scene *sce;
float mat[4][4];
unsigned int lay;
+ int onlyselected, nolamps;
re->scene= scene;
@@ -5000,72 +4754,19 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
init_ao_sphere(&re->wrld);
}
-
/* still bad... doing all */
init_render_textures(re);
init_render_materials(re->r.mode, &re->wrld.ambr);
set_node_shader_lamp_loop(shade_material_loop);
-
- for(SETLOOPER(re->scene, base)) {
- ob= base->object;
- /* imat objects has to be done here, since displace can have texture using Object map-input */
- MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
- MTC_Mat4Invert(ob->imat, mat);
- /* each object should only be rendered once */
- ob->flag &= ~OB_DONE;
- }
/* MAKE RENDER DATA */
- for(SETLOOPER(re->scene, base)) {
- ob= base->object;
-
- /* if the object has been restricted from rendering in the outliner, ignore it */
- if (ob->restrictflag & OB_RESTRICT_RENDER) continue;
-
- /* OB_DONE means the object itself got duplicated, so was already converted */
- if(ob->flag & OB_DONE);
- else if( (base->lay & lay) || ((base->lay & re->scene->lay)) ) {
-
- /* check for dupli lamps or non selected groups */
- if(ob->transflag & OB_DUPLI) {
- DupliObject *dob;
- ListBase *lb= object_duplilist(sce, ob);
-
- for(dob= lb->first; dob; dob= dob->next) {
- Object *obd= dob->ob;
-
- if(obd->type==OB_LAMP) {
- if( ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL) ) {
- Mat4CpyMat4(obd->obmat, dob->mat);
- init_render_object(re, obd, ob, dob->index, 0);
- }
- }
- else if( ELEM(type, RE_BAKE_AO, RE_BAKE_ALL) ) {
- if((base->flag & SELECT)==0) {
- Mat4CpyMat4(obd->obmat, dob->mat);
- init_render_object(re, obd, ob, dob->index, 0);
- }
- }
- }
- free_object_duplilist(lb);
- }
- else {
- if(ob->type==OB_LAMP) {
- if( ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL) )
- init_render_object(re, ob, NULL, 0, 0);
- }
- else if(type!=RE_BAKE_LIGHT) {
- if( !ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) || (ob->flag & SELECT) || (ob == actob) )
- init_render_object(re, ob, NULL, 0, 0);
- }
- }
- }
- }
+ nolamps= !ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL);
+ onlyselected= ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE);
+
+ database_init_objects(re, lay, nolamps, onlyselected, actob, 0);
+
set_material_lightgroups(re);
- check_non_flat_quads(re);
- /* don't call set_normalflags(), no flipping */
-
if(type!=RE_BAKE_LIGHT) {
if(re->r.mode & R_SHADOW) {
LampRen *lar;
@@ -5089,17 +4790,9 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
makeraytree(re);
}
-void RE_DataBase_GetView(Render *re, float mat[][4])
-{
- Mat4CpyMat4(mat, re->viewmat);
-}
-
-
-
-
-/* **************************************************************** */
-/* sticky texture coords */
-/* **************************************************************** */
+/* ------------------------------------------------------------------------- */
+/* Sticky texture coords */
+/* ------------------------------------------------------------------------- */
void RE_make_sticky(void)
{
@@ -5165,172 +4858,3 @@ void RE_make_sticky(void)
}
}
-
-
-/* **************************************************************** */
-/* Displacement mapping */
-/* **************************************************************** */
-static short test_for_displace(Render *re, Object *ob)
-{
- /* return 1 when this object uses displacement textures. */
- Material *ma;
- int i;
-
- for (i=1; i<=ob->totcol; i++) {
- ma=give_render_material(re, ob, i);
- /* ma->mapto is ORed total of all mapto channels */
- if(ma && (ma->mapto & MAP_DISPLACE)) return 1;
- }
- return 0;
-}
-
-static void displace_render_vert(Render *re, ShadeInput *shi, VertRen *vr, int vindex, float *scale)
-{
- MTFace *tface;
- short texco= shi->mat->texco;
- float sample=0;
- char *name;
- int i;
-
- /* shi->co is current render coord, just make sure at least some vector is here */
- VECCOPY(shi->co, vr->co);
- /* vertex normal is used for textures type 'col' and 'var' */
- VECCOPY(shi->vn, vr->n);
-
- if (texco & TEXCO_UV) {
- shi->totuv= 0;
-
- for (i=0; (tface=RE_vlakren_get_tface(re, shi->vlr, i, &name, 0)); i++) {
- ShadeInputUV *suv= &shi->uv[i];
-
- /* shi.uv needs scale correction from tface uv */
- suv->uv[0]= 2*tface->uv[vindex][0]-1.0f;
- suv->uv[1]= 2*tface->uv[vindex][1]-1.0f;
- suv->uv[2]= 0.0f;
- suv->name= name;
- shi->totuv++;
- }
- }
-
- /* set all rendercoords, 'texco' is an ORed value for all textures needed */
- if ((texco & TEXCO_ORCO) && (vr->orco)) {
- VECCOPY(shi->lo, vr->orco);
- }
- if (texco & TEXCO_STICKY) {
- float *sticky= RE_vertren_get_sticky(re, vr, 0);
- if(sticky) {
- shi->sticky[0]= sticky[0];
- shi->sticky[1]= sticky[1];
- shi->sticky[2]= 0.0f;
- }
- }
- if (texco & TEXCO_GLOB) {
- VECCOPY(shi->gl, shi->co);
- MTC_Mat4MulVecfl(re->viewinv, shi->gl);
- }
- if (texco & TEXCO_NORM) {
- VECCOPY(shi->orn, shi->vn);
- }
- if(texco & TEXCO_REFL) {
- /* not (yet?) */
- }
-
- shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
-
- do_material_tex(shi);
-
- //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2],
- //vr->co[0], vr->co[1], vr->co[2]);
-
- /* 0.5 could become button once? */
- vr->co[0] += shi->displace[0] * scale[0] ;
- vr->co[1] += shi->displace[1] * scale[1] ;
- vr->co[2] += shi->displace[2] * scale[2] ;
-
- //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]);
-
- /* we just don't do this vertex again, bad luck for other face using same vertex with
- different material... */
- vr->flag |= 1;
-
- /* Pass sample back so displace_face can decide which way to split the quad */
- sample = shi->displace[0]*shi->displace[0];
- sample += shi->displace[1]*shi->displace[1];
- sample += shi->displace[2]*shi->displace[2];
-
- vr->accum=sample;
- /* Should be sqrt(sample), but I'm only looking for "bigger". Save the cycles. */
- return;
-}
-
-static void displace_render_face(Render *re, VlakRen *vlr, float *scale)
-{
- ShadeInput shi;
-
- /* set up shadeinput struct for multitex() */
- shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */
- shi.vlr= vlr; /* current render face */
- shi.mat= vlr->mat; /* current input material */
-
- /* Displace the verts, flag is set when done */
- if (!vlr->v1->flag)
- displace_render_vert(re, &shi, vlr->v1,0, scale);
-
- if (!vlr->v2->flag)
- displace_render_vert(re, &shi, vlr->v2, 1, scale);
-
- if (!vlr->v3->flag)
- displace_render_vert(re, &shi, vlr->v3, 2, scale);
-
- if (vlr->v4) {
- if (!vlr->v4->flag)
- displace_render_vert(re, &shi, vlr->v4, 3, scale);
-
- /* closest in displace value. This will help smooth edges. */
- if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum))
- vlr->flag |= R_DIVIDE_24;
- else vlr->flag &= ~R_DIVIDE_24; // E: typo?, was missing '='
- }
-
- /* Recalculate the face normal - if flipped before, flip now */
- if(vlr->v4) {
- CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
- }
- else {
- CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
- }
-}
-
-
-static void do_displacement(Render *re, Object *ob, int startface, int numface, int startvert, int numvert )
-{
- VertRen *vr;
- VlakRen *vlr;
-// float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30};
- float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn
- int i; //, texflag=0;
- Object *obt;
-
- /* Object Size with parenting */
- obt=ob;
- while(obt){
- VecAddf(temp, obt->size, obt->dsize);
- scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2];
- obt=obt->parent;
- }
-
- /* Clear all flags */
- for(i=startvert; i<startvert+numvert; i++){
- vr= RE_findOrAddVert(re, i);
- vr->flag= 0;
- }
-
- for(i=startface; i<startface+numface; i++){
- vlr=RE_findOrAddVlak(re, i);
- displace_render_face(re, vlr, scale);
- }
-
- /* Recalc vertex normals */
- calc_vertexnormals(re, startvert, startface, 0);
-}
-
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index cec96c1ab92..b1b907aebb6 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -148,19 +148,16 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->totvlak= re->totvlak;
envre->totvert= re->totvert;
envre->tothalo= re->tothalo;
+ envre->totstrand= re->totstrand;
envre->totlamp= re->totlamp;
envre->lights= re->lights;
- envre->vertnodeslen= re->vertnodeslen;
- envre->vertnodes= re->vertnodes;
- envre->blohalen= re->blohalen;
- envre->bloha= re->bloha;
- envre->vlaknodeslen= re->vlaknodeslen;
- envre->vlaknodes= re->vlaknodes;
- envre->strandnodeslen= re->strandnodeslen;
- envre->strandnodes= re->strandnodes;
+ envre->objecttable= re->objecttable;
envre->strandbuckets= re->strandbuckets;
envre->customdata_names= re->customdata_names;
envre->raytree= re->raytree;
+ envre->totinstance= re->totinstance;
+ envre->instancetable= re->instancetable;
+ envre->objectinstance= re->objectinstance;
return envre;
}
@@ -171,19 +168,16 @@ static void envmap_free_render_copy(Render *envre)
envre->totvlak= 0;
envre->totvert= 0;
envre->tothalo= 0;
+ envre->totstrand= 0;
envre->totlamp= 0;
+ envre->totinstance= 0;
envre->lights.first= envre->lights.last= NULL;
- envre->vertnodeslen= 0;
- envre->vertnodes= NULL;
- envre->blohalen= 0;
- envre->bloha= NULL;
- envre->vlaknodeslen= 0;
- envre->vlaknodes= NULL;
- envre->strandnodeslen= 0;
- envre->strandnodes= NULL;
+ envre->objecttable.first= envre->objecttable.last= NULL;
envre->strandbuckets= NULL;
envre->customdata_names.first= envre->customdata_names.last= NULL;
envre->raytree= NULL;
+ envre->instancetable.first= envre->instancetable.last= NULL;
+ envre->objectinstance= NULL;
RE_FreeRender(envre);
}
@@ -225,11 +219,11 @@ static void envmap_transmatrix(float mat[][4], int part)
static void env_rotate_scene(Render *re, float mat[][4], int mode)
{
GroupObject *go;
- VlakRen *vlr = NULL;
- VertRen *ver = NULL;
+ ObjectRen *obr;
+ ObjectInstanceRen *obi;
LampRen *lar = NULL;
HaloRen *har = NULL;
- float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3];
+ float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3];
int a;
if(mode==0) {
@@ -240,46 +234,36 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode)
MTC_Mat4CpyMat4(tmat, mat);
MTC_Mat3CpyMat4(imat, mat);
}
-
- for(a=0; a<re->totvert; a++) {
- if((a & 255)==0) ver= RE_findOrAddVert(re, a);
- else ver++;
-
- MTC_Mat4MulVecfl(tmat, ver->co);
-
- xn= ver->n[0];
- yn= ver->n[1];
- zn= ver->n[2];
- /* no transpose ! */
- ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
- ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
- ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
- Normalize(ver->n);
+
+ for(obi=re->instancetable.first; obi; obi=obi->next) {
+ /* append or set matrix depending on dupli */
+ if(obi->flag & R_DUPLI_TRANSFORMED)
+ Mat4MulMat4(obi->mat, tmat, obi->mat);
+ else if(mode==1)
+ Mat4CpyMat4(obi->mat, tmat);
+ else
+ Mat4One(obi->mat);
+
+ Mat3CpyMat4(cmat, obi->mat);
+ Mat3Inv(obi->imat, cmat);
+
+ /* indicate the renderer has to use transform matrices */
+ if(mode==0)
+ obi->flag &= ~R_ENV_TRANSFORMED;
+ else
+ obi->flag |= R_ENV_TRANSFORMED;
}
- for(a=0; a<re->tothalo; a++) {
- if((a & 255)==0) har= re->bloha[a>>8];
- else har++;
-
- MTC_Mat4MulVecfl(tmat, har->co);
- }
-
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
+
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->tothalo; a++) {
+ if((a & 255)==0) har= obr->bloha[a>>8];
+ else har++;
- xn= vlr->n[0];
- yn= vlr->n[1];
- zn= vlr->n[2];
- /* no transpose ! */
- vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
- vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
- vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
- Normalize(vlr->n);
+ MTC_Mat4MulVecfl(tmat, har->co);
+ }
}
- set_normalflags(re);
-
for(go=re->lights.first; go; go= go->next) {
lar= go->lampren;
@@ -314,6 +298,7 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode)
static void env_layerflags(Render *re, unsigned int notlay)
{
+ ObjectRen *obr;
VlakRen *vlr = NULL;
int a;
@@ -327,23 +312,47 @@ static void env_layerflags(Render *re, unsigned int notlay)
notlay= ~notlay;
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
- if((vlr->lay & notlay)==0)
- vlr->flag &= ~R_VISIBLE;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+
+ if((vlr->lay & notlay)==0)
+ vlr->flag |= R_HIDDEN;
+ }
}
}
static void env_hideobject(Render *re, Object *ob)
{
+ ObjectRen *obr;
+ VlakRen *vlr = NULL;
+ int a;
+
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+
+ if(obr->ob == ob)
+ vlr->flag |= R_HIDDEN;
+ }
+ }
+}
+
+static void env_showobjects(Render *re)
+{
+ ObjectRen *obr;
VlakRen *vlr = NULL;
int a;
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
- if(vlr->ob == ob) vlr->flag &= ~R_VISIBLE;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+
+ vlr->flag &= ~R_HIDDEN;
+ }
}
}
@@ -419,6 +428,7 @@ static void render_envmap(Render *re, EnvMap *env)
}
/* rotate back */
+ env_showobjects(envre);
env_rotate_scene(envre, tmat, 0);
if(re->test_break()==0) {
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index 8d9f687a32e..23b5e597070 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -984,6 +984,5 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, f
texres->tb*= fx;
}
-
return retval;
}
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index a9699104e01..69e90a7537c 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -88,6 +88,13 @@ static int vlr_check_intersect(Isect *is, RayFace *face)
return (is->lay & vlr->lay);
}
+static float *vlr_get_transform(void *userdata, int i)
+{
+ ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)userdata, i);
+
+ return (obi->flag & R_TRANSFORMED)? (float*)obi->mat: NULL;
+}
+
void freeraytree(Render *re)
{
if(re->raytree) {
@@ -98,25 +105,46 @@ void freeraytree(Render *re)
void makeraytree(Render *re)
{
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
VlakRen *vlr= NULL;
- float min[3], max[3];
+ float min[3], max[3], co1[3], co2[3], co3[3], co4[3];
double lasttime= PIL_check_seconds_timer();
int v, totface = 0;
INIT_MINMAX(min, max);
/* first min max raytree space */
- for(v=0;v<re->totvlak;v++) {
- if((v & 255)==0) vlr= re->vlaknodes[v>>8].vlak;
- else vlr++;
- if(vlr->mat->mode & MA_TRACEBLE) {
- if((vlr->mat->mode & MA_WIRE)==0) {
- if(!re->excludeob || vlr->ob != re->excludeob) {
- DO_MINMAX(vlr->v1->co, min, max);
- DO_MINMAX(vlr->v2->co, min, max);
- DO_MINMAX(vlr->v3->co, min, max);
+ for(obi=re->instancetable.first; obi; obi=obi->next) {
+ obr= obi->obr;
+
+ if(re->excludeob && obr->ob == re->excludeob)
+ continue;
+
+ for(v=0;v<obr->totvlak;v++) {
+ if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
+ else vlr++;
+ if(vlr->mat->mode & MA_TRACEBLE) {
+ if((vlr->mat->mode & MA_WIRE)==0) {
+ VECCOPY(co1, vlr->v1->co);
+ VECCOPY(co2, vlr->v2->co);
+ VECCOPY(co3, vlr->v3->co);
+
+ if(obi->flag & R_TRANSFORMED) {
+ Mat4MulVecfl(obi->mat, co1);
+ Mat4MulVecfl(obi->mat, co2);
+ Mat4MulVecfl(obi->mat, co3);
+ }
+
+ DO_MINMAX(co1, min, max);
+ DO_MINMAX(co2, min, max);
+ DO_MINMAX(co3, min, max);
+
if(vlr->v4) {
- DO_MINMAX(vlr->v4->co, min, max);
+ VECCOPY(co4, vlr->v4->co);
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulVecfl(obi->mat, co4);
+ DO_MINMAX(co4, min, max);
}
totface++;
@@ -125,35 +153,42 @@ void makeraytree(Render *re)
}
}
- re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max, vlr_face_coords, vlr_check_intersect);
+ re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max,
+ vlr_face_coords, vlr_check_intersect, vlr_get_transform, re);
if(min[0] > max[0]) { /* empty raytree */
RE_ray_tree_done(re->raytree);
return;
}
- for(v=0; v<re->totvlak; v++) {
- if((v & 255)==0) {
- double time= PIL_check_seconds_timer();
+ for(obi=re->instancetable.first; obi; obi=obi->next) {
+ obr= obi->obr;
- vlr= re->vlaknodes[v>>8].vlak;
- if(re->test_break())
- break;
- if(time-lasttime>1.0f) {
- char str[32];
- sprintf(str, "Filling Octree: %d", v);
- re->i.infostr= str;
- re->stats_draw(&re->i);
- re->i.infostr= NULL;
- lasttime= time;
+ if(re->excludeob && obr->ob == re->excludeob)
+ continue;
+
+ for(v=0; v<obr->totvlak; v++) {
+ if((v & 255)==0) {
+ double time= PIL_check_seconds_timer();
+
+ vlr= obr->vlaknodes[v>>8].vlak;
+ if(re->test_break())
+ break;
+ if(time-lasttime>1.0f) {
+ char str[32];
+ sprintf(str, "Filling Octree: %d", v);
+ re->i.infostr= str;
+ re->stats_draw(&re->i);
+ re->i.infostr= NULL;
+ lasttime= time;
+ }
}
+ else vlr++;
+
+ if(vlr->mat->mode & MA_TRACEBLE)
+ if((vlr->mat->mode & MA_WIRE)==0)
+ RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr);
}
- else vlr++;
-
- if(vlr->mat->mode & MA_TRACEBLE)
- if((vlr->mat->mode & MA_WIRE)==0)
- if(!re->excludeob || vlr->ob != re->excludeob)
- RE_ray_tree_add_face(re->raytree, (RayFace*)vlr);
}
RE_ray_tree_done(re->raytree);
@@ -165,7 +200,8 @@ void makeraytree(Render *re)
static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
{
VlakRen *vlr= (VlakRen*)is->face;
- int osatex= 0, norflip;
+ ObjectInstanceRen *obi= RAY_OBJECT_GET(&R, is->ob);
+ int osatex= 0;
/* set up view vector */
VECCOPY(shi->view, is->vec);
@@ -177,6 +213,8 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
Normalize(shi->view);
+ shi->obi= obi;
+ shi->obr= obi->obr;
shi->vlr= vlr;
shi->mat= vlr->mat;
memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h
@@ -194,35 +232,26 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
shi->dyno[0]= shi->dyno[1]= shi->dyno[2]= 0.0f;
}
- /* face normal, check for flip, need to set puno here */
- norflip= (vlr->n[0]*shi->view[0]+vlr->n[1]*shi->view[1]+vlr->n[2]*shi->view[2]) < 0.0f;
-
- if(norflip)
- shi->puno= vlr->puno ^ 15;// only flip lower 4 bits
- else
- shi->puno= vlr->puno;
-
if(vlr->v4) {
if(is->isect==2)
- shade_input_set_triangle_i(shi, vlr, 2, 1, 3);
+ shade_input_set_triangle_i(shi, obi, vlr, 2, 1, 3);
else
- shade_input_set_triangle_i(shi, vlr, 0, 1, 3);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 3);
}
else {
- shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
}
-
- /* shade_input_set_triangle_i() sets facenor, now we flip */
- if(norflip) {
- shi->facenor[0]= -vlr->n[0];
- shi->facenor[1]= -vlr->n[1];
- shi->facenor[2]= -vlr->n[2];
- }
-
+
shi->u= is->u;
shi->v= is->v;
shi->dx_u= shi->dx_v= shi->dy_u= shi->dy_v= 0.0f;
+
shade_input_set_normals(shi);
+
+ /* point normals to viewing direction */
+ if(INPR(shi->facenor, shi->view) < 0.0f)
+ shade_input_flip_normals(shi);
+
shade_input_set_shade_texco(shi);
if(is->mode==RE_RAY_SHADOW_TRA)
@@ -371,7 +400,7 @@ static void ray_fadeout(Isect *is, ShadeInput *shi, float *col, float *blendcol,
}
/* the main recursive tracer itself */
-static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *vec, float *col, VlakRen *vlr, int traflag)
+static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, float *start, float *vec, float *col, ObjectInstanceRen *obi, VlakRen *vlr, int traflag)
{
ShadeInput shi;
ShadeResult shr;
@@ -392,6 +421,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
}
isec.mode= RE_RAY_MIRROR;
isec.faceorig= (RayFace*)vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, obi);
if(RE_ray_tree_intersect(R.raytree, &isec)) {
float d= 1.0f;
@@ -441,10 +471,10 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
reflection(refract, shi.vn, shi.view, shi.vn);
}
traflag |= RAY_TRA;
- traceray(origshi, origshr, depth-1, shi.co, refract, tracol, shi.vlr, traflag ^ RAY_TRAFLIP);
+ traceray(origshi, origshr, depth-1, shi.co, refract, tracol, shi.obi, shi.vlr, traflag ^ RAY_TRAFLIP);
}
else
- traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.vlr, 0);
+ traceray(origshi, origshr, depth-1, shi.co, shi.view, tracol, shi.obi, shi.vlr, 0);
f= shr.alpha; f1= 1.0f-f;
nf= d * shi.mat->filter;
@@ -474,7 +504,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
float mircol[4];
reflection(ref, shi.vn, shi.view, NULL);
- traceray(origshi, origshr, depth-1, shi.co, ref, mircol, shi.vlr, 0);
+ traceray(origshi, origshr, depth-1, shi.co, ref, mircol, shi.obi, shi.vlr, 0);
f1= 1.0f-f;
@@ -951,7 +981,7 @@ static void trace_refract(float *col, ShadeInput *shi, ShadeResult *shr)
VECCOPY(v_refract_new, v_refract);
}
- traceray(shi, shr, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->vlr, RAY_TRA|RAY_TRAFLIP);
+ traceray(shi, shr, shi->mat->ray_depth_tra, shi->co, v_refract_new, sampcol, shi->obi, shi->vlr, RAY_TRA|RAY_TRAFLIP);
col[0] += sampcol[0];
col[1] += sampcol[1];
@@ -1047,7 +1077,7 @@ static void trace_reflect(float *col, ShadeInput *shi, ShadeResult *shr, float f
else
reflection(v_reflect, v_nor_new, shi->view, NULL);
- traceray(shi, shr, shi->mat->ray_depth, shi->co, v_reflect, sampcol, shi->vlr, 0);
+ traceray(shi, shr, shi->mat->ray_depth, shi->co, v_reflect, sampcol, shi->obi, shi->vlr, 0);
col[0] += sampcol[0];
@@ -1223,6 +1253,7 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
/* adapt isect struct */
VECCOPY(is->start, shi.co);
+ is->oborig= RAY_OBJECT_SET(&R, shi.obi);
is->faceorig= (RayFace*)shi.vlr;
ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA);
@@ -1250,6 +1281,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
accum[0]= accum[1]= accum[2]= 0.0f;
isec.mode= RE_RAY_MIRROR;
isec.faceorig= (RayFace*)ship->vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, ship->obi);
for(a=0; a<8*8; a++) {
@@ -1448,7 +1480,9 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
int aocolor;
isec.faceorig= (RayFace*)shi->vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
isec.face_last= NULL;
+ isec.ob_last= 0;
isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW;
isec.lay= -1;
VECCOPY(isec.start, shi->co);
@@ -1574,7 +1608,9 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
int j= -1, tot, actual=0, skyadded=0, aocolor;
isec.faceorig= (RayFace*)shi->vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
isec.face_last= NULL;
+ isec.ob_last= 0;
isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW;
isec.lay= -1;
@@ -1737,6 +1773,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
while (samples < max_samples) {
isec->faceorig= (RayFace*)shi->vlr;
+ isec->oborig= RAY_OBJECT_SET(&R, shi->obi);
/* manually jitter the start shading co-ord per sample
* based on the pre-generated OSA texture sampling offsets,
@@ -1873,6 +1910,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
}
isec->faceorig= (RayFace*)shi->vlr;
+ isec->oborig= RAY_OBJECT_SET(&R, shi->obi);
vec[0]= jitlamp[0];
vec[1]= jitlamp[1];
@@ -1929,10 +1967,14 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1;
/* only when not mir tracing, first hit optimm */
- if(shi->depth==0)
+ if(shi->depth==0) {
isec.face_last= (RayFace*)lar->vlr_last[shi->thread];
- else
+ isec.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]);
+ }
+ else {
isec.face_last= NULL;
+ isec.ob_last= 0;
+ }
if(lar->type==LA_SUN || lar->type==LA_HEMI) {
maxsize= RE_ray_tree_max_size(R.raytree);
@@ -1952,6 +1994,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
if(lar->ray_totsamp<2) {
isec.faceorig= (RayFace*)shi->vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
shadfac[3]= 1.0f; // 1.0=full light
/* set up isec vec */
@@ -1974,8 +2017,10 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
}
/* for first hit optim, set last interesected shadow face */
- if(shi->depth==0)
+ if(shi->depth==0) {
lar->vlr_last[shi->thread]= (VlakRen*)isec.face_last;
+ lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, isec.ob_last);
+ }
}
@@ -2001,6 +2046,7 @@ void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co)
}
isec.faceorig= (RayFace*)shi->vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
/* set up isec vec */
VECCOPY(isec.start, shi->co);
diff --git a/source/blender/render/intern/source/raytrace.c b/source/blender/render/intern/source/raytrace.c
index 002148ed97c..54e8e4cfab5 100644
--- a/source/blender/render/intern/source/raytrace.c
+++ b/source/blender/render/intern/source/raytrace.c
@@ -61,6 +61,7 @@ typedef struct OcVal
typedef struct Node
{
struct RayFace *v[8];
+ int ob[8];
struct OcVal ov[8];
struct Node *next;
} Node;
@@ -76,6 +77,8 @@ typedef struct Octree {
char *ocface; /* during building only */
RayCoordsFunc coordsfunc;
RayCheckFunc checkfunc;
+ RayObjectTransformFunc transformfunc;
+ void *userdata;
} Octree;
/* ******** globals ***************** */
@@ -230,7 +233,7 @@ static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3]
return 0;
}
-static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[][3])
+static void ocwrite(Octree *oc, int ob, RayFace *face, int quad, short x, short y, short z, float rtf[][3])
{
Branch *br;
Node *no;
@@ -281,6 +284,7 @@ static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short
}
no->v[a]= face;
+ no->ob[a]= ob;
if(quad)
calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]);
@@ -435,7 +439,7 @@ void RE_ray_tree_free(RayTree *tree)
MEM_freeN(oc);
}
-RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayCoordsFunc coordsfunc, RayCheckFunc checkfunc)
+RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayCoordsFunc coordsfunc, RayCheckFunc checkfunc, RayObjectTransformFunc transformfunc, void *userdata)
{
Octree *oc;
float t00, t01, t02;
@@ -447,6 +451,8 @@ RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayC
oc->coordsfunc= coordsfunc;
oc->checkfunc= checkfunc;
+ oc->transformfunc= transformfunc;
+ oc->userdata= userdata;
/* only for debug info */
raycount=0;
@@ -486,10 +492,11 @@ RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayC
return (RayTree*)oc;
}
-void RE_ray_tree_add_face(RayTree *tree, RayFace *face)
+void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face)
{
Octree *oc = (Octree*)tree;
float *v1, *v2, *v3, *v4, ocfac[3], rtf[4][3];
+ float co1[3], co2[3], co3[3], co4[3];
short rts[4][3], ocmin[6], *ocmax;
char *ocface= oc->ocface; // front, top, size view of face, to fill in
int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2;
@@ -503,16 +510,34 @@ void RE_ray_tree_add_face(RayTree *tree, RayFace *face)
ocmax= ocmin+3;
oc->coordsfunc(face, &v1, &v2, &v3, &v4);
+
+ VECCOPY(co1, v1);
+ VECCOPY(co2, v2);
+ VECCOPY(co3, v3);
+ if(v4)
+ VECCOPY(co4, v4);
+
+ if(ob >= RE_RAY_TRANSFORM_OFFS) {
+ float (*mat)[4]= (float(*)[4])oc->transformfunc(oc->userdata, ob);
+
+ if(mat) {
+ Mat4MulVecfl(mat, co1);
+ Mat4MulVecfl(mat, co2);
+ Mat4MulVecfl(mat, co3);
+ if(v4)
+ Mat4MulVecfl(mat, co4);
+ }
+ }
for(c=0;c<3;c++) {
- rtf[0][c]= (v1[c]-oc->min[c])*ocfac[c] ;
+ rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ;
rts[0][c]= (short)rtf[0][c];
- rtf[1][c]= (v2[c]-oc->min[c])*ocfac[c] ;
+ rtf[1][c]= (co2[c]-oc->min[c])*ocfac[c] ;
rts[1][c]= (short)rtf[1][c];
- rtf[2][c]= (v3[c]-oc->min[c])*ocfac[c] ;
+ rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ;
rts[2][c]= (short)rtf[2][c];
if(v4) {
- rtf[3][c]= (v4[c]-oc->min[c])*ocfac[c] ;
+ rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ;
rts[3][c]= (short)rtf[3][c];
}
}
@@ -535,7 +560,7 @@ void RE_ray_tree_add_face(RayTree *tree, RayFace *face)
}
if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) {
- ocwrite(oc, face, (v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf);
+ ocwrite(oc, ob, face, (v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf);
}
else {
@@ -574,7 +599,7 @@ void RE_ray_tree_add_face(RayTree *tree, RayFace *face)
for(z=ocmin[2];z<=ocmax[2];z++) {
if(ocface[b+z] && ocface[a+z]) {
if(face_in_node(NULL, x, y, z, rtf))
- ocwrite(oc, face, (v4 != NULL), x,y,z, rtf);
+ ocwrite(oc, ob, face, (v4 != NULL), x,y,z, rtf);
}
}
}
@@ -611,9 +636,9 @@ void RE_ray_tree_done(RayTree *tree)
/* ************ raytracer **************** */
/* only for self-intersecting test with current render face (where ray left) */
-static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, float r1, float r2, float rx1, float ry1, float rz1)
+static int intersection2(RayFace *face, int ob, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc, void *userdata, float r0, float r1, float r2, float rx1, float ry1, float rz1)
{
- float *v1, *v2, *v3, *v4;
+ float *v1, *v2, *v3, *v4, co1[3], co2[3], co3[3], co4[3];
float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22;
float m0, m1, m2, divdet, det, det1;
float u1, v, u2;
@@ -623,17 +648,35 @@ static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, floa
/* happens for baking with non existing face */
if(v1==NULL)
return 1;
-
- if (v4) {
+
+ if(v4) {
SWAP(float*, v3, v4);
}
+
+ VECCOPY(co1, v1);
+ VECCOPY(co2, v2);
+ VECCOPY(co3, v3);
+ if(v4)
+ VECCOPY(co4, v4);
+
+ if(ob >= RE_RAY_TRANSFORM_OFFS) {
+ float (*mat)[4]= (float(*)[4])transformfunc(userdata, ob);
+
+ if(mat) {
+ Mat4MulVecfl(mat, co1);
+ Mat4MulVecfl(mat, co2);
+ Mat4MulVecfl(mat, co3);
+ if(v4)
+ Mat4MulVecfl(mat, co4);
+ }
+ }
- t00= v3[0]-v1[0];
- t01= v3[1]-v1[1];
- t02= v3[2]-v1[2];
- t10= v3[0]-v2[0];
- t11= v3[1]-v2[1];
- t12= v3[2]-v2[2];
+ t00= co3[0]-co1[0];
+ t01= co3[1]-co1[1];
+ t02= co3[2]-co1[2];
+ t10= co3[0]-co2[0];
+ t11= co3[1]-co2[1];
+ t12= co3[2]-co2[2];
x0= t11*r2-t12*r1;
x1= t12*r0-t10*r2;
@@ -641,9 +684,9 @@ static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, floa
divdet= t00*x0+t01*x1+t02*x2;
- m0= rx1-v3[0];
- m1= ry1-v3[1];
- m2= rz1-v3[2];
+ m0= rx1-co3[0];
+ m1= ry1-co3[1];
+ m2= rz1-co3[2];
det1= m0*x0+m1*x1+m2*x2;
if(divdet!=0.0f) {
@@ -663,9 +706,9 @@ static int intersection2(RayFace *face, RayCoordsFunc coordsfunc, float r0, floa
if(v4) {
- t20= v3[0]-v4[0];
- t21= v3[1]-v4[1];
- t22= v3[2]-v4[2];
+ t20= co3[0]-co4[0];
+ t21= co3[1]-co4[1];
+ t22= co3[2]-co4[2];
divdet= t20*x0+t21*x1+t22*x2;
if(divdet!=0.0f) {
@@ -752,10 +795,11 @@ static int intersection_strand(Isect *is)
#endif
/* ray - triangle or quad intersection */
-int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
+int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc)
{
RayFace *face= is->face;
- float *v1,*v2,*v3,*v4;
+ int ob= is->ob;
+ float *v1,*v2,*v3,*v4,co1[3],co2[3],co3[3],co4[3];
float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2;
float m0, m1, m2, divdet, det1;
short ok=0;
@@ -767,16 +811,34 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
coordsfunc(face, &v1, &v2, &v3, &v4);
- if (v4) {
+ if(v4) {
SWAP(float*, v3, v4);
}
- t00= v3[0]-v1[0];
- t01= v3[1]-v1[1];
- t02= v3[2]-v1[2];
- t10= v3[0]-v2[0];
- t11= v3[1]-v2[1];
- t12= v3[2]-v2[2];
+ VECCOPY(co1, v1);
+ VECCOPY(co2, v2);
+ VECCOPY(co3, v3);
+ if(v4)
+ VECCOPY(co4, v4);
+
+ if(ob) {
+ float (*mat)[4]= (float(*)[4])transformfunc(is->userdata, ob);
+
+ if(mat) {
+ Mat4MulVecfl(mat, co1);
+ Mat4MulVecfl(mat, co2);
+ Mat4MulVecfl(mat, co3);
+ if(v4)
+ Mat4MulVecfl(mat, co4);
+ }
+ }
+
+ t00= co3[0]-co1[0];
+ t01= co3[1]-co1[1];
+ t02= co3[2]-co1[2];
+ t10= co3[0]-co2[0];
+ t11= co3[1]-co2[1];
+ t12= co3[2]-co2[2];
r0= is->vec[0];
r1= is->vec[1];
@@ -788,9 +850,9 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
divdet= t00*x0+t01*x1+t02*x2;
- m0= is->start[0]-v3[0];
- m1= is->start[1]-v3[1];
- m2= is->start[2]-v3[2];
+ m0= is->start[0]-co3[0];
+ m1= is->start[1]-co3[1];
+ m2= is->start[2]-co3[2];
det1= m0*x0+m1*x1+m2*x2;
if(divdet!=0.0f) {
@@ -821,9 +883,9 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
if(ok==0 && v4) {
- t20= v3[0]-v4[0];
- t21= v3[1]-v4[1];
- t22= v3[2]-v4[2];
+ t20= co3[0]-co4[0];
+ t21= co3[1]-co4[1];
+ t22= co3[2]-co4[2];
divdet= t20*x0+t21*x1+t22*x2;
if(divdet!=0.0f) {
@@ -874,11 +936,13 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
coordsfunc(face, &origv1, &origv2, &origv3, &origv4);
- if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++;
- if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++;
- if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++;
- if(origv4) {
- if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++;
+ if(ob == is->oborig) {
+ if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++;
+ if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++;
+ if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++;
+ if(origv4) {
+ if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++;
+ }
}
if(de) {
/* so there's a shared edge or vertex, let's intersect ray with face
@@ -886,8 +950,9 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
the intersection is invalid, 0 */
if(is->facecontr==NULL) {
+ is->obcontr= is->oborig;
is->facecontr= face;
- is->faceisect= intersection2(face, coordsfunc, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]);
+ is->faceisect= intersection2(face, is->oborig, transformfunc, coordsfunc, is->userdata, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]);
}
if(is->faceisect) return 1;
@@ -905,6 +970,7 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc)
static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc checkfunc)
{
RayFace *face;
+ int ob;
short nr=0;
OcVal *ov;
@@ -912,18 +978,21 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c
if(is->mode==RE_RAY_SHADOW) {
face= no->v[0];
+ ob= no->ob[0];
while(face) {
- if(is->faceorig != face) {
+ if(!(is->faceorig == face && is->oborig == ob)) {
if(checkfunc(is, face)) {
ov= no->ov+nr;
if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) {
//accepted++;
+ is->ob= ob;
is->face= face;
- if(RE_ray_face_intersection(is, oc->coordsfunc)) {
+ if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) {
+ is->ob_last= ob;
is->face_last= face;
return 1;
}
@@ -939,6 +1008,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c
nr=0;
}
face= no->v[nr];
+ ob= no->ob[nr];
}
}
else { /* else mirror or glass or shadowtra, return closest face */
@@ -949,16 +1019,18 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c
isect= *is; /* copy for sorting */
face= no->v[0];
+ ob= no->ob[0];
while(face) {
- if(is->faceorig != face) {
+ if(!(is->faceorig == face && is->oborig == ob)) {
if(checkfunc(is, face)) {
ov= no->ov+nr;
if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) {
//accepted++;
+ isect.ob= ob;
isect.face= face;
- if(RE_ray_face_intersection(&isect, oc->coordsfunc)) {
+ if(RE_ray_face_intersection(&isect, oc->transformfunc, oc->coordsfunc)) {
if(isect.labda<is->labda) *is= isect;
found= 1;
}
@@ -974,6 +1046,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc c
nr=0;
}
face= no->v[nr];
+ ob= no->ob[nr];
}
return found;
@@ -1123,17 +1196,20 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc
/* do this before intersect calls */
is->facecontr= NULL; /* to check shared edge */
+ is->obcontr= 0;
is->faceisect= is->isect= 0; /* shared edge, quad half flag */
+ is->userdata= oc->userdata;
/* only for shadow! */
if(is->mode==RE_RAY_SHADOW) {
/* check with last intersected shadow face */
- if(is->face_last!=NULL && is->face_last!=is->faceorig) {
+ if(is->face_last!=NULL && !(is->face_last==is->faceorig && is->ob_last==is->oborig)) {
if(checkfunc(is, is->face_last)) {
+ is->ob= is->ob_last;
is->face= is->face_last;
VECSUB(is->vec, is->end, is->start);
- if(RE_ray_face_intersection(is, oc->coordsfunc)) return 1;
+ if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) return 1;
}
}
}
@@ -1349,6 +1425,7 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc
}
/* reached end, no intersections found */
+ is->ob_last= 0;
is->face_last= NULL;
return 0;
}
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index f5f1f6cec17..631a2c184ed 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -214,7 +214,7 @@ static void halo_pixelstruct(HaloRen *har, float *rb, float dist, float xn, floa
static void halo_tile(RenderPart *pa, float *pass, unsigned int lay)
{
- HaloRen *har = NULL;
+ HaloRen *har;
rcti disprect= pa->disprect, testrect= pa->disprect;
float dist, xsq, ysq, xn, yn, *rb;
float col[4];
@@ -231,9 +231,7 @@ static void halo_tile(RenderPart *pa, float *pass, unsigned int lay)
}
for(a=0; a<R.tothalo; a++) {
- if((a & 255)==0)
- har= R.bloha[a>>8];
- else har++;
+ har= R.sortedhalos[a];
/* layer test, clip halo with y */
if((har->lay & lay)==0);
@@ -388,8 +386,8 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
if(shi->totuv) {
float mult= (float)count_mask(curmask)/(float)R.osa;
fp= rpass->rect + 3*offset;
- fp[0]+= mult*(0.5f + 0.5f*shi->uv[0].uv[0]);
- fp[1]+= mult*(0.5f + 0.5f*shi->uv[0].uv[1]);
+ fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
+ fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
fp[2]+= mult;
}
break;
@@ -398,7 +396,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
if(shi->vlr) {
fp= rpass->rect + offset;
if(*fp==0.0f)
- *fp= (float)shi->vlr->ob->index;
+ *fp= (float)shi->obr->ob->index;
}
break;
case SCE_PASS_VECTOR:
@@ -463,8 +461,8 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
break;
case SCE_PASS_UV:
if(shi->totuv) {
- uvcol[0]= 0.5f + 0.5f*shi->uv[0].uv[0];
- uvcol[1]= 0.5f + 0.5f*shi->uv[0].uv[1];
+ uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
+ uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
uvcol[2]= 1.0f;
col= uvcol;
}
@@ -476,7 +474,7 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
case SCE_PASS_INDEXOB:
if(shi->vlr) {
fp= rpass->rect + offset;
- *fp= (float)shi->vlr->ob->index;
+ *fp= (float)shi->obr->ob->index;
}
break;
}
@@ -615,7 +613,7 @@ static void freeps(ListBase *lb)
lb->first= lb->last= NULL;
}
-static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask)
+static void addps(ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask)
{
PixStrMain *psm;
PixStr *ps, *last= NULL;
@@ -624,7 +622,7 @@ static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask
ps= (PixStr *)(*rd);
while(ps) {
- if( ps->facenr == facenr ) {
+ if( ps->obi == obi && ps->facenr == facenr ) {
ps->mask |= mask;
return;
}
@@ -645,30 +643,13 @@ static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask
else *rd= (long)ps;
ps->next= NULL;
+ ps->obi= obi;
ps->facenr= facenr;
ps->z= z;
ps->mask = mask;
ps->shadfac= 0;
}
-static void make_pixelstructs(RenderPart *pa, ListBase *lb)
-{
- long *rd= pa->rectdaps;
- int *rp= pa->rectp;
- int *rz= pa->rectz;
- int x, y;
- int mask= 1<<pa->sample;
-
- for(y=0; y<pa->recty; y++) {
- for(x=0; x<pa->rectx; x++, rd++, rp++) {
- if(*rp) {
- addps(lb, rd, *rp, *(rz+x), mask);
- }
- }
- rz+= pa->rectx;
- }
-}
-
static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
{
float addcol[4];
@@ -704,7 +685,7 @@ static void convert_to_key_alpha(RenderPart *pa, float *rectf)
}
/* adds only alpha values */
-static void edge_enhance_tile(RenderPart *pa, float *rectf)
+void edge_enhance_tile(RenderPart *pa, float *rectf)
{
/* use zbuffer to define edges, add it to the image */
int y, x, col, *rz, *rz1, *rz2, *rz3;
@@ -835,6 +816,36 @@ static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dma
dest[3]= (mul*dest[3]) + source[3];
}
+typedef struct ZbufSolidData {
+ RenderLayer *rl;
+ ListBase *psmlist;
+ float *edgerect;
+} ZbufSolidData;
+
+void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data)
+{
+ ZbufSolidData *sdata= (ZbufSolidData*)data;
+ ListBase *lb= sdata->psmlist;
+ long *rd= pa->rectdaps;
+ int *ro= zspan->recto;
+ int *rp= zspan->rectp;
+ int *rz= zspan->rectz;
+ int x, y;
+ int mask= 1<<sample;
+
+ for(y=0; y<pa->recty; y++) {
+ for(x=0; x<pa->rectx; x++, rd++, rp++, ro++) {
+ if(*rp) {
+ addps(lb, rd, *ro, *rp, *(rz+x), mask);
+ }
+ }
+ rz+= pa->rectx;
+ }
+
+ if(sdata->rl->layflag & SCE_LAY_EDGE)
+ if(R.r.mode & R_EDGE)
+ edge_enhance_tile(pa, sdata->edgerect);
+}
/* main call for shading Delta Accum, for OSA */
/* supposed to be fully threadable! */
@@ -845,10 +856,9 @@ void zbufshadeDA_tile(RenderPart *pa)
ListBase psmlist= {NULL, NULL};
float *edgerect= NULL;
- set_part_zbuf_clipflag(pa);
-
/* allocate the necessary buffers */
/* zbuffer inits these rects */
+ pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
@@ -863,14 +873,13 @@ void zbufshadeDA_tile(RenderPart *pa)
edgerect= MEM_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge");
/* always fill visibility */
- for(pa->sample=0; pa->sample<R.osa; pa->sample++) {
- zbuffer_solid(pa, rl->lay, rl->layflag);
- make_pixelstructs(pa, &psmlist);
-
- if(rl->layflag & SCE_LAY_EDGE)
- if(R.r.mode & R_EDGE)
- edge_enhance_tile(pa, edgerect);
-
+ for(pa->sample=0; pa->sample<R.osa; pa->sample+=4) {
+ ZbufSolidData sdata;
+
+ sdata.rl= rl;
+ sdata.psmlist= &psmlist;
+ sdata.edgerect= edgerect;
+ zbuffer_solid(pa, rl->lay, rl->layflag, make_pixelstructs, &sdata);
if(R.test_break()) break;
}
@@ -931,7 +940,7 @@ void zbufshadeDA_tile(RenderPart *pa)
}
/* strand rendering */
- if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) {
+ if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) {
float *fcol, *scol;
unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */
int x;
@@ -998,9 +1007,9 @@ void zbufshadeDA_tile(RenderPart *pa)
}
/* free all */
+ MEM_freeN(pa->recto); pa->recto= NULL;
MEM_freeN(pa->rectp); pa->rectp= NULL;
MEM_freeN(pa->rectz); pa->rectz= NULL;
- MEM_freeN(pa->clipflag); pa->clipflag= NULL;
/* display active layer */
rr->renrect.ymin=rr->renrect.ymax= 0;
@@ -1025,9 +1034,8 @@ void zbufshade_tile(RenderPart *pa)
ps.next= NULL;
ps.mask= 0xFFFF;
- set_part_zbuf_clipflag(pa);
-
/* zbuffer code clears/inits rects */
+ pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
@@ -1037,7 +1045,7 @@ void zbufshade_tile(RenderPart *pa)
shade_sample_initialize(&ssamp, pa, rl);
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
- zbuffer_solid(pa, rl->lay, rl->layflag);
+ zbuffer_solid(pa, rl->lay, rl->layflag, NULL, NULL);
if(!R.test_break()) { /* NOTE: this if() is not consistant */
@@ -1055,7 +1063,8 @@ void zbufshade_tile(RenderPart *pa)
if(rl->layflag & SCE_LAY_SOLID) {
float *fcol= rl->rectf;
- int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0, seed;
+ int *ro= pa->recto, *rp= pa->rectp, *rz= pa->rectz;
+ int x, y, offs=0, seed;
/* we set per pixel a fixed seed, for random AO and shadow samples */
seed= pa->rectx*pa->disprect.ymin;
@@ -1065,15 +1074,19 @@ void zbufshade_tile(RenderPart *pa)
ISB_create(pa, NULL);
for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) {
- for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, rp++, fcol+=4, offs++) {
+ for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) {
/* per pixel fixed seed */
BLI_thread_srandom(pa->thread, seed++);
if(*rp) {
+ ps.obi= *ro;
ps.facenr= *rp;
ps.z= *rz;
if(shade_samples(&ssamp, &ps, x, y)) {
QUATCOPY(fcol, ssamp.shr[0].combined);
+
+ if(!(fcol[0] == fcol[0]))
+ printvecf("fudgecol", fcol);
/* passes */
if(addpassflag)
@@ -1124,7 +1137,7 @@ void zbufshade_tile(RenderPart *pa)
}
/* strand rendering */
- if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first) {
+ if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) {
float *fcol, *scol;
int x;
@@ -1169,9 +1182,9 @@ void zbufshade_tile(RenderPart *pa)
rr->renrect.ymin=rr->renrect.ymax= 0;
rr->renlay= render_get_active_layer(&R, rr);
+ MEM_freeN(pa->recto); pa->recto= NULL;
MEM_freeN(pa->rectp); pa->rectp= NULL;
MEM_freeN(pa->rectz); pa->rectz= NULL;
- MEM_freeN(pa->clipflag); pa->clipflag= NULL;
}
/* SSS preprocess tile render, fully threadable */
@@ -1181,7 +1194,7 @@ typedef struct ZBufSSSHandle {
int totps;
} ZBufSSSHandle;
-static void addps_sss(void *cb_handle, int facenr, int x, int y, int z)
+static void addps_sss(void *cb_handle, int obi, int facenr, int x, int y, int z)
{
ZBufSSSHandle *handle = cb_handle;
RenderPart *pa= handle->pa;
@@ -1196,54 +1209,50 @@ static void addps_sss(void *cb_handle, int facenr, int x, int y, int z)
if(pa->rectall) {
long *rs= pa->rectall + pa->rectx*y + x;
- addps(&handle->psmlist, rs, facenr, z, 0);
+ addps(&handle->psmlist, rs, obi, facenr, z, 0);
handle->totps++;
}
if(pa->rectz) {
int *rz= pa->rectz + pa->rectx*y + x;
int *rp= pa->rectp + pa->rectx*y + x;
+ int *ro= pa->recto + pa->rectx*y + x;
if(z < *rz) {
if(*rp == 0)
handle->totps++;
*rz= z;
*rp= facenr;
+ *ro= obi;
}
}
if(pa->rectbackz) {
int *rz= pa->rectbackz + pa->rectx*y + x;
int *rp= pa->rectbackp + pa->rectx*y + x;
+ int *ro= pa->rectbacko + pa->rectx*y + x;
if(z >= *rz) {
if(*rp == 0)
handle->totps++;
*rz= z;
*rp= facenr;
+ *ro= obi;
}
}
}
-static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area)
+static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRen *obi, VlakRen *vlr, int quad, float x, float y, float z, float *co, float *color, float *area)
{
ShadeInput *shi= ssamp->shi;
ShadeResult shr;
float texfac, orthoarea, nor[3];
- /* normal flipping must be disabled to make back scattering work, so that
- backside faces actually face any lighting from the back */
- shi->puno= 0;
-
/* cache for shadow */
shi->samplenr++;
if(quad)
- shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
else
- shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
-
- /* we don't want flipped normals, they screw up back scattering */
- if(vlr->noflag & R_FLIPPED_NO)
- VecMulf(shi->facenor, -1.0f);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
/* center pixel */
x += 0.5f;
@@ -1269,8 +1278,12 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, in
shade_input_set_uv(shi);
shade_input_set_normals(shi);
+ /* we don't want flipped normals, they screw up back scattering */
+ if(shi->flippednor)
+ shade_input_flip_normals(shi);
+
/* not a pretty solution, but fixes common cases */
- if(vlr->ob && vlr->ob->transflag & OB_NEG_SCALE) {
+ if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
VecMulf(shi->vn, -1.0f);
VecMulf(shi->vno, -1.0f);
}
@@ -1311,15 +1324,16 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, VlakRen *vlr, in
static void zbufshade_sss_free(RenderPart *pa)
{
- MEM_freeN(pa->clipflag); pa->clipflag= NULL;
#if 0
MEM_freeN(pa->rectall); pa->rectall= NULL;
freeps(&handle.psmlist);
#else
MEM_freeN(pa->rectz); pa->rectz= NULL;
MEM_freeN(pa->rectp); pa->rectp= NULL;
+ MEM_freeN(pa->recto); pa->recto= NULL;
MEM_freeN(pa->rectbackz); pa->rectbackz= NULL;
MEM_freeN(pa->rectbackp); pa->rectbackp= NULL;
+ MEM_freeN(pa->rectbacko); pa->rectbacko= NULL;
#endif
}
@@ -1334,15 +1348,13 @@ void zbufshade_sss_tile(RenderPart *pa)
Material *mat= re->sss_mat;
float (*co)[3], (*color)[3], *area, *fcol= rl->rectf;
int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS);
- int *rz, *rp, *rbz, *rbp;
+ int *ro, *rz, *rp, *rbo, *rbz, *rbp;
#if 0
PixStr *ps;
long *rs;
int z;
#endif
- set_part_zbuf_clipflag(pa);
-
/* setup pixelstr list and buffer for zbuffering */
handle.pa= pa;
handle.totps= 0;
@@ -1353,8 +1365,10 @@ void zbufshade_sss_tile(RenderPart *pa)
pa->rectall= MEM_callocN(sizeof(long)*pa->rectx*pa->recty+4, "rectall");
#else
+ pa->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
+ pa->rectbacko= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbacko");
pa->rectbackp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackp");
pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz");
#endif
@@ -1397,8 +1411,10 @@ void zbufshade_sss_tile(RenderPart *pa)
#else
rz= pa->rectz;
rp= pa->rectp;
+ ro= pa->recto;
rbz= pa->rectbackz;
rbp= pa->rectbackp;
+ rbo= pa->rectbacko;
#endif
totpoint= 0;
@@ -1411,11 +1427,13 @@ void zbufshade_sss_tile(RenderPart *pa)
if(rs) {
/* for each sample in this pixel, shade it */
for(ps=(PixStr*)*rs; ps; ps=ps->next) {
- vlr= RE_findOrAddVlak(re, (ps->facenr-1) & RE_QUAD_MASK);
+ ObjectInstanceRen *obi= &re->objectinstance[ps->obi];
+ ObjectRen *obr= obi->obr;
+ vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK);
quad= (ps->facenr & RE_QUAD_OFFS);
z= ps->z;
- shade_sample_sss(&ssamp, mat, vlr, quad, x, y, z,
+ shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, z,
co[totpoint], color[totpoint], &area[totpoint]);
totpoint++;
@@ -1429,11 +1447,14 @@ void zbufshade_sss_tile(RenderPart *pa)
#else
if(rp) {
if(*rp != 0) {
+ ObjectInstanceRen *obi= &re->objectinstance[*ro];
+ ObjectRen *obr= obi->obr;
+
/* shade front */
- vlr= RE_findOrAddVlak(re, (*rp-1) & RE_QUAD_MASK);
+ vlr= RE_findOrAddVlak(obr, (*rp-1) & RE_QUAD_MASK);
quad= ((*rp) & RE_QUAD_OFFS);
- shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rz,
+ shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rz,
co[totpoint], color[totpoint], &area[totpoint]);
VECADD(fcol, fcol, color[totpoint]);
@@ -1441,16 +1462,19 @@ void zbufshade_sss_tile(RenderPart *pa)
totpoint++;
}
- rp++; rz++;
+ rp++; rz++; ro++;
}
if(rbp) {
- if(*rbp != 0 && *rbp != *(rp-1)) {
+ if(*rbp != 0 && !(*rbp == *(rp-1) && *rbo == *(ro-1))) {
+ ObjectInstanceRen *obi= &re->objectinstance[*rbo];
+ ObjectRen *obr= obi->obr;
+
/* shade back */
- vlr= RE_findOrAddVlak(re, (*rbp-1) & RE_QUAD_MASK);
+ vlr= RE_findOrAddVlak(obr, (*rbp-1) & RE_QUAD_MASK);
quad= ((*rbp) & RE_QUAD_OFFS);
- shade_sample_sss(&ssamp, mat, vlr, quad, x, y, *rbz,
+ shade_sample_sss(&ssamp, mat, obi, vlr, quad, x, y, *rbz,
co[totpoint], color[totpoint], &area[totpoint]);
/* to indicate this is a back sample */
@@ -1461,7 +1485,7 @@ void zbufshade_sss_tile(RenderPart *pa)
totpoint++;
}
- rbz++; rbp++;
+ rbz++; rbp++; rbo++;
}
#endif
}
@@ -1637,7 +1661,7 @@ void add_halo_flare(Render *re)
{
RenderResult *rr= re->result;
RenderLayer *rl;
- HaloRen *har = NULL;
+ HaloRen *har;
int a, mode, do_draw=0;
/* for now, we get the first renderlayer in list with halos set */
@@ -1654,8 +1678,7 @@ void add_halo_flare(Render *re)
project_renderdata(&R, projectverto, 0, 0, 0);
for(a=0; a<R.tothalo; a++) {
- if((a & 255)==0) har= R.bloha[a>>8];
- else har++;
+ har= R.sortedhalos[a];
if(har->flarec) {
do_draw= 1;
@@ -1708,6 +1731,7 @@ void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr)
typedef struct BakeShade {
ShadeSample ssamp;
+ ObjectInstanceRen *obi;
VlakRen *vlr;
ZSpan *zspan;
@@ -1723,34 +1747,31 @@ typedef struct BakeShade {
float *rect_float;
} BakeShade;
-static void bake_set_shade_input(VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v)
+static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v)
{
if(isect) {
/* raytrace intersection with different u,v than scanconvert */
if(vlr->v4) {
if(quad)
- shade_input_set_triangle_i(shi, vlr, 2, 1, 3);
+ shade_input_set_triangle_i(shi, obi, vlr, 2, 1, 3);
else
- shade_input_set_triangle_i(shi, vlr, 0, 1, 3);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 3);
}
else
- shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
}
else {
/* regular scanconvert */
if(quad)
- shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
else
- shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
}
/* set up view vector */
VECCOPY(shi->view, shi->co);
Normalize(shi->view);
- /* no face normal flip */
- shi->puno= 0;
-
/* cache for shadow */
shi->samplenr++;
@@ -1760,13 +1781,18 @@ static void bake_set_shade_input(VlakRen *vlr, ShadeInput *shi, int quad, int is
shi->ys= y;
shade_input_set_normals(shi);
+
+ /* no normal flip */
+ if(shi->flippednor)
+ shade_input_flip_normals(shi);
}
-static void bake_shade(void *handle, Object *ob, VlakRen *vlr, ShadeInput *shi, int quad, int x, int y, float u, float v, float *tvn, float *ttang)
+static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int x, int y, float u, float v, float *tvn, float *ttang)
{
BakeShade *bs= handle;
ShadeSample *ssamp= &bs->ssamp;
ShadeResult shr;
+ VlakRen *vlr= shi->vlr;
/* init material vars */
memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h
@@ -1850,9 +1876,9 @@ static int bake_check_intersect(Isect *is, RayFace *face)
BakeShade *bs = (BakeShade*)is->userdata;
/* no direction checking for now, doesn't always improve the result
- * (INPR(vlr->n, bs->dir) > 0.0f); */
+ * (INPR(shi->facenor, bs->dir) > 0.0f); */
- return (vlr->ob != bs->actob);
+ return (vlr->obr->ob != bs->actob);
}
static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *dir, float sign, float *hitco)
@@ -1884,7 +1910,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
{
BakeShade *bs= handle;
VlakRen *vlr= bs->vlr;
- Object *ob= vlr->ob;
+ ObjectInstanceRen *obi= bs->obi;
+ Object *ob= obi->obr->ob;
float l, *v1, *v2, *v3, tvn[3], ttang[3];
int quad;
ShadeSample *ssamp= &bs->ssamp;
@@ -1913,8 +1940,11 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulVecfl(obi->mat, shi->co);
+
quad= bs->quad;
- bake_set_shade_input(vlr, shi, quad, 0, x, y, u, v);
+ bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);
if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) {
shade_input_set_shade_texco(shi);
@@ -1940,6 +1970,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
VECCOPY(isec.start, shi->co);
isec.mode= RE_RAY_MIRROR;
isec.faceorig= (RayFace*)vlr;
+ isec.oborig= RAY_OBJECT_SET(&R, obi);
isec.userdata= bs;
if(bake_intersect_tree(R.raytree, &isec, shi->vn, sign, co)) {
@@ -1954,77 +1985,86 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
/* if hit, we shade from the new point, otherwise from point one starting face */
if(hit) {
vlr= (VlakRen*)minisec.face;
+ obi= RAY_OBJECT_GET(&R, minisec.ob);
quad= (minisec.isect == 2);
VECCOPY(shi->co, minco);
u= -minisec.u;
v= -minisec.v;
- bake_set_shade_input(vlr, shi, quad, 1, x, y, u, v);
+ bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
}
}
if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT)
- bake_shade(handle, ob, vlr, shi, quad, x, y, u, v, tvn, ttang);
+ bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
else
- bake_shade(handle, ob, vlr, shi, quad, x, y, u, v, 0, 0);
+ bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0);
}
static int get_next_bake_face(BakeShade *bs)
{
+ ObjectRen *obr;
VlakRen *vlr;
MTFace *tface;
static int v= 0, vdone= 0;
+ static ObjectInstanceRen *obi= NULL;
if(bs==NULL) {
vlr= NULL;
v= vdone= 0;
+ obi= R.instancetable.first;
return 0;
}
BLI_lock_thread(LOCK_CUSTOM1);
-
- for(; v<R.totvlak; v++) {
- vlr= RE_findOrAddVlak(&R, v);
-
- if((bs->actob && bs->actob == vlr->ob) || (!bs->actob && (vlr->ob->flag & SELECT))) {
- tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0);
- if(tface && tface->tpage) {
- Image *ima= tface->tpage;
- ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
- float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
-
- if(ibuf==NULL)
- continue;
-
- if(ibuf->rect==NULL && ibuf->rect_float==NULL)
- continue;
-
- if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
- continue;
-
- /* find the image for the first time? */
- if(ima->id.flag & LIB_DOIT) {
- ima->id.flag &= ~LIB_DOIT;
+ for(; obi; obi=obi->next, v=0) {
+ obr= obi->obr;
+
+ for(; v<obr->totvlak; v++) {
+ vlr= RE_findOrAddVlak(obr, v);
+
+ if((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
+ tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
+
+ if(tface && tface->tpage) {
+ Image *ima= tface->tpage;
+ ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+ float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
- /* we either fill in float or char, this ensures things go fine */
- if(ibuf->rect_float)
- imb_freerectImBuf(ibuf);
- /* clear image */
- if(R.r.bake_flag & R_BAKE_CLEAR)
- IMB_rectfill(ibuf, vec);
-
- /* might be read by UI to set active image for display */
- R.bakebuf= ima;
- }
-
- bs->vlr= vlr;
-
- bs->vdone++; /* only for error message if nothing was rendered */
- v++;
-
- BLI_unlock_thread(LOCK_CUSTOM1);
- return 1;
+ if(ibuf==NULL)
+ continue;
+
+ if(ibuf->rect==NULL && ibuf->rect_float==NULL)
+ continue;
+
+ if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
+ continue;
+
+ /* find the image for the first time? */
+ if(ima->id.flag & LIB_DOIT) {
+ ima->id.flag &= ~LIB_DOIT;
+
+ /* we either fill in float or char, this ensures things go fine */
+ if(ibuf->rect_float)
+ imb_freerectImBuf(ibuf);
+ /* clear image */
+ if(R.r.bake_flag & R_BAKE_CLEAR)
+ IMB_rectfill(ibuf, vec);
+
+ /* might be read by UI to set active image for display */
+ R.bakebuf= ima;
+ }
+
+ bs->obi= obi;
+ bs->vlr= vlr;
+
+ bs->vdone++; /* only for error message if nothing was rendered */
+ v++;
+
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 1;
+ }
}
}
}
@@ -2037,7 +2077,9 @@ static int get_next_bake_face(BakeShade *bs)
static void shade_tface(BakeShade *bs)
{
VlakRen *vlr= bs->vlr;
- MTFace *tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0);
+ ObjectInstanceRen *obi= bs->obi;
+ ObjectRen *obr= obi->obr;
+ MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
Image *ima= tface->tpage;
float vec[4][2];
int a, i1, i2, i3;
@@ -2099,6 +2141,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
ListBase threads;
Image *ima;
int a, vdone=0;
+
+ /* initialize render global */
+ R= *re;
+ R.bakebuf= NULL;
/* initialize static vars */
get_next_bake_face(NULL);
@@ -2107,10 +2153,6 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
for(ima= G.main->image.first; ima; ima= ima->id.next)
ima->id.flag |= LIB_DOIT;
- /* initialize render global */
- R= *re;
- R.bakebuf= NULL;
-
BLI_init_threads(&threads, do_bake_thread, re->r.threads);
/* get the threads running */
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 1d490637222..3906b1fc001 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -62,6 +62,7 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLI_memarena.h"
#include "DNA_material_types.h"
@@ -104,30 +105,30 @@
#define RE_UV_ELEMS 2
#define RE_SURFNOR_ELEMS 3
-float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
{
float *sticky;
int nr= ver->index>>8;
- sticky= re->vertnodes[nr].sticky;
+ sticky= obr->vertnodes[nr].sticky;
if(sticky==NULL) {
if(verify)
- sticky= re->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
+ sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
else
return NULL;
}
return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
}
-float *RE_vertren_get_stress(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
{
float *stress;
int nr= ver->index>>8;
- stress= re->vertnodes[nr].stress;
+ stress= obr->vertnodes[nr].stress;
if(stress==NULL) {
if(verify)
- stress= re->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
+ stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
else
return NULL;
}
@@ -135,30 +136,30 @@ float *RE_vertren_get_stress(Render *re, VertRen *ver, int verify)
}
/* this one callocs! */
-float *RE_vertren_get_rad(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
{
float *rad;
int nr= ver->index>>8;
- rad= re->vertnodes[nr].rad;
+ rad= obr->vertnodes[nr].rad;
if(rad==NULL) {
if(verify)
- rad= re->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
+ rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
else
return NULL;
}
return rad + (ver->index & 255)*RE_RAD_ELEMS;
}
-float *RE_vertren_get_strand(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
{
float *strand;
int nr= ver->index>>8;
- strand= re->vertnodes[nr].strand;
+ strand= obr->vertnodes[nr].strand;
if(strand==NULL) {
if(verify)
- strand= re->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
+ strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
else
return NULL;
}
@@ -166,15 +167,15 @@ float *RE_vertren_get_strand(Render *re, VertRen *ver, int verify)
}
/* needs calloc */
-float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
{
float *tangent;
int nr= ver->index>>8;
- tangent= re->vertnodes[nr].tangent;
+ tangent= obr->vertnodes[nr].tangent;
if(tangent==NULL) {
if(verify)
- tangent= re->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
+ tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
else
return NULL;
}
@@ -182,64 +183,62 @@ float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify)
}
/* needs calloc! not all renderverts have them */
-float *RE_vertren_get_winspeed(Render *re, VertRen *ver, int verify)
+/* also winspeed is exception, it is stored per instance */
+float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
{
float *winspeed;
- int nr= ver->index>>8;
+ int totvector;
- winspeed= re->vertnodes[nr].winspeed;
+ winspeed= obi->vectors;
if(winspeed==NULL) {
- if(verify)
- winspeed= re->vertnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
+ if(verify) {
+ totvector= obi->obr->totvert + obi->obr->totstrand;
+ winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
+ }
else
return NULL;
}
- return winspeed + (ver->index & 255)*RE_WINSPEED_ELEMS;
+ return winspeed + ver->index*RE_WINSPEED_ELEMS;
}
-VertRen *RE_vertren_copy(Render *re, VertRen *ver)
+VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
{
- VertRen *v1= RE_findOrAddVert(re, re->totvert++);
+ VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
float *fp1, *fp2;
int index= v1->index;
*v1= *ver;
v1->index= index;
- fp1= RE_vertren_get_sticky(re, ver, 0);
+ fp1= RE_vertren_get_sticky(obr, ver, 0);
if(fp1) {
- fp2= RE_vertren_get_sticky(re, v1, 1);
+ fp2= RE_vertren_get_sticky(obr, v1, 1);
memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
}
- fp1= RE_vertren_get_stress(re, ver, 0);
+ fp1= RE_vertren_get_stress(obr, ver, 0);
if(fp1) {
- fp2= RE_vertren_get_stress(re, v1, 1);
+ fp2= RE_vertren_get_stress(obr, v1, 1);
memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
}
- fp1= RE_vertren_get_rad(re, ver, 0);
+ fp1= RE_vertren_get_rad(obr, ver, 0);
if(fp1) {
- fp2= RE_vertren_get_rad(re, v1, 1);
+ fp2= RE_vertren_get_rad(obr, v1, 1);
memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
}
- fp1= RE_vertren_get_strand(re, ver, 0);
+ fp1= RE_vertren_get_strand(obr, ver, 0);
if(fp1) {
- fp2= RE_vertren_get_strand(re, v1, 1);
+ fp2= RE_vertren_get_strand(obr, v1, 1);
memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
}
- fp1= RE_vertren_get_tangent(re, ver, 0);
+ fp1= RE_vertren_get_tangent(obr, ver, 0);
if(fp1) {
- fp2= RE_vertren_get_tangent(re, v1, 1);
+ fp2= RE_vertren_get_tangent(obr, v1, 1);
memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
}
- fp1= RE_vertren_get_winspeed(re, ver, 0);
- if(fp1) {
- fp2= RE_vertren_get_winspeed(re, v1, 1);
- memcpy(fp2, fp1, RE_WINSPEED_ELEMS*sizeof(float));
- }
return v1;
}
-VertRen *RE_findOrAddVert(Render *re, int nr)
+VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
{
VertTableNode *temp;
VertRen *v;
@@ -251,23 +250,23 @@ VertRen *RE_findOrAddVert(Render *re, int nr)
}
a= nr>>8;
- if (a>=re->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */
- temp= re->vertnodes;
+ if (a>=obr->vertnodeslen-1) { /* Need to allocate more columns..., and keep last element NULL for free loop */
+ temp= obr->vertnodes;
- re->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(re->vertnodeslen+TABLEINITSIZE) , "vertnodes");
- if(temp) memcpy(re->vertnodes, temp, re->vertnodeslen*sizeof(VertTableNode));
- memset(re->vertnodes+re->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
+ obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE) , "vertnodes");
+ if(temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode));
+ memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
- re->vertnodeslen+=TABLEINITSIZE;
+ obr->vertnodeslen+=TABLEINITSIZE;
if(temp) MEM_freeN(temp);
}
- v= re->vertnodes[a].vert;
+ v= obr->vertnodes[a].vert;
if(v==NULL) {
int i;
v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
- re->vertnodes[a].vert= v;
+ obr->vertnodes[a].vert= v;
for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
v[a].index= i;
@@ -279,120 +278,94 @@ VertRen *RE_findOrAddVert(Render *re, int nr)
/* ------------------------------------------------------------------------ */
-MTFace *RE_vlakren_get_tface(Render *re, VlakRen *vlr, int n, char **name, int verify)
+MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
{
VlakTableNode *node;
int nr= vlr->index>>8, vlakindex= (vlr->index&255);
int index= (n<<8) + vlakindex;
- node= &re->vlaknodes[nr];
+ node= &obr->vlaknodes[nr];
if(verify) {
if(n>=node->totmtface) {
- MTFace **mtface= node->mtface;
+ MTFace *mtface= node->mtface;
int size= size= (n+1)*256;
- node->mtface= MEM_callocN(size*sizeof(MTFace*), "Vlak mtface");
+ node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
if(mtface) {
size= node->totmtface*256;
- memcpy(node->mtface, mtface, size*sizeof(MTFace*));
+ memcpy(node->mtface, mtface, size*sizeof(MTFace));
MEM_freeN(mtface);
}
node->totmtface= n+1;
-
- if (!node->names) {
- size= sizeof(*node->names)*256;
- node->names= MEM_callocN(size, "Vlak names");
- }
- }
-
- if(node->mtface[index]==NULL) {
- node->mtface[index]= BLI_memarena_alloc(re->memArena,
- sizeof(MTFace)*RE_MTFACE_ELEMS);
-
- node->names[vlakindex]= re->customdata_names.last;
}
}
else {
- if(n>=node->totmtface || node->mtface[index]==NULL)
+ if(n>=node->totmtface)
return NULL;
- if(name) *name= node->names[vlakindex]->mtface[n];
+ if(name) *name= obr->mtface[n];
}
- return node->mtface[index];
+ return node->mtface + index;
}
-MCol *RE_vlakren_get_mcol(Render *re, VlakRen *vlr, int n, char **name, int verify)
+MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
{
VlakTableNode *node;
int nr= vlr->index>>8, vlakindex= (vlr->index&255);
int index= (n<<8) + vlakindex;
- node= &re->vlaknodes[nr];
+ node= &obr->vlaknodes[nr];
if(verify) {
if(n>=node->totmcol) {
- MCol **mcol= node->mcol;
+ MCol *mcol= node->mcol;
int size= (n+1)*256;
- node->mcol= MEM_callocN(size*sizeof(MCol*), "Vlak mcol");
+ node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
if(mcol) {
size= node->totmcol*256;
- memcpy(node->mcol, mcol, size*sizeof(MCol*));
+ memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
MEM_freeN(mcol);
}
node->totmcol= n+1;
-
- if (!node->names) {
- size= sizeof(*node->names)*256;
- node->names= MEM_callocN(size, "Vlak names");
- }
- }
-
- if(node->mcol[index]==NULL) {
- node->mcol[index]= BLI_memarena_alloc(re->memArena,
- sizeof(MCol)*RE_MCOL_ELEMS);
-
- node->names[vlakindex]= re->customdata_names.last;
}
}
else {
- if(n>=node->totmcol || node->mcol[index]==NULL)
+ if(n>=node->totmcol)
return NULL;
- if(name) *name= node->names[vlakindex]->mcol[n];
+ if(name) *name= obr->mcol[n];
}
- return node->mcol[index];
+ return node->mcol + index*RE_MCOL_ELEMS;
}
-float *RE_vlakren_get_surfnor(Render *re, VlakRen *vlak, int verify)
+float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
{
float *surfnor;
int nr= vlak->index>>8;
- surfnor= re->vlaknodes[nr].surfnor;
+ surfnor= obr->vlaknodes[nr].surfnor;
if(surfnor==NULL) {
if(verify)
- surfnor= re->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
+ surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
else
return NULL;
}
return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
}
-VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
+VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
{
- VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++);
+ VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
MTFace *mtface, *mtface1;
MCol *mcol, *mcol1;
- VlakTableNode *node = &re->vlaknodes[vlr->index>>8];
- VlakTableNode *node1 = &re->vlaknodes[vlr1->index>>8];
float *surfnor, *surfnor1;
int i, index = vlr1->index;
char *name;
@@ -400,72 +373,101 @@ VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
*vlr1= *vlr;
vlr1->index= index;
- for (i=0; (mtface=RE_vlakren_get_tface(re, vlr, i, &name, 0)) != NULL; i++) {
- mtface1= RE_vlakren_get_tface(re, vlr1, i, &name, 1);
+ for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
+ mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
}
- for (i=0; (mcol=RE_vlakren_get_mcol(re, vlr, i, &name, 0)) != NULL; i++) {
- mcol1= RE_vlakren_get_mcol(re, vlr1, i, &name, 1);
+ for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
+ mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
}
- surfnor= RE_vlakren_get_surfnor(re, vlr, 0);
+ surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
if(surfnor) {
- surfnor1= RE_vlakren_get_surfnor(re, vlr1, 1);
+ surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
VECCOPY(surfnor1, surfnor);
}
- if (node->names && node1->names)
- node1->names[vlr1->index&255] = node->names[vlr->index&255];
-
return vlr1;
}
-static int vlakren_remap_layer_num(int n, int active)
+int RE_vlakren_get_normal(Render *re, ObjectInstanceRen *obi, VlakRen *vlr, float *nor)
{
- /* make the active layer the first */
- if (n == active) return 0;
- else if (n < active) return n+1;
- else return n;
+ float xn, yn, zn, v1[3];
+ float (*imat)[3]= obi->imat;
+ int flipped= 0;
+
+ if(obi->flag & R_TRANSFORMED) {
+ xn= vlr->n[0];
+ yn= vlr->n[1];
+ zn= vlr->n[2];
+
+ /* transpose! */
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ }
+ else
+ VECCOPY(nor, vlr->n);
+
+ if((vlr->flag & R_NOPUNOFLIP)==0) {
+ if(re->r.mode & R_ORTHO) {
+ if(nor[2] > 0.0f)
+ flipped= 1;
+ }
+ else {
+ VECCOPY(v1, vlr->v1->co);
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulVecfl(obi->mat, v1);
+ if(INPR(v1, nor) < 0.0f) {
+ flipped= 1;
+ }
+ }
+
+ if(flipped) {
+ nor[0]= -nor[0];
+ nor[1]= -nor[1];
+ nor[2]= -nor[2];
+ }
+ }
+
+ return flipped;
}
-void RE_vlakren_set_customdata_names(Render *re, CustomData *data)
+void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
{
/* CustomData layer names are stored per object here, because the
DerivedMesh which stores the layers is freed */
- CustomDataNames *cdn= MEM_callocN(sizeof(*cdn), "CustomDataNames");
CustomDataLayer *layer;
- int numlayers, i, mtfn, mcn, n;
-
- BLI_addtail(&re->customdata_names, cdn);
+ int numlayers, i, mtfn, mcn;
if (CustomData_has_layer(data, CD_MTFACE)) {
numlayers= CustomData_number_of_layers(data, CD_MTFACE);
- cdn->mtface= MEM_callocN(sizeof(*cdn->mtface)*numlayers, "mtfacenames");
+ obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numlayers, "mtfacenames");
}
if (CustomData_has_layer(data, CD_MCOL)) {
numlayers= CustomData_number_of_layers(data, CD_MCOL);
- cdn->mcol= MEM_callocN(sizeof(*cdn->mcol)*numlayers, "mcolnames");
+ obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numlayers, "mcolnames");
}
for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
layer= &data->layers[i];
if (layer->type == CD_MTFACE) {
- n= vlakren_remap_layer_num(mtfn++, layer->active_rnd);
- strcpy(cdn->mtface[n], layer->name);
+ strcpy(obr->mtface[mtfn++], layer->name);
+ obr->actmtface= layer->active_rnd;
}
else if (layer->type == CD_MCOL) {
- n= vlakren_remap_layer_num(mcn++, layer->active_rnd);
- strcpy(cdn->mcol[n], layer->name);
+ strcpy(obr->mcol[mcn++], layer->name);
+ obr->actmcol= layer->active_rnd;
}
}
}
-VlakRen *RE_findOrAddVlak(Render *re, int nr)
+VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
{
VlakTableNode *temp;
VlakRen *v;
@@ -473,28 +475,28 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr)
if(nr<0) {
printf("error in findOrAddVlak: %d\n",nr);
- return re->vlaknodes[0].vlak;
+ return obr->vlaknodes[0].vlak;
}
a= nr>>8;
- if (a>=re->vlaknodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
- temp= re->vlaknodes;
+ if (a>=obr->vlaknodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
+ temp= obr->vlaknodes;
- re->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(re->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
- if(temp) memcpy(re->vlaknodes, temp, re->vlaknodeslen*sizeof(VlakTableNode));
- memset(re->vlaknodes+re->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
+ obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
+ if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
+ memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
- re->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
+ obr->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
if(temp) MEM_freeN(temp);
}
- v= re->vlaknodes[a].vlak;
+ v= obr->vlaknodes[a].vlak;
if(v==NULL) {
int i;
v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
- re->vlaknodes[a].vlak= v;
+ obr->vlaknodes[a].vlak= v;
for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
v[a].index= i;
@@ -505,129 +507,108 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr)
/* ------------------------------------------------------------------------ */
-float *RE_strandren_get_winspeed(Render *re, StrandRen *strand, int verify)
-{
- float *winspeed;
- int nr= strand->index>>8;
-
- winspeed= re->strandnodes[nr].winspeed;
- if(winspeed==NULL) {
- if(verify)
- winspeed= re->strandnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
- else
- return NULL;
- }
- return winspeed + (strand->index & 255)*RE_WINSPEED_ELEMS;
-}
-
-float *RE_strandren_get_surfnor(Render *re, StrandRen *strand, int verify)
+float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
{
float *surfnor;
int nr= strand->index>>8;
- surfnor= re->strandnodes[nr].surfnor;
+ surfnor= obr->strandnodes[nr].surfnor;
if(surfnor==NULL) {
if(verify)
- surfnor= re->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
+ surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
else
return NULL;
}
return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
}
-float *RE_strandren_get_uv(Render *re, StrandRen *strand, int n, char **name, int verify)
+float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
{
StrandTableNode *node;
int nr= strand->index>>8, strandindex= (strand->index&255);
int index= (n<<8) + strandindex;
- node= &re->strandnodes[nr];
+ node= &obr->strandnodes[nr];
if(verify) {
if(n>=node->totuv) {
- float **uv= node->uv;
+ float *uv= node->uv;
int size= (n+1)*256;
- node->uv= MEM_callocN(size*sizeof(float*), "Strand uv");
+ node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "Strand uv");
if(uv) {
size= node->totuv*256;
- memcpy(node->uv, uv, size*sizeof(float*));
+ memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
MEM_freeN(uv);
}
node->totuv= n+1;
-
- if (!node->names) {
- size= sizeof(*node->names)*256;
- node->names= MEM_callocN(size, "Strand names");
- }
- }
-
- if(node->uv[index]==NULL) {
- node->uv[index]= BLI_memarena_alloc(re->memArena,
- sizeof(float)*RE_UV_ELEMS);
-
- node->names[strandindex]= re->customdata_names.last;
}
}
else {
- if(n>=node->totuv || node->uv[index]==NULL)
+ if(n>=node->totuv)
return NULL;
- if(name) *name= node->names[strandindex]->mtface[n];
+ if(name) *name= obr->mtface[n];
}
- return node->uv[index];
+ return node->uv + index*RE_UV_ELEMS;
}
-MCol *RE_strandren_get_mcol(Render *re, StrandRen *strand, int n, char **name, int verify)
+MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
{
StrandTableNode *node;
int nr= strand->index>>8, strandindex= (strand->index&255);
int index= (n<<8) + strandindex;
- node= &re->strandnodes[nr];
+ node= &obr->strandnodes[nr];
if(verify) {
if(n>=node->totmcol) {
- MCol **mcol= node->mcol;
+ MCol *mcol= node->mcol;
int size= (n+1)*256;
- node->mcol= MEM_callocN(size*sizeof(MCol*), "Strand mcol");
+ node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Strand mcol");
if(mcol) {
size= node->totmcol*256;
- memcpy(node->mcol, mcol, size*sizeof(MCol*));
+ memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
MEM_freeN(mcol);
}
node->totmcol= n+1;
-
- if (!node->names) {
- size= sizeof(*node->names)*256;
- node->names= MEM_callocN(size, "Strand names");
- }
- }
-
- if(node->mcol[index]==NULL) {
- node->mcol[index]= BLI_memarena_alloc(re->memArena,
- sizeof(MCol)*RE_MCOL_ELEMS);
-
- node->names[strandindex]= re->customdata_names.last;
}
}
else {
- if(n>=node->totmcol || node->mcol[index]==NULL)
+ if(n>=node->totmcol)
return NULL;
- if(name) *name= node->names[strandindex]->mcol[n];
+ if(name) *name= obr->mcol[n];
}
- return node->mcol[index];
+ return node->mcol + index*RE_MCOL_ELEMS;
+}
+
+/* winspeed is exception, it is stored per instance */
+float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
+{
+ float *winspeed;
+ int totvector;
+
+ winspeed= obi->vectors;
+ if(winspeed==NULL) {
+ if(verify) {
+ totvector= obi->obr->totvert + obi->obr->totstrand;
+ winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
+ }
+ else
+ return NULL;
+ }
+ return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
}
-StrandRen *RE_findOrAddStrand(Render *re, int nr)
+StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
{
StrandTableNode *temp;
StrandRen *v;
@@ -635,28 +616,28 @@ StrandRen *RE_findOrAddStrand(Render *re, int nr)
if(nr<0) {
printf("error in findOrAddStrand: %d\n",nr);
- return re->strandnodes[0].strand;
+ return obr->strandnodes[0].strand;
}
a= nr>>8;
- if (a>=re->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
- temp= re->strandnodes;
+ if (a>=obr->strandnodeslen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
+ temp= obr->strandnodes;
- re->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(re->strandnodeslen+TABLEINITSIZE) , "strandnodes");
- if(temp) memcpy(re->strandnodes, temp, re->strandnodeslen*sizeof(StrandTableNode));
- memset(re->strandnodes+re->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
+ obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes");
+ if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
+ memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
- re->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
+ obr->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
if(temp) MEM_freeN(temp);
}
- v= re->strandnodes[a].strand;
+ v= obr->strandnodes[a].strand;
if(v==NULL) {
int i;
v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
- re->strandnodes[a].strand= v;
+ obr->strandnodes[a].strand= v;
for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
v[a].index= i;
@@ -665,36 +646,38 @@ StrandRen *RE_findOrAddStrand(Render *re, int nr)
return v;
}
-StrandBuffer *RE_addStrandBuffer(Render *re, Object *ob, int totvert)
+StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
{
StrandBuffer *strandbuf;
strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
strandbuf->totvert= totvert;
- strandbuf->ob= ob;
+ strandbuf->obr= obr;
- BLI_addtail(&re->strandbufs, strandbuf);
+ BLI_addtail(&obr->strandbufs, strandbuf);
return strandbuf;
}
/* ------------------------------------------------------------------------ */
-void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est)
+ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex)
{
- ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct");
+ ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
BLI_addtail(&re->objecttable, obr);
obr->ob= ob;
obr->par= par;
obr->index= index;
- obr->startvert= sve;
- obr->endvert= eve;
- obr->startface= sfa;
- obr->endface= efa;
- obr->startstrand= sst;
- obr->endstrand= est;
+ obr->psysindex= psysindex;
+
+ if(!re->objecthash)
+ re->objecthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ if(!BLI_ghash_lookup(re->objecthash, ob))
+ BLI_ghash_insert(re->objecthash, ob, obr);
+
+ return obr;
}
void free_renderdata_vertnodes(VertTableNode *vertnodes)
@@ -738,8 +721,6 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
MEM_freeN(vlaknodes[a].mcol);
if(vlaknodes[a].surfnor)
MEM_freeN(vlaknodes[a].surfnor);
- if(vlaknodes[a].names)
- MEM_freeN(vlaknodes[a].names);
}
MEM_freeN(vlaknodes);
@@ -762,8 +743,6 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes)
MEM_freeN(strandnodes[a].winspeed);
if(strandnodes[a].surfnor)
MEM_freeN(strandnodes[a].surfnor);
- if(strandnodes[a].names)
- MEM_freeN(strandnodes[a].names);
}
MEM_freeN(strandnodes);
@@ -771,35 +750,72 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes)
void free_renderdata_tables(Render *re)
{
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
StrandBuffer *strandbuf;
- CustomDataNames *cdn;
int a=0;
- if(re->bloha) {
- for(a=0; re->bloha[a]; a++)
- MEM_freeN(re->bloha[a]);
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ if(obr->vertnodes) {
+ free_renderdata_vertnodes(obr->vertnodes);
+ obr->vertnodes= NULL;
+ obr->vertnodeslen= 0;
+ }
+
+ if(obr->vlaknodes) {
+ free_renderdata_vlaknodes(obr->vlaknodes);
+ obr->vlaknodes= NULL;
+ obr->vlaknodeslen= 0;
+ obr->totvlak= 0;
+ }
+
+ if(obr->bloha) {
+ for(a=0; obr->bloha[a]; a++)
+ MEM_freeN(obr->bloha[a]);
+
+ MEM_freeN(obr->bloha);
+ obr->bloha= NULL;
+ obr->blohalen= 0;
+ }
+
+ if(obr->strandnodes) {
+ free_renderdata_strandnodes(obr->strandnodes);
+ obr->strandnodes= NULL;
+ obr->strandnodeslen= 0;
+ }
+
+ for(strandbuf=obr->strandbufs.first; strandbuf; strandbuf=strandbuf->next)
+ if(strandbuf->vert) MEM_freeN(strandbuf->vert);
+ BLI_freelistN(&obr->strandbufs);
- MEM_freeN(re->bloha);
- re->bloha= NULL;
- re->blohalen= 0;
+ if(obr->mtface)
+ MEM_freeN(obr->mtface);
+ if(obr->mcol)
+ MEM_freeN(obr->mcol);
}
- if(re->vertnodes) {
- free_renderdata_vertnodes(re->vertnodes);
- re->vertnodes= NULL;
- re->vertnodeslen= 0;
+ if(re->objectinstance) {
+ for(obi=re->instancetable.first; obi; obi=obi->next)
+ if(obi->vectors)
+ MEM_freeN(obi->vectors);
+
+ MEM_freeN(re->objectinstance);
+ re->objectinstance= NULL;
+ re->totinstance= 0;
+ re->instancetable.first= re->instancetable.last= NULL;
}
+ else {
+ BLI_freelistN(&re->instancetable);
- if(re->vlaknodes) {
- free_renderdata_vlaknodes(re->vlaknodes);
- re->vlaknodes= NULL;
- re->vlaknodeslen= 0;
+ if(re->objecthash) {
+ BLI_ghash_free(re->objecthash, NULL, NULL);
+ re->objecthash= NULL;
+ }
}
- if(re->strandnodes) {
- free_renderdata_strandnodes(re->strandnodes);
- re->strandnodes= NULL;
- re->strandnodeslen= 0;
+ if(re->sortedhalos) {
+ MEM_freeN(re->sortedhalos);
+ re->sortedhalos= NULL;
}
if(re->strandbuckets) {
@@ -807,25 +823,13 @@ void free_renderdata_tables(Render *re)
re->strandbuckets= NULL;
}
- for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) {
- if(cdn->mtface)
- MEM_freeN(cdn->mtface);
- if(cdn->mcol)
- MEM_freeN(cdn->mcol);
- }
-
- for(strandbuf=re->strandbufs.first; strandbuf; strandbuf=strandbuf->next)
- if(strandbuf->vert) MEM_freeN(strandbuf->vert);
- BLI_freelistN(&re->strandbufs);
-
BLI_freelistN(&re->customdata_names);
BLI_freelistN(&re->objecttable);
}
-
/* ------------------------------------------------------------------------ */
-HaloRen *RE_findOrAddHalo(Render *re, int nr)
+HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
{
HaloRen *h, **temp;
int a;
@@ -836,22 +840,22 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr)
}
a= nr>>8;
- if (a>=re->blohalen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
+ if (a>=obr->blohalen-1){ /* Need to allocate more columns..., and keep last element NULL for free loop */
//printf("Allocating %i more halo groups. %i total.\n",
- // TABLEINITSIZE, re->blohalen+TABLEINITSIZE );
- temp=re->bloha;
+ // TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
+ temp=obr->bloha;
- re->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(re->blohalen+TABLEINITSIZE) , "Bloha");
- if(temp) memcpy(re->bloha, temp, re->blohalen*sizeof(void*));
- memset(&(re->bloha[re->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
- re->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
+ obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
+ if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
+ memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
+ obr->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
if(temp) MEM_freeN(temp);
}
- h= re->bloha[a];
+ h= obr->bloha[a];
if(h==NULL) {
h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
- re->bloha[a]= h;
+ obr->bloha[a]= h;
}
h+= (nr & 255);
return h;
@@ -859,7 +863,7 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr)
/* ------------------------------------------------------------------------- */
-HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1,
+HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, float *vec, float *vec1,
float *orco, float hasize, float vectsize, int seed)
{
HaloRen *har;
@@ -876,7 +880,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1,
if(hoco1[3]==0.0) return NULL;
}
- har= RE_findOrAddHalo(re, re->tothalo++);
+ har= RE_findOrAddHalo(obr, obr->tothalo++);
VECCOPY(har->co, vec);
har->hasize= hasize;
@@ -969,7 +973,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma, float *vec, float *vec1,
return har;
}
-HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma, float *vec, float *vec1,
+HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, float *vec, float *vec1,
float *orco, float *uvco, float hasize, float vectsize, int seed)
{
HaloRen *har;
@@ -987,7 +991,7 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma, float
if(hoco1[3]==0.0) return NULL;
}
- har= RE_findOrAddHalo(re, re->tothalo++);
+ har= RE_findOrAddHalo(obr, obr->tothalo++);
VECCOPY(har->co, vec);
har->hasize= hasize;
@@ -1153,8 +1157,7 @@ static int panotestclip(Render *re, int do_pano, float *v)
void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets)
{
- VlakRen *vlr = NULL;
- VertRen *ver = NULL;
+ ObjectRen *obr;
HaloRen *har = NULL;
float zn, vec[3], hoco[4];
int a;
@@ -1165,113 +1168,76 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
re->panosi= sin(panophi);
re->panoco= cos(panophi);
}
-
- /* calculate view coordinates (and zbuffer value) */
- for(a=0; a< re->totvert;a++) {
- if((a & 255)==0) ver= RE_findOrAddVert(re, a);
- else ver++;
-
- if(do_pano) {
- vec[0]= re->panoco*ver->co[0] + re->panosi*ver->co[2];
- vec[1]= ver->co[1];
- vec[2]= -re->panosi*ver->co[0] + re->panoco*ver->co[2];
- }
- else {
- VECCOPY(vec, ver->co);
- }
- /* Go from wcs to hcs ... */
- projectfunc(vec, re->winmat, ver->ho);
- /* ... and clip in that system. */
- ver->clip = testclip(ver->ho);
- /*
- Because all other ops are performed in other systems, this is
- the only thing that has to be done.
- */
- }
- /* calculate view coordinates (and zbuffer value) */
- for(a=0; a<re->tothalo; a++) {
- if((a & 255)==0) har= re->bloha[a>>8];
- else har++;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ /* calculate view coordinates (and zbuffer value) */
+ for(a=0; a<obr->tothalo; a++) {
+ if((a & 255)==0) har= obr->bloha[a>>8];
+ else har++;
- if(do_pano) {
- vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
- vec[1]= har->co[1];
- vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
- }
- else {
- VECCOPY(vec, har->co);
- }
+ if(do_pano) {
+ vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
+ vec[1]= har->co[1];
+ vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
+ }
+ else {
+ VECCOPY(vec, har->co);
+ }
- projectfunc(vec, re->winmat, hoco);
-
- /* we clip halos less critical, but not for the Z */
- hoco[0]*= 0.5;
- hoco[1]*= 0.5;
-
- if( panotestclip(re, do_pano, hoco) ) {
- har->miny= har->maxy= -10000; /* that way render clips it */
- }
- else if(hoco[3]<0.0) {
- har->miny= har->maxy= -10000; /* render clips it */
- }
- else /* do the projection...*/
- {
- /* bring back hocos */
- hoco[0]*= 2.0;
- hoco[1]*= 2.0;
+ projectfunc(vec, re->winmat, hoco);
- zn= hoco[3];
- har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
- har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
-
- /* this should be the zbuffer coordinate */
- har->zs= 0x7FFFFF*(hoco[2]/zn);
- /* taking this from the face clip functions? seems ok... */
- har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+ /* we clip halos less critical, but not for the Z */
+ hoco[0]*= 0.5;
+ hoco[1]*= 0.5;
- vec[0]+= har->hasize;
- projectfunc(vec, re->winmat, hoco);
- vec[0]-= har->hasize;
- zn= hoco[3];
- har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
-
- /* this clip is not really OK, to prevent stars to become too large */
- if(har->type & HA_ONLYSKY) {
- if(har->rad>3.0) har->rad= 3.0;
+ if( panotestclip(re, do_pano, hoco) ) {
+ har->miny= har->maxy= -10000; /* that way render clips it */
}
-
- har->radsq= har->rad*har->rad;
-
- har->miny= har->ys - har->rad/re->ycor;
- har->maxy= har->ys + har->rad/re->ycor;
-
- /* the Zd value is still not really correct for pano */
-
- vec[2]-= har->hasize; /* z negative, otherwise it's clipped */
- projectfunc(vec, re->winmat, hoco);
- zn= hoco[3];
- zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
- har->zd= CLAMPIS(zn, 0, INT_MAX);
-
- }
-
- }
-
- /* set flags at 0 if clipped away */
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
-
- if(!re->excludeob || vlr->ob != re->excludeob) {
- vlr->flag |= R_VISIBLE;
- if(vlr->v4) {
- if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE;
+ else if(hoco[3]<0.0) {
+ har->miny= har->maxy= -10000; /* render clips it */
}
- else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE;
+ else /* do the projection...*/
+ {
+ /* bring back hocos */
+ hoco[0]*= 2.0;
+ hoco[1]*= 2.0;
+
+ zn= hoco[3];
+ har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
+ har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
+
+ /* this should be the zbuffer coordinate */
+ har->zs= 0x7FFFFF*(hoco[2]/zn);
+ /* taking this from the face clip functions? seems ok... */
+ har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+
+ vec[0]+= har->hasize;
+ projectfunc(vec, re->winmat, hoco);
+ vec[0]-= har->hasize;
+ zn= hoco[3];
+ har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
+
+ /* this clip is not really OK, to prevent stars to become too large */
+ if(har->type & HA_ONLYSKY) {
+ if(har->rad>3.0) har->rad= 3.0;
+ }
+
+ har->radsq= har->rad*har->rad;
+
+ har->miny= har->ys - har->rad/re->ycor;
+ har->maxy= har->ys + har->rad/re->ycor;
+
+ /* the Zd value is still not really correct for pano */
+
+ vec[2]-= har->hasize; /* z negative, otherwise it's clipped */
+ projectfunc(vec, re->winmat, hoco);
+ zn= hoco[3];
+ zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
+ har->zd= CLAMPIS(zn, 0, INT_MAX);
+
+ }
+
}
- else
- vlr->flag &= ~R_VISIBLE;
}
project_strands(re, projectfunc, do_pano, do_buckets);
@@ -1279,56 +1245,67 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
/* ------------------------------------------------------------------------- */
-void set_normalflags(Render *re)
+void RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4])
{
- VlakRen *vlr = NULL;
- float *v1, xn, yn, zn;
- int a1, doflip;
-
- /* switch normal 'snproj' values (define which axis is the optimal one for calculations) */
- for(a1=0; a1<re->totvlak; a1++) {
- if((a1 & 255)==0) vlr= re->vlaknodes[a1>>8].vlak;
- else vlr++;
-
- vlr->noflag= 0;
+ ObjectInstanceRen *obi;
+ float mat3[3][3];
+
+ obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
+ obi->obr= obr;
+ obi->ob= ob;
+ obi->par= par;
+ obi->index= index;
+ obi->psysindex= psysindex;
+
+ if(mat) {
+ Mat4CpyMat4(obi->mat, mat);
+ Mat3CpyMat4(mat3, mat);
+ Mat3Inv(obi->imat, mat3);
+ obi->flag |= R_DUPLI_TRANSFORMED;
+ }
- /* abuse of this flag... this is code that just sets face normal in direction of camera */
- /* that convention we should get rid of */
- if((vlr->flag & R_NOPUNOFLIP)==0) {
-
- doflip= 0;
- if(re->r.mode & R_ORTHO) {
- if(vlr->n[2]>0.0) doflip= 1;
- }
- else {
- v1= vlr->v1->co;
- if( (v1[0]*vlr->n[0] +v1[1]*vlr->n[1] +v1[2]*vlr->n[2])<0.0 ) doflip= 1;
- }
- if(doflip) {
- vlr->n[0]= -vlr->n[0];
- vlr->n[1]= -vlr->n[1];
- vlr->n[2]= -vlr->n[2];
- vlr->noflag |= R_FLIPPED_NO;
- }
+ BLI_addtail(&re->instancetable, obi);
+}
+
+void RE_makeRenderInstances(Render *re)
+{
+ ObjectInstanceRen *obi, *oldobi;
+ ListBase newlist;
+ int tot;
+
+ /* convert list of object instances to an array for index based lookup */
+ tot= BLI_countlist(&re->instancetable);
+ re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
+ re->totinstance= tot;
+ newlist.first= newlist.last= NULL;
+
+ obi= re->objectinstance;
+ for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
+ *obi= *oldobi;
+
+ if(!obi->obr) {
+ /* dupli objects are created after object instances, so they were
+ * stored in a object -> objectren hash, we do lookup of the actual
+ * pointer here */
+ if(re->objecthash && (obi->obr=BLI_ghash_lookup(re->objecthash, obi->ob)))
+ while(obi->obr && obi->obr->psysindex != obi->psysindex)
+ obi->obr= obi->obr->next;
}
-
- /* recalculate puno. Displace & flipped matrices can screw up */
- vlr->puno= 0;
- if(!(vlr->flag & R_TANGENT)) {
- if( Inpf(vlr->n, vlr->v1->n) < 0.0 ) vlr->puno |= ME_FLIPV1;
- if( Inpf(vlr->n, vlr->v2->n) < 0.0 ) vlr->puno |= ME_FLIPV2;
- if( Inpf(vlr->n, vlr->v3->n) < 0.0 ) vlr->puno |= ME_FLIPV3;
- if(vlr->v4 && Inpf(vlr->n, vlr->v4->n) < 0.0 ) vlr->puno |= ME_FLIPV4;
- }
- xn= fabs(vlr->n[0]);
- yn= fabs(vlr->n[1]);
- zn= fabs(vlr->n[2]);
- if(zn>=xn && zn>=yn) vlr->noflag |= R_SNPROJ_X;
- else if(yn>=xn && yn>=zn) vlr->noflag |= R_SNPROJ_Y;
- else vlr->noflag |= R_SNPROJ_Z;
+ if(obi->obr) {
+ obi->prev= obi->next= NULL;
+ BLI_addtail(&newlist, obi);
+ obi++;
+ }
+ else
+ re->totinstance--;
+ }
+
+ if(re->objecthash) {
+ BLI_ghash_free(re->objecthash, NULL, NULL);
+ re->objecthash= NULL;
}
+ BLI_freelistN(&re->instancetable);
+ re->instancetable= newlist;
}
-
-
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 006a26dc82e..b424a0688fd 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -279,72 +279,82 @@ static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square)
/* sets start/end clipping. lar->shb should be initialized */
static void shadowbuf_autoclip(Render *re, LampRen *lar)
{
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
VlakRen *vlr= NULL;
VertRen *ver= NULL;
Material *ma= NULL;
- float minz, maxz, vec[3], viewmat[4][4];
+ float minz, maxz, vec[3], viewmat[4][4], obviewmat[4][4];
unsigned int lay = -1;
- int a, ok= 1;
+ int i, a, ok= 1;
+ char *clipflag;
minz= 1.0e30f; maxz= -1.0e30f;
Mat4CpyMat4(viewmat, lar->shb->viewmat);
if(lar->mode & LA_LAYER) lay= lar->lay;
-
- /* clear clip, is being set if face is visible (clip is calculated for real later) */
- for(a=0; a<re->totvert; a++) {
- if((a & 255)==0) ver= RE_findOrAddVert(re, a);
- else ver++;
-
- ver->clip= 0;
- }
-
+
+ clipflag= MEM_callocN(sizeof(char)*re->totvert, "autoclipflag");
+
/* set clip in vertices when face visible */
- for(a=0; a<re->totvlak; a++) {
-
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
-
- /* note; these conditions are copied from zbuffer_shadow() */
- if(vlr->mat!= ma) {
- ma= vlr->mat;
- ok= 1;
- if((ma->mode & MA_SHADBUF)==0) ok= 0;
- }
-
- if(ok && (vlr->lay & lay)) {
- vlr->v1->clip= 1;
- vlr->v2->clip= 1;
- vlr->v3->clip= 1;
- if(vlr->v4) vlr->v4->clip= 1;
- }
- }
-
- /* calculate min and max */
- for(a=0; a< re->totvert;a++) {
- if((a & 255)==0) ver= RE_findOrAddVert(re, a);
- else ver++;
+ for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
+ obr= obi->obr;
+
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(obviewmat, obi->mat, viewmat);
+ else
+ Mat4CpyMat4(obviewmat, viewmat);
+
+ memset(clipflag, 0, sizeof(char)*obr->totvert);
+
+ /* clear clip, is being set if face is visible (clip is calculated for real later) */
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+
+ /* note; these conditions are copied from zbuffer_shadow() */
+ if(vlr->mat!= ma) {
+ ma= vlr->mat;
+ ok= 1;
+ if((ma->mode & MA_SHADBUF)==0) ok= 0;
+ }
+
+ if(ok && (vlr->lay & lay)) {
+ clipflag[vlr->v1->index]= 1;
+ clipflag[vlr->v2->index]= 1;
+ clipflag[vlr->v3->index]= 1;
+ if(vlr->v4) clipflag[vlr->v4->index]= 1;
+ }
+ }
- if(ver->clip) {
- VECCOPY(vec, ver->co);
- Mat4MulVecfl(viewmat, vec);
- /* Z on visible side of lamp space */
- if(vec[2] < 0.0f) {
- float inpr, z= -vec[2];
-
- /* since vec is rotated in lampspace, this is how to get the cosine of angle */
- /* precision is set 20% larger */
- vec[2]*= 1.2f;
- Normalize(vec);
- inpr= - vec[2];
-
- if(inpr>=lar->spotsi) {
- if(z<minz) minz= z;
- if(z>maxz) maxz= z;
+ /* calculate min and max */
+ for(a=0; a< obr->totvert;a++) {
+ if((a & 255)==0) ver= RE_findOrAddVert(obr, a);
+ else ver++;
+
+ if(clipflag[a]) {
+ VECCOPY(vec, ver->co);
+ Mat4MulVecfl(obviewmat, vec);
+ /* Z on visible side of lamp space */
+ if(vec[2] < 0.0f) {
+ float inpr, z= -vec[2];
+
+ /* since vec is rotated in lampspace, this is how to get the cosine of angle */
+ /* precision is set 20% larger */
+ vec[2]*= 1.2f;
+ Normalize(vec);
+ inpr= - vec[2];
+
+ if(inpr>=lar->spotsi) {
+ if(z<minz) minz= z;
+ if(z>maxz) maxz= z;
+ }
}
}
}
}
+
+ MEM_freeN(clipflag);
/* set clipping min and max */
if(minz < maxz) {
@@ -391,7 +401,7 @@ void makeshadowbuf(Render *re, LampRen *lar)
MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
if(ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY)) {
- /* jitter, weights */
+ /* jitter, weights - not threadsafe! */
shb->jit= give_jitter_tab(shb->samp);
make_jitter_weight_tab(shb, lar->filtertype);
@@ -400,24 +410,16 @@ void makeshadowbuf(Render *re, LampRen *lar)
else if(shb->totbuf==9) jitbuf= give_jitter_tab(3);
else jitbuf= twozero;
- /* temp, will be restored */
- MTC_Mat4SwapMat4(shb->persmat, re->winmat);
-
- project_renderdata(re, projectvert, 0, 0, 0);
-
/* zbuffering */
rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf");
for(samples=0; samples<shb->totbuf; samples++) {
- zbuffer_shadow(re, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]);
+ zbuffer_shadow(re, shb->persmat, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]);
/* create Z tiles (for compression): this system is 24 bits!!! */
compress_shadowbuf(shb, rectz, lar->mode & LA_SQUARE);
}
MEM_freeN(rectz);
-
- /* old matrix back */
- MTC_Mat4SwapMat4(shb->persmat, re->winmat);
/* printf("lampbuf %d\n", sizeoflampbuf(shb)); */
}
@@ -884,6 +886,7 @@ typedef struct ISBBranch {
typedef struct BSPFace {
Boxf box;
float *v1, *v2, *v3, *v4;
+ int obi; /* object for face lookup */
int facenr; /* index to retrieve VlakRen */
int type; /* only for strand now */
short shad_alpha, is_full;
@@ -1063,7 +1066,7 @@ static int isb_bsp_insert(ISBBranch *root, MemArena *memarena, ISBSample *sample
/* insert */
bspn->samples[bspn->totsamp]= sample;
bspn->totsamp++;
-
+
/* split if allowed and needed */
if(bspn->totsamp==BSPMAX_SAMPLE) {
if(i==BSPMAX_DEPTH) {
@@ -1262,7 +1265,7 @@ static void isb_bsp_face_inside(ISBBranch *bspn, BSPFace *face)
for(a=bspn->totsamp-1; a>=0; a--) {
ISBSample *samp= bspn->samples[a];
- if(samp->facenr!=face->facenr && samp->shadfac) {
+ if((samp->facenr!=face->facenr || samp->obi!=face->obi) && samp->shadfac) {
if(face->box.zmin < samp->zco[2]) {
if(BLI_in_rctf((rctf *)&face->box, samp->zco[0], samp->zco[1])) {
int inshadow= 0;
@@ -1308,7 +1311,7 @@ static void isb_bsp_recalc_box(ISBBranch *root)
}
/* callback function for zbuf clip */
-static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void isb_bsp_test_strand(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
BSPFace face;
@@ -1316,6 +1319,7 @@ static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, f
face.v2= v2;
face.v3= v3;
face.v4= v4;
+ face.obi= obi;
face.facenr= zvlnr & ~RE_QUAD_OFFS;
face.type= R_STRAND;
if(R.osa)
@@ -1341,7 +1345,7 @@ static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, f
}
/* callback function for zbuf clip */
-static void isb_bsp_test_face(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void isb_bsp_test_face(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
BSPFace face;
@@ -1349,6 +1353,7 @@ static void isb_bsp_test_face(ZSpan *zspan, int zvlnr, float *v1, float *v2, flo
face.v2= v2;
face.v3= v3;
face.v4= v4;
+ face.obi= obi;
face.facenr= zvlnr & ~RE_QUAD_OFFS;
face.type= 0;
if(R.osa)
@@ -1386,13 +1391,15 @@ static int testclip_minmax(float *ho, float *minmax)
/* main loop going over all faces and check in bsp overlaps, fill in shadfac values */
static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root)
{
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
ShadBuf *shb= lar->shb;
ZSpan zspan, zspanstrand;
VlakRen *vlr= NULL;
Material *ma= NULL;
- float minmaxf[4];
+ float minmaxf[4], winmat[4][4];
int size= shb->size;
- int a, ok=1, lay= -1;
+ int i, a, ok=1, lay= -1;
/* further optimize, also sets minz maxz */
isb_bsp_recalc_box(root);
@@ -1422,74 +1429,90 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root)
zspan.zbuffunc= isb_bsp_test_face;
zspanstrand.zbuffunc= isb_bsp_test_strand;
- for(a=0; a<re->totvlak; a++) {
-
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
-
- /* note, these conditions are copied in shadowbuf_autoclip() */
- if(vlr->mat!= ma) {
- ma= vlr->mat;
- ok= 1;
- if((ma->mode & MA_SHADBUF)==0) ok= 0;
- if(ma->mode & MA_WIRE) ok= 0;
- zspanstrand.shad_alpha= zspan.shad_alpha= ma->shad_alpha;
- }
-
- if(ok && (vlr->lay & lay)) {
- float hoco[4][4];
- int c1, c2, c3, c4=0;
- int d1, d2, d3, d4=0;
- int partclip;
+ for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
+ obr= obi->obr;
+
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(winmat, obi->mat, shb->persmat);
+ else
+ Mat4CpyMat4(winmat, shb->persmat);
+
+ for(a=0; a<obr->totvlak; a++) {
- /* create hocos per face, it is while render */
- projectvert(vlr->v1->co, shb->persmat, hoco[0]); d1= testclip_minmax(hoco[0], minmaxf);
- projectvert(vlr->v2->co, shb->persmat, hoco[1]); d2= testclip_minmax(hoco[1], minmaxf);
- projectvert(vlr->v3->co, shb->persmat, hoco[2]); d3= testclip_minmax(hoco[2], minmaxf);
- if(vlr->v4) {
- projectvert(vlr->v4->co, shb->persmat, hoco[3]); d4= testclip_minmax(hoco[3], minmaxf);
- }
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
- /* minmax clipping */
- if(vlr->v4) partclip= d1 & d2 & d3 & d4;
- else partclip= d1 & d2 & d3;
+ /* note, these conditions are copied in shadowbuf_autoclip() */
+ if(vlr->mat!= ma) {
+ ma= vlr->mat;
+ ok= 1;
+ if((ma->mode & MA_SHADBUF)==0) ok= 0;
+ if(ma->mode & MA_WIRE) ok= 0;
+ zspanstrand.shad_alpha= zspan.shad_alpha= ma->shad_alpha;
+ }
- if(partclip==0) {
+ if(ok && (vlr->lay & lay)) {
+ float hoco[4][4];
+ int c1, c2, c3, c4=0;
+ int d1, d2, d3, d4=0;
+ int partclip;
- /* window clipping */
- c1= testclip(hoco[0]);
- c2= testclip(hoco[1]);
- c3= testclip(hoco[2]);
- if(vlr->v4)
- c4= testclip(hoco[3]);
+ /* create hocos per face, it is while render */
+ projectvert(vlr->v1->co, winmat, hoco[0]); d1= testclip_minmax(hoco[0], minmaxf);
+ projectvert(vlr->v2->co, winmat, hoco[1]); d2= testclip_minmax(hoco[1], minmaxf);
+ projectvert(vlr->v3->co, winmat, hoco[2]); d3= testclip_minmax(hoco[2], minmaxf);
+ if(vlr->v4) {
+ projectvert(vlr->v4->co, winmat, hoco[3]); d4= testclip_minmax(hoco[3], minmaxf);
+ }
+
+ /* minmax clipping */
+ if(vlr->v4) partclip= d1 & d2 & d3 & d4;
+ else partclip= d1 & d2 & d3;
- /* ***** NO WIRE YET */
- if(ma->mode & MA_WIRE)
- zbufclipwire(&zspan, a+1, vlr);
- else if(vlr->v4) {
- if(vlr->flag & R_STRAND)
- zbufclip4(&zspanstrand, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ if(partclip==0) {
+
+ /* window clipping */
+ c1= testclip(hoco[0]);
+ c2= testclip(hoco[1]);
+ c3= testclip(hoco[2]);
+ if(vlr->v4)
+ c4= testclip(hoco[3]);
+
+ /* ***** NO WIRE YET */
+ if(ma->mode & MA_WIRE) {
+ if(vlr->v4)
+ zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ else
+ zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], 0, c1, c2, c3, 0);
+ }
+ else if(vlr->v4) {
+ if(vlr->flag & R_STRAND)
+ zbufclip4(&zspanstrand, i, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ else
+ zbufclip4(&zspan, i, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ }
else
- zbufclip4(&zspan, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ zbufclip(&zspan, i, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3);
+
}
- else
- zbufclip(&zspan, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3);
-
}
}
}
zbuf_free_span(&zspan);
-
}
-
/* returns 1 when the viewpixel is visible in lampbuffer */
-static int viewpixel_to_lampbuf(ShadBuf *shb, VlakRen *vlr, float x, float y, float *co)
+static int viewpixel_to_lampbuf(ShadBuf *shb, ObjectInstanceRen *obi, VlakRen *vlr, float x, float y, float *co)
{
- float hoco[4], *v1= vlr->v1->co, *nor= vlr->n;
+ float hoco[4], v1[3], nor[3];
float dface, fac, siz;
+ RE_vlakren_get_normal(&R, obi, vlr, nor);
+ VECCOPY(v1, vlr->v1->co);
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulVecfl(obi->mat, v1);
+
/* from shadepixel() */
dface= v1[0]*nor[0] + v1[1]*nor[1] + v1[2]*nor[2];
hoco[3]= 1.0f;
@@ -1550,7 +1573,7 @@ static int viewpixel_to_lampbuf(ShadBuf *shb, VlakRen *vlr, float x, float y, fl
}
/* storage of shadow results, solid osa and transp case */
-static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int facenr, short shadfac, short samples)
+static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int obi, int facenr, short shadfac, short samples)
{
ISBShadfacA *new;
float shadfacf;
@@ -1562,6 +1585,7 @@ static void isb_add_shadfac(ISBShadfacA **isbsapp, MemArena *mem, int facenr, sh
shadfacf= ((float)shadfac)/(4096.0);
new= BLI_memarena_alloc(mem, sizeof(ISBShadfacA));
+ new->obi= obi;
new->facenr= facenr & ~RE_QUAD_OFFS;
new->shadfac= shadfacf;
if(*isbsapp)
@@ -1619,7 +1643,7 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar)
ISBBranch root;
MemArena *memarena;
long *rd;
- int *rectp, x, y, sindex, sample, bsp_err=0;
+ int *recto, *rectp, x, y, sindex, sample, bsp_err=0;
/* storage for shadow, per thread */
isbdata= shb->isb_result[pa->thread];
@@ -1669,11 +1693,14 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar)
ps= ps->next;
}
if(ps && ps->facenr>0) {
- VlakRen *vlr= RE_findOrAddVlak(&R, (ps->facenr-1) & RE_QUAD_MASK);
+ ObjectInstanceRen *obi= &R.objectinstance[ps->obi];
+ ObjectRen *obr= obi->obr;
+ VlakRen *vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK);
samp= samplebuf[sample] + sindex;
/* convert image plane pixel location to lamp buffer space */
- if(viewpixel_to_lampbuf(shb, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], samp->zco)) {
+ if(viewpixel_to_lampbuf(shb, obi, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], samp->zco)) {
+ samp->obi= ps->obi;
samp->facenr= ps->facenr & ~RE_QUAD_OFFS;
ps->shadfac= 0;
samp->shadfac= &ps->shadfac;
@@ -1685,14 +1712,18 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar)
}
else {
rectp= pa->rectp + sindex;
+ recto= pa->recto + sindex;
if(*rectp>0) {
- VlakRen *vlr= RE_findOrAddVlak(&R, (*rectp-1) & RE_QUAD_MASK);
+ ObjectInstanceRen *obi= &R.objectinstance[*recto];
+ ObjectRen *obr= obi->obr;
+ VlakRen *vlr= RE_findOrAddVlak(obr, (*rectp-1) & RE_QUAD_MASK);
float xs= (float)(x + pa->disprect.xmin);
float ys= (float)(y + pa->disprect.ymin);
samp= samplebuf[0] + sindex;
/* convert image plane pixel location to lamp buffer space */
- if(viewpixel_to_lampbuf(shb, vlr, xs, ys, samp->zco)) {
+ if(viewpixel_to_lampbuf(shb, obi, vlr, xs, ys, samp->zco)) {
+ samp->obi= *recto;
samp->facenr= *rectp & ~RE_QUAD_OFFS;
samp->shadfac= isbdata->shadfacs + sindex;
bound_rectf((rctf *)&root.box, samp->zco);
@@ -1729,7 +1760,7 @@ static void isb_make_buffer(RenderPart *pa, LampRen *lar)
PixStr *ps= (PixStr *)(*rd);
while(ps) {
if(ps->shadfac)
- isb_add_shadfac(isbsa, isbdata->memarena, ps->facenr, ps->shadfac, count_mask(ps->mask));
+ isb_add_shadfac(isbsa, isbdata->memarena, ps->obi, ps->facenr, ps->shadfac, count_mask(ps->mask));
ps= ps->next;
}
}
@@ -1857,7 +1888,9 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la
int a;
for(a=0; a<4; a++) {
if(apn->p[a]) {
- VlakRen *vlr= RE_findOrAddVlak(&R, (apn->p[a]-1) & RE_QUAD_MASK);
+ ObjectInstanceRen *obi= &R.objectinstance[apn->obi[a]];
+ ObjectRen *obr= obi->obr;
+ VlakRen *vlr= RE_findOrAddVlak(obr, (apn->p[a]-1) & RE_QUAD_MASK);
float zco[3];
/* here we store shadfac, easier to create the end storage buffer. needs zero'ed, multiple shadowbufs use it */
@@ -1870,8 +1903,9 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la
if(apn->mask[a] & mask) {
/* convert image plane pixel location to lamp buffer space */
- if(viewpixel_to_lampbuf(shb, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], zco)) {
+ if(viewpixel_to_lampbuf(shb, obi, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], zco)) {
samp= isb_alloc_sample_transp(samplebuf[sample] + sindex, memarena);
+ samp->obi= apn->obi[a];
samp->facenr= apn->p[a] & ~RE_QUAD_OFFS;
samp->shadfac= &apn->shadfac[a];
@@ -1884,9 +1918,10 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la
else {
/* convert image plane pixel location to lamp buffer space */
- if(viewpixel_to_lampbuf(shb, vlr, xs, ys, zco)) {
+ if(viewpixel_to_lampbuf(shb, obi, vlr, xs, ys, zco)) {
samp= isb_alloc_sample_transp(samplebuf[0] + sindex, memarena);
+ samp->obi= apn->obi[a];
samp->facenr= apn->p[a] & ~RE_QUAD_OFFS;
samp->shadfac= &apn->shadfac[a];
@@ -1930,9 +1965,9 @@ static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *la
for(a=0; a<4; a++) {
if(apn->p[a] && apn->shadfac[a]) {
if(R.osa)
- isb_add_shadfac(isbsa, isbdata->memarena, apn->p[a], apn->shadfac[a], count_mask(apn->mask[a]));
+ isb_add_shadfac(isbsa, isbdata->memarena, apn->obi[a], apn->p[a], apn->shadfac[a], count_mask(apn->mask[a]));
else
- isb_add_shadfac(isbsa, isbdata->memarena, apn->p[a], apn->shadfac[a], 0);
+ isb_add_shadfac(isbsa, isbdata->memarena, apn->obi[a], apn->p[a], apn->shadfac[a], 0);
}
}
}
@@ -1977,10 +2012,11 @@ float ISB_getshadow(ShadeInput *shi, ShadBuf *shb)
}
else {
int sindex= y*isbdata->rectx + x;
+ int obi= shi->obi - R.objectinstance;
ISBShadfacA *isbsa= *(isbdata->shadfaca + sindex);
while(isbsa) {
- if(isbsa->facenr==shi->facenr+1)
+ if(isbsa->facenr==shi->facenr+1 && isbsa->obi==obi)
return isbsa->shadfac>=1.0f?0.0f:1.0f - isbsa->shadfac;
isbsa= isbsa->next;
}
@@ -2044,7 +2080,3 @@ void ISB_free(RenderPart *pa)
}
}
-
-
-
-
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index acd04910565..f937218cdb6 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -50,6 +50,7 @@
#include "shading.h"
#include "strand.h"
#include "texture.h"
+#include "zbuf.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
@@ -122,7 +123,6 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
if(shi->depth==0) {
if(R.r.mode & R_RAYTRACE) {
if(shi->ray_mirror!=0.0f || ((shi->mat->mode & MA_RAYTRANSP) && shr->alpha!=1.0f)) {
-
/* ray trace works on combined, but gives pass info */
ray_trace(shi, shr);
}
@@ -209,14 +209,28 @@ void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3)
}
}
+static void normal_transform(float imat[][3], float *nor)
+{
+ float xn, yn, zn;
+
+ xn= nor[0];
+ yn= nor[1];
+ zn= nor[2];
+
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+}
/* copy data from face to ShadeInput, general case */
-/* indices 0 1 2 3 only. shi->puno should be set! */
-void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i2, short i3)
+/* indices 0 1 2 3 only */
+void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen *vlr, short i1, short i2, short i3)
{
VertRen **vpp= &vlr->v1;
shi->vlr= vlr;
+ shi->obi= obi;
+ shi->obr= obi->obr;
shi->v1= vpp[i1];
shi->v2= vpp[i2];
@@ -231,40 +245,45 @@ void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i
shi->osatex= (shi->mat->texco & TEXCO_OSA);
shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */
+
+ /* facenormal copy, can get flipped */
+ shi->flippednor= RE_vlakren_get_normal(&R, obi, vlr, shi->facenor);
+
+ /* copy of original pre-flipped normal, for geometry->front/back node output */
+ VECCOPY(shi->orignor, shi->facenor);
+ if(shi->flippednor)
+ VECMUL(shi->orignor, -1.0f);
/* calculate vertexnormals */
if(vlr->flag & R_SMOOTH) {
- float *n1= shi->v1->n, *n2= shi->v2->n, *n3= shi->v3->n;
- char p1, p2, p3;
-
- p1= 1<<i1;
- p2= 1<<i2;
- p3= 1<<i3;
-
- if(shi->puno & p1) {
- shi->n1[0]= -n1[0]; shi->n1[1]= -n1[1]; shi->n1[2]= -n1[2];
- } else {
- VECCOPY(shi->n1, n1);
- }
- if(shi->puno & p2) {
- shi->n2[0]= -n2[0]; shi->n2[1]= -n2[1]; shi->n2[2]= -n2[2];
- } else {
- VECCOPY(shi->n2, n2);
+ VECCOPY(shi->n1, shi->v1->n);
+ VECCOPY(shi->n2, shi->v2->n);
+ VECCOPY(shi->n3, shi->v3->n);
+
+ if(obi->flag & R_TRANSFORMED) {
+ normal_transform(obi->imat, shi->n1);
+ normal_transform(obi->imat, shi->n2);
+ normal_transform(obi->imat, shi->n3);
}
- if(shi->puno & p3) {
- shi->n3[0]= -n3[0]; shi->n3[1]= -n3[1]; shi->n3[2]= -n3[2];
- } else {
- VECCOPY(shi->n3, n3);
+
+ if(!(vlr->flag & (R_NOPUNOFLIP|R_TANGENT))) {
+ if(INPR(shi->facenor, shi->n1) < 0.0f) {
+ shi->n1[0]= -shi->n1[0];
+ shi->n1[1]= -shi->n1[1];
+ shi->n1[2]= -shi->n1[2];
+ }
+ if(INPR(shi->facenor, shi->n2) < 0.0f) {
+ shi->n2[0]= -shi->n2[0];
+ shi->n2[1]= -shi->n2[1];
+ shi->n2[2]= -shi->n2[2];
+ }
+ if(INPR(shi->facenor, shi->n3) < 0.0f) {
+ shi->n3[0]= -shi->n3[0];
+ shi->n3[1]= -shi->n3[1];
+ shi->n3[2]= -shi->n3[2];
+ }
}
}
- /* facenormal copy, can get flipped */
- VECCOPY(shi->facenor, vlr->n);
-
- /* copy of original pre-flipped normal, for geometry->front/back node output */
- VECCOPY(shi->orignor, vlr->n);
- if (vlr->noflag & R_FLIPPED_NO) {
- VECMUL(shi->orignor, -1.0f);
- }
}
/* note, facenr declared volatile due to over-eager -O2 optimizations
@@ -272,26 +291,25 @@ void shade_input_set_triangle_i(ShadeInput *shi, VlakRen *vlr, short i1, short i
*/
/* copy data from face to ShadeInput, scanline case */
-void shade_input_set_triangle(ShadeInput *shi, volatile int facenr, int normal_flip)
+void shade_input_set_triangle(ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip)
{
if(facenr>0) {
+ shi->obi= &R.objectinstance[obi];
+ shi->obr= shi->obi->obr;
shi->facenr= (facenr-1) & RE_QUAD_MASK;
- if( shi->facenr < R.totvlak ) {
- VlakRen *vlr= RE_findOrAddVlak(&R, shi->facenr);
-
- shi->puno= normal_flip?vlr->puno:0;
+ if( shi->facenr < shi->obr->totvlak ) {
+ VlakRen *vlr= RE_findOrAddVlak(shi->obr, shi->facenr);
if(facenr & RE_QUAD_OFFS)
- shade_input_set_triangle_i(shi, vlr, 0, 2, 3);
+ shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 2, 3);
else
- shade_input_set_triangle_i(shi, vlr, 0, 1, 2);
+ shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 1, 2);
}
else
shi->vlr= NULL; /* general signal we got sky */
}
else
shi->vlr= NULL; /* general signal we got sky */
-
}
/* full osa case: copy static info */
@@ -310,8 +328,6 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo
shi->osatex= (shi->mat->texco & TEXCO_OSA);
shi->mode= shi->mat->mode_l; /* or-ed result for all nodes */
- shi->puno= 0; /* always faces camera automatically */
-
/* shade_input_set_viewco equivalent */
VECCOPY(shi->co, spoint->co);
VECCOPY(shi->view, shi->co);
@@ -343,6 +359,7 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo
void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert *svert, StrandPoint *spoint)
{
StrandBuffer *strandbuf= strand->buffer;
+ ObjectRen *obr= strandbuf->obr;
StrandVert *sv;
int mode= shi->mode; /* or-ed result for all nodes */
short texco= shi->mat->texco;
@@ -360,7 +377,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
if(mode & MA_STR_SURFDIFF) {
- float *surfnor= RE_strandren_get_surfnor(&R, strand, 0);
+ float *surfnor= RE_strandren_get_surfnor(obr, strand, 0);
if(surfnor)
VECCOPY(shi->surfnor, surfnor)
@@ -378,7 +395,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
if(R.r.mode & R_SPEED) {
float *speed;
- speed= RE_strandren_get_winspeed(&R, strand, 0);
+ speed= RE_strandren_get_winspeed(shi->obi, strand, 0);
if(speed)
QUATCOPY(shi->winspeed, speed)
else
@@ -423,7 +440,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
shi->totcol= 0;
if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
- for (i=0; (mcol=RE_strandren_get_mcol(&R, strand, i, &name, 0)); i++) {
+ for (i=0; (mcol=RE_strandren_get_mcol(obr, strand, i, &name, 0)); i++) {
ShadeInputCol *scol= &shi->col[i];
char *cp= (char*)mcol;
@@ -447,7 +464,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
}
- for (i=0; (uv=RE_strandren_get_uv(&R, strand, i, &name, 0)); i++) {
+ for (i=0; (uv=RE_strandren_get_uv(obr, strand, i, &name, 0)); i++) {
ShadeInputUV *suv= &shi->uv[i];
shi->totuv++;
@@ -569,7 +586,12 @@ void shade_input_set_viewco(ShadeInput *shi, float x, float y, float z)
calc_renderco_zbuf(shi->co, shi->view, z);
}
else {
- float dface, *v1= shi->v1->co;
+ float dface, v1[3];
+
+ VECCOPY(v1, shi->v1->co);
+
+ if(shi->obi->flag & R_TRANSFORMED)
+ Mat4MulVecfl(shi->obi->mat, v1);
dface= v1[0]*shi->facenor[0]+v1[1]*shi->facenor[1]+v1[2]*shi->facenor[2];
@@ -652,9 +674,19 @@ void shade_input_set_uv(ShadeInput *shi)
{
VlakRen *vlr= shi->vlr;
- if( (vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) || (shi->passflag & SCE_PASS_UV)) {
- float *v1= shi->v1->co, *v2= shi->v2->co, *v3= shi->v3->co;
-
+ if((vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) || (shi->passflag & SCE_PASS_UV)) {
+ float v1[3], v2[3], v3[3];
+
+ VECCOPY(v1, shi->v1->co);
+ VECCOPY(v2, shi->v2->co);
+ VECCOPY(v3, shi->v3->co);
+
+ if(shi->obi->flag & R_TRANSFORMED) {
+ Mat4MulVecfl(shi->obi->mat, v1);
+ Mat4MulVecfl(shi->obi->mat, v2);
+ Mat4MulVecfl(shi->obi->mat, v3);
+ }
+
/* exception case for wire render of edge */
if(vlr->v2==vlr->v3) {
float lend, lenc;
@@ -679,55 +711,35 @@ void shade_input_set_uv(ShadeInput *shi)
}
else {
/* most of this could become re-used for faces */
- float detsh, t00, t10, t01, t11;
-
- if(vlr->noflag & R_SNPROJ_X) {
- t00= v3[0]-v1[0]; t01= v3[1]-v1[1];
- t10= v3[0]-v2[0]; t11= v3[1]-v2[1];
- }
- else if(vlr->noflag & R_SNPROJ_Y) {
- t00= v3[0]-v1[0]; t01= v3[2]-v1[2];
- t10= v3[0]-v2[0]; t11= v3[2]-v2[2];
- }
- else {
- t00= v3[1]-v1[1]; t01= v3[2]-v1[2];
- t10= v3[1]-v2[1]; t11= v3[2]-v2[2];
- }
-
+ float detsh, t00, t10, t01, t11, xn, yn, zn;
+ int axis1, axis2;
+
+ /* find most stable axis to project */
+ xn= fabs(shi->facenor[0]);
+ yn= fabs(shi->facenor[1]);
+ zn= fabs(shi->facenor[2]);
+
+ if(zn>=xn && zn>=yn) { axis1= 0; axis2= 1; }
+ else if(yn>=xn && yn>=zn) { axis1= 0; axis2= 2; }
+ else { axis1= 1; axis2= 2; }
+
+ /* compute u,v and derivatives */
+ t00= v3[axis1]-v1[axis1]; t01= v3[axis2]-v1[axis2];
+ t10= v3[axis1]-v2[axis1]; t11= v3[axis2]-v2[axis2];
+
detsh= 1.0f/(t00*t11-t10*t01);
t00*= detsh; t01*=detsh;
t10*=detsh; t11*=detsh;
-
- if(vlr->noflag & R_SNPROJ_X) {
- shi->u= (shi->co[0]-v3[0])*t11-(shi->co[1]-v3[1])*t10;
- shi->v= (shi->co[1]-v3[1])*t00-(shi->co[0]-v3[0])*t01;
- if(shi->osatex) {
- shi->dx_u= shi->dxco[0]*t11- shi->dxco[1]*t10;
- shi->dx_v= shi->dxco[1]*t00- shi->dxco[0]*t01;
- shi->dy_u= shi->dyco[0]*t11- shi->dyco[1]*t10;
- shi->dy_v= shi->dyco[1]*t00- shi->dyco[0]*t01;
- }
- }
- else if(vlr->noflag & R_SNPROJ_Y) {
- shi->u= (shi->co[0]-v3[0])*t11-(shi->co[2]-v3[2])*t10;
- shi->v= (shi->co[2]-v3[2])*t00-(shi->co[0]-v3[0])*t01;
- if(shi->osatex) {
- shi->dx_u= shi->dxco[0]*t11- shi->dxco[2]*t10;
- shi->dx_v= shi->dxco[2]*t00- shi->dxco[0]*t01;
- shi->dy_u= shi->dyco[0]*t11- shi->dyco[2]*t10;
- shi->dy_v= shi->dyco[2]*t00- shi->dyco[0]*t01;
- }
- }
- else {
- shi->u= (shi->co[1]-v3[1])*t11-(shi->co[2]-v3[2])*t10;
- shi->v= (shi->co[2]-v3[2])*t00-(shi->co[1]-v3[1])*t01;
- if(shi->osatex) {
- shi->dx_u= shi->dxco[1]*t11- shi->dxco[2]*t10;
- shi->dx_v= shi->dxco[2]*t00- shi->dxco[1]*t01;
- shi->dy_u= shi->dyco[1]*t11- shi->dyco[2]*t10;
- shi->dy_v= shi->dyco[2]*t00- shi->dyco[1]*t01;
- }
+
+ shi->u= (shi->co[axis1]-v3[axis1])*t11-(shi->co[axis2]-v3[axis2])*t10;
+ shi->v= (shi->co[axis2]-v3[axis2])*t00-(shi->co[axis1]-v3[axis1])*t01;
+ if(shi->osatex) {
+ shi->dx_u= shi->dxco[axis1]*t11- shi->dxco[axis2]*t10;
+ shi->dx_v= shi->dxco[axis2]*t00- shi->dxco[axis1]*t01;
+ shi->dy_u= shi->dyco[axis1]*t11- shi->dyco[axis2]*t10;
+ shi->dy_v= shi->dyco[axis2]*t00- shi->dyco[axis1]*t01;
}
+
/* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
CLAMP(shi->u, -2.0f, 1.0f);
CLAMP(shi->v, -2.0f, 1.0f);
@@ -750,17 +762,36 @@ void shade_input_set_normals(ShadeInput *shi)
Normalize(shi->vn);
}
- else {
+ else
VECCOPY(shi->vn, shi->facenor);
- }
/* used in nodes */
VECCOPY(shi->vno, shi->vn);
}
+/* use by raytrace, sss, bake to flip into the right direction */
+void shade_input_flip_normals(ShadeInput *shi)
+{
+ shi->facenor[0]= -shi->facenor[0];
+ shi->facenor[1]= -shi->facenor[1];
+ shi->facenor[2]= -shi->facenor[2];
+
+ shi->vn[0]= -shi->vn[0];
+ shi->vn[1]= -shi->vn[1];
+ shi->vn[2]= -shi->vn[2];
+
+ shi->vno[0]= -shi->vno[0];
+ shi->vno[1]= -shi->vno[1];
+ shi->vno[2]= -shi->vno[2];
+
+ shi->flippednor= !shi->flippednor;
+}
+
void shade_input_set_shade_texco(ShadeInput *shi)
{
+ ObjectInstanceRen *obi= shi->obi;
+ ObjectRen *obr= shi->obr;
VertRen *v1= shi->v1, *v2= shi->v2, *v3= shi->v3;
float u= shi->u, v= shi->v;
float l= 1.0f+u+v, dl;
@@ -788,13 +819,17 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if (mode & (MA_TANGENT_V|MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) {
float *s1, *s2, *s3;
- s1= RE_vertren_get_tangent(&R, v1, 0);
- s2= RE_vertren_get_tangent(&R, v2, 0);
- s3= RE_vertren_get_tangent(&R, v3, 0);
+ s1= RE_vertren_get_tangent(obr, v1, 0);
+ s2= RE_vertren_get_tangent(obr, v2, 0);
+ s3= RE_vertren_get_tangent(obr, v3, 0);
if(s1 && s2 && s3) {
shi->tang[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
shi->tang[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
shi->tang[2]= (l*s3[2] - u*s1[2] - v*s2[2]);
+
+ if(obi->flag & R_TRANSFORMED)
+ normal_transform(obi->imat, shi->tang);
+
/* qdn: normalize just in case */
Normalize(shi->tang);
}
@@ -806,13 +841,17 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if (mode & (MA_TANGENT_V|MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) {
/* qdn: flat faces have tangents too,
could pick either one, using average here */
- float *s1 = RE_vertren_get_tangent(&R, v1, 0);
- float *s2 = RE_vertren_get_tangent(&R, v2, 0);
- float *s3 = RE_vertren_get_tangent(&R, v3, 0);
+ float *s1 = RE_vertren_get_tangent(obr, v1, 0);
+ float *s2 = RE_vertren_get_tangent(obr, v2, 0);
+ float *s3 = RE_vertren_get_tangent(obr, v3, 0);
if (s1 && s2 && s3) {
shi->tang[0] = (s1[0] + s2[0] + s3[0]);
shi->tang[1] = (s1[1] + s2[1] + s3[1]);
shi->tang[2] = (s1[2] + s2[2] + s3[2]);
+
+ if(obi->flag & R_TRANSFORMED)
+ normal_transform(obi->imat, shi->tang);
+
Normalize(shi->tang);
}
else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f;
@@ -820,10 +859,13 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
if(mode & MA_STR_SURFDIFF) {
- float *surfnor= RE_vlakren_get_surfnor(&R, shi->vlr, 0);
+ float *surfnor= RE_vlakren_get_surfnor(obr, shi->vlr, 0);
- if(surfnor)
+ if(surfnor) {
VECCOPY(shi->surfnor, surfnor)
+ if(obi->flag & R_TRANSFORMED)
+ normal_transform(obi->imat, shi->surfnor);
+ }
else
VECCOPY(shi->surfnor, shi->vn)
@@ -833,9 +875,9 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if(R.r.mode & R_SPEED) {
float *s1, *s2, *s3;
- s1= RE_vertren_get_winspeed(&R, v1, 0);
- s2= RE_vertren_get_winspeed(&R, v2, 0);
- s3= RE_vertren_get_winspeed(&R, v3, 0);
+ s1= RE_vertren_get_winspeed(obi, v1, 0);
+ s2= RE_vertren_get_winspeed(obi, v2, 0);
+ s3= RE_vertren_get_winspeed(obi, v3, 0);
if(s1 && s2 && s3) {
shi->winspeed[0]= (l*s3[0] - u*s1[0] - v*s2[0]);
shi->winspeed[1]= (l*s3[1] - u*s1[1] - v*s2[1]);
@@ -912,9 +954,11 @@ void shade_input_set_shade_texco(ShadeInput *shi)
shi->totuv= 0;
shi->totcol= 0;
+ shi->actuv= obr->actmtface;
+ shi->actcol= obr->actmcol;
if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
- for (i=0; (mcol=RE_vlakren_get_mcol(&R, vlr, i, &name, 0)); i++) {
+ for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) {
ShadeInputCol *scol= &shi->col[i];
char *cp1, *cp2, *cp3;
@@ -944,7 +988,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
}
- for (i=0; (tface=RE_vlakren_get_tface(&R, vlr, i, &name, 0)); i++) {
+ for (i=0; (tface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) {
ShadeInputUV *suv= &shi->uv[i];
float *uv1, *uv2, *uv3;
@@ -977,7 +1021,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
suv->dyuv[1]= 2.0f*(dl*uv3[1]-duv[0]*uv1[1]-duv[1]*uv2[1]);
}
- if((mode & MA_FACETEXTURE) && i==0) {
+ if((mode & MA_FACETEXTURE) && i==obr->actmtface) {
if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) {
shi->vcol[0]= 1.0f;
shi->vcol[1]= 1.0f;
@@ -1015,22 +1059,20 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if(mode & MA_RADIO) {
float *r1, *r2, *r3;
- r1= RE_vertren_get_rad(&R, v1, 0);
- r2= RE_vertren_get_rad(&R, v2, 0);
- r3= RE_vertren_get_rad(&R, v3, 0);
+ r1= RE_vertren_get_rad(obr, v1, 0);
+ r2= RE_vertren_get_rad(obr, v2, 0);
+ r3= RE_vertren_get_rad(obr, v3, 0);
if(r1 && r2 && r3) {
shi->rad[0]= (l*r3[0] - u*r1[0] - v*r2[0]);
shi->rad[1]= (l*r3[1] - u*r1[1] - v*r2[1]);
shi->rad[2]= (l*r3[2] - u*r1[2] - v*r2[2]);
}
- else {
+ else
shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
- }
}
- else {
+ else
shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
- }
if(texco & TEXCO_REFL) {
/* mirror reflection color textures (and envmap) */
@@ -1040,9 +1082,9 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if(texco & TEXCO_STRESS) {
float *s1, *s2, *s3;
- s1= RE_vertren_get_stress(&R, v1, 0);
- s2= RE_vertren_get_stress(&R, v2, 0);
- s3= RE_vertren_get_stress(&R, v3, 0);
+ s1= RE_vertren_get_stress(obr, v1, 0);
+ s2= RE_vertren_get_stress(obr, v2, 0);
+ s3= RE_vertren_get_stress(obr, v3, 0);
if(s1 && s2 && s3) {
shi->stress= l*s3[0] - u*s1[0] - v*s2[0];
if(shi->stress<1.0f) shi->stress-= 1.0f;
@@ -1058,9 +1100,8 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
}
}
- else {
+ else
shi->rad[0]= shi->rad[1]= shi->rad[2]= 0.0f;
- }
/* this only avalailable for scanline renders */
if(shi->depth==0) {
@@ -1082,22 +1123,32 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if(texco & TEXCO_STICKY) {
float *s1, *s2, *s3;
- s1= RE_vertren_get_sticky(&R, v1, 0);
- s2= RE_vertren_get_sticky(&R, v2, 0);
- s3= RE_vertren_get_sticky(&R, v3, 0);
+ s1= RE_vertren_get_sticky(obr, v1, 0);
+ s2= RE_vertren_get_sticky(obr, v2, 0);
+ s3= RE_vertren_get_sticky(obr, v3, 0);
if(s1 && s2 && s3) {
+ float winmat[4][4], ho1[4], ho2[4], ho3[4];
float Zmulx, Zmuly;
float hox, hoy, l, dl, u, v;
float s00, s01, s10, s11, detsh;
/* old globals, localized now */
Zmulx= ((float)R.winx)/2.0f; Zmuly= ((float)R.winy)/2.0f;
+
+ if(shi->obi->flag & R_TRANSFORMED)
+ zbuf_make_winmat(&R, shi->obi->mat, winmat);
+ else
+ zbuf_make_winmat(&R, NULL, winmat);
+
+ zbuf_render_project(winmat, v1->co, ho1);
+ zbuf_render_project(winmat, v2->co, ho2);
+ zbuf_render_project(winmat, v3->co, ho3);
- s00= v3->ho[0]/v3->ho[3] - v1->ho[0]/v1->ho[3];
- s01= v3->ho[1]/v3->ho[3] - v1->ho[1]/v1->ho[3];
- s10= v3->ho[0]/v3->ho[3] - v2->ho[0]/v2->ho[3];
- s11= v3->ho[1]/v3->ho[3] - v2->ho[1]/v2->ho[3];
+ s00= ho3[0]/ho3[3] - ho1[0]/ho1[3];
+ s01= ho3[1]/ho3[3] - ho1[1]/ho1[3];
+ s10= ho3[0]/ho3[3] - ho2[0]/ho2[3];
+ s11= ho3[1]/ho3[3] - ho2[1]/ho2[3];
detsh= s00*s11-s10*s01;
s00/= detsh; s01/=detsh;
@@ -1106,8 +1157,8 @@ void shade_input_set_shade_texco(ShadeInput *shi)
/* recalc u and v again */
hox= x/Zmulx -1.0f;
hoy= y/Zmuly -1.0f;
- u= (hox - v3->ho[0]/v3->ho[3])*s11 - (hoy - v3->ho[1]/v3->ho[3])*s10;
- v= (hoy - v3->ho[1]/v3->ho[3])*s00 - (hox - v3->ho[0]/v3->ho[3])*s01;
+ u= (hox - ho3[0]/ho3[3])*s11 - (hoy - ho3[1]/ho3[3])*s10;
+ v= (hoy - ho3[1]/ho3[3])*s00 - (hox - ho3[0]/ho3[3])*s01;
l= 1.0f+u+v;
shi->sticky[0]= l*s3[0]-u*s1[0]-v*s2[0];
@@ -1197,7 +1248,7 @@ static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, in
ssamp->tot= 0;
for(shi= ssamp->shi; ps; ps= ps->next) {
- shade_input_set_triangle(shi, ps->facenr, 1);
+ shade_input_set_triangle(shi, ps->obi, ps->facenr, 1);
if(shi->vlr) { /* NULL happens for env material or for 'all z' */
unsigned short curmask= ps->mask;
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 037a3aa8409..a08046da0da 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1262,7 +1262,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
if(ma->mode & MA_SHADOW) {
if(lar->type==LA_HEMI || lar->type==LA_AREA);
else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) {
- float thresh= vlr->ob->smoothresh;
+ float thresh= shi->obr->ob->smoothresh;
if(inp>thresh)
phongcorr= (inp-thresh)/(inp*(1.0f-thresh));
else
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 0c1590c216b..bbc2b62536f 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -59,7 +59,7 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr);
void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha);
void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco);
void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) );
-void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2);
+void zbufsinglewire(ZSpan *zspan, ObjectRen *obr, int zvlnr, float *ho1, float *ho2);
int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag);
void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect);
void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf);
@@ -210,6 +210,7 @@ typedef struct RenderPrimitiveIterator {
BucketPrims *bpr;
int bprindex;
+ ObjectInstanceRen *obi;
StrandRen *strand;
int index, tot;
} RenderPrimitiveIterator;
@@ -239,7 +240,9 @@ RenderPrimitiveIterator *init_primitive_iterator(Render *re, RenderBuckets *buck
}
else {
iter->index= 0;
- iter->tot= re->totstrand;
+ iter->obi= re->instancetable.first;
+ if(iter->obi)
+ iter->tot= iter->obi->obr->totstrand;
}
return iter;
@@ -264,9 +267,22 @@ void *next_primitive_iterator(RenderPrimitiveIterator *iter)
return iter->bpr->prim[iter->bprindex++];
}
else {
+ if(!iter->obi)
+ return NULL;
+
+ if(iter->index >= iter->tot) {
+ while((iter->obi=iter->obi->next) && !iter->obi->obr->totstrand)
+ iter->obi= iter->obi->next;
+
+ if(iter->obi)
+ iter->tot= iter->obi->obr->totstrand;
+ else
+ return NULL;
+ }
+
if(iter->index < iter->tot) {
if((iter->index & 255)==0)
- iter->strand= iter->re->strandnodes[iter->index>>8].strand;
+ iter->strand= iter->obi->obr->strandnodes[iter->index>>8].strand;
else
iter->strand++;
@@ -318,8 +334,15 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
VECCOPY(p[2], sseg->v[2]->co);
VECCOPY(p[3], sseg->v[3]->co);
+ if(sseg->obi->flag & R_TRANSFORMED) {
+ Mat4MulVecfl(sseg->obi->mat, p[0]);
+ Mat4MulVecfl(sseg->obi->mat, p[1]);
+ Mat4MulVecfl(sseg->obi->mat, p[2]);
+ Mat4MulVecfl(sseg->obi->mat, p[3]);
+ }
+
if(t == 0.0f) {
- VECCOPY(spoint->co, sseg->v[1]->co);
+ VECCOPY(spoint->co, p[1]);
spoint->strandco= sseg->v[1]->strandco;
spoint->dtstrandco= (sseg->v[2]->strandco - sseg->v[0]->strandco);
@@ -327,7 +350,7 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
spoint->dtstrandco *= 0.5f;
}
else if(t == 1.0f) {
- VECCOPY(spoint->co, sseg->v[2]->co);
+ VECCOPY(spoint->co, p[2]);
spoint->strandco= sseg->v[2]->strandco;
spoint->dtstrandco= (sseg->v[3]->strandco - sseg->v[1]->strandco);
@@ -408,7 +431,7 @@ typedef struct StrandPart {
typedef struct StrandSortSegment {
struct StrandSortSegment *next;
- int strand, segment;
+ int obi, strand, segment;
float z;
} StrandSortSegment;
@@ -474,22 +497,22 @@ static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float
}
}
-static void add_strand_obindex(RenderLayer *rl, int offset, Object *ob)
+static void add_strand_obindex(RenderLayer *rl, int offset, ObjectRen *obr)
{
RenderPass *rpass;
for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
if(rpass->passtype == SCE_PASS_INDEXOB) {
float *fp= rpass->rect + offset;
- *fp= (float)ob->index;
+ *fp= (float)obr->ob->index;
break;
}
}
}
-static void do_strand_point_project(Render *re, ZSpan *zspan, float *co, float *hoco, float *zco)
+static void do_strand_point_project(float winmat[][4], ZSpan *zspan, float *co, float *hoco, float *zco)
{
- projectvert(co, re->winmat, hoco);
+ projectvert(co, winmat, hoco);
hoco_to_zco(zspan, zco, hoco);
}
@@ -606,16 +629,16 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float
#endif
if(spart->addpassflag & SCE_PASS_INDEXOB)
- add_strand_obindex(spart->rl, offset, buffer->ob);
+ add_strand_obindex(spart->rl, offset, buffer->obr);
}
}
-static int strand_test_clip(Render *re, ZSpan *zspan, float *bounds, float *co, float *zcomp)
+static int strand_test_clip(float winmat[][4], ZSpan *zspan, float *bounds, float *co, float *zcomp)
{
float hoco[4];
int clipflag= 0;
- projectvert(co, re->winmat, hoco);
+ projectvert(co, winmat, hoco);
/* we compare z without perspective division for segment sorting */
*zcomp= hoco[2];
@@ -635,12 +658,15 @@ void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, Str
VlakRen vlr;
memset(&vlr, 0, sizeof(vlr));
- vlr.flag= R_SMOOTH|R_VISIBLE;
+ vlr.flag= R_SMOOTH;
vlr.lay= sseg->strand->buffer->lay;
- vlr.ob= sseg->strand->buffer->ob;
+ vlr.obr= sseg->strand->buffer->obr;
if(sseg->buffer->ma->mode & MA_TANGENT_STR)
vlr.flag |= R_TANGENT;
+
shi->vlr= &vlr;
+ shi->obi= sseg->obi;
+ shi->obr= sseg->obi->obr;
/* cache for shadow */
shi->samplenr++;
@@ -660,7 +686,7 @@ void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, Str
/* include lamphalos for strand, since halo layer was added already */
if(re->flag & R_LAMPHALO)
if(shi->layflag & SCE_LAY_HALO)
- renderspothalo(shi, shr->combined, shr->combined[3]);
+ renderspothalo(shi, shr->combined, shr->combined[3]);
}
static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, float t, float dt, float *co1, float *co2, float *co3, float *co4, int sample)
@@ -703,7 +729,7 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f
zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend);
}
-static void strand_render(Render *re, StrandPart *spart, ZSpan *zspan, StrandPoint *p1, StrandPoint *p2)
+static void strand_render(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandPoint *p1, StrandPoint *p2)
{
if(spart) {
float t= p2->t;
@@ -720,16 +746,16 @@ static void strand_render(Render *re, StrandPart *spart, ZSpan *zspan, StrandPoi
else {
float hoco1[4], hoco2[3];
- projectvert(p1->co, re->winmat, hoco1);
- projectvert(p2->co, re->winmat, hoco2);
+ projectvert(p1->co, winmat, hoco1);
+ projectvert(p2->co, winmat, hoco2);
/* render both strand and single pixel wire to counter aliasing */
- zbufclip4(zspan, 0, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, 0, 0, 0, 0);
- zbufsinglewire(zspan, 0, hoco1, hoco2);
+ zbufclip4(zspan, 0, 0, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, 0, 0, 0, 0);
+ zbufsinglewire(zspan, 0, 0, hoco1, hoco2);
}
}
-static int strand_segment_recursive(Render *re, StrandPart *spart, ZSpan *zspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth)
+static int strand_segment_recursive(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth)
{
StrandPoint p;
StrandBuffer *buffer= sseg->buffer;
@@ -758,23 +784,23 @@ static int strand_segment_recursive(Render *re, StrandPart *spart, ZSpan *zspan,
return 0;
if(spart) {
- do_strand_point_project(re, zspan, p.co1, p.hoco1, p.zco1);
- do_strand_point_project(re, zspan, p.co2, p.hoco2, p.zco2);
+ do_strand_point_project(winmat, zspan, p.co1, p.hoco1, p.zco1);
+ do_strand_point_project(winmat, zspan, p.co2, p.hoco2, p.zco2);
}
else {
- projectvert(p.co1, re->winmat, p.hoco1);
- projectvert(p.co2, re->winmat, p.hoco2);
+ projectvert(p.co1, winmat, p.hoco1);
+ projectvert(p.co2, winmat, p.hoco2);
}
- if(!strand_segment_recursive(re, spart, zspan, sseg, p1, &p, depth+1))
- strand_render(re, spart, zspan, p1, &p);
- if(!strand_segment_recursive(re, spart, zspan, sseg, &p, p2, depth+1))
- strand_render(re, spart, zspan, &p, p2);
+ if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, p1, &p, depth+1))
+ strand_render(re, winmat, spart, zspan, p1, &p);
+ if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, &p, p2, depth+1))
+ strand_render(re, winmat, spart, zspan, &p, p2);
return 1;
}
-void render_strand_segment(Render *re, StrandPart *spart, ZSpan *zspan, StrandSegment *sseg)
+void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandSegment *sseg)
{
StrandBuffer *buffer= sseg->buffer;
StrandPoint *p1= &sseg->point1;
@@ -789,20 +815,20 @@ void render_strand_segment(Render *re, StrandPart *spart, ZSpan *zspan, StrandSe
strand_project_point(buffer->winmat, buffer->winx, buffer->winy, p2);
if(spart) {
- do_strand_point_project(re, zspan, p1->co1, p1->hoco1, p1->zco1);
- do_strand_point_project(re, zspan, p1->co2, p1->hoco2, p1->zco2);
- do_strand_point_project(re, zspan, p2->co1, p2->hoco1, p2->zco1);
- do_strand_point_project(re, zspan, p2->co2, p2->hoco2, p2->zco2);
+ do_strand_point_project(winmat, zspan, p1->co1, p1->hoco1, p1->zco1);
+ do_strand_point_project(winmat, zspan, p1->co2, p1->hoco2, p1->zco2);
+ do_strand_point_project(winmat, zspan, p2->co1, p2->hoco1, p2->zco1);
+ do_strand_point_project(winmat, zspan, p2->co2, p2->hoco2, p2->zco2);
}
else {
- projectvert(p1->co1, re->winmat, p1->hoco1);
- projectvert(p1->co2, re->winmat, p1->hoco2);
- projectvert(p2->co1, re->winmat, p2->hoco1);
- projectvert(p2->co2, re->winmat, p2->hoco2);
+ projectvert(p1->co1, winmat, p1->hoco1);
+ projectvert(p1->co2, winmat, p1->hoco2);
+ projectvert(p2->co1, winmat, p2->hoco1);
+ projectvert(p2->co2, winmat, p2->hoco2);
}
- if(!strand_segment_recursive(re, spart, zspan, sseg, p1, p2, 0))
- strand_render(re, spart, zspan, p1, p2);
+ if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, p1, p2, 0))
+ strand_render(re, winmat, spart, zspan, p1, p2);
}
static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, StrandPart *spart, float *pass)
@@ -878,7 +904,9 @@ static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl,
/* render call to fill in strands */
unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *rl, float *pass)
{
- struct RenderPrimitiveIterator *iter;
+ //struct RenderPrimitiveIterator *iter;
+ ObjectRen *obr;
+ ObjectInstanceRen *obi;
ZSpan zspan;
StrandRen *strand=0;
StrandVert *svert;
@@ -886,12 +914,12 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
StrandSegment sseg;
StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg;
MemArena *memarena;
- float z[4], bounds[4];
- int a, b, resultsize, totsegment, clip[4];
+ float z[4], bounds[4], winmat[4][4];
+ int a, b, i, resultsize, totsegment, clip[4];
if(re->test_break())
return NULL;
- if(re->strandbufs.first == NULL)
+ if(re->totstrand == 0)
return NULL;
/* setup StrandPart */
@@ -957,57 +985,75 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy;
/* sort segments */
- iter= init_primitive_iterator(re, re->strandbuckets, pa);
+ //iter= init_primitive_iterator(re, re->strandbuckets, pa);
memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
firstseg= NULL;
sortseg= sortsegments;
totsegment= 0;
- while((strand = next_primitive_iterator(iter))) {
- if(re->test_break())
- break;
+ //while((strand = next_primitive_iterator(iter))) {
+ for(obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) {
+ obr= obi->obr;
- if(strand->clip)
- continue;
+ if(obi->flag & R_TRANSFORMED)
+ zbuf_make_winmat(re, obi->mat, winmat);
+ else
+ zbuf_make_winmat(re, NULL, winmat);
- svert= strand->vert;
+ for(a=0; a<obr->totstrand; a++) {
+ if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
+ else strand++;
- /* keep clipping and z depth for 4 control points */
- clip[1]= strand_test_clip(re, &zspan, bounds, svert->co, &z[1]);
- clip[2]= strand_test_clip(re, &zspan, bounds, (svert+1)->co, &z[2]);
- clip[0]= clip[1]; z[0]= z[1];
+ if(re->test_break())
+ break;
- for(b=0; b<strand->totvert-1; b++, svert++) {
- /* compute 4th point clipping and z depth */
- if(b < strand->totvert-2) {
- clip[3]= strand_test_clip(re, &zspan, bounds, (svert+2)->co, &z[3]);
- }
- else {
- clip[3]= clip[2]; z[3]= z[2];
- }
+#if 0
+ if(strand->clip)
+ continue;
+#endif
- /* check clipping and add to sortsegments buffer */
- if(!(clip[0] & clip[1] & clip[2] & clip[3])) {
- sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment));
- sortseg->strand= strand->index;
- sortseg->segment= b;
+ svert= strand->vert;
- sortseg->z= 0.5f*(z[1] + z[2]);
+ /* keep clipping and z depth for 4 control points */
+ clip[1]= strand_test_clip(winmat, &zspan, bounds, svert->co, &z[1]);
+ clip[2]= strand_test_clip(winmat, &zspan, bounds, (svert+1)->co, &z[2]);
+ clip[0]= clip[1]; z[0]= z[1];
- sortseg->next= firstseg;
- firstseg= sortseg;
- totsegment++;
- }
+ for(b=0; b<strand->totvert-1; b++, svert++) {
+ /* compute 4th point clipping and z depth */
+ if(b < strand->totvert-2) {
+ clip[3]= strand_test_clip(winmat, &zspan, bounds, (svert+2)->co, &z[3]);
+ }
+ else {
+ clip[3]= clip[2]; z[3]= z[2];
+ }
- /* shift clipping and z depth */
- clip[0]= clip[1]; z[0]= z[1];
- clip[1]= clip[2]; z[1]= z[2];
- clip[2]= clip[3]; z[2]= z[3];
+ /* check clipping and add to sortsegments buffer */
+ if(!(clip[0] & clip[1] & clip[2] & clip[3])) {
+ sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment));
+ sortseg->obi= i;
+ sortseg->strand= strand->index;
+ sortseg->segment= b;
+
+ sortseg->z= 0.5f*(z[1] + z[2]);
+
+ sortseg->next= firstseg;
+ firstseg= sortseg;
+ totsegment++;
+ }
+
+ /* shift clipping and z depth */
+ clip[0]= clip[1]; z[0]= z[1];
+ clip[1]= clip[2]; z[1]= z[2];
+ clip[2]= clip[3]; z[2]= z[3];
+ }
}
}
+#if 0
free_primitive_iterator(iter);
+#endif
if(!re->test_break()) {
/* convert list to array and sort */
@@ -1028,7 +1074,12 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
if(re->test_break())
break;
- sseg.strand= RE_findOrAddStrand(re, sortseg->strand);
+ obi= &re->objectinstance[sortseg->obi];
+ obr= obi->obr;
+ zbuf_make_winmat(re, NULL, winmat);
+
+ sseg.obi= obi;
+ sseg.strand= RE_findOrAddStrand(obr, sortseg->strand);
sseg.buffer= sseg.strand->buffer;
sseg.sqadaptcos= sseg.buffer->adaptcos;
sseg.sqadaptcos *= sseg.sqadaptcos;
@@ -1042,7 +1093,7 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
spart.segment= &sseg;
- render_strand_segment(re, &spart, &zspan, &sseg);
+ render_strand_segment(re, winmat, &spart, &zspan, &sseg);
}
}
@@ -1072,6 +1123,8 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets)
{
+#if 0
+ ObjectRen *obr;
StrandRen *strand = NULL;
StrandVert *svert;
float hoco[4], min[2], max[2], bucketco[2], vec[3];
@@ -1083,84 +1136,92 @@ void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], fl
re->strandbuckets= NULL;
}
+ if(re->totstrand == 0)
+ return;
+
if(do_buckets)
re->strandbuckets= init_buckets(re);
/* calculate view coordinates (and zbuffer value) */
- for(a=0; a<re->totstrand; a++) {
- if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
- else strand++;
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ for(a=0; a<obr->totstrand; a++) {
+ if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
+ else strand++;
- strand->clip= ~0;
+ strand->clip= ~0;
#if 0
- if(!(strand->buffer->flag & R_STRAND_BSPLINE)) {
- INIT_MINMAX(bmin, bmax);
- svert= strand->vert;
- for(b=0; b<strand->totvert; b++, svert++)
- DO_MINMAX(svert->co, bmin, bmax)
-
- bpad[0]= (bmax[0]-bmin[0])*0.2f;
- bpad[1]= (bmax[1]-bmin[1])*0.2f;
- bpad[2]= (bmax[2]-bmin[2])*0.2f;
- }
- else
- bpad[0]= bpad[1]= bpad[2]= 0.0f;
-
- ma= strand->buffer->ma;
- width= MAX2(ma->strand_sta, ma->strand_end);
- if(strand->buffer->flag & R_STRAND_B_UNITS) {
- bpad[0] += 0.5f*width;
- bpad[1] += 0.5f*width;
- bpad[2] += 0.5f*width;
- }
-#endif
-
- INIT_MINMAX2(min, max);
- svert= strand->vert;
- for(b=0; b<strand->totvert; b++, svert++) {
- //VECADD(vec, svert->co, bpad);
-
- /* same as VertRen */
- if(do_pano) {
- vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2];
- vec[1]= svert->co[1];
- vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2];
+ if(!(strand->buffer->flag & R_STRAND_BSPLINE)) {
+ INIT_MINMAX(bmin, bmax);
+ svert= strand->vert;
+ for(b=0; b<strand->totvert; b++, svert++)
+ DO_MINMAX(svert->co, bmin, bmax)
+
+ bpad[0]= (bmax[0]-bmin[0])*0.2f;
+ bpad[1]= (bmax[1]-bmin[1])*0.2f;
+ bpad[2]= (bmax[2]-bmin[2])*0.2f;
}
else
- VECCOPY(vec, svert->co)
+ bpad[0]= bpad[1]= bpad[2]= 0.0f;
+
+ ma= strand->buffer->ma;
+ width= MAX2(ma->strand_sta, ma->strand_end);
+ if(strand->buffer->flag & R_STRAND_B_UNITS) {
+ bpad[0] += 0.5f*width;
+ bpad[1] += 0.5f*width;
+ bpad[2] += 0.5f*width;
+ }
+#endif
- /* Go from wcs to hcs ... */
- projectfunc(vec, re->winmat, hoco);
- /* ... and clip in that system. */
- strand->clip &= testclip(hoco);
+ INIT_MINMAX2(min, max);
+ svert= strand->vert;
+ for(b=0; b<strand->totvert; b++, svert++) {
+ //VECADD(vec, svert->co, bpad);
+
+ /* same as VertRen */
+ if(do_pano) {
+ vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2];
+ vec[1]= svert->co[1];
+ vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2];
+ }
+ else
+ VECCOPY(vec, svert->co)
- if(do_buckets) {
- project_hoco_to_bucket(re->strandbuckets, hoco, bucketco);
- DO_MINMAX2(bucketco, min, max);
- }
- }
+ /* Go from wcs to hcs ... */
+ projectfunc(vec, re->winmat, hoco);
+ /* ... and clip in that system. */
+ strand->clip &= testclip(hoco);
- if(do_buckets) {
#if 0
- if(strand->buffer->flag & R_STRAND_BSPLINE) {
- min[0] -= width;
- min[1] -= width;
- max[0] += width;
- max[1] += width;
+ if(do_buckets) {
+ project_hoco_to_bucket(re->strandbuckets, hoco, bucketco);
+ DO_MINMAX2(bucketco, min, max);
+ }
+#endif
}
- else {
- /* catmull-rom stays within 1.2f bounds in object space,
- * is this still true after projection? */
- min[0] -= width + (max[0]-min[0])*0.2f;
- min[1] -= width + (max[1]-min[1])*0.2f;
- max[0] += width + (max[0]-min[0])*0.2f;
- max[1] += width + (max[1]-min[1])*0.2f;
+
+#if 0
+ if(do_buckets) {
+ if(strand->buffer->flag & R_STRAND_BSPLINE) {
+ min[0] -= width;
+ min[1] -= width;
+ max[0] += width;
+ max[1] += width;
+ }
+ else {
+ /* catmull-rom stays within 1.2f bounds in object space,
+ * is this still true after projection? */
+ min[0] -= width + (max[0]-min[0])*0.2f;
+ min[1] -= width + (max[1]-min[1])*0.2f;
+ max[0] += width + (max[0]-min[0])*0.2f;
+ max[1] += width + (max[1]-min[1])*0.2f;
+ }
+
+ add_buckets_primitive(re->strandbuckets, min, max, strand);
}
#endif
-
- add_buckets_primitive(re->strandbuckets, min, max, strand);
}
}
+#endif
}
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index 41a46679e95..b502fb2b421 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -755,16 +755,16 @@ static int plugintex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex
}
-static int cubemap_glob(VlakRen *vlr, float x, float y, float z, float *adr1, float *adr2)
+static int cubemap_glob(float *n, float x, float y, float z, float *adr1, float *adr2)
{
float x1, y1, z1, nor[3];
int ret;
- if(vlr==NULL) {
+ if(n==NULL) {
nor[0]= x; nor[1]= y; nor[2]= z; // use local render coord
}
else {
- VECCOPY(nor, vlr->n);
+ VECCOPY(nor, n);
}
MTC_Mat4Mul3Vecfl(R.viewinv, nor);
@@ -793,7 +793,7 @@ static int cubemap_glob(VlakRen *vlr, float x, float y, float z, float *adr1, fl
/* ------------------------------------------------------------------------- */
/* mtex argument only for projection switches */
-static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *adr1, float *adr2)
+static int cubemap(MTex *mtex, VlakRen *vlr, float *n, float x, float y, float z, float *adr1, float *adr2)
{
int proj[4]={0, ME_PROJXY, ME_PROJXZ, ME_PROJYZ}, ret= 0;
@@ -811,7 +811,7 @@ static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *a
else if( fabs(nor[0])<fabs(nor[1]) && fabs(nor[2])<fabs(nor[1]) ) vlr->puno |= ME_PROJXZ;
else vlr->puno |= ME_PROJYZ;
}
- else return cubemap_glob(vlr, x, y, z, adr1, adr2);
+ else return cubemap_glob(n, x, y, z, adr1, adr2);
}
if(mtex) {
@@ -843,7 +843,7 @@ static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *a
}
}
else {
- return cubemap_glob(vlr, x, y, z, adr1, adr2);
+ return cubemap_glob(n, x, y, z, adr1, adr2);
}
return ret;
@@ -851,14 +851,14 @@ static int cubemap(MTex *mtex, VlakRen *vlr, float x, float y, float z, float *a
/* ------------------------------------------------------------------------- */
-static int cubemap_ob(Object *ob, VlakRen *vlr, float x, float y, float z, float *adr1, float *adr2)
+static int cubemap_ob(Object *ob, float *n, float x, float y, float z, float *adr1, float *adr2)
{
float x1, y1, z1, nor[3];
int ret;
- if(vlr==NULL) return 0;
+ if(n==NULL) return 0;
- VECCOPY(nor, vlr->n);
+ VECCOPY(nor, n);
if(ob) MTC_Mat4Mul3Vecfl(ob->imat, nor);
x1= fabs(nor[0]);
@@ -885,7 +885,7 @@ static int cubemap_ob(Object *ob, VlakRen *vlr, float x, float y, float z, float
/* ------------------------------------------------------------------------- */
-static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float *dyt)
+static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *n, float *dxt, float *dyt)
{
Tex *tex;
Object *ob= NULL;
@@ -907,9 +907,9 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float
else if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy);
else if(wrap==MTEX_SPHERE) spheremap(t[0], t[1], t[2], &fx, &fy);
else {
- if(texco==TEXCO_OBJECT) cubemap_ob(ob, vlr, t[0], t[1], t[2], &fx, &fy);
- else if(texco==TEXCO_GLOB) cubemap_glob(vlr, t[0], t[1], t[2], &fx, &fy);
- else cubemap(mtex, vlr, t[0], t[1], t[2], &fx, &fy);
+ if(texco==TEXCO_OBJECT) cubemap_ob(ob, n, t[0], t[1], t[2], &fx, &fy);
+ else if(texco==TEXCO_GLOB) cubemap_glob(n, t[0], t[1], t[2], &fx, &fy);
+ else cubemap(mtex, vlr, n, t[0], t[1], t[2], &fx, &fy);
}
/* repeat */
@@ -998,9 +998,9 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float
}
else {
- if(texco==TEXCO_OBJECT) proj = cubemap_ob(ob, vlr, t[0], t[1], t[2], &fx, &fy);
- else if (texco==TEXCO_GLOB) proj = cubemap_glob(vlr, t[0], t[1], t[2], &fx, &fy);
- else proj = cubemap(mtex, vlr, t[0], t[1], t[2], &fx, &fy);
+ if(texco==TEXCO_OBJECT) proj = cubemap_ob(ob, n, t[0], t[1], t[2], &fx, &fy);
+ else if (texco==TEXCO_GLOB) proj = cubemap_glob(n, t[0], t[1], t[2], &fx, &fy);
+ else proj = cubemap(mtex, vlr, n, t[0], t[1], t[2], &fx, &fy);
if(proj==1) {
SWAP(float, dxt[1], dxt[2]);
@@ -1230,7 +1230,7 @@ int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, Te
dyt_l[0]= dyt_l[1]= dyt_l[2]= 0.0f;
}
- do_2d_mapping(&mtex, texvec_l, NULL, dxt_l, dyt_l);
+ do_2d_mapping(&mtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
return multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres);
}
@@ -1466,7 +1466,7 @@ void do_material_tex(ShadeInput *shi)
co= shi->gl; dx= shi->dxco; dy= shi->dyco;
}
else if(mtex->texco==TEXCO_UV) {
- ShadeInputUV *suv= &shi->uv[0];
+ ShadeInputUV *suv= &shi->uv[shi->actuv];
int i;
if(mtex->uvname[0] != 0) {
@@ -1549,7 +1549,7 @@ void do_material_tex(ShadeInput *shi)
else dxt[2]= dyt[2]= 0.0;
}
- do_2d_mapping(mtex, texvec, shi->vlr, dxt, dyt);
+ do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
/* translate and scale */
texvec[0]= mtex->size[0]*(texvec[0]-0.5) +mtex->ofs[0]+0.5;
@@ -1669,10 +1669,10 @@ void do_material_tex(ShadeInput *shi)
if(mtex->texflag & MTEX_VIEWSPACE) {
// rotate to global coords
if(mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) {
- if(shi->vlr && shi->vlr->ob) {
+ if(shi->vlr && shi->obr->ob) {
float len= Normalize(texres.nor);
// can be optimized... (ton)
- Mat4Mul3Vecfl(shi->vlr->ob->obmat, texres.nor);
+ Mat4Mul3Vecfl(shi->obr->ob->obmat, texres.nor);
Mat4Mul3Vecfl(R.viewmat, texres.nor);
Normalize(texres.nor);
VecMulf(texres.nor, len);
@@ -1762,8 +1762,8 @@ void do_material_tex(ShadeInput *shi)
Mat4Mul3Vecfl(R.viewmat, nor);
}
else if(mtex->normapspace == MTEX_NSPACE_OBJECT) {
- if(shi->vlr && shi->vlr->ob)
- Mat4Mul3Vecfl(shi->vlr->ob->obmat, nor);
+ if(shi->vlr && shi->vlr->obr->ob)
+ Mat4Mul3Vecfl(shi->vlr->obr->ob->obmat, nor);
Mat4Mul3Vecfl(R.viewmat, nor);
}
@@ -1985,7 +1985,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
}
- if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
+ if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres);
@@ -2156,7 +2156,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f
else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
/* texture */
- if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
+ if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres);
@@ -2336,7 +2336,7 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf)
/* texture */
if(tex->type==TEX_IMAGE) {
- do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
+ do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres);
@@ -2421,7 +2421,7 @@ int externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *t
/* texture */
if(tex->type==TEX_IMAGE) {
- do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
+ do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
}
rgb= multitex(tex, texvec, dxt, dyt, 0, &texr);
@@ -2454,6 +2454,7 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
static int firsttime= 1;
Tex *tex;
float texvec[3], dx[2], dy[2];
+ ShadeInputUV *suv= &shi->uv[shi->actuv];
if(firsttime) {
firsttime= 0;
@@ -2465,14 +2466,14 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
if(shi->ys & 1) tex= &tex1; else tex= &tex2; // threadsafe
- texvec[0]= 0.5+0.5*shi->uv[0].uv[0];
- texvec[1]= 0.5+0.5*shi->uv[0].uv[1];
+ texvec[0]= 0.5+0.5*suv->uv[0];
+ texvec[1]= 0.5+0.5*suv->uv[1];
texvec[2] = 0; // initalize it because imagewrap looks at it.
if(shi->osatex) {
- dx[0]= 0.5*shi->uv[0].dxuv[0];
- dx[1]= 0.5*shi->uv[0].dxuv[1];
- dy[0]= 0.5*shi->uv[0].dyuv[0];
- dy[1]= 0.5*shi->uv[0].dyuv[1];
+ dx[0]= 0.5*suv->dxuv[0];
+ dx[1]= 0.5*suv->dxuv[1];
+ dy[0]= 0.5*suv->dyuv[0];
+ dy[1]= 0.5*suv->dyuv[1];
}
texr.nor= NULL;
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index cb92f8cefb3..9e9a407472c 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -298,7 +298,7 @@ static APixstr *addpsA(ZSpan *zspan)
return zspan->curpstr;
}
-static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
APixstr *ap, *apofs, *apn;
double zxd, zyd, zy0, zverg;
@@ -388,16 +388,16 @@ static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
apn= ap;
while(apn) {
- if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
- if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
- if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
- if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
- if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
- if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
- if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
- if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
-// if(apn->p[i]==0) {apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; }
-// if(apn->p[i]==zvlnr) {apn->mask[i]|= mask; break; }
+ if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
+ if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
+ if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
+ if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
+ if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; }
+// if(apn->p[i]==0) {apn->obi[i]= obi; apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; }
+// if(apn->p[i]==zvlnr && apn->obi[i]==obi) {apn->mask[i]|= mask; break; }
if(apn->next==NULL) apn->next= addpsA(zspan);
apn= apn->next;
}
@@ -417,7 +417,7 @@ static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
-static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
+static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2)
{
APixstr *ap, *apn;
int *rectz;
@@ -476,14 +476,14 @@ static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
apn= ap;
while(apn) { /* loop unrolled */
- if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
- if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
- if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
- if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
- if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
- if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
- if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
- if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
+ if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
+ if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; }
+ if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
+ if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; }
+ if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
+ if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; }
+ if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
+ if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; }
if(apn->next==0) apn->next= addpsA(zspan);
apn= apn->next;
}
@@ -568,9 +568,9 @@ static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
/* ************* NORMAL ZBUFFER ************ */
-static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
+static void zbufline(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2)
{
- int *rectz, *rectp;
+ int *rectz, *rectp, *recto;
int start, end, x, y, oldx, oldy, ofs;
int dz, vergz, maxtest= 0;
float dx, dy;
@@ -605,21 +605,24 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
rectz= zspan->rectz + oldy*zspan->rectx+ start;
rectp= zspan->rectp + oldy*zspan->rectx+ start;
+ recto= zspan->recto + oldy*zspan->rectx+ start;
if(dy<0) ofs= -zspan->rectx;
else ofs= zspan->rectx;
- for(x= start; x<=end; x++, rectz++, rectp++) {
+ for(x= start; x<=end; x++, rectz++, rectp++, recto++) {
y= floor(v1[1]);
if(y!=oldy) {
oldy= y;
rectz+= ofs;
rectp+= ofs;
+ recto+= ofs;
}
if(x>=0 && y>=0 && y<zspan->recty) {
if(vergz<*rectz) {
+ *recto= obi;
*rectz= vergz;
*rectp= zvlnr;
}
@@ -657,23 +660,26 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
rectz= zspan->rectz + start*zspan->rectx+ oldx;
rectp= zspan->rectp + start*zspan->rectx+ oldx;
+ recto= zspan->recto + start*zspan->rectx+ oldx;
if(dx<0) ofs= -1;
else ofs= 1;
- for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx) {
+ for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx, recto+=zspan->rectx) {
x= floor(v1[0]);
if(x!=oldx) {
oldx= x;
rectz+= ofs;
rectp+= ofs;
+ recto+= ofs;
}
if(x>=0 && y>=0 && x<zspan->rectx) {
if(vergz<*rectz) {
*rectz= vergz;
*rectp= zvlnr;
+ *recto= obi;
}
}
@@ -684,7 +690,7 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
}
}
-static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
+static void zbufline_onlyZ(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2)
{
int *rectz, *rectz1= NULL;
int start, end, x, y, oldx, oldy, ofs;
@@ -872,26 +878,15 @@ void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco)
zco[2]= 0x7FFFFFFF *(hoco[2]*div);
}
-void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr)
+void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec, float *ho1, float *ho2, float *ho3, float *ho4, int c1, int c2, int c3, int c4)
{
- float vez[20], *f1, *f2, *f3, *f4= 0;
- int c1, c2, c3, c4, ec, and, or;
+ float vez[20];
+ int and, or;
/* edgecode: 1= draw */
- ec = vlr->ec;
if(ec==0) return;
- c1= vlr->v1->clip;
- c2= vlr->v2->clip;
- c3= vlr->v3->clip;
- f1= vlr->v1->ho;
- f2= vlr->v2->ho;
- f3= vlr->v3->ho;
-
- if(vlr->v4) {
- f4= vlr->v4->ho;
- c4= vlr->v4->clip;
-
+ if(ho4) {
and= (c1 & c2 & c3 & c4);
or= (c1 | c2 | c3 | c4);
}
@@ -907,51 +902,51 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr)
else { /* clipping */
if(ec & ME_V1V2) {
- QUATCOPY(vez, f1);
- QUATCOPY(vez+4, f2);
+ QUATCOPY(vez, ho1);
+ QUATCOPY(vez+4, ho2);
if( clipline(vez, vez+4)) {
hoco_to_zco(zspan, vez, vez);
hoco_to_zco(zspan, vez+4, vez+4);
- zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
}
}
if(ec & ME_V2V3) {
- QUATCOPY(vez, f2);
- QUATCOPY(vez+4, f3);
+ QUATCOPY(vez, ho2);
+ QUATCOPY(vez+4, ho3);
if( clipline(vez, vez+4)) {
hoco_to_zco(zspan, vez, vez);
hoco_to_zco(zspan, vez+4, vez+4);
- zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
}
}
- if(vlr->v4) {
+ if(ho4) {
if(ec & ME_V3V4) {
- QUATCOPY(vez, f3);
- QUATCOPY(vez+4, f4);
+ QUATCOPY(vez, ho3);
+ QUATCOPY(vez+4, ho4);
if( clipline(vez, vez+4)) {
hoco_to_zco(zspan, vez, vez);
hoco_to_zco(zspan, vez+4, vez+4);
- zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
}
}
if(ec & ME_V4V1) {
- QUATCOPY(vez, f4);
- QUATCOPY(vez+4, f1);
+ QUATCOPY(vez, ho4);
+ QUATCOPY(vez+4, ho1);
if( clipline(vez, vez+4)) {
hoco_to_zco(zspan, vez, vez);
hoco_to_zco(zspan, vez+4, vez+4);
- zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
}
}
}
else {
if(ec & ME_V3V1) {
- QUATCOPY(vez, f3);
- QUATCOPY(vez+4, f1);
+ QUATCOPY(vez, ho3);
+ QUATCOPY(vez+4, ho1);
if( clipline(vez, vez+4)) {
hoco_to_zco(zspan, vez, vez);
hoco_to_zco(zspan, vez+4, vez+4);
- zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
}
}
}
@@ -960,25 +955,25 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr)
}
}
- hoco_to_zco(zspan, vez, f1);
- hoco_to_zco(zspan, vez+4, f2);
- hoco_to_zco(zspan, vez+8, f3);
- if(vlr->v4) {
- hoco_to_zco(zspan, vez+12, f4);
+ hoco_to_zco(zspan, vez, ho1);
+ hoco_to_zco(zspan, vez+4, ho2);
+ hoco_to_zco(zspan, vez+8, ho3);
+ if(ho4) {
+ hoco_to_zco(zspan, vez+12, ho4);
- if(ec & ME_V3V4) zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez+12);
- if(ec & ME_V4V1) zspan->zbuflinefunc(zspan, zvlnr, vez+12, vez);
+ if(ec & ME_V3V4) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez+12);
+ if(ec & ME_V4V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+12, vez);
}
else {
- if(ec & ME_V3V1) zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez);
+ if(ec & ME_V3V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez);
}
- if(ec & ME_V1V2) zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
- if(ec & ME_V2V3) zspan->zbuflinefunc(zspan, zvlnr, vez+4, vez+8);
+ if(ec & ME_V1V2) zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
+ if(ec & ME_V2V3) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+4, vez+8);
}
-void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2)
+void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, float *ho1, float *ho2)
{
float f1[4], f2[4];
int c1, c2;
@@ -994,7 +989,7 @@ void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2)
if(clipline(f1, f2)) {
hoco_to_zco(zspan, f1, f1);
hoco_to_zco(zspan, f2, f2);
- zspan->zbuflinefunc(zspan, zvlnr, f1, f2);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2);
}
}
}
@@ -1002,7 +997,7 @@ void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2)
hoco_to_zco(zspan, f1, ho1);
hoco_to_zco(zspan, f2, ho2);
- zspan->zbuflinefunc(zspan, zvlnr, f1, f2);
+ zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2);
}
}
@@ -1017,12 +1012,13 @@ void zbufsinglewire(ZSpan *zspan, int zvlnr, float *ho1, float *ho2)
* @param v2 [4 floats, world coordinates] second vertex
* @param v3 [4 floats, world coordinates] third vertex
*/
-static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
double zxd, zyd, zy0, zverg;
float x0,y0,z0;
float x1,y1,z1,x2,y2,z2,xx1;
float *span1, *span2;
+ int *rectoofs, *ro;
int *rectpofs, *rp;
int *rz, x, y;
int sn1, sn2, rectx, *rectzofs, my0, my2;
@@ -1073,6 +1069,7 @@ static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float
rectx= zspan->rectx;
rectzofs= (zspan->rectz+rectx*my2);
rectpofs= (zspan->rectp+rectx*my2);
+ rectoofs= (zspan->recto+rectx*my2);
/* correct span */
sn1= (my0 + my2)/2;
@@ -1098,16 +1095,19 @@ static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float
zverg= (double)sn1*zxd + zy0;
rz= rectzofs+sn1;
rp= rectpofs+sn1;
+ ro= rectoofs+sn1;
x= sn2-sn1;
while(x>=0) {
if( (int)zverg > *rz || *rz==0x7FFFFFFF) {
+ *ro= obi;
*rz= (int)zverg;
*rp= zvlnr;
}
zverg+= zxd;
rz++;
rp++;
+ ro++;
x--;
}
}
@@ -1115,17 +1115,19 @@ static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float
zy0-=zyd;
rectzofs-= rectx;
rectpofs-= rectx;
+ rectoofs-= rectx;
}
}
/* uses spanbuffers */
-static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
double zxd, zyd, zy0, zverg;
float x0,y0,z0;
float x1,y1,z1,x2,y2,z2,xx1;
float *span1, *span2;
+ int *rectoofs, *ro;
int *rectpofs, *rp;
int *rz, x, y;
int sn1, sn2, rectx, *rectzofs, my0, my2;
@@ -1176,6 +1178,7 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
rectx= zspan->rectx;
rectzofs= (zspan->rectz+rectx*my2);
rectpofs= (zspan->rectp+rectx*my2);
+ rectoofs= (zspan->recto+rectx*my2);
/* correct span */
sn1= (my0 + my2)/2;
@@ -1201,16 +1204,19 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
zverg= (double)sn1*zxd + zy0;
rz= rectzofs+sn1;
rp= rectpofs+sn1;
+ ro= rectoofs+sn1;
x= sn2-sn1;
while(x>=0) {
if( (int)zverg < *rz) {
*rz= (int)zverg;
*rp= zvlnr;
+ *ro= obi;
}
zverg+= zxd;
rz++;
rp++;
+ ro++;
x--;
}
}
@@ -1218,6 +1224,7 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
zy0-=zyd;
rectzofs-= rectx;
rectpofs-= rectx;
+ rectoofs-= rectx;
}
}
@@ -1233,7 +1240,7 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
*/
/* now: filling two Z values, the closest and 2nd closest */
-static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void zbuffillGL_onlyZ(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
double zxd, zyd, zy0, zverg;
float x0,y0,z0;
@@ -1670,9 +1677,115 @@ void projectvert(float *v1, float winmat[][4], float *adr)
adr[3]= x*winmat[0][3]+ y*winmat[1][3]+ z*winmat[2][3]+ winmat[3][3];
}
+/* ------------------------------------------------------------------------- */
+
+#define ZBUF_PROJECT_CACHE_SIZE 256
+
+typedef struct ZbufProjectCache {
+ int index, clip;
+ float ho[4];
+} ZbufProjectCache;
+
+static void zbuf_project_cache_clear(ZbufProjectCache *cache, int size)
+{
+ int i;
+
+ if(size > ZBUF_PROJECT_CACHE_SIZE)
+ size= ZBUF_PROJECT_CACHE_SIZE;
+
+ memset(cache, 0, sizeof(ZbufProjectCache)*size);
+ for(i=0; i<size; i++)
+ cache[i].index= -1;
+}
+
+static int zbuf_shadow_project(ZbufProjectCache *cache, int index, float winmat[][4], float *co, float *ho)
+{
+ int clipflag, cindex= index & 255;
+
+ if(cache[cindex].index == index) {
+ QUATCOPY(ho, cache[cindex].ho);
+ return cache[cindex].clip;
+ }
+ else {
+ projectvert(co, winmat, ho);
+ clipflag= testclip(ho);
+
+ QUATCOPY(cache[cindex].ho, ho);
+ cache[cindex].clip= clipflag;
+ cache[cindex].index= index;
+
+ return clipflag;
+ }
+}
+
+static void zbuffer_part_bounds(Render *re, RenderPart *pa, float *bounds)
+{
+ bounds[0]= (2*pa->disprect.xmin - re->winx-1)/(float)re->winx;
+ bounds[1]= (2*pa->disprect.xmax - re->winx+1)/(float)re->winx;
+ bounds[2]= (2*pa->disprect.ymin - re->winy-1)/(float)re->winy;
+ bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy;
+}
+
+static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[][4], float *bounds, float *co, float *ho)
+{
+ float vec[3], wco;
+ int clipflag= 0, cindex= index & 255;
+
+ if(cache[cindex].index == index) {
+ QUATCOPY(ho, cache[cindex].ho);
+ return cache[cindex].clip;
+ }
+ else {
+ VECCOPY(vec, co)
+ projectvert(co, winmat, ho);
+
+ wco= ho[3];
+ if(ho[0] > bounds[1]*wco) clipflag |= 1;
+ else if(ho[0]< bounds[0]*wco) clipflag |= 2;
+ if(ho[1] > bounds[3]*wco) clipflag |= 4;
+ else if(ho[1]< bounds[2]*wco) clipflag |= 8;
+
+ QUATCOPY(cache[cindex].ho, ho);
+ cache[cindex].clip= clipflag;
+ cache[cindex].index= index;
+
+ return clipflag;
+ }
+}
+
+void zbuf_render_project(float winmat[][4], float *co, float *ho)
+{
+ float vec[3];
+
+ VECCOPY(vec, co)
+ projectvert(vec, winmat, ho);
+}
+
+void zbuf_make_winmat(Render *re, float duplimat[][4], float winmat[][4])
+{
+ float panomat[4][4];
+
+ if(re->r.mode & R_PANORAMA) {
+ Mat4One(panomat);
+ panomat[0][0]= re->panoco;
+ panomat[0][2]= re->panosi;
+ panomat[2][0]= -re->panosi;
+ panomat[2][2]= re->panoco;
+
+ if(duplimat)
+ Mat4MulSerie(winmat, re->winmat, panomat, duplimat, 0, 0, 0, 0, 0);
+ else
+ Mat4MulMat4(winmat, panomat, re->winmat);
+ }
+ else if(duplimat)
+ Mat4MulMat4(winmat, duplimat, re->winmat);
+ else
+ Mat4CpyMat4(winmat, re->winmat);
+}
+
/* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */
-void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3)
+void zbufclip(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3)
{
float *vlzp[32][3], labda[3][2];
float vez[400], *trias[40];
@@ -1771,7 +1884,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
}
for(b=1;b<clvl;b++) {
if(vlzp[b][0]) {
- zspan->zbuffunc(zspan, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL);
+ zspan->zbuffunc(zspan, obi, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL);
}
}
return;
@@ -1782,10 +1895,10 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
hoco_to_zco(zspan, vez, f1);
hoco_to_zco(zspan, vez+4, f2);
hoco_to_zco(zspan, vez+8, f3);
- zspan->zbuffunc(zspan, zvlnr, vez,vez+4,vez+8, NULL);
+ zspan->zbuffunc(zspan, obi, zvlnr, vez,vez+4,vez+8, NULL);
}
-void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4)
+void zbufclip4(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4)
{
float vez[16];
@@ -1793,8 +1906,8 @@ void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *
if(c1 & c2 & c3 & c4) { /* completely out */
return;
} else { /* clipping */
- zbufclip(zspan, zvlnr, f1, f2, f3, c1, c2, c3);
- zbufclip(zspan, zvlnr, f1, f3, f4, c1, c3, c4);
+ zbufclip(zspan, obi, zvlnr, f1, f2, f3, c1, c2, c3);
+ zbufclip(zspan, obi, zvlnr, f1, f3, f4, c1, c3, c4);
}
return;
}
@@ -1805,90 +1918,89 @@ void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *
hoco_to_zco(zspan, vez+8, f3);
hoco_to_zco(zspan, vez+12, f4);
- zspan->zbuffunc(zspan, zvlnr, vez, vez+4, vez+8, vez+12);
+ zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12);
}
/* ***************** ZBUFFER MAIN ROUTINES **************** */
-void set_part_zbuf_clipflag(RenderPart *pa)
-{
- VertRen *ver=NULL;
- float minx, miny, maxx, maxy, wco;
- int v;
- char *clipflag;
-
- /* flags stored in part now */
- clipflag= pa->clipflag= MEM_mallocN(R.totvert+1, "part clipflags");
-
- minx= (2*pa->disprect.xmin - R.winx-1)/(float)R.winx;
- maxx= (2*pa->disprect.xmax - R.winx+1)/(float)R.winx;
- miny= (2*pa->disprect.ymin - R.winy-1)/(float)R.winy;
- maxy= (2*pa->disprect.ymax - R.winy+1)/(float)R.winy;
-
- for(v=0; v<R.totvert; v++, clipflag++) {
- if((v & 255)==0)
- ver= RE_findOrAddVert(&R, v);
- else ver++;
-
- wco= ver->ho[3];
-
- *clipflag= 0;
- if( ver->ho[0] > maxx*wco) *clipflag |= 1;
- else if( ver->ho[0]< minx*wco) *clipflag |= 2;
- if( ver->ho[1] > maxy*wco) *clipflag |= 4;
- else if( ver->ho[1]< miny*wco) *clipflag |= 8;
- }
-}
-
-void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
+void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data)
{
- ZSpan zspan;
+ ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
+ ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */
VlakRen *vlr= NULL;
VertRen *v1, *v2, *v3, *v4;
Material *ma=0;
- int v, zvlnr;
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
+ float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+ int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0, all_z= layflag & SCE_LAY_ALL_Z;
- char *clipflag= pa->clipflag;
-
- zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
-
- /* needed for transform from hoco to zbuffer co */
- zspan.zmulx= ((float)R.winx)/2.0;
- zspan.zmuly= ((float)R.winy)/2.0;
-
- if(R.osa) {
- zspan.zofsx= -pa->disprect.xmin - R.jit[pa->sample][0];
- zspan.zofsy= -pa->disprect.ymin - R.jit[pa->sample][1];
- }
- else if(R.i.curblur) {
- zspan.zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0];
- zspan.zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1];
- }
- else {
- zspan.zofsx= -pa->disprect.xmin;
- zspan.zofsy= -pa->disprect.ymin;
- }
- /* to center the sample position */
- zspan.zofsx -= 0.5f;
- zspan.zofsy -= 0.5f;
-
- /* the buffers */
- zspan.rectz= pa->rectz;
- zspan.rectp= pa->rectp;
- fillrect(pa->rectp, pa->rectx, pa->recty, 0);
- fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
-
- /* filling methods */
- zspan.zbuffunc= zbuffillGL4;
- zspan.zbuflinefunc= zbufline;
- for(v=0; v<R.totvlak; v++) {
+ samples= (R.osa? R.osa: 1);
+ samples= MIN2(4, samples-pa->sample);
+
+ for(zsample=0; zsample<samples; zsample++) {
+ zspan= &zspans[zsample];
- if((v & 255)==0) vlr= R.vlaknodes[v>>8].vlak;
- else vlr++;
+ zbuffer_part_bounds(&R, pa, bounds);
+ zbuf_alloc_span(zspan, pa->rectx, pa->recty);
- if((vlr->flag & R_VISIBLE)) {
+ /* needed for transform from hoco to zbuffer co */
+ zspan->zmulx= ((float)R.winx)/2.0;
+ zspan->zmuly= ((float)R.winy)/2.0;
+
+ if(R.osa) {
+ zspan->zofsx= -pa->disprect.xmin - R.jit[pa->sample+zsample][0];
+ zspan->zofsy= -pa->disprect.ymin - R.jit[pa->sample+zsample][1];
+ }
+ else if(R.i.curblur) {
+ zspan->zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0];
+ zspan->zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1];
+ }
+ else {
+ zspan->zofsx= -pa->disprect.xmin;
+ zspan->zofsy= -pa->disprect.ymin;
+ }
+ /* to center the sample position */
+ zspan->zofsx -= 0.5f;
+ zspan->zofsy -= 0.5f;
+
+ /* the buffers */
+ if(zsample == samples-1) {
+ zspan->rectz= pa->rectz;
+ zspan->rectp= pa->rectp;
+ zspan->recto= pa->recto;
+ }
+ else {
+ zspan->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
+ zspan->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
+ zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
+ }
+
+ fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
+ fillrect(zspan->rectp, pa->rectx, pa->recty, 0);
+ fillrect(zspan->recto, pa->rectx, pa->recty, 0);
+
+ /* filling methods */
+ zspan->zbuffunc= zbuffillGL4;
+ zspan->zbuflinefunc= zbufline;
+ }
+
+ for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
+ obr= obi->obr;
+
+ if(obi->flag & R_TRANSFORMED)
+ zbuf_make_winmat(&R, obi->mat, winmat);
+ else
+ zbuf_make_winmat(&R, NULL, winmat);
+
+ zbuf_project_cache_clear(cache, obr->totvert);
+
+ for(v=0; v<obr->totvlak; v++) {
+ if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
+ else vlr++;
+
/* three cases, visible for render, only z values and nothing */
if(vlr->lay & lay) {
if(vlr->mat!=ma) {
@@ -1897,8 +2009,10 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
env= (ma->mode & MA_ENV);
wire= (ma->mode & MA_WIRE);
- if(ma->mode & MA_ZINV) zspan.zbuffunc= zbuffillGLinv4;
- else zspan.zbuffunc= zbuffillGL4;
+ for(zsample=0; zsample<samples; zsample++) {
+ if(ma->mode & MA_ZINV) zspans[zsample].zbuffunc= zbuffillGLinv4;
+ else zspans[zsample].zbuffunc= zbuffillGL4;
+ }
}
}
else if(all_z) {
@@ -1910,36 +2024,55 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
nofill= 1;
ma= NULL; /* otherwise nofill can hang */
}
-
- if(nofill==0) {
+
+ if(!(vlr->flag & R_HIDDEN) && nofill==0) {
unsigned short partclip;
v1= vlr->v1;
v2= vlr->v2;
v3= vlr->v3;
v4= vlr->v4;
-
+
+ c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
+ c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
+ c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
+
/* partclipping doesn't need viewplane clipping */
- partclip= clipflag[v1->index] & clipflag[v2->index] & clipflag[v3->index];
- if(v4)
- partclip &= clipflag[v4->index];
-
+ partclip= c1 & c2 & c3;
+ if(v4) {
+ c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
+ partclip &= c4;
+ }
+
if(partclip==0) {
if(env) zvlnr= -1;
else zvlnr= v+1;
-
- if(wire) zbufclipwire(&zspan, zvlnr, vlr);
- else {
- /* strands allow to be filled in as quad */
- if(v4 && (vlr->flag & R_STRAND)) {
- zbufclip4(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v4->ho, v1->clip, v2->clip, v3->clip, v4->clip);
+
+ c1= testclip(ho1);
+ c2= testclip(ho2);
+ c3= testclip(ho3);
+ if(v4)
+ c4= testclip(ho4);
+
+ for(zsample=0; zsample<samples; zsample++) {
+ zspan= &zspans[zsample];
+
+ if(wire) {
+ if(v4)
+ zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+ else
+ zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
}
else {
- zbufclip(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v1->clip, v2->clip, v3->clip);
- if(v4) {
- if(zvlnr>0) zvlnr+= RE_QUAD_OFFS;
- zbufclip(&zspan, zvlnr, v1->ho, v3->ho, v4->ho, v1->clip, v3->clip, v4->clip);
+ /* strands allow to be filled in as quad */
+ if(v4 && (vlr->flag & R_STRAND)) {
+ zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+ }
+ else {
+ zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
+ if(v4)
+ zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
}
}
}
@@ -1947,8 +2080,21 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
}
}
}
-
- zbuf_free_span(&zspan);
+
+ for(zsample=0; zsample<samples; zsample++) {
+ zspan= &zspans[zsample];
+
+ if(fillfunc)
+ fillfunc(pa, zspan, pa->sample+zsample, data);
+
+ if(zsample != samples-1) {
+ MEM_freeN(zspan->rectz);
+ MEM_freeN(zspan->rectp);
+ MEM_freeN(zspan->recto);
+ }
+
+ zbuf_free_span(zspan);
+ }
}
typedef struct {
@@ -2008,6 +2154,7 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re
/* the buffers */
zspan.rectz= (int *)vw->rectz;
zspan.rectp= (int *)vw->rect;
+ zspan.recto= MEM_callocN(sizeof(int)*vw->rectx*vw->recty, "radiorecto");
fillrect(zspan.rectz, vw->rectx, vw->recty, 0x7FFFFFFF);
fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF);
@@ -2036,58 +2183,69 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re
}
if(rn->v4)
- zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
else
- zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
+ zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
}
}
}
else { /* radio render */
+ ObjectRen *obr;
VlakRen *vlr=NULL;
RadFace *rf;
int totface=0;
- for(a=0; a<re->totvlak; a++) {
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-
- if(vlr->radface) {
- rf= vlr->radface;
- if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */
-
- if( rf->flag & RAD_TWOSIDED) zvlnr= totface;
- else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */
- else zvlnr= totface;
-
- c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]);
- c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]);
- c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]);
-
- if(vlr->v4) {
- c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]);
+ /* note: radio render doesn't support duplis */
+ for(obr=re->objecttable.first; obr; obr=obr->next) {
+ hashlist_projectvert(NULL, NULL, NULL); /* clear hashlist */
+
+ for(a=0; a<obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+
+ if(vlr->radface) {
+ rf= vlr->radface;
+ if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */
+
+ if( rf->flag & RAD_TWOSIDED) zvlnr= totface;
+ else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */
+ else zvlnr= totface;
+
+ c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]);
+ c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]);
+ c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]);
+
+ if(vlr->v4) {
+ c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]);
+ }
+
+ if(vlr->v4)
+ zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
+ else
+ zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
}
-
- if(vlr->v4)
- zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
- else
- zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
+ totface++;
}
- totface++;
}
}
}
+ MEM_freeN(zspan.recto);
zbuf_free_span(&zspan);
}
-void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, float jity)
+void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int size, float jitx, float jity)
{
+ ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
ZSpan zspan;
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
VlakRen *vlr= NULL;
Material *ma= NULL;
StrandSegment sseg;
StrandRen *strand= NULL;
StrandVert *svert;
- int a, b, ok=1, lay= -1;
+ float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4];
+ int a, b, i, c1, c2, c3, c4, ok=1, lay= -1;
if(lar->mode & LA_LAYER) lay= lar->lay;
@@ -2109,59 +2267,92 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx,
zspan.zbuflinefunc= zbufline_onlyZ;
zspan.zbuffunc= zbuffillGL_onlyZ;
- for(a=0; a<re->totvlak; a++) {
+ for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
+ obr= obi->obr;
- if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
- else vlr++;
+ if(obr->ob==re->excludeob)
+ continue;
- /* note, these conditions are copied in shadowbuf_autoclip() */
- if(vlr->mat!= ma) {
- ma= vlr->mat;
- ok= 1;
- if((ma->mode & MA_SHADBUF)==0) ok= 0;
- }
-
- if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
- if(ma->mode & MA_WIRE) zbufclipwire(&zspan, a+1, vlr);
- else if(vlr->flag & R_STRAND) zbufclipwire(&zspan, a+1, vlr);
- else {
- if(vlr->v4)
- zbufclip4(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
- else
- zbufclip(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
+ else
+ Mat4CpyMat4(obwinmat, winmat);
+
+ zbuf_project_cache_clear(cache, obr->totvert);
+
+ /* faces */
+ for(a=0; a<obr->totvlak; a++) {
+
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+
+ /* note, these conditions are copied in shadowbuf_autoclip() */
+ if(vlr->mat!= ma) {
+ ma= vlr->mat;
+ ok= 1;
+ if((ma->mode & MA_SHADBUF)==0) ok= 0;
+ }
+
+ if(ok && (vlr->lay & lay) && !(vlr->flag & R_HIDDEN)) {
+ c1= zbuf_shadow_project(cache, vlr->v1->index, obwinmat, vlr->v1->co, ho1);
+ c2= zbuf_shadow_project(cache, vlr->v2->index, obwinmat, vlr->v2->co, ho2);
+ c3= zbuf_shadow_project(cache, vlr->v3->index, obwinmat, vlr->v3->co, ho3);
+
+ if((ma->mode & MA_WIRE) || (vlr->flag & R_STRAND)) {
+ if(vlr->v4) {
+ c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4);
+ zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+ }
+ else
+ zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
+ }
+ else {
+ if(vlr->v4) {
+ c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4);
+ zbufclip4(&zspan, 0, 0, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+ }
+ else
+ zbufclip(&zspan, 0, 0, ho1, ho2, ho3, c1, c2, c3);
+ }
}
}
- }
- /* shadow */
- for(a=0; a<re->totstrand; a++) {
- if((a & 255)==0) strand= re->strandnodes[a>>8].strand;
- else strand++;
+ /* strands */
+ for(a=0; a<obr->totstrand; a++) {
+ if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
+ else strand++;
- if(strand->clip)
- continue;
+ sseg.obi= obi;
+ sseg.buffer= strand->buffer;
+ sseg.sqadaptcos= sseg.buffer->adaptcos;
+ sseg.sqadaptcos *= sseg.sqadaptcos;
+ sseg.strand= strand;
+ svert= strand->vert;
- sseg.buffer= strand->buffer;
- sseg.sqadaptcos= sseg.buffer->adaptcos;
- sseg.sqadaptcos *= sseg.sqadaptcos;
- sseg.strand= strand;
- svert= strand->vert;
+ /* note, these conditions are copied in shadowbuf_autoclip() */
+ if(sseg.buffer->ma!= ma) {
+ ma= sseg.buffer->ma;
+ ok= 1;
+ if((ma->mode & MA_SHADBUF)==0) ok= 0;
+ }
- /* note, these conditions are copied in shadowbuf_autoclip() */
- if(sseg.buffer->ma!= ma) {
- ma= sseg.buffer->ma;
- ok= 1;
- if((ma->mode & MA_SHADBUF)==0) ok= 0;
- }
+ if(ok && (sseg.buffer->lay & lay)) {
+ zbuf_project_cache_clear(cache, strand->totvert);
- if(ok && (sseg.buffer->lay & lay)) {
- for(b=0; b<strand->totvert-1; b++, svert++) {
- sseg.v[0]= (b > 0)? (svert-1): svert;
- sseg.v[1]= svert;
- sseg.v[2]= svert+1;
- sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
+ for(b=0; b<strand->totvert-1; b++, svert++) {
+ sseg.v[0]= (b > 0)? (svert-1): svert;
+ sseg.v[1]= svert;
+ sseg.v[2]= svert+1;
+ sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
- render_strand_segment(re, NULL, &zspan, &sseg);
+ c1= zbuf_shadow_project(cache, strand->vert-sseg.v[0], obwinmat, sseg.v[0]->co, ho1);
+ c2= zbuf_shadow_project(cache, strand->vert-sseg.v[1], obwinmat, sseg.v[1]->co, ho2);
+ c3= zbuf_shadow_project(cache, strand->vert-sseg.v[2], obwinmat, sseg.v[2]->co, ho3);
+ c4= zbuf_shadow_project(cache, strand->vert-sseg.v[3], obwinmat, sseg.v[3]->co, ho4);
+
+ if(!(c1 & c2 & c3 & c4))
+ render_strand_segment(NULL, winmat, NULL, &zspan, &sseg);
+ }
}
}
}
@@ -2177,7 +2368,7 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx,
zbuf_free_span(&zspan);
}
-static void zbuffill_sss(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
+static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
{
double zxd, zyd, zy0, z;
float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2;
@@ -2244,22 +2435,26 @@ static void zbuffill_sss(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v
z= (double)sn1*zxd + zy0;
for(x= sn1; x<=sn2; x++, z+=zxd)
- zspan->sss_func(zspan->sss_handle, zvlnr, x, y, z);
+ zspan->sss_func(zspan->sss_handle, obi, zvlnr, x, y, z);
zy0 -= zyd;
}
}
-void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int))
+void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int))
{
+ ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
ZSpan zspan;
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
VlakRen *vlr= NULL;
VertRen *v1, *v2, *v3, *v4;
Material *ma=0, *sss_ma= R.sss_mat;
+ float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+ int i, v, zvlnr, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0;
- char *clipflag= pa->clipflag;
- int v, zvlnr;
+ zbuffer_part_bounds(&R, pa, bounds);
zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
zspan.sss_handle= handle;
@@ -2278,59 +2473,81 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo
/* fill front and back zbuffer */
if(pa->rectz) {
+ fillrect(pa->recto, pa->rectx, pa->recty, 0);
fillrect(pa->rectp, pa->rectx, pa->recty, 0);
fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
}
if(pa->rectbackz) {
+ fillrect(pa->rectbacko, pa->rectx, pa->recty, 0);
fillrect(pa->rectbackp, pa->rectx, pa->recty, 0);
fillrect(pa->rectbackz, pa->rectx, pa->recty, -0x7FFFFFFF);
}
- for(v=0; v<R.totvlak; v++) {
- if((v & 255)==0) vlr= R.vlaknodes[v>>8].vlak;
- else vlr++;
-
- if((vlr->flag & R_VISIBLE) && material_in_material(vlr->mat, sss_ma)) {
- /* three cases, visible for render, only z values and nothing */
- if(vlr->lay & lay) {
- if(vlr->mat!=ma) {
- ma= vlr->mat;
- nofill= ma->mode & MA_ONLYCAST;
- env= (ma->mode & MA_ENV);
- wire= (ma->mode & MA_WIRE);
- }
- }
- else {
- nofill= 1;
- ma= NULL; /* otherwise nofill can hang */
- }
+ for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
+ obr= obi->obr;
+
+ if(obi->flag & R_TRANSFORMED)
+ zbuf_make_winmat(&R, obi->mat, winmat);
+ else
+ zbuf_make_winmat(&R, NULL, winmat);
+
+ zbuf_project_cache_clear(cache, obr->totvert);
+
+ for(v=0; v<obr->totvlak; v++) {
+ if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
+ else vlr++;
- if(nofill==0 && wire==0 && env==0) {
- unsigned short partclip;
-
- v1= vlr->v1;
- v2= vlr->v2;
- v3= vlr->v3;
- v4= vlr->v4;
-
- /* partclipping doesn't need viewplane clipping */
- partclip= clipflag[v1->index] & clipflag[v2->index] & clipflag[v3->index];
- if(v4)
- partclip &= clipflag[v4->index];
+ if(material_in_material(vlr->mat, sss_ma)) {
+ /* three cases, visible for render, only z values and nothing */
+ if(vlr->lay & lay) {
+ if(vlr->mat!=ma) {
+ ma= vlr->mat;
+ nofill= ma->mode & MA_ONLYCAST;
+ env= (ma->mode & MA_ENV);
+ wire= (ma->mode & MA_WIRE);
+ }
+ }
+ else {
+ nofill= 1;
+ ma= NULL; /* otherwise nofill can hang */
+ }
+ if(nofill==0 && wire==0 && env==0) {
+ unsigned short partclip;
+
+ v1= vlr->v1;
+ v2= vlr->v2;
+ v3= vlr->v3;
+ v4= vlr->v4;
- if(partclip==0) {
- zvlnr= v+1;
- zbufclip(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v1->clip, v2->clip, v3->clip);
+ c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
+ c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
+ c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
+
+ /* partclipping doesn't need viewplane clipping */
+ partclip= c1 & c2 & c3;
if(v4) {
- zvlnr+= RE_QUAD_OFFS;
- zbufclip(&zspan, zvlnr, v1->ho, v3->ho, v4->ho, v1->clip, v3->clip, v4->clip);
+ c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
+ partclip &= c4;
+ }
+
+ if(partclip==0) {
+ c1= testclip(ho1);
+ c2= testclip(ho2);
+ c3= testclip(ho3);
+
+ zvlnr= v+1;
+ zbufclip(&zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
+ if(v4) {
+ c4= testclip(ho4);
+ zbufclip(&zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
+ }
}
}
}
}
}
-
+
zbuf_free_span(&zspan);
}
@@ -2861,56 +3078,76 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int sample)
static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay)
{
- ZSpan zspan;
+ ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
+ ZSpan zspans[16], *zspan; /* MAX_OSA */
Material *ma=NULL;
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
VlakRen *vlr=NULL;
VertRen *v1, *v2, *v3, *v4;
float vec[3], hoco[4], mul, zval, fval;
- int v, zvlnr= 0, zsample, dofill= 0;
- char *clipflag= pa->clipflag;
-
- zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
-
- /* needed for transform from hoco to zbuffer co */
- zspan.zmulx= ((float)R.winx)/2.0;
- zspan.zmuly= ((float)R.winy)/2.0;
-
- /* the buffers */
- zspan.arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz");
- zspan.apixbuf= APixbuf;
- zspan.apsmbase= apsmbase;
-
- /* filling methods */
- zspan.zbuffunc= zbuffillAc4;
- zspan.zbuflinefunc= zbuflineAc;
-
- for(zsample=0; zsample<R.osa || R.osa==0; zsample++) {
+ float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+ int i, v, zvlnr, c1, c2, c3, c4=0, dofill= 0;
+ int zsample, samples, polygon_offset;
+
+ zbuffer_part_bounds(&R, pa, bounds);
+ samples= (R.osa? R.osa: 1);
+
+ for(zsample=0; zsample<samples; zsample++) {
+ zspan= &zspans[zsample];
+
+ zbuf_alloc_span(zspan, pa->rectx, pa->recty);
- copyto_abufz(pa, zspan.arectz, zsample); /* init zbuffer */
- zspan.mask= 1<<zsample;
+ /* needed for transform from hoco to zbuffer co */
+ zspan->zmulx= ((float)R.winx)/2.0;
+ zspan->zmuly= ((float)R.winy)/2.0;
+ /* the buffers */
+ zspan->arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz");
+ zspan->apixbuf= APixbuf;
+ zspan->apsmbase= apsmbase;
+
+ /* filling methods */
+ zspan->zbuffunc= zbuffillAc4;
+ zspan->zbuflinefunc= zbuflineAc;
+
+ copyto_abufz(pa, zspan->arectz, zsample); /* init zbuffer */
+ zspan->mask= 1<<zsample;
+
if(R.osa) {
- zspan.zofsx= -pa->disprect.xmin - R.jit[zsample][0];
- zspan.zofsy= -pa->disprect.ymin - R.jit[zsample][1];
+ zspan->zofsx= -pa->disprect.xmin - R.jit[zsample][0];
+ zspan->zofsy= -pa->disprect.ymin - R.jit[zsample][1];
}
else if(R.i.curblur) {
- zspan.zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0];
- zspan.zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1];
+ zspan->zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0];
+ zspan->zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1];
}
else {
- zspan.zofsx= -pa->disprect.xmin;
- zspan.zofsy= -pa->disprect.ymin;
+ zspan->zofsx= -pa->disprect.xmin;
+ zspan->zofsy= -pa->disprect.ymin;
}
/* to center the sample position */
- zspan.zofsx -= 0.5f;
- zspan.zofsy -= 0.5f;
+ zspan->zofsx -= 0.5f;
+ zspan->zofsy -= 0.5f;
- /* we use this to test if nothing was filled in */
- zvlnr= 0;
+ }
+
+ /* we use this to test if nothing was filled in */
+ zvlnr= 0;
- for(v=0; v<R.totvlak; v++) {
+ for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
+ obr= obi->obr;
+
+ if(obi->flag & R_TRANSFORMED)
+ zbuf_make_winmat(&R, obi->mat, winmat);
+ else
+ zbuf_make_winmat(&R, NULL, winmat);
+
+ zbuf_project_cache_clear(cache, obr->totvert);
+
+ for(v=0; v<obr->totvlak; v++) {
if((v & 255)==0)
- vlr= R.vlaknodes[v>>8].vlak;
+ vlr= obr->vlaknodes[v>>8].vlak;
else vlr++;
if(vlr->mat!=ma) {
@@ -2919,24 +3156,30 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un
}
if(dofill) {
- if((vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
+ if(!(vlr->flag & R_HIDDEN) && (vlr->lay & lay)) {
unsigned short partclip;
v1= vlr->v1;
v2= vlr->v2;
v3= vlr->v3;
v4= vlr->v4;
-
+
+ c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
+ c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
+ c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
+
/* partclipping doesn't need viewplane clipping */
- partclip= clipflag[v1->index] & clipflag[v2->index] & clipflag[v3->index];
- if(v4)
- partclip &= clipflag[v4->index];
-
+ partclip= c1 & c2 & c3;
+ if(v4) {
+ c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
+ partclip &= c4;
+ }
+
if(partclip==0) {
/* a little advantage for transp rendering (a z offset) */
if( ma->zoffs != 0.0) {
mul= 0x7FFFFFFF;
- zval= mul*(1.0+v1->ho[2]/v1->ho[3]);
+ zval= mul*(1.0+ho1[2]/ho1[3]);
VECCOPY(vec, v1->co);
/* z is negative, otherwise its being clipped */
@@ -2944,40 +3187,55 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un
projectverto(vec, R.winmat, hoco);
fval= mul*(1.0+hoco[2]/hoco[3]);
- zspan.polygon_offset= (int) fabs(zval - fval );
+ polygon_offset= (int) fabs(zval - fval );
}
- else zspan.polygon_offset= 0;
+ else polygon_offset= 0;
zvlnr= v+1;
-
- if(ma->mode & (MA_WIRE)) zbufclipwire(&zspan, zvlnr, vlr);
- else {
- if(v4 && (vlr->flag & R_STRAND)) {
- zbufclip4(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v4->ho, v1->clip, v2->clip, v3->clip, v4->clip);
+
+ c1= testclip(ho1);
+ c2= testclip(ho2);
+ c3= testclip(ho3);
+ if(v4)
+ c4= testclip(ho4);
+
+ for(zsample=0; zsample<samples; zsample++) {
+ zspan= &zspans[zsample];
+ zspan->polygon_offset= polygon_offset;
+
+ if(ma->mode & (MA_WIRE)) {
+ if(v4)
+ zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+ else
+ zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
}
else {
- zbufclip(&zspan, zvlnr, v1->ho, v2->ho, v3->ho, v1->clip, v2->clip, v3->clip);
- if(v4) {
- zvlnr+= RE_QUAD_OFFS;
- zbufclip(&zspan, zvlnr, v1->ho, v3->ho, v4->ho, v1->clip, v3->clip, v4->clip);
+ if(v4 && (vlr->flag & R_STRAND)) {
+ zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+ }
+ else {
+ zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
+ if(v4)
+ zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
}
}
}
}
+ if((v & 255)==255)
+ if(R.test_break())
+ break;
}
- if( (v & 255)==255)
- if(R.test_break())
- break;
}
}
-
- if(R.osa==0) break;
+
if(R.test_break()) break;
- if(zvlnr==0) break;
}
- MEM_freeN(zspan.arectz);
- zbuf_free_span(&zspan);
+ for(zsample=0; zsample<samples; zsample++) {
+ zspan= &zspans[zsample];
+ MEM_freeN(zspan->arectz);
+ zbuf_free_span(zspan);
+ }
return zvlnr;
}
@@ -3020,16 +3278,18 @@ void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, lo
}
}
-static void add_transp_obindex(RenderLayer *rl, int offset, int facenr)
+static void add_transp_obindex(RenderLayer *rl, int offset, int obi, int facenr)
{
- VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & RE_QUAD_MASK);
- if(vlr && vlr->ob) {
+ ObjectRen *obr= R.objectinstance[obi].obr;
+ VlakRen *vlr= RE_findOrAddVlak(obr, (facenr-1) & RE_QUAD_MASK);
+
+ if(vlr && obr->ob) {
RenderPass *rpass;
for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
if(rpass->passtype == SCE_PASS_INDEXOB) {
float *fp= rpass->rect + offset;
- *fp= (float)vlr->ob->index;
+ *fp= (float)obr->ob->index;
break;
}
}
@@ -3170,25 +3430,30 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph
}
+typedef struct ZTranspRow {
+ int obi;
+ int z;
+ int p;
+ int mask;
+} ZTranspRow;
static int vergzvlak(const void *a1, const void *a2)
{
- const int *x1=a1, *x2=a2;
+ const ZTranspRow *r1 = a1, *r2 = a2;
- if( x1[0] < x2[0] ) return 1;
- else if( x1[0] > x2[0]) return -1;
+ if(r1->z < r2->z) return 1;
+ else if(r1->z > r2->z) return -1;
return 0;
}
-
-static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int facenr, int curmask)
+static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask)
{
ShadeInput *shi= ssamp->shi;
float xs, ys;
ssamp->tot= 0;
- shade_input_set_triangle(shi, facenr, 1);
+ shade_input_set_triangle(shi, obi, facenr, 1);
/* officially should always be true... we have no sky info */
if(shi->vlr) {
@@ -3238,9 +3503,9 @@ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int
}
}
-static int shade_tra_samples(ShadeSample *ssamp, int x, int y, int z, int facenr, int mask)
+static int shade_tra_samples(ShadeSample *ssamp, int x, int y, ZTranspRow *row)
{
- shade_tra_samples_fill(ssamp, x, y, z, facenr, mask);
+ shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask);
if(ssamp->tot) {
ShadeInput *shi= ssamp->shi;
@@ -3352,6 +3617,7 @@ void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf)
}
#define MAX_ZROW 2000
+
/* main render call to fill in pass the full transparent layer */
/* returns a mask, only if a) transp rendered and b) solid was rendered */
unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
@@ -3362,9 +3628,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
APixstr *ap, *aprect, *apn;
ListBase apsmbase={NULL, NULL};
ShadeResult samp_shr[16]; /* MAX_OSA */
+ ZTranspRow zrow[MAX_ZROW];
float sampalpha, *passrect= pass;
long *rdrect;
- int x, y, crop=0, a, zrow[MAX_ZROW][3], totface;
+ int x, y, crop=0, a, totface;
int addpassflag, offs= 0, od, addzbuf;
unsigned short *ztramask= NULL;
@@ -3383,7 +3650,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
/* general shader info, passes */
shade_sample_initialize(&ssamp, pa, rl);
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
- if((rl->layflag & SCE_LAY_STRAND) && R.strandbufs.first)
+ if((rl->layflag & SCE_LAY_STRAND) && R.totstrand)
addzbuf= 1; /* strands layer needs the z-buffer */
else
addzbuf= rl->passflag & SCE_PASS_Z;
@@ -3452,9 +3719,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
while(apn) {
for(a=0; a<4; a++) {
if(apn->p[a]) {
- zrow[totface][0]= apn->z[a];
- zrow[totface][1]= apn->p[a];
- zrow[totface][2]= apn->mask[a];
+ zrow[totface].obi= apn->obi[a];
+ zrow[totface].z= apn->z[a];
+ zrow[totface].p= apn->p[a];
+ zrow[totface].mask= apn->mask[a];
totface++;
if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
}
@@ -3464,31 +3732,29 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
}
if(totface==2) {
- if(zrow[0][0] < zrow[1][0]) {
- a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
- a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
- a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
+ if(zrow[0].z < zrow[1].z) {
+ SWAP(ZTranspRow, zrow[0], zrow[1]);
}
}
else if(totface>2) {
- qsort(zrow, totface, sizeof(int)*3, vergzvlak);
+ qsort(zrow, totface, sizeof(ZTranspRow), vergzvlak);
}
/* zbuffer and index pass for transparent, no AA or filters */
if(addzbuf)
- if(pa->rectz[od]>zrow[totface-1][0])
- pa->rectz[od]= zrow[totface-1][0];
+ if(pa->rectz[od]>zrow[totface-1].z)
+ pa->rectz[od]= zrow[totface-1].z;
if(addpassflag & SCE_PASS_INDEXOB)
- add_transp_obindex(rl, od, zrow[totface-1][1]);
+ add_transp_obindex(rl, od, zrow[totface-1].obi, zrow[totface-1].p);
if(R.osa==0) {
while(totface>0) {
totface--;
- if(shade_tra_samples(&ssamp, x, y, zrow[totface][0], zrow[totface][1], zrow[totface][2])) {
+ if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) {
if(addpassflag)
add_transp_passes(rl, od, ssamp.shr, (1.0f-pass[3])*ssamp.shr[0].combined[3]);
@@ -3512,11 +3778,11 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
while(totface>0) {
totface--;
- if(shade_tra_samples(&ssamp, x, y, zrow[totface][0], zrow[totface][1], zrow[totface][2])) {
+ if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) {
filled= addtosamp_shr(samp_shr, &ssamp, addpassflag);
if(ztramask)
- *sp |= zrow[totface][2];
+ *sp |= zrow[totface].mask;
if(filled==0)
break;
}
diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c
index 292fcba055e..5907d3cd7c3 100644
--- a/source/blender/src/meshlaplacian.c
+++ b/source/blender/src/meshlaplacian.c
@@ -426,14 +426,14 @@ static void heat_ray_tree_create(LaplacianSystem *sys)
DO_MINMAX(sys->heat.verts[a], min, max);
tree= RE_ray_tree_create(64, me->totface, min, max,
- heat_ray_coords_func, heat_ray_check_func);
+ heat_ray_coords_func, heat_ray_check_func, NULL, NULL);
sys->heat.vface= MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces");
HeatSys= sys;
for(a=0, mface=me->mface; a<me->totface; a++, mface++) {
- RE_ray_tree_add_face(tree, mface);
+ RE_ray_tree_add_face(tree, 0, mface);
sys->heat.vface[mface->v1]= mface;
sys->heat.vface[mface->v2]= mface;
diff --git a/source/blender/yafray/YafRay_Api.h b/source/blender/yafray/YafRay_Api.h
index 8c47a79837f..a05e9752a1a 100644
--- a/source/blender/yafray/YafRay_Api.h
+++ b/source/blender/yafray/YafRay_Api.h
@@ -8,8 +8,6 @@ extern "C" {
void YAF_switchPlugin();
void YAF_switchFile();
int YAF_exportScene(Render* re);
- void YAF_addDupliMtx(Object* obj);
- int YAF_objectKnownData(Object* obj);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/yafray/intern/api.cpp b/source/blender/yafray/intern/api.cpp
index f59c5e1f73e..0cb1c6fafdf 100644
--- a/source/blender/yafray/intern/api.cpp
+++ b/source/blender/yafray/intern/api.cpp
@@ -11,6 +11,4 @@ extern "C"
void YAF_switchPlugin() { YAFBLEND = &byplugin; }
void YAF_switchFile() { YAFBLEND = &byfile; }
int YAF_exportScene(Render* re) { return (int)YAFBLEND->exportScene(re); }
- void YAF_addDupliMtx(Object* obj) { YAFBLEND->addDupliMtx(obj); }
- int YAF_objectKnownData(Object* obj) { return (int)YAFBLEND->objectKnownData(obj); }
}
diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp
index c8c0b3c6bb1..48e4f267177 100644
--- a/source/blender/yafray/intern/export_File.cpp
+++ b/source/blender/yafray/intern/export_File.cpp
@@ -1230,7 +1230,8 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li
string matname(face0mat->id.name);
// use name in imgtex_shader list if 'TexFace' enabled for this material
if (face0mat->mode & MA_FACETEXTURE) {
- MTFace* tface = RE_vlakren_get_tface(re, face0, 0, NULL, 0);
+ ObjectRen *obr = face0->obr;
+ MTFace* tface = RE_vlakren_get_tface(obr, face0, obr->actmtface, NULL, 0);
if (tface) {
Image* fimg = (Image*)tface->tpage;
if (fimg) matname = imgtex_shader[string(face0mat->id.name) + string(fimg->id.name)];
@@ -1407,12 +1408,13 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li
fci2!=VLR_list.end();++fci2)
{
VlakRen* vlr = *fci2;
+ ObjectRen *obr = vlr->obr;
Material* fmat = vlr->mat;
bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
string fmatname(fmat->id.name);
// use name in imgtex_shader list if 'TexFace' enabled for this face material
if (fmat->mode & MA_FACETEXTURE) {
- MTFace* tface = RE_vlakren_get_tface(re, vlr, 0, NULL, 0);
+ MTFace* tface = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
if (tface) {
Image* fimg = (Image*)tface->tpage;
if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)];
@@ -1437,14 +1439,14 @@ void yafrayFileRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_li
}
else if (vlr->flag & R_FACE_SPLIT) { ui2++; ui3++; }
- MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down)
+ MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down)
if (uvc) {
ostr << " u_a=\"" << uvc->uv[ui1][0] << "\" v_a=\"" << 1-uvc->uv[ui1][1] << "\""
<< " u_b=\"" << uvc->uv[ui2][0] << "\" v_b=\"" << 1-uvc->uv[ui2][1] << "\""
<< " u_c=\"" << uvc->uv[ui3][0] << "\" v_c=\"" << 1-uvc->uv[ui3][1] << "\"";
}
- MCol *mcol= RE_vlakren_get_mcol(re, vlr, 0, NULL, 0);
+ MCol *mcol= RE_vlakren_get_mcol(obr, vlr, obr->actmcol, NULL, 0);
// since Blender seems to need vcols when uvs are used, for yafray only export when the material actually uses vcols
if ((EXPORT_VCOL) && mcol) {
diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp
index 6a6137fefe9..cccd6b1ab8d 100644
--- a/source/blender/yafray/intern/export_Plugin.cpp
+++ b/source/blender/yafray/intern/export_Plugin.cpp
@@ -1109,7 +1109,8 @@ void yafrayPluginRender_t::genUVcoords(vector<yafray::GFLOAT> &uvcoords, VlakRen
void yafrayPluginRender_t::genVcol(vector<yafray::CFLOAT> &vcol, VlakRen *vlr, bool comple)
{
- MCol *mcol= RE_vlakren_get_mcol(re, vlr, 0, NULL, 0);
+ ObjectRen *obr= vlr->obr;
+ MCol *mcol= RE_vlakren_get_mcol(obr, vlr, obr->actmcol, NULL, 0);
if (mcol)
{
@@ -1145,12 +1146,13 @@ void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,ve
map<VertRen*, int> &vert_idx,VlakRen *vlr,
int has_orco,bool has_uv)
{
+ ObjectRen *obr= vlr->obr;
Material* fmat = vlr->mat;
bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
string fmatname(fmat->id.name);
// use name in imgtex_shader list if 'TexFace' enabled for this face material
if (fmat->mode & MA_FACETEXTURE) {
- MTFace* tface = RE_vlakren_get_tface(re, vlr, 0, NULL, 0);
+ MTFace* tface = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
if (tface) {
Image* fimg = (Image*)tface->tpage;
if (fimg) fmatname = imgtex_shader[fmatname + string(fimg->id.name)];
@@ -1171,7 +1173,7 @@ void yafrayPluginRender_t::genFace(vector<int> &faces,vector<string> &shaders,ve
faceshader.push_back(shaders.size()-1);
}
- MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down)
+ MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down)
int idx1, idx2, idx3;
idx1 = vert_idx.find(vlr->v1)->second;
@@ -1192,11 +1194,12 @@ void yafrayPluginRender_t::genCompleFace(vector<int> &faces,/*vector<string> &sh
map<VertRen*, int> &vert_idx,VlakRen *vlr,
int has_orco,bool has_uv)
{
+ ObjectRen *obr= vlr->obr;
Material* fmat = vlr->mat;
bool EXPORT_VCOL = ((fmat->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))!=0);
faceshader.push_back(faceshader.back());
- MTFace* uvc = RE_vlakren_get_tface(re, vlr, 0, NULL, 0); // possible uvcoords (v upside down)
+ MTFace* uvc = RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); // possible uvcoords (v upside down)
int idx1, idx2, idx3;
idx1 = vert_idx.find(vlr->v3)->second;
idx2 = vert_idx.find(vlr->v4)->second;
@@ -1338,8 +1341,9 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_
fci!=VLR_list.end();++fci)
{
VlakRen* vlr = *fci;
+ ObjectRen *obr = vlr->obr;
genVertices(verts, vidx, vert_idx, vlr, has_orco, obj);
- if(RE_vlakren_get_tface(re, vlr, 0, NULL, 0)) has_uv=true;
+ if(RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0)) has_uv=true;
}
// all faces using the index list created above
vector<int> faces;
@@ -1382,7 +1386,6 @@ void yafrayPluginRender_t::writeObject(Object* obj, const vector<VlakRen*> &VLR_
// write all objects
void yafrayPluginRender_t::writeAllObjects()
{
-
// first all objects except dupliverts (and main instance object for dups)
for (map<Object*, vector<VlakRen*> >::const_iterator obi=all_objects.begin();
obi!=all_objects.end(); ++obi)
@@ -1437,7 +1440,6 @@ void yafrayPluginRender_t::writeAllObjects()
}
}
-
}
void yafrayPluginRender_t::writeAreaLamp(LampRen* lamp, int num, float iview[4][4])
diff --git a/source/blender/yafray/intern/yafray_Render.cpp b/source/blender/yafray/intern/yafray_Render.cpp
index 1106e197335..fa7c61072f4 100644
--- a/source/blender/yafray/intern/yafray_Render.cpp
+++ b/source/blender/yafray/intern/yafray_Render.cpp
@@ -73,7 +73,20 @@ bool yafrayRender_t::exportScene(Render* re)
// as well as associating them again with the original Object.
bool yafrayRender_t::getAllMatTexObs()
{
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
VlakRen* vlr;
+ float mat[4][4];
+
+ // convert blender object instances to dupli matrices
+ for(obi=(ObjectInstanceRen*)re->instancetable.first; obi; obi=obi->next) {
+ if(obi->flag & R_DUPLI_TRANSFORMED) {
+ // compute object matrix with dupli transform, need to transform
+ // obi->mat out of view space for it
+ MTC_Mat4MulSerie(mat, re->viewinv, obi->mat, re->viewmat, obi->obr->ob->obmat, 0, 0, 0, 0);
+ addDupliMtx(obi->obr->ob, mat);
+ }
+ }
// Blender does not include object which have total 0 alpha materials,
// however, the objects might have been included in the dupliMtx list,
@@ -84,69 +97,72 @@ bool yafrayRender_t::getAllMatTexObs()
// but on the other hand that could also hide the real problem of course...
map<string, Object*> renderobs;
- for (int i=0; i < re->totvlak; i++) {
-
- if ((i & 255)==0) vlr=re->vlaknodes[i>>8].vlak; else vlr++;
-
- // ---- The materials & textures
- // in this case, probably every face has a material assigned, which can be the default material,
- // so checking that this is !0 is probably not necessary, but just in case...
- Material* matr = vlr->mat;
- if (matr) {
- // The default assigned material seems to be nameless, no MA id, an empty string.
- // Since this name is needed in yafray, make it 'blender_default'
- if (strlen(matr->id.name)==0)
- used_materials["blender_default"] = matr;
- else
- used_materials[matr->id.name] = matr;
- // textures, all active channels
- for (int m=0;m<MAX_MTEX;m++) {
- if (matr->septex & (1<<m)) continue; // only active channels
- MTex* mx = matr->mtex[m];
- // if no mtex, ignore
- if (mx==NULL) continue;
- // if no tex, ignore
- Tex* tx = mx->tex;
- if (tx==NULL) continue;
- short txtp = tx->type;
- // if texture type not available in yafray, ignore
- if ((txtp==0) ||
- (txtp==TEX_MAGIC) ||
- (txtp==TEX_PLUGIN) ||
- (txtp==TEX_ENVMAP)) continue;
- // if texture is stucci, only export if 'nor' enabled
- if ((txtp==TEX_STUCCI) && !((mx->mapto & MAP_NORM) || (mx->maptoneg & MAP_NORM))) continue;
- // In the case of an image texture, check that there is an actual image, otherwise ignore.
- // Stupid error was here (...if (txtp & TEX_IMAGE)...),
- // which happened to work sofar, but not anymore with the extended texture support..
- if ((txtp==TEX_IMAGE) && (!tx->ima)) continue;
- used_textures[tx->id.name] = mx;
+ for(obr=(ObjectRen*)re->objecttable.first; obr; obr=obr->next) {
+ for (int i=0; i < obr->totvlak; i++) {
+
+ if ((i & 255)==0) vlr=obr->vlaknodes[i>>8].vlak; else vlr++;
+
+ // ---- The materials & textures
+ // in this case, probably every face has a material assigned, which can be the default material,
+ // so checking that this is !0 is probably not necessary, but just in case...
+ Material* matr = vlr->mat;
+ if (matr) {
+ // The default assigned material seems to be nameless, no MA id, an empty string.
+ // Since this name is needed in yafray, make it 'blender_default'
+ if (strlen(matr->id.name)==0)
+ used_materials["blender_default"] = matr;
+ else
+ used_materials[matr->id.name] = matr;
+ // textures, all active channels
+ for (int m=0;m<MAX_MTEX;m++) {
+ if (matr->septex & (1<<m)) continue; // only active channels
+ MTex* mx = matr->mtex[m];
+ // if no mtex, ignore
+ if (mx==NULL) continue;
+ // if no tex, ignore
+ Tex* tx = mx->tex;
+ if (tx==NULL) continue;
+ short txtp = tx->type;
+ // if texture type not available in yafray, ignore
+ if ((txtp==0) ||
+ (txtp==TEX_MAGIC) ||
+ (txtp==TEX_PLUGIN) ||
+ (txtp==TEX_ENVMAP)) continue;
+ // if texture is stucci, only export if 'nor' enabled
+ if ((txtp==TEX_STUCCI) && !((mx->mapto & MAP_NORM) || (mx->maptoneg & MAP_NORM))) continue;
+ // In the case of an image texture, check that there is an actual image, otherwise ignore.
+ // Stupid error was here (...if (txtp & TEX_IMAGE)...),
+ // which happened to work sofar, but not anymore with the extended texture support..
+ if ((txtp==TEX_IMAGE) && (!tx->ima)) continue;
+ used_textures[tx->id.name] = mx;
+ }
}
- }
- // Make list of faces per object, ignore <3 vert faces, duplicate vertex sorting done later.
- // ignore null object pointers.
- // Also make list of facetexture images (material 'TexFace').
- if (vlr->ob) {
- int nv = 0; // number of vertices
- MTFace *tface;
-
- if (vlr->v4) nv=4; else if (vlr->v3) nv=3;
- if (nv) {
- renderobs[vlr->ob->id.name] = vlr->ob;
- all_objects[vlr->ob].push_back(vlr);
-
- tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0);
- if (tface && tface->tpage) {
- Material* fmat = vlr->mat;
-
- // only save if TexFace enabled
- if(fmat && (fmat->mode & MA_FACETEXTURE))
- imagetex[tface->tpage].insert(fmat);
+ // Make list of faces per object, ignore <3 vert faces, duplicate vertex sorting done later.
+ // ignore null object pointers.
+ // Also make list of facetexture images (material 'TexFace').
+ if (vlr->obr->ob) {
+ int nv = 0; // number of vertices
+ MTFace *tface;
+
+ if (vlr->v4) nv=4; else if (vlr->v3) nv=3;
+ if (nv) {
+ ObjectRen *obr= vlr->obr;
+ renderobs[obr->ob->id.name] = obr->ob;
+ all_objects[obr->ob].push_back(vlr);
+
+ tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
+ if (tface && tface->tpage) {
+ Material* fmat = vlr->mat;
+
+ // only save if TexFace enabled
+ if(fmat && (fmat->mode & MA_FACETEXTURE))
+ imagetex[tface->tpage].insert(fmat);
+ }
}
}
- }
+ }
}
// now remove any objects from dupliMtx_list which are not in the renderlist
@@ -187,16 +203,16 @@ bool yafrayRender_t::getAllMatTexObs()
return true;
}
-
-
-void yafrayRender_t::addDupliMtx(Object* obj)
+void yafrayRender_t::addDupliMtx(Object* obj, float mat[][4])
{
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
- dupliMtx_list[obj->id.name].push_back(obj->obmat[i][j]);
+ dupliMtx_list[obj->id.name].push_back(mat[i][j]);
}
+#if 0
+
bool yafrayRender_t::objectKnownData(Object* obj)
{
// if object data already known, no need to include in renderlist, otherwise save object datapointer
@@ -217,3 +233,5 @@ bool yafrayRender_t::objectKnownData(Object* obj)
objectData[obj->data] = obj;
return false;
}
+#endif
+
diff --git a/source/blender/yafray/intern/yafray_Render.h b/source/blender/yafray/intern/yafray_Render.h
index 4002f514a6e..0debb0009fa 100644
--- a/source/blender/yafray/intern/yafray_Render.h
+++ b/source/blender/yafray/intern/yafray_Render.h
@@ -62,7 +62,7 @@ class yafrayRender_t
// mtds
bool exportScene(Render* re);
- void addDupliMtx(Object* obj);
+ void addDupliMtx(Object* obj, float mat[][4]);
bool objectKnownData(Object* obj);
protected: