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.
This commit is contained in:
Brecht Van Lommel 2007-12-15 20:41:45 +00:00
parent dbc8e1e883
commit 460dd7a7bb
34 changed files with 3998 additions and 3915 deletions

@ -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);
}

@ -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

@ -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;

@ -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;

@ -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) {
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++;
/* 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]);
}
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;
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++;
/* 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(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<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];
}
}
}
/* 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];
}
}
}
/* main call, extern */

@ -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 */

@ -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];

@ -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 */

@ -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;

@ -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);
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);
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 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);
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_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);
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 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);
struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver);
struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr);
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);
void RE_vlakren_set_customdata_names(struct Render *re, struct CustomData *data);
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

@ -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;

@ -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);

@ -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);

@ -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

File diff suppressed because it is too large Load Diff

@ -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(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++;
for(a=0; a<re->totvlak; a++) {
if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
else vlr++;
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(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++;
if(obr->ob == ob)
vlr->flag |= R_HIDDEN;
}
}
}
static void env_showobjects(Render *re)
{
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++;
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) {

@ -984,6 +984,5 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, f
texres->tb*= fx;
}
return retval;
}

@ -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);

@ -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;
}

@ -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 */

File diff suppressed because it is too large Load Diff

@ -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;
}
/* 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++;
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;
clipflag= MEM_callocN(sizeof(char)*re->totvert, "autoclipflag");
/* set clip in vertices when face visible */
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;
}
}
/* 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++;
/* 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;
}
/* minmax clipping */
if(vlr->v4) partclip= d1 & d2 & d3 & d4;
else partclip= d1 & d2 & d3;
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]);
/* ***** 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);
else
zbufclip4(&zspan, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
/* 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);
}
else
zbufclip(&zspan, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3);
/* minmax clipping */
if(vlr->v4) partclip= d1 & d2 & d3 & d4;
else partclip= d1 & d2 & d3;
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
zbufclip(&zspan, i, 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)
}
}

@ -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,39 +245,44 @@ 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);
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 & p2) {
shi->n2[0]= -n2[0]; shi->n2[1]= -n2[1]; shi->n2[2]= -n2[2];
} else {
VECCOPY(shi->n2, n2);
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];
}
}
if(shi->puno & p3) {
shi->n3[0]= -n3[0]; shi->n3[1]= -n3[1]; shi->n3[2]= -n3[2];
} else {
VECCOPY(shi->n3, n3);
}
}
/* 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);
}
}
@ -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;

@ -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

@ -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]);
sortseg->next= firstseg;
firstseg= sortseg;
totsegment++;
}
/* shift clipping and z depth */
/* 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];
clip[1]= clip[2]; z[1]= z[2];
clip[2]= clip[3]; z[2]= z[3];
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];
}
/* 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)
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];
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;
/* Go from wcs to hcs ... */
projectfunc(vec, re->winmat, hoco);
/* ... and clip in that system. */
strand->clip &= testclip(hoco);
if(do_buckets) {
project_hoco_to_bucket(re->strandbuckets, hoco, bucketco);
DO_MINMAX2(bucketco, min, max);
}
}
if(do_buckets) {
#if 0
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;
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
add_buckets_primitive(re->strandbuckets, min, max, strand);
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)
/* Go from wcs to hcs ... */
projectfunc(vec, re->winmat, hoco);
/* ... and clip in that system. */
strand->clip &= testclip(hoco);
#if 0
if(do_buckets) {
project_hoco_to_bucket(re->strandbuckets, hoco, bucketco);
DO_MINMAX2(bucketco, min, max);
}
#endif
}
#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
}
}
#endif
}

@ -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;

File diff suppressed because it is too large Load Diff

@ -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;

@ -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

@ -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); }
}

@ -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) {

@ -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])

@ -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++) {
for(obr=(ObjectRen*)re->objecttable.first; obr; obr=obr->next) {
for (int i=0; i < obr->totvlak; i++) {
if ((i & 255)==0) vlr=re->vlaknodes[i>>8].vlak; else vlr++;
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);
// ---- 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->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

@ -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: