diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-12-15 23:41:45 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-12-15 23:41:45 +0300 |
commit | 460dd7a7bbd43526e684bde96fcb6098676afdc8 (patch) | |
tree | 84f48511c9fbc9cf3bef84e139b22191cd581e1f /source/blender | |
parent | dbc8e1e883c136ffa69e7216370bc5100fad5970 (diff) |
Render Instancing
=================
Big commit, but little user visible changes.
- Dupliverts and duplifaces are now rendered as instances, instead
of storing all of the geometry for each dupli, now an instance is
created with a matrix transform refering to the source object.
This should allow us to render tree leaves more memory efficient.
- Radiosity and to some degree raytracing of such objects is not
really efficient still. For radiosity this is fundamentally hard
to solve, but raytracing an octree could be created for each object,
but the current octree code with it's fixed size doesn't allow this
efficiently.
- The regression tests survived, but with I expect that some bugs will
pop up .. hopefully not too many :).
Implementation Notes
====================
- Dupligroups and linked meshes are not rendered as instances yet,
since they can in fact be different due to various reasons,
instancing of these types of duplis that are the same can be added
for them at a later point.
- Each ObjectRen now stores it's own database, instead of there being
one big databases of faces, verts, .. . Which objects that are actually
rendered are defined by the list of ObjectRenInstances, which all refer
to an ObjectRen.
- Homogeneous coordinatess and clipping is now not stored in vertices
anymore, but instead computed on the fly. This couldn't work for
instances. That does mean some extra computation has to be done, but
memory lookups can be slow too, and this saves some memory. Overall
I didn't find a significant speed impact.
- OSA rendering for solid and ztransp now is different. Instead of e.g.
going 8 times over the databases times and rendering the z-buffer, it
now goes over the database once and renders each polygon 8 times. That
was necessary to keep instances efficient, and can also give some
performance improvement without instances.
- There was already instancing support in the yafray export code, now it
uses Blender's render instances for export.
- UV and color layer storage in the render was a bit messy before, now
should be easier to understand.
- convertblender.c was reorganized somewhat. Regular render, speedvector
and baking now use a single function to create the database, previously
there was code duplicated for it.
- Some of these changes were done with future multithreading of scene
and shadow buffer creation in mind, though especially for scene creation
much work remains to be done to make it threadsafe, since it also involves
a lot of code from blenkernel, and there is an ugly conflict with the way
dupli groups work here .. though in the render code itself it's almost there.
Diffstat (limited to 'source/blender')
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: |