Render Instancing
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 15 Dec 2007 20:41:45 +0000 (20:41 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 15 Dec 2007 20:41:45 +0000 (20:41 +0000)
=================

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.

34 files changed:
source/blender/blenkernel/intern/anim.c
source/blender/makesdna/DNA_object_types.h
source/blender/nodes/intern/SHD_nodes/SHD_geom.c
source/blender/radiosity/intern/source/radfactors.c
source/blender/radiosity/intern/source/radrender.c
source/blender/render/extern/include/RE_raytrace.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/rendercore.h
source/blender/render/intern/include/renderdatabase.h
source/blender/render/intern/include/shadbuf.h
source/blender/render/intern/include/shading.h
source/blender/render/intern/include/strand.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/raytrace.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/shadbuf.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/strand.c
source/blender/render/intern/source/texture.c
source/blender/render/intern/source/zbuf.c
source/blender/src/meshlaplacian.c
source/blender/yafray/YafRay_Api.h
source/blender/yafray/intern/api.cpp
source/blender/yafray/intern/export_File.cpp
source/blender/yafray/intern/export_Plugin.cpp
source/blender/yafray/intern/yafray_Render.cpp
source/blender/yafray/intern/yafray_Render.h

index 4aebd099885244dc6ede0bd1627a8a4707ad97c3..1eb7e232382c08da9298cfc1b03742ae1dcc622b 100644 (file)
@@ -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);
                }
index 8e15f6b16847d527ced9e083961ea635d8465e2d..16ecc4b88f06a2800a331d493fbe93a44e86ff91 100644 (file)
@@ -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
index b15aa6802f37a9d3881d7362fcb17473ffa427d0..24395059c600fe862df41ffe3df6d122dfd27778 100644 (file)
@@ -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;
index 46fb6b2c910bb7edc20dd026f25e749bde97fae7..b6411522179b5f7e4de39e420bcffc6d38cbf29d 100644 (file)
@@ -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;
index 42c7fa58da59db855e37a8e8d299ff215d1816e5..ee52956bbd2510bc2e4f65054177cbe1fac0ce73 100644 (file)
@@ -87,6 +87,7 @@ static float maxenergy;
 static VlakRen *findshoot_rr(Render *re)
 {
        RadFace *rf;
+       ObjectRen *obr;
        VlakRen *vlr=NULL, *shoot;
        float energy;
        int a;
@@ -94,19 +95,21 @@ static VlakRen *findshoot_rr(Render *re)
        shoot= NULL;
        maxenergy= 0.0;
        
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               if(vlr->radface) {
-                       rf= vlr->radface;
-                       rf->flag &= ~RAD_SHOOT;
-                       
-                       energy= rf->unshot[0]*rf->area;
-                       energy+= rf->unshot[1]*rf->area;
-                       energy+= rf->unshot[2]*rf->area;
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+                       if(vlr->radface) {
+                               rf= vlr->radface;
+                               rf->flag &= ~RAD_SHOOT;
+                               
+                               energy= rf->unshot[0]*rf->area;
+                               energy+= rf->unshot[1]*rf->area;
+                               energy+= rf->unshot[2]*rf->area;
 
-                       if(energy>maxenergy) {
-                               shoot= vlr;
-                               maxenergy= energy;
+                               if(energy>maxenergy) {
+                                       shoot= vlr;
+                                       maxenergy= energy;
+                               }
                        }
                }
        }
@@ -122,22 +125,22 @@ static VlakRen *findshoot_rr(Render *re)
 
 static void backface_test_rr(Render *re, VlakRen *shoot)
 {
+       ObjectRen *obr;
        VlakRen *vlr=NULL;
        RadFace *rf;
        float tvec[3];
        int a;
        
        /* backface testing */
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               if(vlr->radface) {
-                       if(vlr!=shoot) {
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+                       if(vlr->radface && vlr!=shoot) {
                                rf= vlr->radface;
                                VecSubf(tvec, shoot->radface->cent, rf->cent);
                                
-                               if( tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0) {              
+                               if(tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0)
                                        rf->flag |= RAD_BACKFACE;
-                               }
                        }
                }
        }
@@ -145,17 +148,20 @@ static void backface_test_rr(Render *re, VlakRen *shoot)
 
 static void clear_backface_test_rr(Render *re)
 {
+       ObjectRen *obr;
        VlakRen *vlr=NULL;
        RadFace *rf;
        int a;
        
        /* backface flag clear */
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               
-               if(vlr->radface) {
-                       rf= vlr->radface;
-                       rf->flag &= ~RAD_BACKFACE;
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+                       
+                       if(vlr->radface) {
+                               rf= vlr->radface;
+                               rf->flag &= ~RAD_BACKFACE;
+                       }
                }
        }
 }
@@ -165,6 +171,7 @@ extern RadView hemitop, hemiside; // radfactors.c
 /* hemi-zbuffering, delivers formfactors array */
 static void makeformfactors_rr(Render *re, VlakRen *shoot)
 {
+       ObjectRen *obr;
        VlakRen *vlr=NULL;
        RadFace *rf;
        float len, vec[3], up[3], side[3], tar[5][3], *fp;
@@ -207,16 +214,18 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot)
        /* convert factors to real radiosity */
        fp= RG.formfactors;
 
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               
-               if(vlr->radface) {
-                       rf= vlr->radface;
-                       if(*fp!=0.0 && rf->area!=0.0) {
-                               *fp *= shoot->radface->area/rf->area;
-                               if(*fp>1.0) *fp= 1.0001;
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+                       
+                       if(vlr->radface) {
+                               rf= vlr->radface;
+                               if(*fp!=0.0 && rf->area!=0.0) {
+                                       *fp *= shoot->radface->area/rf->area;
+                                       if(*fp>1.0) *fp= 1.0001;
+                               }
+                               fp++;
                        }
-                       fp++;
                }
        }
 }
@@ -224,6 +233,7 @@ static void makeformfactors_rr(Render *re, VlakRen *shoot)
 /* based at RG.formfactors array, distribute shoot energy over other faces */
 static void applyformfactors_rr(Render *re, VlakRen *shoot)
 {
+       ObjectRen *obr;
        VlakRen *vlr=NULL;
        RadFace *rf;
        float *fp, *ref, unr, ung, unb, r, g, b;
@@ -235,30 +245,32 @@ static void applyformfactors_rr(Render *re, VlakRen *shoot)
 
        fp= RG.formfactors;
        
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               
-               if(vlr->radface) {
-                       rf= vlr->radface;
-                       if(*fp!= 0.0) {
-                               
-                               ref= &(vlr->mat->r);
-                               
-                               r= (*fp)*unr*ref[0];
-                               g= (*fp)*ung*ref[1];
-                               b= (*fp)*unb*ref[2];
-                               
-                               // if(rf->flag & RAD_BACKFACE) {
-                               
-                               rf->totrad[0]+= r;
-                               rf->totrad[1]+= g;
-                               rf->totrad[2]+= b;
-                               
-                               rf->unshot[0]+= r;
-                               rf->unshot[1]+= g;
-                               rf->unshot[2]+= b;
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+                       
+                       if(vlr->radface) {
+                               rf= vlr->radface;
+                               if(*fp!= 0.0) {
+                                       
+                                       ref= &(vlr->mat->r);
+                                       
+                                       r= (*fp)*unr*ref[0];
+                                       g= (*fp)*ung*ref[1];
+                                       b= (*fp)*unb*ref[2];
+                                       
+                                       // if(rf->flag & RAD_BACKFACE) {
+                                       
+                                       rf->totrad[0]+= r;
+                                       rf->totrad[1]+= g;
+                                       rf->totrad[2]+= b;
+                                       
+                                       rf->unshot[0]+= r;
+                                       rf->unshot[1]+= g;
+                                       rf->unshot[2]+= b;
+                               }
+                               fp++;
                        }
-                       fp++;
                }
        }
        /* shoot energy has been shot */
@@ -313,6 +325,7 @@ static RadFace *radfaces=NULL;
 
 static void initradfaces(Render *re)   
 {
+       ObjectRen *obr;
        VlakRen *vlr= NULL;
        RadFace *rf;
        int a, b;
@@ -326,58 +339,62 @@ static void initradfaces(Render *re)
        RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20;
        
        /* count first for fast malloc */
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               
-               if(vlr->mat->mode & MA_RADIO) {
-                       if(vlr->mat->emit > 0.0) {
-                               RG.totpatch++;
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
+                       
+                       if(vlr->mat->mode & MA_RADIO) {
+                               if(vlr->mat->emit > 0.0) {
+                                       RG.totpatch++;
+                               }
+                               RG.totelem++;
                        }
-                       RG.totelem++;
                }
        }
-       
+               
 printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch);       
        if(RG.totelem==0 || RG.totpatch==0) return;
 
        /* make/init radfaces */
        rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces");
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               
-               if(vlr->mat->mode & MA_RADIO) {
-                       
-                       /* during render, vlr->n gets flipped/corrected, we cannot have that */
-                       if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm);
-                       else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm);
-                       
-                       rf->totrad[0]= vlr->mat->emit*vlr->mat->r;
-                       rf->totrad[1]= vlr->mat->emit*vlr->mat->g;
-                       rf->totrad[2]= vlr->mat->emit*vlr->mat->b;
-                       VECCOPY(rf->unshot, rf->totrad);
-                       
-                       if(vlr->v4) {
-                               rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
-                               CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
-                       }
-                       else {
-                               rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co);
-                               CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co);
-                       }
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
                        
-                       RG.totenergy+= rf->unshot[0]*rf->area;
-                       RG.totenergy+= rf->unshot[1]*rf->area;
-                       RG.totenergy+= rf->unshot[2]*rf->area;
-                       
-                       for(b=0; b<3; b++) {
-                               RG.min[b]= MIN2(RG.min[b], rf->cent[b]);
-                               RG.max[b]= MAX2(RG.max[b], rf->cent[b]);
-                       }
+                       if(vlr->mat->mode & MA_RADIO) {
+                               
+                               /* during render, vlr->n gets flipped/corrected, we cannot have that */
+                               if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm);
+                               else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm);
+                               
+                               rf->totrad[0]= vlr->mat->emit*vlr->mat->r;
+                               rf->totrad[1]= vlr->mat->emit*vlr->mat->g;
+                               rf->totrad[2]= vlr->mat->emit*vlr->mat->b;
+                               VECCOPY(rf->unshot, rf->totrad);
+                               
+                               if(vlr->v4) {
+                                       rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+                                       CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
+                               }
+                               else {
+                                       rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co);
+                                       CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co);
+                               }
+                               
+                               RG.totenergy+= rf->unshot[0]*rf->area;
+                               RG.totenergy+= rf->unshot[1]*rf->area;
+                               RG.totenergy+= rf->unshot[2]*rf->area;
+                               
+                               for(b=0; b<3; b++) {
+                                       RG.min[b]= MIN2(RG.min[b], rf->cent[b]);
+                                       RG.max[b]= MAX2(RG.max[b], rf->cent[b]);
+                               }
 
-// uncommented; this isnt satisfying, but i leave it in the code for now (ton)                 
-//                     if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED;
-                       
-                       vlr->radface= rf++;
+       // uncommented; this isnt satisfying, but i leave it in the code for now (ton)                  
+       //                      if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED;
+                               
+                               vlr->radface= rf++;
+                       }
                }
        }
        RG.size[0]= (RG.max[0]- RG.min[0]);
@@ -408,6 +425,7 @@ static void vecaddfac(float *vec, float *v1, float *v2, float fac)
 
 static void make_vertex_rad_values(Render *re)
 {
+       ObjectRen *obr;
        VertRen *v1=NULL;
        VlakRen *vlr=NULL;
        RadFace *rf;
@@ -418,54 +436,55 @@ static void make_vertex_rad_values(Render *re)
        RG.radfactor= RG.radfac*pow(64*64, RG.igamma)/128.0; /* compatible with radio-tool */
 
        /* accumulate vertexcolors */
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++;
-               
-               if(vlr->radface) {
-                       rf= vlr->radface;
-                       
-                       /* apply correction */
-                       rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma);
-                       rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma);
-                       rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma);
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               for(a=0; a<obr->totvlak; a++) {
+                       if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
                        
-                       /* correct rf->rad values for color */
-                       if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r;
-                       if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g;
-                       if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b;
-                       
-                       col= RE_vertren_get_rad(re, vlr->v1, 1);
-                       vecaddfac(col, col, rf->totrad, rf->area); 
-                       col[3]+= rf->area;
-                       
-                       col= RE_vertren_get_rad(re, vlr->v2, 1);
-                       vecaddfac(col, col, rf->totrad, rf->area); 
-                       col[3]+= rf->area;
-                       
-                       col= RE_vertren_get_rad(re, vlr->v3, 1);
-                       vecaddfac(col, col, rf->totrad, rf->area); 
-                       col[3]+= rf->area;
-
-                       if(vlr->v4) {
-                               col= RE_vertren_get_rad(re, vlr->v4, 1);
+                       if(vlr->radface) {
+                               rf= vlr->radface;
+                               
+                               /* apply correction */
+                               rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma);
+                               rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma);
+                               rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma);
+                               
+                               /* correct rf->rad values for color */
+                               if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r;
+                               if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g;
+                               if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b;
+                               
+                               col= RE_vertren_get_rad(obr, vlr->v1, 1);
                                vecaddfac(col, col, rf->totrad, rf->area); 
                                col[3]+= rf->area;
+                               
+                               col= RE_vertren_get_rad(obr, vlr->v2, 1);
+                               vecaddfac(col, col, rf->totrad, rf->area); 
+                               col[3]+= rf->area;
+                               
+                               col= RE_vertren_get_rad(obr, vlr->v3, 1);
+                               vecaddfac(col, col, rf->totrad, rf->area); 
+                               col[3]+= rf->area;
+
+                               if(vlr->v4) {
+                                       col= RE_vertren_get_rad(obr, vlr->v4, 1);
+                                       vecaddfac(col, col, rf->totrad, rf->area); 
+                                       col[3]+= rf->area;
+                               }
                        }
                }
-       }
        
-       /* make vertex colors */
-       for(a=0; a<re->totvert; a++) {
-               if((a & 255)==0) v1= RE_findOrAddVert(re, a); else v1++;
-               
-               col= RE_vertren_get_rad(re, v1, 0);
-               if(col && col[3]>0.0) {
-                       col[0]/= col[3];
-                       col[1]/= col[3];
-                       col[2]/= col[3];
+               /* make vertex colors */
+               for(a=0; a<obr->totvert; a++) {
+                       if((a & 255)==0) v1= RE_findOrAddVert(obr, a); else v1++;
+                       
+                       col= RE_vertren_get_rad(obr, v1, 0);
+                       if(col && col[3]>0.0) {
+                               col[0]/= col[3];
+                               col[1]/= col[3];
+                               col[2]/= col[3];
+                       }
                }
        }
-
 }
 
 /* main call, extern */
index d20e3130fa4bdd95feb53cfafddc6d9ba3703147..39bf2be4256c7461ab19f08f855b7e1954f84fcf 100644 (file)
@@ -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 */
index 8a4f6bb2ec8596660543a2af7048b2bc267d573c..5b81052f5d2789c0da3ecb5de466b94048997428 100644 (file)
@@ -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];
index f7f2222e98d9eb9586e0552e1cfbb3adc5a16e53..84230bd4f6d4a471a567682d0ee0106fb0e4d34d 100644 (file)
@@ -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 */
 
index 0d807d561806e4bb89a2f6b2bed7d83f9b4e2490..600ece8ad50923a7971b3880985e68144e2782e5 100644 (file)
@@ -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;
index febf90d9d6e679d983337aa5c4281967c129c94d..0346f2d64138ca194e668975ec30eefedf98fed7 100644 (file)
@@ -41,6 +41,7 @@ struct MTFace;
 struct CustomData;
 struct StrandBuffer;
 struct StrandRen;
+struct ObjectInstanceRen;
 
 #define RE_QUAD_MASK   0x7FFFFFF
 #define RE_QUAD_OFFS   0x8000000
@@ -58,71 +59,65 @@ typedef struct VertTableNode {
 
 typedef struct VlakTableNode {
        struct VlakRen *vlak;
-       struct MTFace **mtface;
-       struct MCol **mcol;
+       struct MTFace *mtface;
+       struct MCol *mcol;
        int totmtface, totmcol;
        float *surfnor;
-       struct CustomDataNames **names;
 } VlakTableNode;
 
 typedef struct StrandTableNode {
        struct StrandRen *strand;
        float *winspeed;
        float *surfnor;
-       struct MCol **mcol;
-       float **uv;
+       struct MCol *mcol;
+       float *uv;
        int totuv, totmcol;
-       struct CustomDataNames **names;
 } StrandTableNode;
 
-typedef struct CustomDataNames{
-       struct CustomDataNames *next, *prev;
-
-       char (*mtface)[32];
-       char (*mcol)[32];
-} CustomDataNames;
-
 /* renderdatabase.c */
 void free_renderdata_tables(struct Render *re);
 void free_renderdata_vertnodes(struct VertTableNode *vertnodes);
 void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes);
 
-void set_normalflags(Render *re);
+void set_normalflags(struct Render *re, struct ObjectRen *obr);
 void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, float xoffs, int do_buckets);
 
 /* functions are not exported... so wrong names */
 
-struct VlakRen *RE_findOrAddVlak(struct Render *re, int nr);
-struct VertRen *RE_findOrAddVert(struct Render *re, int nr);
-struct StrandRen *RE_findOrAddStrand(struct Render *re, int nr);
-struct HaloRen *RE_findOrAddHalo(struct Render *re, int nr);
-struct HaloRen *RE_inithalo(struct Render *re, struct Material *ma, float *vec, float *vec1, float *orco, float hasize, 
-                                        float vectsize, int seed);
-struct HaloRen *RE_inithalo_particle(struct Render *re, struct DerivedMesh *dm, struct Material *ma,   float *vec,   float *vec1, 
-                                 float *orco, float *uvco, float hasize, float vectsize, int seed);
-void RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est);
-struct StrandBuffer *RE_addStrandBuffer(struct Render *re, struct Object *ob, int totvert);
-
-float *RE_vertren_get_sticky(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_stress(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_rad(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_strand(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_tangent(struct Render *re, struct VertRen *ver, int verify);
-float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verify);
-
-struct MTFace *RE_vlakren_get_tface(struct Render *re, VlakRen *ren, int n, char **name, int verify);
-struct MCol *RE_vlakren_get_mcol(struct Render *re, VlakRen *ren, int n, char **name, int verify);
-float *RE_vlakren_get_surfnor(struct Render *re, VlakRen *ren, int verify);
-
-float *RE_strandren_get_winspeed(struct Render *re, struct StrandRen *strand, int verify);
-float *RE_strandren_get_surfnor(struct Render *re, struct StrandRen *strand, int verify);
-float *RE_strandren_get_uv(struct Render *re, struct StrandRen *strand, int n, char **name, int verify);
-struct MCol *RE_strandren_get_mcol(struct Render *re, struct StrandRen *strand, int n, char **name, int verify);
-
-struct VertRen *RE_vertren_copy(struct Render *re, struct VertRen *ver);
-struct VlakRen *RE_vlakren_copy(struct Render *re, struct VlakRen *vlr);
-
-void RE_vlakren_set_customdata_names(struct Render *re, struct CustomData *data);
+struct VlakRen *RE_findOrAddVlak(struct ObjectRen *obr, int nr);
+struct VertRen *RE_findOrAddVert(struct ObjectRen *obr, int nr);
+struct StrandRen *RE_findOrAddStrand(struct ObjectRen *obr, int nr);
+struct HaloRen *RE_findOrAddHalo(struct ObjectRen *obr, int nr);
+struct HaloRen *RE_inithalo(struct Render *re, struct ObjectRen *obr, struct Material *ma, float *vec, float *vec1, float *orco, float hasize,  float vectsize, int seed);
+struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, struct Material *ma,   float *vec,   float *vec1, float *orco, float *uvco, float hasize, float vectsize, int seed);
+struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert);
+
+struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex);
+void RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]);
+void RE_makeRenderInstances(struct Render *re);
+void RE_instanceTransformNormal(struct ObjectInstanceRen *obi, float *nor, float *tnor);
+
+float *RE_vertren_get_sticky(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_stress(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify);
+float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify);
+
+struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
+struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
+float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
+int RE_vlakren_get_normal(struct Render *re, struct ObjectInstanceRen *obi, struct VlakRen *vlr, float *nor);
+
+float *RE_strandren_get_surfnor(struct ObjectRen *obr, struct StrandRen *strand, int verify);
+float *RE_strandren_get_uv(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify);
+struct MCol *RE_strandren_get_mcol(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify);
+float *RE_strandren_get_winspeed(struct ObjectInstanceRen *obi, struct StrandRen *strand, int verify);
+
+struct VertRen *RE_vertren_copy(struct ObjectRen *obr, struct VertRen *ver);
+struct VlakRen *RE_vlakren_copy(struct ObjectRen *obr, struct VlakRen *vlr);
+
+void RE_set_customdata_names(struct ObjectRen *obr, struct CustomData *data);
 
 /* haloren->type: flags */
 #define HA_ONLYSKY             1
index 8b786c6e0988b583d8d9a4450973f53580850509..b4f196a89fac08874f6da630d36a17db079f5de5 100644 (file)
@@ -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;
index 3390c32ebfe633fe01e2c2f1650d68f37a2c4c93..6ca63a2976d3041edf0862584927c79f897190a8 100644 (file)
@@ -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);
index 55c789de764cdd59066d452a723bce098226b201..7f37317d4d524b7afed0bbb8de92552d773fed27 100644 (file)
@@ -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);
index 0d88d40e7acbc8e0e22a3c8761bd1f0f413dafce..5f1aa5679bfd4d8c4d935e2e1a1a3a7205bdb607 100644 (file)
@@ -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
 
index 9280b457a4cee0ac64340b54c0f3b0d2ffa8ef98..4b68344183345cab6307ddd86f51c89167ba8243 100644 (file)
  * Same is true for lamp coords & vec.
  * Duplicated data objects & dupliframe/duplivert objects are only stored once,
  * only the matrix is stored for all others, in yafray these objects are instances of the original.
- * The main changes are in RE_rotateBlenderScene().
+ * The main changes are in RE_Database_FromScene().
  */
 
 #endif /* disable yafray */
 
-/* ------------------------------------------------------------------------- */
-/* Local functions                                                           */
-/* ------------------------------------------------------------------------- */
-static short test_for_displace(Render *re, Object *ob);
-static void do_displacement(Render *re, Object *ob, int startface, int numface, int startvert, int numvert );
-static int vlakren_customdata_layer_num(int n, int active);
-
 /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */
 /* or for checking vertex normal flips */
 #define FLT_EPSILON10 1.19209290e-06F
 
-
 /* ------------------------------------------------------------------------- */
 
 /* Stuff for stars. This sits here because it uses gl-things. Part of
@@ -143,14 +135,14 @@ this code may move down to the converter.  */
 /* ------------------------------------------------------------------------- */
 /* this is a bad beast, since it is misused by the 3d view drawing as well. */
 
-static HaloRen *initstar(Render *re, float *vec, float hasize)
+static HaloRen *initstar(Render *re, ObjectRen *obr, float *vec, float hasize)
 {
        HaloRen *har;
        float hoco[4];
        
        projectverto(vec, re->winmat, hoco);
        
-       har= RE_findOrAddHalo(re, re->tothalo++);
+       har= RE_findOrAddHalo(obr, obr->tothalo++);
        
        /* projectvert is done in function zbufvlaggen again, because of parts */
        VECCOPY(har->co, vec);
@@ -171,6 +163,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
                                   void (*vertexfunc)(float*),  void (*termfunc)(void))
 {
        extern unsigned char hash[512];
+       ObjectRen *obr= NULL;
        World *wrld= NULL;
        HaloRen *har;
        Scene *scene;
@@ -234,11 +227,14 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
        if (initfunc) {
                initfunc();     
        }
+
+       if(re) /* add render object for stars */
+               obr= RE_addRenderObject(re, NULL, NULL, 0, 0);
        
        for (x = sx, fx = sx * stargrid; x <= ex; x++, fx += stargrid) {
                for (y = sy, fy = sy * stargrid; y <= ey ; y++, fy += stargrid) {
                        for (z = sz, fz = sz * stargrid; z <= ez; z++, fz += stargrid) {
-                               
+
                                BLI_srand((hash[z & 0xff] << 24) + (hash[y & 0xff] << 16) + (hash[x & 0xff] << 8));
                                vec[0] = fx + (hlfrand * BLI_drand()) - dblrand;
                                vec[1] = fy + (hlfrand * BLI_drand()) - dblrand;
@@ -281,7 +277,7 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
                                        if (alpha != 0.0) {
                                                fac = force * BLI_drand();
                                                
-                                               har = initstar(re, vec, fac);
+                                               har = initstar(re, obr, vec, fac);
                                                
                                                if (har) {
                                                        har->alfa = sqrt(sqrt(alpha));
@@ -305,6 +301,9 @@ void RE_make_stars(Render *re, void (*initfunc)(void),
                }
        }
        if (termfunc) termfunc();
+
+       if(obr)
+               re->tothalo += obr->tothalo;
 }
 
 
@@ -328,35 +327,35 @@ u |     |  F1 |  F2 |
 
 /* ------------------------------------------------------------------------- */
 
-static void split_v_renderfaces(Render *re, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv)
+static void split_v_renderfaces(ObjectRen *obr, int startvlak, int startvert, int usize, int vsize, int uIndex, int cyclu, int cyclv)
 {
        int vLen = vsize-1+(!!cyclv);
        int v;
 
        for (v=0; v<vLen; v++) {
-               VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v);
-               VertRen *vert = RE_vertren_copy(re, vlr->v2);
+               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v);
+               VertRen *vert = RE_vertren_copy(obr, vlr->v2);
 
                if (cyclv) {
                        vlr->v2 = vert;
 
                        if (v==vLen-1) {
-                               VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + 0);
+                               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + 0);
                                vlr->v1 = vert;
                        } else {
-                               VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v+1);
+                               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
                                vlr->v1 = vert;
                        }
                } else {
                        vlr->v2 = vert;
 
                        if (v<vLen-1) {
-                               VlakRen *vlr = RE_findOrAddVlak(re, startvlak + vLen*uIndex + v+1);
+                               VlakRen *vlr = RE_findOrAddVlak(obr, startvlak + vLen*uIndex + v+1);
                                vlr->v1 = vert;
                        }
 
                        if (v==0) {
-                               vlr->v1 = RE_vertren_copy(re, vlr->v1);
+                               vlr->v1 = RE_vertren_copy(obr, vlr->v1);
                        } 
                }
        }
@@ -373,6 +372,8 @@ static int check_vnormal(float *n, float *veno)
        return 0;
 }
 
+/* ------------------------------------------------------------------------- */
+/* Stress, tangents and normals                                              */
 /* ------------------------------------------------------------------------- */
 
 static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2)
@@ -389,20 +390,20 @@ static void calc_edge_stress_add(float *accum, VertRen *v1, VertRen *v2)
        acc[1]+= 1.0f;
 }
 
-static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
+static void calc_edge_stress(Render *re, ObjectRen *obr, Mesh *me)
 {
        float loc[3], size[3], *accum, *acc, *accumoffs, *stress;
        int a;
        
-       if(startvert==re->totvert) return;
+       if(obr->totvert==0) return;
        
        mesh_get_texspace(me, loc, NULL, size);
        
-       accum= MEM_callocN(2*sizeof(float)*(re->totvert-startvert), "temp accum for stress");
+       accum= MEM_callocN(2*sizeof(float)*obr->totvert, "temp accum for stress");
        
        /* de-normalize orco */
-       for(a=startvert; a<re->totvert; a++) {
-               VertRen *ver= RE_findOrAddVert(re, a);
+       for(a=0; a<obr->totvert; a++) {
+               VertRen *ver= RE_findOrAddVert(obr, a);
                if(ver->orco) {
                        ver->orco[0]= ver->orco[0]*size[0] +loc[0];
                        ver->orco[1]= ver->orco[1]*size[1] +loc[1];
@@ -411,9 +412,9 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
        }
        
        /* add stress values */
-       accumoffs= accum - 2*startvert; /* so we can use vertex index */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
+       accumoffs= accum;       /* so we can use vertex index */
+       for(a=0; a<obr->totvlak; a++) {
+               VlakRen *vlr= RE_findOrAddVlak(obr, a);
 
                if(vlr->v1->orco && vlr->v4) {
                        calc_edge_stress_add(accumoffs, vlr->v1, vlr->v2);
@@ -427,14 +428,14 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak)
                }
        }
        
-       for(a=startvert; a<re->totvert; a++) {
-               VertRen *ver= RE_findOrAddVert(re, a);
+       for(a=0; a<obr->totvert; a++) {
+               VertRen *ver= RE_findOrAddVert(obr, a);
                if(ver->orco) {
                        /* find stress value */
                        acc= accumoffs + 2*ver->index;
                        if(acc[1]!=0.0f)
                                acc[0]/= acc[1];
-                       stress= RE_vertren_get_stress(re, ver, 1);
+                       stress= RE_vertren_get_stress(obr, ver, 1);
                        *stress= *acc;
                        
                        /* restore orcos */
@@ -474,9 +475,9 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2,
 }
 
 /* gets tangent from tface or orco */
-static void calc_tangent_vector(Render *re, VlakRen *vlr)
+static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr)
 {
-       MTFace *tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0);
+       MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
        VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4;
        float tang[3], *tav;
        float *uv1, *uv2, *uv3, *uv4;
@@ -500,40 +501,40 @@ static void calc_tangent_vector(Render *re, VlakRen *vlr)
 
        tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang);
        
-       tav= RE_vertren_get_tangent(re, v1, 1);
+       tav= RE_vertren_get_tangent(obr, v1, 1);
        VECADD(tav, tav, tang);
-       tav= RE_vertren_get_tangent(re, v2, 1);
+       tav= RE_vertren_get_tangent(obr, v2, 1);
        VECADD(tav, tav, tang);
-       tav= RE_vertren_get_tangent(re, v3, 1);
+       tav= RE_vertren_get_tangent(obr, v3, 1);
        VECADD(tav, tav, tang);
        
        if(v4) {
                tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang);
                
-               tav= RE_vertren_get_tangent(re, v1, 1);
+               tav= RE_vertren_get_tangent(obr, v1, 1);
                VECADD(tav, tav, tang);
-               tav= RE_vertren_get_tangent(re, v3, 1);
+               tav= RE_vertren_get_tangent(obr, v3, 1);
                VECADD(tav, tav, tang);
-               tav= RE_vertren_get_tangent(re, v4, 1);
+               tav= RE_vertren_get_tangent(obr, v4, 1);
                VECADD(tav, tav, tang);
        }
 }
 
 
-static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_tangent)
+static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent)
 {
        int a;
 
                /* clear all vertex normals */
-       for(a=startvert; a<re->totvert; a++) {
-               VertRen *ver= RE_findOrAddVert(re, a);
+       for(a=0; a<obr->totvert; a++) {
+               VertRen *ver= RE_findOrAddVert(obr, a);
                ver->n[0]=ver->n[1]=ver->n[2]= 0.0f;
        }
 
                /* calculate cos of angles and point-masses, use as weight factor to
                   add face normal to vertex */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
+       for(a=0; a<obr->totvlak; a++) {
+               VlakRen *vlr= RE_findOrAddVlak(obr, a);
                if(vlr->flag & ME_SMOOTH) {
                        VertRen *v1= vlr->v1;
                        VertRen *v2= vlr->v2;
@@ -599,13 +600,13 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
                if(do_tangent) {
                        /* tangents still need to be calculated for flat faces too */
                        /* weighting removed, they are not vertexnormals */
-                       calc_tangent_vector(re, vlr);
+                       calc_tangent_vector(obr, vlr);
                }
        }
 
                /* do solid faces */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
+       for(a=0; a<obr->totvlak; a++) {
+               VlakRen *vlr= RE_findOrAddVlak(obr, a);
                if((vlr->flag & ME_SMOOTH)==0) {
                        float *f1= vlr->v1->n;
                        if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
@@ -621,11 +622,11 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
        }
        
                /* normalize vertex normals */
-       for(a=startvert; a<re->totvert; a++) {
-               VertRen *ver= RE_findOrAddVert(re, a);
+       for(a=0; a<obr->totvert; a++) {
+               VertRen *ver= RE_findOrAddVert(obr, a);
                Normalize(ver->n);
                if(do_tangent) {
-                       float *tav= RE_vertren_get_tangent(re, ver, 0);
+                       float *tav= RE_vertren_get_tangent(obr, ver, 0);
                        if (tav) {
                                /* orthonorm. */
                                float tdn = tav[0]*ver->n[0] + tav[1]*ver->n[1] + tav[2]*ver->n[2];
@@ -636,40 +637,20 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
                        }
                }
        }
-
-               /* vertex normal (puno) switch flags for during render */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
-
-               if((vlr->flag & R_NOPUNOFLIP)==0) {
-                       float *v1= vlr->v1->n;
-                       float *v2= vlr->v2->n;
-                       float *v3= vlr->v3->n;
-                       float *v4= vlr->v4?vlr->v4->n:NULL;
-                       float *nor= vlr->n;
-                       vlr->puno &= ~15;
-                       if ((nor[0]*v1[0] + nor[1]*v1[1] + nor[2]*v1[2]) < -FLT_EPSILON10) vlr->puno= 1;
-                       if ((nor[0]*v2[0] + nor[1]*v2[1] + nor[2]*v2[2]) < -FLT_EPSILON10) vlr->puno+= 2;
-                       if ((nor[0]*v3[0] + nor[1]*v3[1] + nor[2]*v3[2]) < -FLT_EPSILON10) vlr->puno+= 4;
-                       if(v4) {
-                               if((nor[0]*v4[0] + nor[1]*v4[1] + nor[2]*v4[2]) < -FLT_EPSILON10 ) vlr->puno+= 8;
-                       }
-               }
-       }
 }
 
 // NT same as calc_vertexnormals, but dont modify the existing vertex normals
 // only recalculate other render data. If this is at some point used for other things than fluidsim,
 // this could be made on option for the normal calc_vertexnormals
-static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int do_tangent)
+static void calc_fluidsimnormals(Render *re, ObjectRen *obr, int do_tangent)
 {
        int a;
 
        /* dont clear vertex normals here */
-       // OFF for(a=startvert; a<re->totvert; a++) { VertRen *ver= RE_findOrAddVert(re, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; }
+       // OFF for(a=0; a<obr->totvert; a++) { VertRen *ver= RE_findOrAddVert(obr, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; }
        /* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
+       for(a=0; a<obr->totvlak; a++) {
+               VlakRen *vlr= RE_findOrAddVlak(obr, a);
                if(vlr->flag & ME_SMOOTH) {
                        VertRen *v1= vlr->v1;
                        VertRen *v2= vlr->v2;
@@ -709,18 +690,18 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d
                        }
 
                        //if(do_tangent)
-                       //      calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
+                       //      calc_tangent_vector(obr, vlr, fac1, fac2, fac3, fac4);
                }
                if(do_tangent) {
                        /* tangents still need to be calculated for flat faces too */
                        /* weighting removed, they are not vertexnormals */
-                       calc_tangent_vector(re, vlr);
+                       calc_tangent_vector(obr, vlr);
                }
        }
 
        /* do solid faces */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
+       for(a=0; a<obr->totvlak; a++) {
+               VlakRen *vlr= RE_findOrAddVlak(obr, a);
                if((vlr->flag & ME_SMOOTH)==0) {
                        float *f1= vlr->v1->n;
                        if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
@@ -736,32 +717,14 @@ static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int d
        }
        
        /* normalize vertex normals */
-       for(a=startvert; a<re->totvert; a++) {
-               VertRen *ver= RE_findOrAddVert(re, a);
+       for(a=0; a<obr->totvert; a++) {
+               VertRen *ver= RE_findOrAddVert(obr, a);
                Normalize(ver->n);
                if(do_tangent) {
-                       float *tav= RE_vertren_get_tangent(re, ver, 0);
+                       float *tav= RE_vertren_get_tangent(obr, ver, 0);
                        if(tav) Normalize(tav);
                }
        }
-
-       /* vertex normal (puno) switch flags for during render */
-       for(a=startvlak; a<re->totvlak; a++) {
-               VlakRen *vlr= RE_findOrAddVlak(re, a);
-               if((vlr->flag & R_NOPUNOFLIP)==0) {
-                       VertRen *v1= vlr->v1;
-                       VertRen *v2= vlr->v2;
-                       VertRen *v3= vlr->v3;
-                       VertRen *v4= vlr->v4;
-                       vlr->puno &= ~15;
-                       if ((vlr->n[0]*v1->n[0]+vlr->n[1]*v1->n[1]+vlr->n[2]*v1->n[2])<0.0) vlr->puno= 1;
-                       if ((vlr->n[0]*v2->n[0]+vlr->n[1]*v2->n[1]+vlr->n[2]*v2->n[2])<0.0) vlr->puno+= 2;
-                       if ((vlr->n[0]*v3->n[0]+vlr->n[1]*v3->n[1]+vlr->n[2]*v3->n[2])<0.0) vlr->puno+= 4;
-                       if(v4) {
-                               if((vlr->n[0]*v4->n[0]+vlr->n[1]*v4->n[1]+vlr->n[2]*v4->n[2])<0.0) vlr->puno+= 8;
-                       }
-               }
-       }
 }
 
 /* ------------------------------------------------------------------------- */
@@ -860,18 +823,17 @@ static VertRen *as_findvertex(VlakRen *vlr, VertRen *ver, ASvert *asv, float thr
 
 /* note; autosmooth happens in object space still, after applying autosmooth we rotate */
 /* note2; actually, when original mesh and displist are equal sized, face normals are from original mesh */
-static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak, int degr)
+static void autosmooth(Render *re, ObjectRen *obr, float mat[][4], int degr)
 {
-       ASvert *asv, *asverts, *asvertoffs;
+       ASvert *asv, *asverts;
        ASface *asf;
        VertRen *ver, *v1;
        VlakRen *vlr;
        float thresh;
        int a, b, totvert;
        
-       if(startvert==re->totvert) return;
-       asverts= MEM_callocN(sizeof(ASvert)*(re->totvert-startvert), "all smooth verts");
-       asvertoffs= asverts-startvert;   /* se we can use indices */
+       if(obr->totvert==0) return;
+       asverts= MEM_callocN(sizeof(ASvert)*obr->totvert, "all smooth verts");
        
        thresh= cos( M_PI*(0.5f+(float)degr)/180.0 );
        
@@ -879,24 +841,24 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
        
        
        /* step one: construct listbase of all vertices and pointers to faces */
-       for(a=startvlak; a<re->totvlak; a++) {
-               vlr= RE_findOrAddVlak(re, a);
+       for(a=0; a<obr->totvlak; a++) {
+               vlr= RE_findOrAddVlak(obr, a);
                /* skip wire faces */
                if(vlr->v2 != vlr->v3) {
-                       as_addvert(asvertoffs+vlr->v1->index, vlr->v1, vlr);
-                       as_addvert(asvertoffs+vlr->v2->index, vlr->v2, vlr);
-                       as_addvert(asvertoffs+vlr->v3->index, vlr->v3, vlr);
+                       as_addvert(asverts+vlr->v1->index, vlr->v1, vlr);
+                       as_addvert(asverts+vlr->v2->index, vlr->v2, vlr);
+                       as_addvert(asverts+vlr->v3->index, vlr->v3, vlr);
                        if(vlr->v4) 
-                               as_addvert(asvertoffs+vlr->v4->index, vlr->v4, vlr);
+                               as_addvert(asverts+vlr->v4->index, vlr->v4, vlr);
                }
        }
        
+       totvert= obr->totvert;
        /* we now test all vertices, when faces have a normal too much different: they get a new vertex */
-       totvert= re->totvert;
-       for(a=startvert, asv=asverts; a<totvert; a++, asv++) {
+       for(a=0, asv=asverts; a<totvert; a++, asv++) {
                if(asv && asv->totface>1) {
-                       ver= RE_findOrAddVert(re, a);
-                       
+                       ver= RE_findOrAddVert(obr, a);
+
                        asf= asv->faces.first;
                        while(asf) {
                                for(b=0; b<4; b++) {
@@ -909,7 +871,7 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
                                                v1= as_findvertex(vlr, ver, asv, thresh);
                                                if(v1==NULL) {
                                                        /* make a new vertex */
-                                                       v1= RE_vertren_copy(re, ver);
+                                                       v1= RE_vertren_copy(obr, ver);
                                                }
                                                asf->nver[b]= v1;
                                                if(vlr->v1==ver) vlr->v1= v1;
@@ -924,18 +886,18 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
        }
        
        /* free */
-       for(a=0; a<totvert-startvert; a++) {
+       for(a=0; a<totvert; a++) {
                BLI_freelistN(&asverts[a].faces);
        }
        MEM_freeN(asverts);
        
        /* rotate vertices and calculate normal of faces */
-       for(a=startvert; a<re->totvert; a++) {
-               ver= RE_findOrAddVert(re, a);
+       for(a=0; a<obr->totvert; a++) {
+               ver= RE_findOrAddVert(obr, a);
                MTC_Mat4MulVecfl(mat, ver->co);
        }
-       for(a=startvlak; a<re->totvlak; a++) {
-               vlr= RE_findOrAddVlak(re, a);
+       for(a=0; a<obr->totvlak; a++) {
+               vlr= RE_findOrAddVlak(obr, a);
                
                /* skip wire faces */
                if(vlr->v2 != vlr->v3) {
@@ -948,14 +910,9 @@ static void autosmooth(Render *re, float mat[][4], int startvert, int startvlak,
 }
 
 /* ------------------------------------------------------------------------- */
-/* End of autosmoothing:                                                     */
-/* ------------------------------------------------------------------------- */
-
-/* ------------------------------------------------------------------------- */
-/* Orco hash                                                                                                                            */
+/* Orco hash and Materials                                                   */
 /* ------------------------------------------------------------------------- */
 
-
 static float *get_object_orco(Render *re, Object *ob)
 {
        float *orco;
@@ -995,59 +952,6 @@ static void free_mesh_orco_hash(Render *re)
        }
 }
 
-/* ******************** END ORCO HASH ***************** */
-
-
-static void make_render_halos(Render *re, Object *ob, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco)
-{
-       HaloRen *har;
-       float xn, yn, zn, nor[3], view[3];
-       float vec[3], hasize, mat[4][4], imat[3][3];
-       int a, ok, seed= ma->seed1;
-
-       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-       MTC_Mat3CpyMat4(imat, ob->imat);
-
-       re->flag |= R_HALO;
-
-       for(a=0; a<totvert; a++, mvert++) {
-               ok= 1;
-
-               if(ok) {
-                       hasize= ma->hasize;
-
-                       VECCOPY(vec, mvert->co);
-                       MTC_Mat4MulVecfl(mat, vec);
-
-                       if(ma->mode & MA_HALOPUNO) {
-                               xn= mvert->no[0];
-                               yn= mvert->no[1];
-                               zn= mvert->no[2];
-
-                               /* transpose ! */
-                               nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
-                               nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
-                               nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
-                               Normalize(nor);
-
-                               VECCOPY(view, vec);
-                               Normalize(view);
-
-                               zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
-                               if(zn>=0.0) hasize= 0.0;
-                               else hasize*= zn*zn*zn*zn;
-                       }
-
-                       if(orco) har= RE_inithalo(re, ma, vec, NULL, orco, hasize, 0.0, seed);
-                       else har= RE_inithalo(re, ma, vec, NULL, mvert->co, hasize, 0.0, seed);
-                       if(har) har->lay= ob->lay;
-               }
-               if(orco) orco+= 3;
-               seed++;
-       }
-}
-
-/* ------------------------------------------------------------------------- */
 static Material *give_render_material(Render *re, Object *ob, int nr)
 {
        extern Material defmaterial;    /* material.c */
@@ -1068,158 +972,12 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
        return ma;
 }
 
-
-
-static void render_particle_system(Render *re, Object *ob, Object *par, PartEff *paf)
-{
-       Particle *pa=0;
-       HaloRen *har=0;
-       Material *ma=0;
-       float xn, yn, zn, imat[3][3], tmat[4][4], mat[4][4], hasize, stime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
-       float haloScale = 1.0;  //NT scale halos 
-       float iniAlpha = 0.0; // restore material alpha 
-       int a, mat_nr=1, seed;
-       int useFluidsimParticles = 0; // FSPARTICLE
-
-       ma= give_render_material(re, ob, paf->omat);
-       
-       if( (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) {
-               useFluidsimParticles = 1;
-               iniAlpha = ma->alpha;
-       }
-       
-       pa= paf->keys;
-       if(pa==NULL || paf->disp!=100 || useFluidsimParticles) {
-               build_particle_system(ob);
-               pa= paf->keys;
-               if(pa==NULL) return;
-       }
-
-       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-       MTC_Mat4Invert(ob->imat, mat);  /* this is correct, for imat texture */
-
-       /* enable duplicators to work */
-       if(par) {
-               Mat4MulMat4(tmat, paf->imat, ob->obmat);
-               MTC_Mat4MulMat4(mat, tmat, re->viewmat);
-               
-               MTC_Mat4Invert(tmat, mat);
-               MTC_Mat3CpyMat4(imat, tmat);
-       }
-       else {
-               MTC_Mat4CpyMat4(mat, re->viewmat);
-               
-               MTC_Mat4Invert(tmat, re->viewmat);
-               MTC_Mat3CpyMat4(imat, tmat);
-               
-       }       
-
-       re->flag |= R_HALO;
-
-       if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
-       else ptime= 0.0;
-       ctime= bsystem_time(ob, (float)re->scene->r.cfra, ptime);
-       seed= ma->seed1;
-       
-       for(a=0; a<paf->totpart; a++, pa+=paf->totkey, seed++) {
-
-               /* offset time for calculating normal */
-               stime= ctime;
-               ptime= ctime+1.0f;
-               if(ctime < pa->time) {
-                       if(paf->flag & PAF_UNBORN)
-                               ptime= pa->time+1.0f;
-                       else
-                               continue;
-               }
-               if(ctime > pa->time+pa->lifetime) {
-                       if(paf->flag & PAF_DIED)
-                               stime= pa->time+pa->lifetime-1.0f;
-                       else
-                               continue;
-               }
-               
-               /* watch it: also calculate the normal of a particle */
-               if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
-                       where_is_particle(paf, pa, stime, vec);
-                       MTC_Mat4MulVecfl(mat, vec);
-                       where_is_particle(paf, pa, ptime, vec1);
-                       MTC_Mat4MulVecfl(mat, vec1);
-               }
-               else {
-                       where_is_particle(paf, pa, ctime, vec);
-                       MTC_Mat4MulVecfl(mat, vec);
-               }
-
-               if(pa->mat_nr != mat_nr) {
-                       mat_nr= pa->mat_nr;
-                       ma= give_render_material(re, ob, mat_nr);
-               }
-
-               if(ma->ipo) {
-                       /* correction for lifetime */
-                       ptime= 100.0*(ctime-pa->time)/pa->lifetime;
-                       calc_ipo(ma->ipo, ptime);
-                       execute_ipo((ID *)ma, ma->ipo);
-               }
-
-               //NT scale halos FSPARTICLE
-               if(useFluidsimParticles) {
-                       // rescale to 1.0-10.0, then div by 5 afterwards, gives values in range 0.2-2.0
-                       double fspsize = ((double)pa->rt / 1000.0f) / 5.0 ; 
-                       haloScale = 1.0/(float)pow(fspsize, (double)ob->fluidsimSettings->particleInfSize);
-                       ma->alpha = iniAlpha / (float)pow( fspsize, (double)ob->fluidsimSettings->particleInfAlpha);
-                       if(ma->alpha>1.) ma->alpha = 1.;
-               }
-
-               hasize= ma->hasize * haloScale;
-
-               if(ma->mode & MA_HALOPUNO) {
-                       xn= pa->no[0];
-                       yn= pa->no[1];
-                       zn= pa->no[2];
-
-                       /* transpose ! */
-                       nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
-                       nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
-                       nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
-                       Normalize(nor);
-
-                       VECCOPY(view, vec);
-                       Normalize(view);
-
-                       zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
-                       if(zn>=0.0) hasize= 0.0;
-                       else hasize*= zn*zn*zn*zn;
-               }
-
-               if(paf->stype==PAF_VECT) har= RE_inithalo(re, ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
-               else {
-                       har= RE_inithalo(re, ma, vec, NULL, pa->co, hasize, 0.0, seed);
-                       if(har && ma->mode & MA_HALO_SHADE) {
-                               VecSubf(har->no, vec, vec1);
-                               Normalize(har->no);
-                       }
-               }
-               if(har) har->lay= ob->lay;
-       }
-
-       /* restore material */
-       for(a=1; a<=ob->totcol; a++) {
-               ma= give_render_material(re, ob, a);
-               if(ma) do_mat_ipo(ma);
-       }
-       
-       if(paf->disp!=100) {
-               MEM_freeN(paf->keys);
-               paf->keys= NULL;
-       }
-
-       if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore...
-}
+/* ------------------------------------------------------------------------- */
+/* Particles                                                                 */
+/* ------------------------------------------------------------------------- */
 
 /* future thread problem... */
-static void static_particle_strand(Render *re, Object *ob, Material *ma, float *orco, float *surfnor,
+static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, float *orco, float *surfnor,
                                                                   float *uvco, int totuv, float *vec, float *vec1, float ctime,
                                                                   int first, int line, int adapt, float adapt_angle, float adapt_pix, int override_uv)
 {
@@ -1280,13 +1038,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
        
        /* single face line */
        if(line) {
-               vlr= RE_findOrAddVlak(re, re->totvlak++);
+               vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                vlr->flag= flag;
-               vlr->ob= ob;
-               vlr->v1= RE_findOrAddVert(re, re->totvert++);
-               vlr->v2= RE_findOrAddVert(re, re->totvert++);
-               vlr->v3= RE_findOrAddVert(re, re->totvert++);
-               vlr->v4= RE_findOrAddVert(re, re->totvert++);
+               vlr->obr= obr;
+               vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
+               vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
+               vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+               vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
                
                VECCOPY(vlr->v1->co, vec);
                VecAddf(vlr->v1->co, vlr->v1->co, cross);
@@ -1316,17 +1074,17 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                
                vlr->mat= ma;
                vlr->ec= ME_V2V3;
-               vlr->lay= ob->lay;
+               vlr->lay= obr->ob->lay;
 
                if(surfnor) {
-                       float *snor= RE_vlakren_get_surfnor(re, vlr, 1);
+                       float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
                        VECCOPY(snor, surfnor);
                }
 
                if(uvco){
                        for(i=0; i<totuv; i++){
                                MTFace *mtf;
-                               mtf=RE_vlakren_get_tface(re,vlr,i,NULL,1);
+                               mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1);
                                mtf->uv[0][0]=mtf->uv[1][0]=
                                mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0];
                                mtf->uv[0][1]=mtf->uv[1][1]=
@@ -1334,7 +1092,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                        }
                        if(override_uv>=0){
                                MTFace *mtf;
-                               mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0);
+                               mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0);
                                
                                mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
                                mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
@@ -1352,8 +1110,8 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                        second=1;
                }
 
-               v1= RE_findOrAddVert(re, re->totvert++);
-               v2= RE_findOrAddVert(re, re->totvert++);
+               v1= RE_findOrAddVert(obr, obr->totvert++);
+               v2= RE_findOrAddVert(obr, obr->totvert++);
                
                VECCOPY(v1->co, vec);
                VecAddf(v1->co, v1->co, cross);
@@ -1370,13 +1128,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
        /* more vertices & faces to strand */
        else {
                if(adapt==0 || second){
-                       vlr= RE_findOrAddVlak(re, re->totvlak++);
+                       vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                        vlr->flag= flag;
-                       vlr->ob= ob;
+                       vlr->obr= obr;
                        vlr->v1= v1;
                        vlr->v2= v2;
-                       vlr->v3= RE_findOrAddVert(re, re->totvert++);
-                       vlr->v4= RE_findOrAddVert(re, re->totvert++);
+                       vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+                       vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
                        
                        v1= vlr->v4; // cycle
                        v2= vlr->v3; // cycle
@@ -1400,13 +1158,13 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                        dy= re->winy*dvec[1]*re->winmat[1][1]/w;
                        w= sqrt(dx*dx + dy*dy);
                        if(Inpf(anor,nor)<adapt_angle && w>adapt_pix){
-                               vlr= RE_findOrAddVlak(re, re->totvlak++);
+                               vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                                vlr->flag= flag;
-                               vlr->ob= ob;
+                               vlr->obr= obr;
                                vlr->v1= v1;
                                vlr->v2= v2;
-                               vlr->v3= RE_findOrAddVert(re, re->totvert++);
-                               vlr->v4= RE_findOrAddVert(re, re->totvert++);
+                               vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+                               vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
                                
                                v1= vlr->v4; // cycle
                                v2= vlr->v3; // cycle
@@ -1415,7 +1173,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                                VECCOPY(avec,vec);
                        }
                        else{
-                               vlr= RE_findOrAddVlak(re, re->totvlak-1);
+                               vlr= RE_findOrAddVlak(obr, obr->totvlak-1);
                        }
                }
        
@@ -1435,17 +1193,17 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                
                vlr->mat= ma;
                vlr->ec= ME_V2V3;
-               vlr->lay= ob->lay;
+               vlr->lay= obr->ob->lay;
 
                if(surfnor) {
-                       float *snor= RE_vlakren_get_surfnor(re, vlr, 1);
+                       float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
                        VECCOPY(snor, surfnor);
                }
 
                if(uvco){
                        for(i=0; i<totuv; i++){
                                MTFace *mtf;
-                               mtf=RE_vlakren_get_tface(re,vlr,i,NULL,1);
+                               mtf=RE_vlakren_get_tface(obr,vlr,i,NULL,1);
                                mtf->uv[0][0]=mtf->uv[1][0]=
                                mtf->uv[2][0]=mtf->uv[3][0]=(uvco+2*i)[0];
                                mtf->uv[0][1]=mtf->uv[1][1]=
@@ -1453,7 +1211,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
                        }
                        if(override_uv>=0){
                                MTFace *mtf;
-                               mtf=RE_vlakren_get_tface(re,vlr,override_uv,NULL,0);
+                               mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0);
                                
                                mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
                                mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
@@ -1465,16 +1223,16 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float *
        }
 }
 
-static void static_particle_wire(Render *re, Object *ob, Material *ma, float *vec, float *vec1, int first, int line)
+static void static_particle_wire(ObjectRen *obr, Material *ma, float *vec, float *vec1, int first, int line)
 {
        VlakRen *vlr;
        static VertRen *v1;
 
        if(line) {
-               vlr= RE_findOrAddVlak(re, re->totvlak++);
-               vlr->ob= ob;
-               vlr->v1= RE_findOrAddVert(re, re->totvert++);
-               vlr->v2= RE_findOrAddVert(re, re->totvert++);
+               vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+               vlr->obr= obr;
+               vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
+               vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
                vlr->v3= vlr->v2;
                vlr->v4= NULL;
                
@@ -1488,18 +1246,18 @@ static void static_particle_wire(Render *re, Object *ob, Material *ma, float *ve
                
                vlr->mat= ma;
                vlr->ec= ME_V1V2;
-               vlr->lay= ob->lay;
+               vlr->lay= obr->ob->lay;
 
        }
        else if(first) {
-               v1= RE_findOrAddVert(re, re->totvert++);
+               v1= RE_findOrAddVert(obr, obr->totvert++);
                VECCOPY(v1->co, vec);
        }
        else {
-               vlr= RE_findOrAddVlak(re, re->totvlak++);
-               vlr->ob= ob;
+               vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+               vlr->obr= obr;
                vlr->v1= v1;
-               vlr->v2= RE_findOrAddVert(re, re->totvert++);
+               vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
                vlr->v3= vlr->v2;
                vlr->v4= NULL;
                
@@ -1512,11 +1270,11 @@ static void static_particle_wire(Render *re, Object *ob, Material *ma, float *ve
                
                vlr->mat= ma;
                vlr->ec= ME_V1V2;
-               vlr->lay= ob->lay;
+               vlr->lay= obr->ob->lay;
        }
 
 }
-static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align,
+static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, Object *bb_ob, float *vec, float *vel, float size, float tilt, short align,
                                                           int lock, int p, int totpart, short uv_split, short anim, short split_offset, float random, float pa_time, float offset[2], int uv[3])
 {
        VlakRen *vlr;
@@ -1528,12 +1286,12 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
        if(align<PART_BB_VIEW)
                onevec[align]=1.0f;
 
-       vlr= RE_findOrAddVlak(re, re->totvlak++);
-       vlr->ob= ob;
-       vlr->v1= RE_findOrAddVert(re, re->totvert++);
-       vlr->v2= RE_findOrAddVert(re, re->totvert++);
-       vlr->v3= RE_findOrAddVert(re, re->totvert++);
-       vlr->v4= RE_findOrAddVert(re, re->totvert++);
+       vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+       vlr->obr= obr;
+       vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
+       vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
+       vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
+       vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
 
        if(lock && align==PART_BB_VIEW){
                VECCOPY(xvec,bb_ob->obmat[0]);
@@ -1612,7 +1370,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
        
        vlr->mat= ma;
        vlr->ec= ME_V2V3;
-       vlr->lay= ob->lay;
+       vlr->lay= obr->ob->lay;
 
        if(uv_split>1){
                uvdx=uvdy=1.0f/(float)uv_split;
@@ -1665,7 +1423,7 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
 
        /* normal UVs */
        if(uv[0]>=0){
-               mtf=RE_vlakren_get_tface(re,vlr,uv[0],NULL,1);
+               mtf=RE_vlakren_get_tface(obr,vlr,uv[0],NULL,1);
                mtf->uv[0][0]=1.0f;
                mtf->uv[0][1]=1.0f;
                mtf->uv[1][0]=0.0f;
@@ -1678,14 +1436,14 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
 
        /* time-index UVs */
        if(uv[1]>=0){
-               mtf=RE_vlakren_get_tface(re,vlr,uv[1],NULL,1);
+               mtf=RE_vlakren_get_tface(obr,vlr,uv[1],NULL,1);
                mtf->uv[0][0]=mtf->uv[1][0]=mtf->uv[2][0]=mtf->uv[3][0]=pa_time;
                mtf->uv[0][1]=mtf->uv[1][1]=mtf->uv[2][1]=mtf->uv[3][1]=(float)p/(float)totpart;
        }
 
        /* split UVs */
        if(uv_split>1 && uv[2]>=0){
-               mtf=RE_vlakren_get_tface(re,vlr,uv[2],NULL,1);
+               mtf=RE_vlakren_get_tface(obr,vlr,uv[2],NULL,1);
                mtf->uv[0][0]=uvx+uvdx;
                mtf->uv[0][1]=uvy+uvdy;
                mtf->uv[1][0]=uvx;
@@ -1696,28 +1454,29 @@ static void particle_billboard(Render *re, Object *ob, Material *ma, Object *bb_
                mtf->uv[3][1]=uvy;
        }
 }
-static void render_new_particle(Render *re, Object *ob, DerivedMesh *dm, Material *ma, int path, int first, int line,
+static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, int path, int first, int line,
                                                                float time, float *loc, float *loc1, float *orco, float *surfnor, int totuv, float *uvco,
                                                                float size, int seed, int override_uv, int adapt, float adapt_angle, float adapt_pix)
 {
        HaloRen *har=0;
        if(path){
                if(ma->mode&MA_WIRE)
-                       static_particle_wire(re, ob, ma, loc, loc1, first, line);
+                       static_particle_wire(obr, ma, loc, loc1, first, line);
                else if(ma->mode & MA_HALO){
-                       har= RE_inithalo_particle(re, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed);
-                       if(har) har->lay= ob->lay;
+                       har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed);
+                       if(har) har->lay= obr->ob->lay;
                }
                else
-                       static_particle_strand(re, ob, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
+                       static_particle_strand(re, obr, ma, orco, surfnor, uvco, totuv, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
        }
        else{
-               har= RE_inithalo_particle(re, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
-               if(har) har->lay= ob->lay;
+               har= RE_inithalo_particle(re, obr, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
+               if(har) har->lay= obr->ob->lay;
        }
 }
-static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *psys)
+static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys)
 {
+       Object *ob= obr->ob;
        Object *tob=0, *bb_ob=re->scene->camera;
        Material *ma=0;
        CustomDataLayer *layer;
@@ -1737,7 +1496,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
        float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f;
        float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
        float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random;
-       int i, a, k, max_k=0, totpart, totvlako, totverto, totuv=0, override_uv=-1;
+       int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1;
        int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild;
        int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0};
        char **uv_name=0;
@@ -1785,7 +1544,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                execute_ipo((ID *)ma, ma->ipo);
        }
 
-       RE_vlakren_set_customdata_names(re, &psmd->dm->faceData);
+       RE_set_customdata_names(obr, &psmd->dm->faceData);
        totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE);
 
        if(ma->texco & TEXCO_UV && totuv) {
@@ -1845,9 +1604,6 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
        Mat3CpyMat4(nmat, ob->imat);
        Mat3Transp(nmat);
 
-       totvlako= re->totvlak;
-       totverto= re->totvert;
-
        totpart=psys->totpart;
 
        mesh_get_texspace(ob->data, loc_tex, NULL, size_tex);
@@ -1877,7 +1633,7 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                        }
 
                        if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) {
-                               strandbuf= RE_addStrandBuffer(re, ob, (totpart+totchild)*(path_nbr+1));
+                               strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
                                strandbuf->ma= ma;
                                strandbuf->lay= ob->lay;
                                Mat4CpyMat4(strandbuf->winmat, re->winmat);
@@ -1944,15 +1700,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                        if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
                                layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE);
                                for(i=0; i<totuv; i++){
-                                       int n;
                                        MFace *mface=psmd->dm->getFaceData(psmd->dm,pa->num,CD_MFACE);
 
                                        mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
                                        mtface+=pa->num;
                                        
-                                       n= vlakren_customdata_layer_num(i, layer->active);
-
-                                       psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*n);
+                                       psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i);
                                }
                        }
 
@@ -2000,15 +1753,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                                if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
                                        for(i=0; i<totuv; i++){
                                                if(part->childtype==PART_CHILD_FACES){
-                                                       int n;
                                                        MFace *mface=psmd->dm->getFaceData(psmd->dm,cpa->num,CD_MFACE);
 
                                                        mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
                                                        mtface+=cpa->num;
                                                        
-                                                       n= vlakren_customdata_layer_num(i, layer->active);
-
-                                                       psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*n);
+                                                       psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*i);
                                                }
                                                else{
                                                        uvco[2*i]=uvco[2*i+1]=0.0f;
@@ -2018,15 +1768,12 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                                else if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
                                        for(i=0; i<totuv; i++){
                                                ParticleData *parent = psys->particles+cpa->parent;
-                                               int n;
                                                MFace *mface=psmd->dm->getFaceData(psmd->dm,parent->num,CD_MFACE);
 
                                                mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
                                                mtface+=parent->num;
                                                
-                                               n= vlakren_customdata_layer_num(i, layer->active);
-
-                                               psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*n);
+                                               psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*i);
                                        }
                                }
                        }
@@ -2053,20 +1800,20 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
 
                /* strand render setup */
                if(strandbuf) {
-                       strand= RE_findOrAddStrand(re, re->totstrand++);
+                       strand= RE_findOrAddStrand(obr, obr->totstrand++);
                        strand->buffer= strandbuf;
                        strand->vert= svert;
                        VECCOPY(strand->orco, orco);
 
                        if(surfnor) {
-                               float *snor= RE_strandren_get_surfnor(re, strand, 1);
+                               float *snor= RE_strandren_get_surfnor(obr, strand, 1);
                                VECCOPY(snor, surfnor);
                        }
 
                        if(uvco){
                                for(i=0; i<totuv; i++){
                                        if(i != override_uv) {
-                                               float *uv= RE_strandren_get_uv(re, strand, i, NULL, 1);
+                                               float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
 
                                                uv[0]= uvco[2*i];
                                                uv[1]= uvco[2*i+1];
@@ -2121,13 +1868,13 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                                VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
                                VECADDFAC(loc1,loc,vel,part->draw_line[1]);
 
-                               render_new_particle(re,ob,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
+                               render_new_particle(re,obr,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
                                                                        orco,surfnor,totuv,uvco,hasize,seed,override_uv,0,0,0);
                        }
                        else if(part->draw_as==PART_DRAW_BB) {
                                VECCOPY(vel,state.vel);
                                //MTC_Mat4Mul3Vecfl(re->viewmat,vel);
-                               particle_billboard(re,ob,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt),
+                               particle_billboard(re,obr,ma,bb_ob,loc,vel,pa_size,part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt),
                                                                        part->bb_align,part->draw&PART_DRAW_BB_LOCK,
                                                                        a,totpart+totchild,part->bb_uv_split,part->bb_anim,part->bb_split_offset,random,pa_time,part->bb_offset,uv);
                        }
@@ -2141,13 +1888,13 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
                                if(k==1){
                                        VECSUB(loc0,loc1,loc);
                                        VECADD(loc0,loc1,loc0);
-                                       render_new_particle(re,ob,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
+                                       render_new_particle(re,obr,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
                                                                                orco,surfnor,totuv,uvco,hasize,seed,override_uv,
                                                                                adapt,adapt_angle,adapt_pix);
                                }
 
                                if(path_nbr==0 || k)
-                                       render_new_particle(re,ob,psmd->dm,ma,path,0,0,time,loc,loc1,
+                                       render_new_particle(re,obr,psmd->dm,ma,path,0,0,time,loc,loc1,
                                                                                orco,surfnor,totuv,uvco,hasize,seed,override_uv,
                                                                                adapt,adapt_angle,adapt_pix);
 
@@ -2187,255 +1934,284 @@ static int render_new_particle_system(Render *re, Object *ob, ParticleSystem *ps
        }
 
        if(path && (ma->mode_l & MA_TANGENT_STR)==0)
-               calc_vertexnormals(re, totverto, totvlako, 0);
+               calc_vertexnormals(re, obr, 0);
 
        return 1;
 }
 
-static void render_static_particle_system(Render *re, Object *ob, PartEff *paf)
-{
-       Particle *pa=0;
-       HaloRen *har=0;
-       Material *ma=0;
-       VertRen *v1= NULL;
-       VlakRen *vlr;
-       float xn, yn, zn, imat[3][3], mat[4][4], hasize;
-       float mtime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
-       float *orco= NULL, loc_tex[3], size_tex[3];
-       int a, mat_nr=1, seed, totvlako, totverto, first;
-
-       pa= paf->keys;
-       if(pa==NULL || (paf->flag & PAF_ANIMATED) || paf->disp!=100) {
-               build_particle_system(ob);
-               pa= paf->keys;
-               if(pa==NULL) return;
-       }
+/* ------------------------------------------------------------------------- */
+/* Halo's                                                                                                                               */
+/* ------------------------------------------------------------------------- */
 
-       totvlako= re->totvlak;
-       totverto= re->totvert;
-       
-       ma= give_render_material(re, ob, paf->omat);
-       if(ma->mode & MA_HALO)
-               re->flag |= R_HALO;
+static void make_render_halos(Render *re, ObjectRen *obr, Mesh *me, int totvert, MVert *mvert, Material *ma, float *orco)
+{
+       Object *ob= obr->ob;
+       HaloRen *har;
+       float xn, yn, zn, nor[3], view[3];
+       float vec[3], hasize, mat[4][4], imat[3][3];
+       int a, ok, seed= ma->seed1;
 
        MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-       MTC_Mat4Invert(ob->imat, mat);  /* need to be that way, for imat texture */
-
        MTC_Mat3CpyMat4(imat, ob->imat);
-       
-       /* orcos */
-       if(!(ma->mode & (MA_HALO|MA_WIRE))) {
-               orco= MEM_mallocN(3*sizeof(float)*paf->totpart, "static particle orcos");
-               set_object_orco(re, paf, orco);
-       }
-       
-       mesh_get_texspace(ob->data, loc_tex, NULL, size_tex);
-       
-       if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
-       else ptime= 0.0;
-       ctime= bsystem_time(ob, (float)re->scene->r.cfra, ptime);
-       seed= ma->seed1;
 
-       for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
-               
-               where_is_particle(paf, pa, pa->time, vec1);
-               if(orco) {
-                       orco[0] = (vec1[0]-loc_tex[0])/size_tex[0];
-                       orco[1] = (vec1[1]-loc_tex[1])/size_tex[1];
-                       orco[2] = (vec1[2]-loc_tex[2])/size_tex[2];
-               }
-               MTC_Mat4MulVecfl(mat, vec1);
-               mtime= pa->time+pa->lifetime+paf->staticstep-1;
-               
-               first= 1;
-               for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
-                       
-                       /* make sure hair grows until the end.. */
-                       if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
-                       
-                       /* watch it: also calc the normal of a particle */
-                       if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
-                               where_is_particle(paf, pa, ctime+1.0, vec);
-                               MTC_Mat4MulVecfl(mat, vec);
-                       }
-                       else {
-                               where_is_particle(paf, pa, ctime, vec);
-                               MTC_Mat4MulVecfl(mat, vec);
-                       }
+       re->flag |= R_HALO;
 
-                       if(pa->mat_nr != mat_nr) {
-                               mat_nr= pa->mat_nr;
-                               ma= give_render_material(re, ob, mat_nr);
-                       }
-                       
-                       /* wires */
-                       if(ma->mode & MA_WIRE) {
-                               if(ctime == pa->time) {
-                                       v1= RE_findOrAddVert(re, re->totvert++);
-                                       VECCOPY(v1->co, vec);
-                               }
-                               else {
-                                       vlr= RE_findOrAddVlak(re, re->totvlak++);
-                                       vlr->ob= ob;
-                                       vlr->v1= v1;
-                                       vlr->v2= RE_findOrAddVert(re, re->totvert++);
-                                       vlr->v3= vlr->v2;
-                                       vlr->v4= NULL;
-                                       
-                                       v1= vlr->v2; // cycle
-                                       VECCOPY(v1->co, vec);
-                                       
-                                       VecSubf(vlr->n, vec, vec1);
-                                       Normalize(vlr->n);
-                                       VECCOPY(v1->n, vlr->n);
-                                       
-                                       vlr->mat= ma;
-                                       vlr->ec= ME_V1V2;
-                                       vlr->lay= ob->lay;
-                               }
-                       }
-                       else {
-                               if(ma->ipo) {
-                                       /* correction for lifetime */
-                                       ptime= 100.0*(ctime-pa->time)/pa->lifetime;
-                                       calc_ipo(ma->ipo, ptime);
-                                       execute_ipo((ID *)ma, ma->ipo);
-                               }
-                               
-                               if(ma->mode & MA_HALO) {
-                                       hasize= ma->hasize;
+       for(a=0; a<totvert; a++, mvert++) {
+               ok= 1;
 
-                                       if(ma->mode & MA_HALOPUNO) {
-                                               xn= pa->no[0];
-                                               yn= pa->no[1];
-                                               zn= pa->no[2];
+               if(ok) {
+                       hasize= ma->hasize;
 
-                                               /* transpose ! */
-                                               nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
-                                               nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
-                                               nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
-                                               Normalize(nor);
+                       VECCOPY(vec, mvert->co);
+                       MTC_Mat4MulVecfl(mat, vec);
 
-                                               VECCOPY(view, vec);
-                                               Normalize(view);
+                       if(ma->mode & MA_HALOPUNO) {
+                               xn= mvert->no[0];
+                               yn= mvert->no[1];
+                               zn= mvert->no[2];
 
-                                               zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
-                                               if(zn>=0.0) hasize= 0.0;
-                                               else hasize*= zn*zn*zn*zn;
-                                       }
+                               /* transpose ! */
+                               nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+                               nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+                               nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+                               Normalize(nor);
 
-                                       if(paf->stype==PAF_VECT) har= RE_inithalo(re, ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
-                                       else {
-                                               har= RE_inithalo(re, ma, vec, NULL, pa->co, hasize, 0.0, seed);
-                                               if(har && (ma->mode & MA_HALO_SHADE)) {
-                                                       VecSubf(har->no, vec, vec1);
-                                                       Normalize(har->no);
-                                                       har->lay= ob->lay;
-                                               }
-                                       }
-                                       if(har) har->lay= ob->lay;
-                               }
-                               else {  /* generate pixel sized hair strand */
-                                       float strandco= 1.0f;
-                                       
-                                       /* last strand, texco to end */
-                                       if(ctime + paf->staticstep < mtime)
-                                               strandco= (ctime-pa->time)/(mtime-pa->time);
-                                       
-                                       static_particle_strand(re, ob, ma, orco, 0, 0, 0, vec, vec1, strandco, first, 0,0,0,0,-1);
-                               }
+                               VECCOPY(view, vec);
+                               Normalize(view);
+
+                               zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
+                               if(zn>=0.0) hasize= 0.0;
+                               else hasize*= zn*zn*zn*zn;
                        }
-                       
-                       VECCOPY(vec1, vec);
-                       first= 0;
+
+                       if(orco) har= RE_inithalo(re, obr, ma, vec, NULL, orco, hasize, 0.0, seed);
+                       else har= RE_inithalo(re, obr, ma, vec, NULL, mvert->co, hasize, 0.0, seed);
+                       if(har) har->lay= ob->lay;
                }
-               
+               if(orco) orco+= 3;
                seed++;
-               if(orco) orco+=3;
-       }
-
-       if(paf->disp!=100) {
-               MEM_freeN(paf->keys);
-               paf->keys= NULL;
        }
-
-       if((ma->mode & MA_TANGENT_STR)==0)
-               calc_vertexnormals(re, totverto, totvlako, 0);
 }
 
-
-/* ------------------------------------------------------------------------- */
-
 static int verghalo(const void *a1, const void *a2)
 {
-       const struct halosort *x1=a1, *x2=a2;
+       const HaloRen *har1= a1, *har2= a2;
        
-       if( x1->z < x2->z ) return 1;
-       else if( x1->z > x2->z) return -1;
+       if(har1->zs < har2->zs) return 1;
+       else if(har1->zs > har2->zs) return -1;
        return 0;
 }
 
-/* ------------------------------------------------------------------------- */
-static void sort_halos(Render *re)
+static void sort_halos(Render *re, int totsort)
 {
-       struct halosort *hablock, *haso;
-       HaloRen *har = NULL, **bloha;
+       ObjectRen *obr;
+       HaloRen *har= NULL, **haso;
        int a;
 
        if(re->tothalo==0) return;
 
-       /* make datablock with halo pointers, sort */
-       haso= hablock= MEM_mallocN(sizeof(struct halosort)*re->tothalo, "hablock");
-
-       for(a=0; a<re->tothalo; a++) {
-               if((a & 255)==0) har= re->bloha[a>>8];
-               else har++;
-               haso->har= har;
-               haso->z= har->zs;
-               haso++;
-       }
-
-       qsort(hablock, re->tothalo, sizeof(struct halosort), verghalo);
+       re->sortedhalos= MEM_callocN(sizeof(HaloRen*)*re->tothalo, "sorthalos");
+       haso= re->sortedhalos;
 
-       /* re-assamble re->bloha */
-
-       bloha= re->bloha;
-       re->bloha= (HaloRen **)MEM_callocN(sizeof(void *)*(re->blohalen),"Bloha");
-
-       haso= hablock;
-       for(a=0; a<re->tothalo; a++) {
-               har= RE_findOrAddHalo(re, a);
-               *har= *(haso->har);
-
-               haso++;
-       }
+       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++;
 
-       /* free */
-       a= 0;
-       while(bloha[a]) {
-               MEM_freeN(bloha[a]);
-               a++;
+                       *(haso++)= har;
+               }
        }
-       MEM_freeN(bloha);
-       MEM_freeN(hablock);
 
+       qsort(re->sortedhalos, totsort, sizeof(HaloRen*), verghalo);
 }
 
 /* ------------------------------------------------------------------------- */
-static void init_render_mball(Render *re, Object *ob)
+/* Displacement Mapping                                                                                                                 */
+/* ------------------------------------------------------------------------- */
+
+static short test_for_displace(Render *re, Object *ob)
 {
-       DispList *dl;
-       VertRen *ver;
-       VlakRen *vlr, *vlr1;
+       /* return 1 when this object uses displacement textures. */
        Material *ma;
-       float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn;
-       int a, need_orco, startvert, *index;
-
-       if (ob!=find_basis_mball(ob))
-               return;
-
-       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-       MTC_Mat4Invert(ob->imat, mat);
+       int i;
+       
+       for (i=1; i<=ob->totcol; i++) {
+               ma=give_render_material(re, ob, i);
+               /* ma->mapto is ORed total of all mapto channels */
+               if(ma && (ma->mapto & MAP_DISPLACE)) return 1;
+       }
+       return 0;
+}
+
+static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, VertRen *vr, int vindex, float *scale)
+{
+       MTFace *tface;
+       short texco= shi->mat->texco;
+       float sample=0;
+       char *name;
+       int i;
+
+       /* shi->co is current render coord, just make sure at least some vector is here */
+       VECCOPY(shi->co, vr->co);
+       /* vertex normal is used for textures type 'col' and 'var' */
+       VECCOPY(shi->vn, vr->n);
+
+       if (texco & TEXCO_UV) {
+               shi->totuv= 0;
+               shi->actuv= obr->actmtface;
+
+               for (i=0; (tface=RE_vlakren_get_tface(obr, shi->vlr, i, &name, 0)); i++) {
+                       ShadeInputUV *suv= &shi->uv[i];
+
+                       /* shi.uv needs scale correction from tface uv */
+                       suv->uv[0]= 2*tface->uv[vindex][0]-1.0f;
+                       suv->uv[1]= 2*tface->uv[vindex][1]-1.0f;
+                       suv->uv[2]= 0.0f;
+                       suv->name= name;
+                       shi->totuv++;
+               }
+       }
+
+       /* set all rendercoords, 'texco' is an ORed value for all textures needed */
+       if ((texco & TEXCO_ORCO) && (vr->orco)) {
+               VECCOPY(shi->lo, vr->orco);
+       }
+       if (texco & TEXCO_STICKY) {
+               float *sticky= RE_vertren_get_sticky(obr, vr, 0);
+               if(sticky) {
+                       shi->sticky[0]= sticky[0];
+                       shi->sticky[1]= sticky[1];
+                       shi->sticky[2]= 0.0f;
+               }
+       }
+       if (texco & TEXCO_GLOB) {
+               VECCOPY(shi->gl, shi->co);
+               MTC_Mat4MulVecfl(re->viewinv, shi->gl);
+       }
+       if (texco & TEXCO_NORM) {
+               VECCOPY(shi->orn, shi->vn);
+       }
+       if(texco & TEXCO_REFL) {
+               /* not (yet?) */
+       }
+       
+       shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
+       
+       do_material_tex(shi);
+       
+       //printf("no=%f, %f, %f\nbefore co=%f, %f, %f\n", vr->n[0], vr->n[1], vr->n[2], 
+       //vr->co[0], vr->co[1], vr->co[2]);
+       
+       /* 0.5 could become button once?  */
+       vr->co[0] +=  shi->displace[0] * scale[0] ; 
+       vr->co[1] +=  shi->displace[1] * scale[1] ; 
+       vr->co[2] +=  shi->displace[2] * scale[2] ; 
+       
+       //printf("after co=%f, %f, %f\n", vr->co[0], vr->co[1], vr->co[2]); 
+       
+       /* we just don't do this vertex again, bad luck for other face using same vertex with
+               different material... */
+       vr->flag |= 1;
+       
+       /* Pass sample back so displace_face can decide which way to split the quad */
+       sample  = shi->displace[0]*shi->displace[0];
+       sample += shi->displace[1]*shi->displace[1];
+       sample += shi->displace[2]*shi->displace[2];
+       
+       vr->accum=sample; 
+       /* Should be sqrt(sample), but I'm only looking for "bigger".  Save the cycles. */
+       return;
+}
+
+static void displace_render_face(Render *re, VlakRen *vlr, float *scale)
+{
+       ShadeInput shi;
+
+       /* set up shadeinput struct for multitex() */
+       shi.osatex= 0;          /* signal not to use dx[] and dy[] texture AA vectors */
+       shi.vlr= vlr;           /* current render face */
+       shi.mat= vlr->mat;              /* current input material */
+       
+       /* Displace the verts, flag is set when done */
+       if (!vlr->v1->flag)
+               displace_render_vert(re, vlr->obr, &shi, vlr->v1,0,  scale);
+       
+       if (!vlr->v2->flag)
+               displace_render_vert(re, vlr->obr, &shi, vlr->v2, 1, scale);
+
+       if (!vlr->v3->flag)
+               displace_render_vert(re, vlr->obr, &shi, vlr->v3, 2, scale);
+
+       if (vlr->v4) {
+               if (!vlr->v4->flag)
+                       displace_render_vert(re, vlr->obr, &shi, vlr->v4, 3, scale);
+
+               /*      closest in displace value.  This will help smooth edges.   */ 
+               if ( fabs(vlr->v1->accum - vlr->v3->accum) > fabs(vlr->v2->accum - vlr->v4->accum)) 
+                       vlr->flag |= R_DIVIDE_24;
+               else vlr->flag &= ~R_DIVIDE_24;
+       }
+       
+       /* Recalculate the face normal  - if flipped before, flip now */
+       if(vlr->v4) {
+               CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+       }       
+       else {
+               CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+       }
+}
+
+static void do_displacement(Render *re, ObjectRen *obr)
+{
+       VertRen *vr;
+       VlakRen *vlr;
+//     float min[3]={1e30, 1e30, 1e30}, max[3]={-1e30, -1e30, -1e30};
+       float scale[3]={1.0f, 1.0f, 1.0f}, temp[3];//, xn
+       int i; //, texflag=0;
+       Object *obt;
+               
+       /* Object Size with parenting */
+       obt=obr->ob;
+       while(obt){
+               VecAddf(temp, obt->size, obt->dsize);
+               scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2];
+               obt=obt->parent;
+       }
+       
+       /* Clear all flags */
+       for(i=0; i<obr->totvert; i++){ 
+               vr= RE_findOrAddVert(obr, i);
+               vr->flag= 0;
+       }
+
+       for(i=0; i<obr->totvlak; i++){
+               vlr=RE_findOrAddVlak(obr, i);
+               displace_render_face(re, vlr, scale);
+       }
+       
+       /* Recalc vertex normals */
+       calc_vertexnormals(re, obr, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+/* Metaball                                                                                                                             */
+/* ------------------------------------------------------------------------- */
+
+static void init_render_mball(Render *re, ObjectRen *obr)
+{
+       Object *ob= obr->ob;
+       DispList *dl;
+       VertRen *ver;
+       VlakRen *vlr, *vlr1;
+       Material *ma;
+       float *data, *nors, mat[4][4], imat[3][3], xn, yn, zn;
+       int a, need_orco, *index;
+
+       if (ob!=find_basis_mball(ob))
+               return;
+
+       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+       MTC_Mat4Invert(ob->imat, mat);
        MTC_Mat3CpyMat4(imat, ob->imat);
 
        ma= give_render_material(re, ob, 1);
@@ -2449,19 +2225,19 @@ static void init_render_mball(Render *re, Object *ob)
        dl= ob->disp.first;
        if(dl==0) return;
 
-       startvert= re->totvert;
        data= dl->verts;
        nors= dl->nors;
 
        for(a=0; a<dl->nr; a++, data+=3, nors+=3) {
 
-               ver= RE_findOrAddVert(re, re->totvert++);
+               ver= RE_findOrAddVert(obr, obr->totvert++);
                VECCOPY(ver->co, data);
                MTC_Mat4MulVecfl(mat, ver->co);
 
-               xn= nors[0];
-               yn= nors[1];
-               zn= nors[2];
+               /* render normals are inverted */
+               xn= -nors[0];
+               yn= -nors[1];
+               zn= -nors[2];
 
                /* transpose ! */
                ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
@@ -2476,11 +2252,11 @@ static void init_render_mball(Render *re, Object *ob)
        index= dl->index;
        for(a=0; a<dl->parts; a++, index+=4) {
 
-               vlr= RE_findOrAddVlak(re, re->totvlak++);
-               vlr->ob= ob;
-               vlr->v1= RE_findOrAddVert(re, startvert+index[0]);
-               vlr->v2= RE_findOrAddVert(re, startvert+index[1]);
-               vlr->v3= RE_findOrAddVert(re, startvert+index[2]);
+               vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+               vlr->obr= obr;
+               vlr->v1= RE_findOrAddVert(obr, index[0]);
+               vlr->v2= RE_findOrAddVert(obr, index[1]);
+               vlr->v3= RE_findOrAddVert(obr, index[2]);
                vlr->v4= 0;
 
                if(ob->transflag & OB_NEG_SCALE) 
@@ -2495,10 +2271,10 @@ static void init_render_mball(Render *re, Object *ob)
 
                /* mball -too bad- always has triangles, because quads can be non-planar */
                if(index[3] && index[3]!=index[2]) {
-                       vlr1= RE_findOrAddVlak(re, re->totvlak++);
+                       vlr1= RE_findOrAddVlak(obr, obr->totvlak++);
                        *vlr1= *vlr;
                        vlr1->v2= vlr1->v3;
-                       vlr1->v3= RE_findOrAddVert(re, startvert+index[3]);
+                       vlr1->v3= RE_findOrAddVert(obr, index[3]);
                        if(ob->transflag & OB_NEG_SCALE) 
                                CalcNormFloat(vlr1->v1->co, vlr1->v2->co, vlr1->v3->co, vlr1->n);
                        else
@@ -2518,1452 +2294,1383 @@ static void init_render_mball(Render *re, Object *ob)
        /* this enforces remake for real, orco displist is small (in scale) */
        ob->recalc |= OB_RECALC_DATA;
 }
-/* ------------------------------------------------------------------------- */
-/* convert */
-
-static int vlakren_customdata_layer_num(int n, int active)
-{
-       /* make the active layer the first */
-       if (n == active) return 0;
-       else if (n < active) return n+1;
-       else return n;
-}
-
-struct edgesort {
-       int v1, v2;
-       int f;
-       int i1, i2;
-};
-
-/* edges have to be added with lowest index first for sorting */
-static void to_edgesort(struct edgesort *ed, int i1, int i2, int v1, int v2, int f)
-{
-       if(v1>v2) {
-               SWAP(int, v1, v2);
-               SWAP(int, i1, i2);
-       }
 
-       ed->v1= v1;
-       ed->v2= v2;
-       ed->i1= i1;
-       ed->i2= i2;
-       ed->f = f;
-}
+/* ------------------------------------------------------------------------- */
+/* Surfaces and Curves                                                                                                          */
+/* ------------------------------------------------------------------------- */
 
-static int vergedgesort(const void *v1, const void *v2)
+/* returns amount of vertices added for orco */
+static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, float *orco, float mat[4][4])
 {
-       const struct edgesort *x1=v1, *x2=v2;
-       
-       if( x1->v1 > x2->v1) return 1;
-       else if( x1->v1 < x2->v1) return -1;
-       else if( x1->v2 > x2->v2) return 1;
-       else if( x1->v2 < x2->v2) return -1;
+       Object *ob= obr->ob;
+       VertRen *v1, *v2, *v3, *v4, *ver;
+       VlakRen *vlr, *vlr1, *vlr2, *vlr3;
+       Curve *cu= ob->data;
+       float *data, n1[3], flen;
+       int u, v, orcoret= 0;
+       int p1, p2, p3, p4, a;
+       int sizeu, nsizeu, sizev, nsizev;
+       int startvert, startvlak;
        
-       return 0;
-}
-
-static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
-{
-       MFace *mf, *mface;
-       MTFace *tface=NULL;
-       struct edgesort *edsort, *ed;
-       unsigned int *mcol=NULL;
-       int a, totedge=0, totface;
+       startvert= obr->totvert;
+       nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; 
        
-       mface= dm->getFaceArray(dm);
-       totface= dm->getNumFaces(dm);
-       tface= dm->getFaceDataArray(dm, CD_MTFACE);
-       mcol= dm->getFaceDataArray(dm, CD_MCOL);
+       data= dl->verts;
+       for (u = 0; u < sizeu; u++) {
+               v1 = RE_findOrAddVert(obr, obr->totvert++); /* save this for possible V wrapping */
+               VECCOPY(v1->co, data); data += 3;
+               if(orco) {
+                       v1->orco= orco; orco+= 3; orcoret++;
+               }       
+               MTC_Mat4MulVecfl(mat, v1->co);
+               
+               for (v = 1; v < sizev; v++) {
+                       ver= RE_findOrAddVert(obr, obr->totvert++);
+                       VECCOPY(ver->co, data); data += 3;
+                       if(orco) {
+                               ver->orco= orco; orco+= 3; orcoret++;
+                       }       
+                       MTC_Mat4MulVecfl(mat, ver->co);
+               }
+               /* if V-cyclic, add extra vertices at end of the row */
+               if (dl->flag & DL_CYCL_U) {
+                       ver= RE_findOrAddVert(obr, obr->totvert++);
+                       VECCOPY(ver->co, v1->co);
+                       if(orco) {
+                               ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0);
+                       }
+               }       
+       }       
        
-       if(mcol==NULL && tface==NULL) return NULL;
+       /* Done before next loop to get corner vert */
+       if (dl->flag & DL_CYCL_U) nsizev++;
+       if (dl->flag & DL_CYCL_V) nsizeu++;
        
-       /* make sorted table with edges and face indices in it */
-       for(a= totface, mf= mface; a>0; a--, mf++) {
-               if(mf->v4) totedge+=4;
-               else if(mf->v3) totedge+=3;
+       /* if U cyclic, add extra row at end of column */
+       if (dl->flag & DL_CYCL_V) {
+               for (v = 0; v < nsizev; v++) {
+                       v1= RE_findOrAddVert(obr, startvert + v);
+                       ver= RE_findOrAddVert(obr, obr->totvert++);
+                       VECCOPY(ver->co, v1->co);
+                       if(orco) {
+                               ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v);
+                       }
+               }
        }
-
-       if(totedge==0)
-               return NULL;
        
-       ed= edsort= MEM_callocN(totedge*sizeof(struct edgesort), "edgesort");
+       sizeu = nsizeu;
+       sizev = nsizev;
        
-       for(a=0, mf=mface; a<totface; a++, mf++) {
-               to_edgesort(ed++, 0, 1, mf->v1, mf->v2, a);
-               to_edgesort(ed++, 1, 2, mf->v2, mf->v3, a);
-               if(mf->v4) {
-                       to_edgesort(ed++, 2, 3, mf->v3, mf->v4, a);
-                       to_edgesort(ed++, 3, 0, mf->v4, mf->v1, a);
+       startvlak= obr->totvlak;
+       
+       for(u = 0; u < sizeu - 1; u++) {
+               p1 = startvert + u * sizev; /* walk through face list */
+               p2 = p1 + 1;
+               p3 = p2 + sizev;
+               p4 = p3 - 1;
+               
+               for(v = 0; v < sizev - 1; v++) {
+                       v1= RE_findOrAddVert(obr, p1);
+                       v2= RE_findOrAddVert(obr, p2);
+                       v3= RE_findOrAddVert(obr, p3);
+                       v4= RE_findOrAddVert(obr, p4);
+                       
+                       vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+                       vlr->obr= obr;
+                       vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
+                       
+                       flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
+                       VECCOPY(vlr->n, n1);
+                       
+                       vlr->lay= ob->lay;
+                       vlr->mat= matar[ dl->col];
+                       vlr->ec= ME_V1V2+ME_V2V3;
+                       vlr->flag= dl->rt;
+                       if( (cu->flag & CU_NOPUNOFLIP) ) {
+                               vlr->flag |= R_NOPUNOFLIP;
+                       }
+                       
+                       VecAddf(v1->n, v1->n, n1);
+                       VecAddf(v2->n, v2->n, n1);
+                       VecAddf(v3->n, v3->n, n1);
+                       VecAddf(v4->n, v4->n, n1);
+                       
+                       p1++; p2++; p3++; p4++;
+               }
+       }       
+       /* fix normals for U resp. V cyclic faces */
+       sizeu--; sizev--;  /* dec size for face array */
+       if (dl->flag & DL_CYCL_V) {
+               
+               for (v = 0; v < sizev; v++)
+               {
+                       /* optimize! :*/
+                       vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, v));
+                       vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0, v));
+                       VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
+                       VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
+                       VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
+                       VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
+               }
+       }
+       if (dl->flag & DL_CYCL_U) {
+               
+               for (u = 0; u < sizeu; u++)
+               {
+                       /* optimize! :*/
+                       vlr= RE_findOrAddVlak(obr, UVTOINDEX(u, 0));
+                       vlr1= RE_findOrAddVlak(obr, UVTOINDEX(u, sizev-1));
+                       VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
+                       VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
+                       VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
+                       VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
                }
-               else if(mf->v3)
-                       to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a);
        }
+       /* last vertex is an extra case: 
+               
+               ^       ()----()----()----()
+               |       |     |     ||     |
+               u       |     |(0,n)||(0,0)|
+               |     |     ||     |
+               ()====()====[]====()
+               |     |     ||     |
+               |     |(m,n)||(m,0)|
+               |     |     ||     |
+               ()----()----()----()
+               v ->
+               
+               vertex [] is no longer shared, therefore distribute
+               normals of the surrounding faces to all of the duplicates of []
+               */
        
-       qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort);
+       if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U))
+       {
+               vlr= RE_findOrAddVlak(obr, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
+               vlr1= RE_findOrAddVlak(obr, UVTOINDEX(0,0));  /* (0,0) */
+               VecAddf(n1, vlr->n, vlr1->n);
+               vlr2= RE_findOrAddVlak(obr, UVTOINDEX(0, sizev-1)); /* (0,n) */
+               VecAddf(n1, n1, vlr2->n);
+               vlr3= RE_findOrAddVlak(obr, UVTOINDEX(sizeu-1, 0)); /* (m,0) */
+               VecAddf(n1, n1, vlr3->n);
+               VECCOPY(vlr->v3->n, n1);
+               VECCOPY(vlr1->v1->n, n1);
+               VECCOPY(vlr2->v2->n, n1);
+               VECCOPY(vlr3->v4->n, n1);
+       }
+       for(a = startvert; a < obr->totvert; a++) {
+               ver= RE_findOrAddVert(obr, a);
+               Normalize(ver->n);
+       }
        
-       *totedgesort= totedge;
-
-       return edsort;
+       
+       return orcoret;
 }
 
-static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge)
+static void init_render_surf(Render *re, ObjectRen *obr)
 {
-       struct edgesort ed, *edp;
-       CustomDataLayer *layer;
-       MTFace *mtface, *mtf;
-       MCol *mcol, *mc;
-       int index, mtfn, mcn, n;
-       char *name;
-       
-       if(medge->v1 < medge->v2) {
-               ed.v1= medge->v1;
-               ed.v2= medge->v2;
-       }
-       else {
-               ed.v1= medge->v2;
-               ed.v2= medge->v1;
-       }
-       
-       edp= bsearch(&ed, edgetable, totedge, sizeof(struct edgesort), vergedgesort);
+       Object *ob= obr->ob;
+       Nurb *nu=0;
+       Curve *cu;
+       ListBase displist;
+       DispList *dl;
+       Material *matar[32];
+       float *orco=NULL, *orcobase=NULL, mat[4][4];
+       int a, need_orco=0;
 
-       /* since edges have different index ordering, we have to duplicate mcol and tface */
-       if(edp) {
-               mtfn= mcn= 0;
+       cu= ob->data;
+       nu= cu->nurb.first;
+       if(nu==0) return;
 
-               for(index=0; index<dm->faceData.totlayer; index++) {
-                       layer= &dm->faceData.layers[index];
-                       name= layer->name;
+       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+       MTC_Mat4Invert(ob->imat, mat);
 
-                       if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
-                               mtface= &((MTFace*)layer->data)[edp->f];
-                               n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd);
-                               mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
+       /* material array */
+       memset(matar, 0, 4*32);
+       matar[0]= give_render_material(re, ob, 0);
+       for(a=0; a<ob->totcol; a++) {
+               matar[a]= give_render_material(re, ob, a+1);
+               if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
+                       need_orco= 1;
+               }
+       }
 
-                               *mtf= *mtface;
+       if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
 
-                               memcpy(mtf->uv[0], mtface->uv[edp->i1], sizeof(float)*2);
-                               memcpy(mtf->uv[1], mtface->uv[edp->i2], sizeof(float)*2);
-                               memcpy(mtf->uv[2], mtface->uv[1], sizeof(float)*2);
-                               memcpy(mtf->uv[3], mtface->uv[1], sizeof(float)*2);
-                       }
-                       else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
-                               mcol= &((MCol*)layer->data)[edp->f*4];
-                               n= vlakren_customdata_layer_num(mcn++, layer->active_rnd);
-                               mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
+       if(need_orco) orcobase= orco= get_object_orco(re, ob);
 
-                               mc[0]= mcol[edp->i1];
-                               mc[1]= mc[2]= mc[3]= mcol[edp->i2];
-                       }
+       displist.first= displist.last= 0;
+       makeDispListSurf(ob, &displist, 1);
+
+       dl= displist.first;
+       /* walk along displaylist and create rendervertices/-faces */
+       while(dl) {
+                       /* watch out: u ^= y, v ^= x !! */
+               if(dl->type==DL_SURF) {
+                       orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
                }
+
+               dl= dl->next;
        }
+       freedisplist(&displist);
 }
 
-static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts)
+static void init_render_curve(Render *re, ObjectRen *obr, int only_verts)
 {
-       Mesh *me;
-       MVert *mvert = NULL;
-       MFace *mface;
-       VlakRen *vlr; //, *vlr1;
+       Object *ob= obr->ob;
+       Curve *cu;
        VertRen *ver;
-       Material *ma;
-       MSticky *ms = NULL;
-       PartEff *paf;
-       DerivedMesh *dm;
-       CustomDataMask mask;
-       float xn, yn, zn,  imat[3][3], mat[4][4];  //nor[3],
-       float *orco=0;
-       int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs;
-       int end, do_autosmooth=0, totvert = 0;
-       int useFluidmeshNormals= 0; // NT fluidsim, use smoothed normals?
-       int use_original_normals= 0;
-
-       me= ob->data;
+       VlakRen *vlr;
+       DispList *dl;
+       ListBase olddl={NULL, NULL};
+       Material *matar[32];
+       float len, *data, *fp, *orco=NULL, *orcobase= NULL;
+       float n[3], mat[4][4];
+       int nr, startvert, startvlak, a, b;
+       int frontside, need_orco=0;
 
-       paf = give_parteff(ob);
-       if(paf) {
-               /* warning; build_particle_system does modifier calls itself */
-               if(paf->flag & PAF_STATIC) render_static_particle_system(re, ob, paf);
-               else render_particle_system(re, ob, par, paf);
-               if((paf->flag & PAF_SHOWE)==0) return;
-       }
+       cu= ob->data;
+       if(cu->nurb.first==NULL) return;
 
-       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-       MTC_Mat4Invert(ob->imat, mat);
-       MTC_Mat3CpyMat4(imat, ob->imat);
+       /* no modifier call here, is in makedisp */
 
-       if(me->totvert==0) {
-               return;
-       }
+       if(cu->resolu_ren) 
+               SWAP(ListBase, olddl, cu->disp);
        
-       totvlako= re->totvlak;
-       totverto= re->totvert;
+       /* test displist */
+       if(cu->disp.first==NULL) 
+               makeDispListCurveTypes(ob, 0);
+       dl= cu->disp.first;
+       if(cu->disp.first==NULL) return;
        
-       need_orco= 0;
-       for(a=1; a<=ob->totcol; a++) {
-               ma= give_render_material(re, ob, a);
-               if(ma) {
-                       if(ma->texco & (TEXCO_ORCO|TEXCO_STRESS))
-                               need_orco= 1;
-                       if(ma->texco & TEXCO_STRESS)
-                               need_stress= 1;
-                       /* normalmaps, test if tangents needed, separated from shading */
-                       if ((ma->mode_l & MA_TANGENT_V) || (ma->mode_l & MA_NORMAP_TANG)) {
-                               need_tangent= 1;
-                               if(me->mtface==NULL)
-                                       need_orco= 1;
-                       }
-                       /* radio faces need autosmooth, to separate shared vertices in corners */
-                       if(re->r.mode & R_RADIO)
-                               if(ma->mode & MA_RADIO) 
-                                       do_autosmooth= 1;
-               }
-       }
+       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
+       MTC_Mat4Invert(ob->imat, mat);
 
-       if(re->flag & R_NEED_TANGENT) {
-               /* exception for tangent space baking */
-               need_tangent= 1;
-               if(me->mtface==NULL)
+       /* material array */
+       memset(matar, 0, 4*32);
+       matar[0]= give_render_material(re, ob, 0);
+       for(a=0; a<ob->totcol; a++) {
+               matar[a]= give_render_material(re, ob, a+1);
+               if(matar[a]->texco & TEXCO_ORCO) {
                        need_orco= 1;
+               }
        }
-       
-       /* check autosmooth and displacement, we then have to skip only-verts optimize */
-       do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
-       if(do_autosmooth)
-               only_verts= 0;
-       if(test_for_displace(re, ob ) )
-               only_verts= 0;
-       
-       mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
-       if(!only_verts)
-               if(need_orco)
-                       mask |= CD_MASK_ORCO;
 
-       dm= mesh_create_derived_render(ob, mask);
-       if(dm==NULL) return;    /* in case duplicated object fails? */
+       if(need_orco) orcobase=orco= get_object_orco(re, ob);
 
-       if(mask & CD_MASK_ORCO) {
-               orco= dm->getVertDataArray(dm, CD_ORCO);
-               if(orco) {
-                       orco= MEM_dupallocN(orco);
-                       set_object_orco(re, ob, orco);
-               }
-       }
+       dl= cu->disp.first;
+       while(dl) {
+               if(dl->type==DL_INDEX3) {
+                       int *index;
 
-       if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
-                (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
-          (ob->fluidsimSettings->meshSurface) ) {
-               useFluidmeshNormals = 1;
-       }
+                       startvert= obr->totvert;
+                       data= dl->verts;
 
-       mvert= dm->getVertArray(dm);
-       totvert= dm->getNumVerts(dm);
+                       n[0]= ob->imat[0][2];
+                       n[1]= ob->imat[1][2];
+                       n[2]= ob->imat[2][2];
+                       Normalize(n);
 
-       /* attempt to autsmooth on original mesh, only without subsurf */
-       if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumFaces(dm))
-               use_original_normals= 1;
-       
-       ms = (totvert==me->totvert)?me->msticky:NULL;
-       
-       ma= give_render_material(re, ob, 1);
+                       for(a=0; a<dl->nr; a++, data+=3) {
+                               ver= RE_findOrAddVert(obr, obr->totvert++);
+                               VECCOPY(ver->co, data);
 
-       if(ma->mode & MA_HALO) {
-               make_render_halos(re, ob, me, totvert, mvert, ma, orco);
-       }
-       else {
+                               /* flip normal if face is backfacing, also used in face loop below */
+                               if(ver->co[2] < 0.0) {
+                                       VECCOPY(ver->n, n);
+                                       ver->flag = 1;
+                               }
+                               else {
+                                       ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
+                                       ver->flag = 0;
+                               }
 
-               for(a=0; a<totvert; a++, mvert++) {
-                       ver= RE_findOrAddVert(re, re->totvert++);
-                       VECCOPY(ver->co, mvert->co);
-                       if(do_autosmooth==0)    /* autosmooth on original unrotated data to prevent differences between frames */
                                MTC_Mat4MulVecfl(mat, ver->co);
-
-                       if(useFluidmeshNormals) {
-                               /* normals are inverted in render */
-                               xn = -mvert->no[0]/ 32767.0;
-                               yn = -mvert->no[1]/ 32767.0;
-                               zn = -mvert->no[2]/ 32767.0;
-                               /* transfor to cam  space */
-                               ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
-                               ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
-                               ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
-                       } // useFluidmeshNormals
-
-                       if(orco) {
-                               ver->orco= orco;
-                               orco+=3;
+                               
+                               if (orco) {
+                                       ver->orco = orco;
+                                       orco += 3;
+                               }
                        }
-                       if(ms) {
-                               float *sticky= RE_vertren_get_sticky(re, ver, 1);
-                               sticky[0]= ms->co[0];
-                               sticky[1]= ms->co[1];
-                               ms++;
+                       
+                       if(only_verts==0) {
+                               startvlak= obr->totvlak;
+                               index= dl->index;
+                               for(a=0; a<dl->parts; a++, index+=3) {
+
+                                       vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+                                       vlr->obr = obr;
+                                       vlr->v1= RE_findOrAddVert(obr, startvert+index[0]);
+                                       vlr->v2= RE_findOrAddVert(obr, startvert+index[1]);
+                                       vlr->v3= RE_findOrAddVert(obr, startvert+index[2]);
+                                       vlr->v4= NULL;
+                                       
+                                       if(vlr->v1->flag) {
+                                               VECCOPY(vlr->n, n);
+                                       }
+                                       else {
+                                               vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
+                                       }
+                                       
+                                       vlr->mat= matar[ dl->col ];
+                                       vlr->flag= 0;
+                                       if( (cu->flag & CU_NOPUNOFLIP) ) {
+                                               vlr->flag |= R_NOPUNOFLIP;
+                                       }
+                                       vlr->ec= 0;
+                                       vlr->lay= ob->lay;
+                               }
                        }
                }
-               
-               if(!only_verts) {
-                       /* store customdata names, because DerivedMesh is freed */
-                       RE_vlakren_set_customdata_names(re, &dm->faceData);
+               else if (dl->type==DL_SURF) {
                        
-                       /* still to do for keys: the correct local texture coordinate */
+                       /* cyclic U means an extruded full circular curve, we skip bevel splitting then */
+                       if (dl->flag & DL_CYCL_U) {
+                               orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat);
+                       }
+                       else {
+                               int p1,p2,p3,p4;
 
-                       /* faces in order of color blocks */
-                       vertofs= re->totvert - totvert;
-                       for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
+                               fp= dl->verts;
+                               startvert= obr->totvert;
+                               nr= dl->nr*dl->parts;
 
-                               ma= give_render_material(re, ob, a1+1);
-                               
-                               /* test for 100% transparant */
-                               ok= 1;
-                               if(ma->alpha==0.0 && ma->spectra==0.0) {
-                                       ok= 0;
-                                       /* texture on transparency? */
-                                       for(a=0; a<MAX_MTEX; a++) {
-                                               if(ma->mtex[a] && ma->mtex[a]->tex) {
-                                                       if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1;
-                                               }
+                               while(nr--) {
+                                       ver= RE_findOrAddVert(obr, obr->totvert++);
+                                               
+                                       VECCOPY(ver->co, fp);
+                                       MTC_Mat4MulVecfl(mat, ver->co);
+                                       fp+= 3;
+
+                                       if (orco) {
+                                               ver->orco = orco;
+                                               orco += 3;
                                        }
                                }
-                               
-                               /* if wire material, and we got edges, don't do the faces */
-                               if(ma->mode & MA_WIRE) {
-                                       end= dm->getNumEdges(dm);
-                                       if(end) ok= 0;
-                               }
 
-                               if(ok) {
-                                       end= dm->getNumFaces(dm);
-                                       mface= dm->getFaceArray(dm);
+                               if(dl->bevelSplitFlag || only_verts==0) {
+                                       startvlak= obr->totvlak;
 
-                                       for(a=0; a<end; a++, mface++) {
-                                               int v1, v2, v3, v4, flag;
-                                               
-                                               if( mface->mat_nr==a1 ) {
-                                                       float len;
-                                                               
-                                                       v1= mface->v1;
-                                                       v2= mface->v2;
-                                                       v3= mface->v3;
-                                                       v4= mface->v4;
-                                                       flag= mface->flag & ME_SMOOTH;
-                                                       
-                                                       vlr= RE_findOrAddVlak(re, re->totvlak++);
-                                                       vlr->ob= ob;
-                                                       vlr->v1= RE_findOrAddVert(re, vertofs+v1);
-                                                       vlr->v2= RE_findOrAddVert(re, vertofs+v2);
-                                                       vlr->v3= RE_findOrAddVert(re, vertofs+v3);
-                                                       if(v4) vlr->v4= RE_findOrAddVert(re, vertofs+v4);
-                                                       else vlr->v4= 0;
+                                       for(a=0; a<dl->parts; a++) {
 
-                                                       /* render normals are inverted in render */
-                                                       if(use_original_normals) {
-                                                               MFace *mf= me->mface+a;
-                                                               MVert *mv= me->mvert;
-                                                               
-                                                               if(vlr->v4) 
-                                                                       len= CalcNormFloat4( mv[mf->v4].co, mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co, vlr->n);
-                                                               else 
-                                                                       len= CalcNormFloat(mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co, vlr->n);
-                                                       }
-                                                       else {
-                                                               if(vlr->v4) 
-                                                                       len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
-                                                               else 
-                                                                       len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
-                                                       }
+                                               frontside= (a >= dl->nr/2);
 
-                                                       vlr->mat= ma;
-                                                       vlr->flag= flag;
-                                                       if((me->flag & ME_NOPUNOFLIP) ) {
-                                                               vlr->flag |= R_NOPUNOFLIP;
-                                                       }
-                                                       vlr->ec= 0; /* mesh edges rendered separately */
+                                               DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
+                                               p1+= startvert;
+                                               p2+= startvert;
+                                               p3+= startvert;
+                                               p4+= startvert;
+
+                                               for(; b<dl->nr; b++) {
+                                                       vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+                                                       vlr->obr= obr;
+                                                       vlr->v1= RE_findOrAddVert(obr, p2);
+                                                       vlr->v2= RE_findOrAddVert(obr, p1);
+                                                       vlr->v3= RE_findOrAddVert(obr, p3);
+                                                       vlr->v4= RE_findOrAddVert(obr, p4);
+                                                       vlr->ec= ME_V2V3+ME_V3V4;
+                                                       if(a==0) vlr->ec+= ME_V1V2;
+
+                                                       vlr->flag= dl->rt;
                                                        vlr->lay= ob->lay;
 
-                                                       if(len==0) re->totvlak--;
-                                                       else {
-                                                               CustomDataLayer *layer;
-                                                               MTFace *mtface, *mtf;
-                                                               MCol *mcol, *mc;
-                                                               int index, mtfn= 0, mcn= 0, n;
-                                                               char *name;
+                                                       /* this is not really scientific: the vertices
+                                                               * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
+                                                               * front and backside treated different!!
+                                                               */
 
-                                                               for(index=0; index<dm->faceData.totlayer; index++) {
-                                                                       layer= &dm->faceData.layers[index];
-                                                                       name= layer->name;
-                                                                       
-                                                                       if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
-                                                                               n= vlakren_customdata_layer_num(mtfn++, layer->active_rnd);
-                                                                               mtf= RE_vlakren_get_tface(re, vlr, n, &name, 1);
-                                                                               mtface= (MTFace*)layer->data;
-                                                                               *mtf= mtface[a];
-                                                                       }
-                                                                       else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
-                                                                               n= vlakren_customdata_layer_num(mcn++, layer->active_rnd);
-                                                                               mc= RE_vlakren_get_mcol(re, vlr, n, &name, 1);
-                                                                               mcol= (MCol*)layer->data;
-                                                                               memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
-                                                                       }
-                                                               }
-                                                       }
+                                                       if(frontside)
+                                                               CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
+                                                       else 
+                                                               CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
+
+                                                       vlr->mat= matar[ dl->col ];
+
+                                                       p4= p3;
+                                                       p3++;
+                                                       p2= p1;
+                                                       p1++;
                                                }
                                        }
+
+                                       if (dl->bevelSplitFlag) {
+                                               for(a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
+                                                       if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
+                                                               split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
+                                       }
+
+                                       /* vertex normals */
+                                       for(a= startvlak; a<obr->totvlak; a++) {
+                                               vlr= RE_findOrAddVlak(obr, a);
+
+                                               VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
+                                               VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
+                                               VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
+                                               VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
+                                       }
+                                       for(a=startvert; a<obr->totvert; a++) {
+                                               ver= RE_findOrAddVert(obr, a);
+                                               len= Normalize(ver->n);
+                                               if(len==0.0) ver->flag= 1;      /* flag abuse, its only used in zbuf now  */
+                                               else ver->flag= 0;
+                                       }
+                                       for(a= startvlak; a<obr->totvlak; a++) {
+                                               vlr= RE_findOrAddVlak(obr, a);
+                                               if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n);
+                                               if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n);
+                                               if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n);
+                                               if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n);
+                                       }
                                }
                        }
-                       
-                       /* exception... we do edges for wire mode. potential conflict when faces exist... */
-                       end= dm->getNumEdges(dm);
-                       mvert= dm->getVertArray(dm);
-                       ma= give_render_material(re, ob, 1);
-                       if(end && (ma->mode & MA_WIRE)) {
-                               MEdge *medge;
-                               struct edgesort *edgetable;
-                               int totedge= 0;
-                               
-                               medge= dm->getEdgeArray(dm);
-                               
-                               /* we want edges to have UV and vcol too... */
-                               edgetable= make_mesh_edge_lookup(dm, &totedge);
-                               
-                               for(a1=0; a1<end; a1++, medge++) {
-                                       if (medge->flag&ME_EDGERENDER) {
-                                               MVert *v0 = &mvert[medge->v1];
-                                               MVert *v1 = &mvert[medge->v2];
-
-                                               vlr= RE_findOrAddVlak(re, re->totvlak++);
-                                               vlr->ob= ob;
-                                               vlr->v1= RE_findOrAddVert(re, vertofs+medge->v1);
-                                               vlr->v2= RE_findOrAddVert(re, vertofs+medge->v2);
-                                               vlr->v3= vlr->v2;
-                                               vlr->v4= NULL;
-                                               
-                                               if(edgetable) {
-                                                       use_mesh_edge_lookup(re, dm, medge, vlr, edgetable, totedge);
-                                               }
-                                               
-                                               xn= -(v0->no[0]+v1->no[0]);
-                                               yn= -(v0->no[1]+v1->no[1]);
-                                               zn= -(v0->no[2]+v1->no[2]);
-                                               /* transpose ! */
-                                               vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
-                                               vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
-                                               vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
-                                               Normalize(vlr->n);
-                                               
-                                               vlr->mat= ma;
-                                               vlr->flag= 0;
-                                               vlr->ec= ME_V1V2;
-                                               vlr->lay= ob->lay;
-                                       }
-                               }
-                               if(edgetable)
-                                       MEM_freeN(edgetable);
-                       }
                }
+
+               dl= dl->next;
        }
        
-       if(!only_verts) {
-               if (test_for_displace(re, ob ) ) {
-                       calc_vertexnormals(re, totverto, totvlako, 0);
-                       do_displacement(re, ob, totvlako, re->totvlak-totvlako, totverto, re->totvert-totverto);
-               }
+       /* not very elegant... but we want original displist in UI */
+       if(cu->resolu_ren) {
+               freedisplist(&cu->disp);
+               SWAP(ListBase, olddl, cu->disp);
+       }
+}
 
-               if(do_autosmooth) {
-                       autosmooth(re, mat, totverto, totvlako, me->smoothresh);
-               }
+/* ------------------------------------------------------------------------- */
+/* Mesh                                                                                                                                 */
+/* ------------------------------------------------------------------------- */
 
-               if(useFluidmeshNormals) {
-                       // do not recalculate, only init render data
-                       calc_fluidsimnormals(re, totverto, totvlako, need_tangent);
-               } else {
-                       calc_vertexnormals(re, totverto, totvlako, need_tangent);
-               }
+struct edgesort {
+       int v1, v2;
+       int f;
+       int i1, i2;
+};
 
-               if(need_stress)
-                       calc_edge_stress(re, me, totverto, totvlako);
+/* edges have to be added with lowest index first for sorting */
+static void to_edgesort(struct edgesort *ed, int i1, int i2, int v1, int v2, int f)
+{
+       if(v1>v2) {
+               SWAP(int, v1, v2);
+               SWAP(int, i1, i2);
        }
 
-       dm->release(dm);
+       ed->v1= v1;
+       ed->v2= v2;
+       ed->i1= i1;
+       ed->i2= i2;
+       ed->f = f;
 }
 
-/* ------------------------------------------------------------------------- */
-
-static void initshadowbuf(Render *re, LampRen *lar, float mat[][4])
+static int vergedgesort(const void *v1, const void *v2)
 {
-       struct ShadBuf *shb;
-       float viewinv[4][4];
-       
-       /* if(la->spsi<16) return; */
-       
-       /* memory alloc */
-       shb= (struct ShadBuf *)MEM_callocN( sizeof(struct ShadBuf),"initshadbuf");
-       lar->shb= shb;
-       
-       if(shb==NULL) return;
-       
-       VECCOPY(shb->co, lar->co);
+       const struct edgesort *x1=v1, *x2=v2;
        
-       /* percentage render: keep track of min and max */
-       shb->size= (lar->bufsize*re->r.size)/100;
+       if( x1->v1 > x2->v1) return 1;
+       else if( x1->v1 < x2->v1) return -1;
+       else if( x1->v2 > x2->v2) return 1;
+       else if( x1->v2 < x2->v2) return -1;
        
-       if(lar->buffers>1) shb->size/= 2;
+       return 0;
+}
+
+static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
+{
+       MFace *mf, *mface;
+       MTFace *tface=NULL;
+       struct edgesort *edsort, *ed;
+       unsigned int *mcol=NULL;
+       int a, totedge=0, totface;
        
-       if(shb->size<512) shb->size= 512;
-       else if(shb->size > lar->bufsize) shb->size= lar->bufsize;
+       mface= dm->getFaceArray(dm);
+       totface= dm->getNumFaces(dm);
+       tface= dm->getFaceDataArray(dm, CD_MTFACE);
+       mcol= dm->getFaceDataArray(dm, CD_MCOL);
        
-       shb->size &= ~15;       /* make sure its multiples of 16 */
+       if(mcol==NULL && tface==NULL) return NULL;
        
-       shb->samp= lar->samp;
-       shb->soft= lar->soft;
-       shb->shadhalostep= lar->shadhalostep;
+       /* make sorted table with edges and face indices in it */
+       for(a= totface, mf= mface; a>0; a--, mf++) {
+               if(mf->v4) totedge+=4;
+               else if(mf->v3) totedge+=3;
+       }
+
+       if(totedge==0)
+               return NULL;
        
-       MTC_Mat4Ortho(mat);
-       MTC_Mat4Invert(shb->winmat, mat);       /* winmat is temp */
+       ed= edsort= MEM_callocN(totedge*sizeof(struct edgesort), "edgesort");
        
-       /* matrix: combination of inverse view and lampmat */
-       /* calculate again: the ortho-render has no correct viewinv */
-       MTC_Mat4Invert(viewinv, re->viewmat);
-       MTC_Mat4MulMat4(shb->viewmat, viewinv, shb->winmat);
+       for(a=0, mf=mface; a<totface; a++, mf++) {
+               to_edgesort(ed++, 0, 1, mf->v1, mf->v2, a);
+               to_edgesort(ed++, 1, 2, mf->v2, mf->v3, a);
+               if(mf->v4) {
+                       to_edgesort(ed++, 2, 3, mf->v3, mf->v4, a);
+                       to_edgesort(ed++, 3, 0, mf->v4, mf->v1, a);
+               }
+               else if(mf->v3)
+                       to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a);
+       }
        
-       /* projection */
-       shb->d= lar->clipsta;
-       shb->clipend= lar->clipend;
+       qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort);
        
-       /* bias is percentage, made 2x larger because of correction for angle of incidence */
-       /* when a ray is closer to parallel of a face, bias value is increased during render */
-       shb->bias= (0.02*lar->bias)*0x7FFFFFFF;
-       shb->bias= shb->bias*(100/re->r.size);
+       *totedgesort= totedge;
+
+       return edsort;
+}
+
+static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, VlakRen *vlr, struct edgesort *edgetable, int totedge)
+{
+       struct edgesort ed, *edp;
+       CustomDataLayer *layer;
+       MTFace *mtface, *mtf;
+       MCol *mcol, *mc;
+       int index, mtfn, mcn;
+       char *name;
        
-       /* halfway method (average of first and 2nd z) reduces bias issues */
-       if(lar->buftype==LA_SHADBUF_HALFWAY)
-               shb->bias= 0.1f*shb->bias;
+       if(medge->v1 < medge->v2) {
+               ed.v1= medge->v1;
+               ed.v2= medge->v2;
+       }
+       else {
+               ed.v1= medge->v2;
+               ed.v2= medge->v1;
+       }
        
-}
+       edp= bsearch(&ed, edgetable, totedge, sizeof(struct edgesort), vergedgesort);
 
+       /* since edges have different index ordering, we have to duplicate mcol and tface */
+       if(edp) {
+               mtfn= mcn= 0;
 
-static void area_lamp_vectors(LampRen *lar)
-{
-       float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
+               for(index=0; index<dm->faceData.totlayer; index++) {
+                       layer= &dm->faceData.layers[index];
+                       name= layer->name;
 
-       /* make it smaller, so area light can be multisampled */
-       multifac= 1.0f/sqrt((float)lar->ray_totsamp);
-       xsize *= multifac;
-       ysize *= multifac;
-       
-       /* corner vectors */
-       lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
-       lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
-       lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
+                       if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
+                               mtface= &((MTFace*)layer->data)[edp->f];
+                               mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1);
 
-       /* corner vectors */
-       lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
-       lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
-       lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
+                               *mtf= *mtface;
 
-       /* corner vectors */
-       lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
-       lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
-       lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
+                               memcpy(mtf->uv[0], mtface->uv[edp->i1], sizeof(float)*2);
+                               memcpy(mtf->uv[1], mtface->uv[edp->i2], sizeof(float)*2);
+                               memcpy(mtf->uv[2], mtface->uv[1], sizeof(float)*2);
+                               memcpy(mtf->uv[3], mtface->uv[1], sizeof(float)*2);
+                       }
+                       else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
+                               mcol= &((MCol*)layer->data)[edp->f*4];
+                               mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1);
 
-       /* corner vectors */
-       lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
-       lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
-       lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
-       /* only for correction button size, matrix size works on energy */
-       lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
+                               mc[0]= mcol[edp->i1];
+                               mc[1]= mc[2]= mc[3]= mcol[edp->i2];
+                       }
+               }
+       }
 }
 
-/* If lar takes more lamp data, the decoupling will be better. */
-static GroupObject *add_render_lamp(Render *re, Object *ob)
+static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts)
 {
-       Lamp *la= ob->data;
-       LampRen *lar;
-       GroupObject *go;
-       float mat[4][4], angle, xn, yn;
-       int c;
+       Object *ob= obr->ob;
+       Mesh *me;
+       MVert *mvert = NULL;
+       MFace *mface;
+       VlakRen *vlr; //, *vlr1;
+       VertRen *ver;
+       Material *ma;
+       MSticky *ms = NULL;
+       DerivedMesh *dm;
+       CustomDataMask mask;
+       float xn, yn, zn,  imat[3][3], mat[4][4];  //nor[3],
+       float *orco=0;
+       int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, vertofs;
+       int end, do_autosmooth=0, totvert = 0;
+       int useFluidmeshNormals= 0; // NT fluidsim, use smoothed normals?
+       int use_original_normals= 0;
 
-       /* previewrender sets this to zero... prevent accidents */
-       if(la==NULL) return NULL;
-       
-       /* prevent only shadow from rendering light */
-       if(la->mode & LA_ONLYSHADOW)
-               if((re->r.mode & R_SHADOW)==0)
-                       return NULL;
-       
-       re->totlamp++;
-       
-       /* groups is used to unify support for lightgroups, this is the global lightgroup */
-       go= MEM_callocN(sizeof(GroupObject), "groupobject");
-       BLI_addtail(&re->lights, go);
-       go->ob= ob;
-       /* lamprens are in own list, for freeing */
-       lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
-       BLI_addtail(&re->lampren, lar);
-       go->lampren= lar;
+       me= ob->data;
 
        MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
        MTC_Mat4Invert(ob->imat, mat);
+       MTC_Mat3CpyMat4(imat, ob->imat);
 
-       MTC_Mat3CpyMat4(lar->mat, mat);
-       MTC_Mat3CpyMat4(lar->imat, ob->imat);
-
-       lar->bufsize = la->bufsize;
-       lar->samp = la->samp;
-       lar->buffers= la->buffers;
-       if(lar->buffers==0) lar->buffers= 1;
-       lar->buftype= la->buftype;
-       lar->filtertype= la->filtertype;
-       lar->soft = la->soft;
-       lar->shadhalostep = la->shadhalostep;
-       lar->clipsta = la->clipsta;
-       lar->clipend = la->clipend;
-       
-       lar->bias = la->bias;
-
-       lar->type= la->type;
-       lar->mode= la->mode;
-
-       lar->energy= la->energy;
-       if(la->mode & LA_NEG) lar->energy= -lar->energy;
-
-       lar->vec[0]= -mat[2][0];
-       lar->vec[1]= -mat[2][1];
-       lar->vec[2]= -mat[2][2];
-       Normalize(lar->vec);
-       lar->co[0]= mat[3][0];
-       lar->co[1]= mat[3][1];
-       lar->co[2]= mat[3][2];
-       lar->dist= la->dist;
-       lar->haint= la->haint;
-       lar->distkw= lar->dist*lar->dist;
-       lar->r= lar->energy*la->r;
-       lar->g= lar->energy*la->g;
-       lar->b= lar->energy*la->b;
-       lar->k= la->k;
-
-       // area
-       lar->ray_samp= la->ray_samp;
-       lar->ray_sampy= la->ray_sampy;
-       lar->ray_sampz= la->ray_sampz;
-       
-       lar->area_size= la->area_size;
-       lar->area_sizey= la->area_sizey;
-       lar->area_sizez= la->area_sizez;
-
-       lar->area_shape= la->area_shape;
-       lar->ray_samp_method= la->ray_samp_method;
-       lar->ray_samp_type= la->ray_samp_type;
-       
-       lar->adapt_thresh= la->adapt_thresh;
+       if(me->totvert==0)
+               return;
        
-       if( ELEM3(lar->type, LA_SPOT, LA_SUN, LA_LOCAL)) {
-               lar->ray_totsamp= lar->ray_samp*lar->ray_samp;
-               lar->area_shape = LA_AREA_SQUARE;
-               lar->area_sizey= lar->area_size;
-       }
-       else if(lar->type==LA_AREA) {
-               switch(lar->area_shape) {
-               case LA_AREA_SQUARE:
-                       lar->ray_totsamp= lar->ray_samp*lar->ray_samp;
-                       lar->ray_sampy= lar->ray_samp;
-                       lar->area_sizey= lar->area_size;
-                       break;
-               case LA_AREA_RECT:
-                       lar->ray_totsamp= lar->ray_samp*lar->ray_sampy;
-                       break;
-               case LA_AREA_CUBE:
-                       lar->ray_totsamp= lar->ray_samp*lar->ray_samp*lar->ray_samp;
-                       lar->ray_sampy= lar->ray_samp;
-                       lar->ray_sampz= lar->ray_samp;
-                       lar->area_sizey= lar->area_size;
-                       lar->area_sizez= lar->area_size;
-                       break;
-               case LA_AREA_BOX:
-                       lar->ray_totsamp= lar->ray_samp*lar->ray_sampy*lar->ray_sampz;
-                       break;
+       need_orco= 0;
+       for(a=1; a<=ob->totcol; a++) {
+               ma= give_render_material(re, ob, a);
+               if(ma) {
+                       if(ma->texco & (TEXCO_ORCO|TEXCO_STRESS))
+                               need_orco= 1;
+                       if(ma->texco & TEXCO_STRESS)
+                               need_stress= 1;
+                       /* normalmaps, test if tangents needed, separated from shading */
+                       if ((ma->mode_l & MA_TANGENT_V) || (ma->mode_l & MA_NORMAP_TANG)) {
+                               need_tangent= 1;
+                               if(me->mtface==NULL)
+                                       need_orco= 1;
+                       }
+                       /* radio faces need autosmooth, to separate shared vertices in corners */
+                       if(re->r.mode & R_RADIO)
+                               if(ma->mode & MA_RADIO) 
+                                       do_autosmooth= 1;
                }
+       }
 
-               area_lamp_vectors(lar);
-               init_jitter_plane(lar); // subsamples
+       if(re->flag & R_NEED_TANGENT) {
+               /* exception for tangent space baking */
+               need_tangent= 1;
+               if(me->mtface==NULL)
+                       need_orco= 1;
        }
-       else lar->ray_totsamp= 0;
        
-#ifndef DISABLE_YAFRAY
-       /* yafray: photonlight and other params */
-       if (re->r.renderer==R_YAFRAY) {
-               lar->YF_numphotons = la->YF_numphotons;
-               lar->YF_numsearch = la->YF_numsearch;
-               lar->YF_phdepth = la->YF_phdepth;
-               lar->YF_useqmc = la->YF_useqmc;
-               lar->YF_causticblur = la->YF_causticblur;
-               lar->YF_ltradius = la->YF_ltradius;
-               lar->YF_bufsize = la->YF_bufsize;
-               lar->YF_glowint = la->YF_glowint;
-               lar->YF_glowofs = la->YF_glowofs;
-               lar->YF_glowtype = la->YF_glowtype;
+       /* check autosmooth and displacement, we then have to skip only-verts optimize */
+       do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
+       if(do_autosmooth)
+               only_verts= 0;
+       if(test_for_displace(re, ob ) )
+               only_verts= 0;
+       
+       mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
+       if(!only_verts)
+               if(need_orco)
+                       mask |= CD_MASK_ORCO;
+
+       dm= mesh_create_derived_render(ob, mask);
+       if(dm==NULL) return;    /* in case duplicated object fails? */
+
+       if(mask & CD_MASK_ORCO) {
+               orco= dm->getVertDataArray(dm, CD_ORCO);
+               if(orco) {
+                       orco= MEM_dupallocN(orco);
+                       set_object_orco(re, ob, orco);
+               }
        }
-#endif /* disable yafray */
 
-       lar->spotsi= la->spotsize;
-       if(lar->mode & LA_HALO) {
-               if(lar->spotsi>170.0) lar->spotsi= 170.0;
+       if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+                (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
+          (ob->fluidsimSettings->meshSurface) ) {
+               useFluidmeshNormals = 1;
        }
-       lar->spotsi= cos( M_PI*lar->spotsi/360.0 );
-       lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
 
-       memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *));
+       mvert= dm->getVertArray(dm);
+       totvert= dm->getNumVerts(dm);
 
-       lar->lay= ob->lay & 0xFFFFFF;   // higher 8 bits are localview layers
+       /* attempt to autsmooth on original mesh, only without subsurf */
+       if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumFaces(dm))
+               use_original_normals= 1;
+       
+       ms = (totvert==me->totvert)?me->msticky:NULL;
+       
+       ma= give_render_material(re, ob, 1);
 
-       lar->falloff_type = la->falloff_type;
-       lar->ld1= la->att1;
-       lar->ld2= la->att2;
-       lar->curfalloff = curvemapping_copy(la->curfalloff);
+       if(ma->mode & MA_HALO) {
+               make_render_halos(re, obr, me, totvert, mvert, ma, orco);
+       }
+       else {
 
-       if(lar->type==LA_SPOT) {
+               for(a=0; a<totvert; a++, mvert++) {
+                       ver= RE_findOrAddVert(obr, obr->totvert++);
+                       VECCOPY(ver->co, mvert->co);
+                       if(do_autosmooth==0)    /* autosmooth on original unrotated data to prevent differences between frames */
+                               MTC_Mat4MulVecfl(mat, ver->co);
+  
+                       if(useFluidmeshNormals) {
+                               /* normals are inverted in render */
+                               xn = -mvert->no[0]/ 32767.0;
+                               yn = -mvert->no[1]/ 32767.0;
+                               zn = -mvert->no[2]/ 32767.0;
+                               /* transfor to cam  space */
+                               ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+                               ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+                               ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+                       } // useFluidmeshNormals
 
-               Normalize(lar->imat[0]);
-               Normalize(lar->imat[1]);
-               Normalize(lar->imat[2]);
+                       if(orco) {
+                               ver->orco= orco;
+                               orco+=3;
+                       }
+                       if(ms) {
+                               float *sticky= RE_vertren_get_sticky(obr, ver, 1);
+                               sticky[0]= ms->co[0];
+                               sticky[1]= ms->co[1];
+                               ms++;
+                       }
+               }
+               
+               if(!only_verts) {
+                       /* store customdata names, because DerivedMesh is freed */
+                       RE_set_customdata_names(obr, &dm->faceData);
+                       
+                       /* still to do for keys: the correct local texture coordinate */
 
-               xn= saacos(lar->spotsi);
-               xn= sin(xn)/cos(xn);
-               lar->spottexfac= 1.0/(xn);
+                       /* faces in order of color blocks */
+                       vertofs= obr->totvert - totvert;
+                       for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) {
 
-               if(lar->mode & LA_ONLYSHADOW) {
-                       if((lar->mode & (LA_SHAD_BUF|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW;
-               }
+                               ma= give_render_material(re, ob, a1+1);
+                               
+                               /* test for 100% transparant */
+                               ok= 1;
+                               if(ma->alpha==0.0 && ma->spectra==0.0) {
+                                       ok= 0;
+                                       /* texture on transparency? */
+                                       for(a=0; a<MAX_MTEX; a++) {
+                                               if(ma->mtex[a] && ma->mtex[a]->tex) {
+                                                       if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1;
+                                               }
+                                       }
+                               }
+                               
+                               /* if wire material, and we got edges, don't do the faces */
+                               if(ma->mode & MA_WIRE) {
+                                       end= dm->getNumEdges(dm);
+                                       if(end) ok= 0;
+                               }
 
-       }
+                               if(ok) {
+                                       end= dm->getNumFaces(dm);
+                                       mface= dm->getFaceArray(dm);
 
-       /* set flag for spothalo en initvars */
-       if(la->type==LA_SPOT && (la->mode & LA_HALO)) {
-               if(la->haint>0.0) {
-                       re->flag |= R_LAMPHALO;
+                                       for(a=0; a<end; a++, mface++) {
+                                               int v1, v2, v3, v4, flag;
+                                               
+                                               if( mface->mat_nr==a1 ) {
+                                                       float len;
+                                                               
+                                                       v1= mface->v1;
+                                                       v2= mface->v2;
+                                                       v3= mface->v3;
+                                                       v4= mface->v4;
+                                                       flag= mface->flag & ME_SMOOTH;
 
-                       /* camera position (0,0,0) rotate around lamp */
-                       lar->sh_invcampos[0]= -lar->co[0];
-                       lar->sh_invcampos[1]= -lar->co[1];
-                       lar->sh_invcampos[2]= -lar->co[2];
-                       MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
+                                                       vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+                                                       vlr->obr= obr;
+                                                       vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
+                                                       vlr->v2= RE_findOrAddVert(obr, vertofs+v2);
+                                                       vlr->v3= RE_findOrAddVert(obr, vertofs+v3);
+                                                       if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4);
+                                                       else vlr->v4= 0;
 
-                       /* z factor, for a normalized volume */
-                       angle= saacos(lar->spotsi);
-                       xn= lar->spotsi;
-                       yn= sin(angle);
-                       lar->sh_zfac= yn/xn;
-                       /* pre-scale */
-                       lar->sh_invcampos[2]*= lar->sh_zfac;
+                                                       /* render normals are inverted in render */
+                                                       if(use_original_normals) {
+                                                               MFace *mf= me->mface+a;
+                                                               MVert *mv= me->mvert;
+                                                               
+                                                               if(vlr->v4) 
+                                                                       len= CalcNormFloat4( mv[mf->v4].co, mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co, vlr->n);
+                                                               else 
+                                                                       len= CalcNormFloat(mv[mf->v3].co, mv[mf->v2].co, mv[mf->v1].co, vlr->n);
+                                                       }
+                                                       else {
+                                                               if(vlr->v4) 
+                                                                       len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+                                                               else 
+                                                                       len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
+                                                       }
 
-               }
-       }
-       else if(la->type==LA_HEMI) {
-               lar->mode &= ~(LA_SHAD_RAY|LA_SHAD_BUF);
-       }
+                                                       vlr->mat= ma;
+                                                       vlr->flag= flag;
+                                                       if((me->flag & ME_NOPUNOFLIP) ) {
+                                                               vlr->flag |= R_NOPUNOFLIP;
+                                                       }
+                                                       vlr->ec= 0; /* mesh edges rendered separately */
+                                                       vlr->lay= ob->lay;
 
-       for(c=0; c<MAX_MTEX; c++) {
-               if(la->mtex[c] && la->mtex[c]->tex) {
-                       lar->mode |= LA_TEXTURE;
+                                                       if(len==0) obr->totvlak--;
+                                                       else {
+                                                               CustomDataLayer *layer;
+                                                               MTFace *mtface, *mtf;
+                                                               MCol *mcol, *mc;
+                                                               int index, mtfn= 0, mcn= 0;
+                                                               char *name;
 
-                       if(G.rendering) {
-                               if(re->osa) {
-                                       if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX;
+                                                               for(index=0; index<dm->faceData.totlayer; index++) {
+                                                                       layer= &dm->faceData.layers[index];
+                                                                       name= layer->name;
+                                                                       
+                                                                       if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
+                                                                               mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1);
+                                                                               mtface= (MTFace*)layer->data;
+                                                                               *mtf= mtface[a];
+                                                                       }
+                                                                       else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
+                                                                               mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1);
+                                                                               mcol= (MCol*)layer->data;
+                                                                               memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
                                }
                        }
-               }
-       }
-       /* yafray: shadow flag should not be cleared, only used with internal renderer */
-       if (re->r.renderer==R_INTERN) {
-               /* to make sure we can check ray shadow easily in the render code */
-               if(lar->mode & LA_SHAD_RAY) {
-                       if( (re->r.mode & R_RAYTRACE)==0)
-                               lar->mode &= ~LA_SHAD_RAY;
-               }
-       
-
-               if(re->r.mode & R_SHADOW) {
-                       
-                       if ((lar->mode & LA_SHAD_RAY) && (lar->ray_samp_method == LA_SAMP_HAMMERSLEY)) {
-                               init_lamp_hammersley(lar);
-                       }
-                       if(la->type==LA_AREA && (lar->mode & LA_SHAD_RAY) && (lar->ray_samp_method == LA_SAMP_CONSTANT)) {
-                               init_jitter_plane(lar);
-                       }
-                       else if (la->type==LA_SPOT && (lar->mode & LA_SHAD_BUF) ) {
-                               /* Per lamp, one shadow buffer is made. */
-                               lar->bufflag= la->bufflag;
-                               Mat4CpyMat4(mat, ob->obmat);
-                               initshadowbuf(re, lar, mat);    // mat is altered
-                       }
-                       
                        
-                       /* this is the way used all over to check for shadow */
-                       if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
-                               LampShadowSubSample *lss;
-                               int a, b, tot= re->r.threads*re->r.osa;
+                       /* exception... we do edges for wire mode. potential conflict when faces exist... */
+                       end= dm->getNumEdges(dm);
+                       mvert= dm->getVertArray(dm);
+                       ma= give_render_material(re, ob, 1);
+                       if(end && (ma->mode & MA_WIRE)) {
+                               MEdge *medge;
+                               struct edgesort *edgetable;
+                               int totedge= 0;
                                
-                               lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample");
-                               lss= lar->shadsamp[0].s;
-                               /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */
-                               for(a=0; a<tot; a++, lss++) {
-                                       for(b=0; b<4; b++) {
-                                               lss->samplenr= -1;      /* used to detect whether we store or read */
-                                               lss->shadfac[b]= 1.0f;
+                               medge= dm->getEdgeArray(dm);
+                               
+                               /* we want edges to have UV and vcol too... */
+                               edgetable= make_mesh_edge_lookup(dm, &totedge);
+                               
+                               for(a1=0; a1<end; a1++, medge++) {
+                                       if (medge->flag&ME_EDGERENDER) {
+                                               MVert *v0 = &mvert[medge->v1];
+                                               MVert *v1 = &mvert[medge->v2];
+
+                                               vlr= RE_findOrAddVlak(obr, obr->totvlak++);
+                                               vlr->obr= obr;
+                                               vlr->v1= RE_findOrAddVert(obr, vertofs+medge->v1);
+                                               vlr->v2= RE_findOrAddVert(obr, vertofs+medge->v2);
+                                               vlr->v3= vlr->v2;
+                                               vlr->v4= NULL;
+                                               
+                                               if(edgetable)
+                                                       use_mesh_edge_lookup(obr, dm, medge, vlr, edgetable, totedge);
+                                               
+                                               xn= -(v0->no[0]+v1->no[0]);
+                                               yn= -(v0->no[1]+v1->no[1]);
+                                               zn= -(v0->no[2]+v1->no[2]);
+                                               /* transpose ! */
+                                               vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+                                               vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+                                               vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+                                               Normalize(vlr->n);
+                                               
+                                               vlr->mat= ma;
+                                               vlr->flag= 0;
+                                               vlr->ec= ME_V1V2;
+                                               vlr->lay= ob->lay;
                                        }
                                }
+                               if(edgetable)
+                                       MEM_freeN(edgetable);
                        }
                }
        }
-       
-       return go;
+       
+       if(!only_verts) {
+               if (test_for_displace(re, ob ) ) {
+                       calc_vertexnormals(re, obr, 0);
+                       do_displacement(re, obr);
+               }
+
+               if(do_autosmooth) {
+                       autosmooth(re, obr, mat, me->smoothresh);
+               }
+
+               if(useFluidmeshNormals) {
+                       // do not recalculate, only init render data
+                       calc_fluidsimnormals(re, obr, need_tangent);
+               } else {
+                       calc_vertexnormals(re, obr, need_tangent);
+               }
+
+               if(need_stress)
+                       calc_edge_stress(re, obr, me);
+       }
+
+       dm->release(dm);
 }
 
+/* ------------------------------------------------------------------------- */
+/* Lamps and Shadowbuffers                                                                                                      */
 /* ------------------------------------------------------------------------- */
 
-/* returns amount of vertices added for orco */
-static int dl_surf_to_renderdata(Render *re, Object *ob, DispList *dl, Material **matar, float *orco, float mat[4][4])
+static void initshadowbuf(Render *re, LampRen *lar, float mat[][4])
 {
-       VertRen *v1, *v2, *v3, *v4, *ver;
-       VlakRen *vlr, *vlr1, *vlr2, *vlr3;
-       Curve *cu= ob->data;
-       float *data, n1[3], flen;
-       int u, v, orcoret= 0;
-       int p1, p2, p3, p4, a;
-       int sizeu, nsizeu, sizev, nsizev;
-       int startvert, startvlak;
+       struct ShadBuf *shb;
+       float viewinv[4][4];
        
-       startvert= re->totvert;
-       nsizeu = sizeu = dl->parts; nsizev = sizev = dl->nr; 
+       /* if(la->spsi<16) return; */
        
-       data= dl->verts;
-       for (u = 0; u < sizeu; u++) {
-               v1 = RE_findOrAddVert(re, re->totvert++); /* save this for possible V wrapping */
-               VECCOPY(v1->co, data); data += 3;
-               if(orco) {
-                       v1->orco= orco; orco+= 3; orcoret++;
-               }       
-               MTC_Mat4MulVecfl(mat, v1->co);
-               
-               for (v = 1; v < sizev; v++) {
-                       ver= RE_findOrAddVert(re, re->totvert++);
-                       VECCOPY(ver->co, data); data += 3;
-                       if(orco) {
-                               ver->orco= orco; orco+= 3; orcoret++;
-                       }       
-                       MTC_Mat4MulVecfl(mat, ver->co);
-               }
-               /* if V-cyclic, add extra vertices at end of the row */
-               if (dl->flag & DL_CYCL_U) {
-                       ver= RE_findOrAddVert(re, re->totvert++);
-                       VECCOPY(ver->co, v1->co);
-                       if(orco) {
-                               ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0);
-                       }
-               }       
-       }       
+       /* memory alloc */
+       shb= (struct ShadBuf *)MEM_callocN( sizeof(struct ShadBuf),"initshadbuf");
+       lar->shb= shb;
        
-       /* Done before next loop to get corner vert */
-       if (dl->flag & DL_CYCL_U) nsizev++;
-       if (dl->flag & DL_CYCL_V) nsizeu++;
+       if(shb==NULL) return;
        
-       /* if U cyclic, add extra row at end of column */
-       if (dl->flag & DL_CYCL_V) {
-               for (v = 0; v < nsizev; v++) {
-                       v1= RE_findOrAddVert(re, startvert + v);
-                       ver= RE_findOrAddVert(re, re->totvert++);
-                       VECCOPY(ver->co, v1->co);
-                       if(orco) {
-                               ver->orco= orco; orco+=3; orcoret++; //ver->orco= orcobase + 3*(0*sizev + v);
-                       }
-               }
-       }
+       VECCOPY(shb->co, lar->co);
        
-       sizeu = nsizeu;
-       sizev = nsizev;
+       /* percentage render: keep track of min and max */
+       shb->size= (lar->bufsize*re->r.size)/100;
        
-       startvlak= re->totvlak;
+       if(lar->buffers>1) shb->size/= 2;
        
-       for(u = 0; u < sizeu - 1; u++) {
-               p1 = startvert + u * sizev; /* walk through face list */
-               p2 = p1 + 1;
-               p3 = p2 + sizev;
-               p4 = p3 - 1;
-               
-               for(v = 0; v < sizev - 1; v++) {
-                       v1= RE_findOrAddVert(re, p1);
-                       v2= RE_findOrAddVert(re, p2);
-                       v3= RE_findOrAddVert(re, p3);
-                       v4= RE_findOrAddVert(re, p4);
-                       
-                       vlr= RE_findOrAddVlak(re, re->totvlak++);
-                       vlr->ob= ob;
-                       vlr->v1= v1; vlr->v2= v2; vlr->v3= v3; vlr->v4= v4;
-                       
-                       flen= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, n1);
-                       VECCOPY(vlr->n, n1);
-                       
-                       vlr->lay= ob->lay;
-                       vlr->mat= matar[ dl->col];
-                       vlr->ec= ME_V1V2+ME_V2V3;
-                       vlr->flag= dl->rt;
-                       if( (cu->flag & CU_NOPUNOFLIP) ) {
-                               vlr->flag |= R_NOPUNOFLIP;
-                       }
-                       
-                       VecAddf(v1->n, v1->n, n1);
-                       VecAddf(v2->n, v2->n, n1);
-                       VecAddf(v3->n, v3->n, n1);
-                       VecAddf(v4->n, v4->n, n1);
-                       
-                       p1++; p2++; p3++; p4++;
-               }
-       }       
-       /* fix normals for U resp. V cyclic faces */
-       sizeu--; sizev--;  /* dec size for face array */
-       if (dl->flag & DL_CYCL_V) {
-               
-               for (v = 0; v < sizev; v++)
-               {
-                       /* optimize! :*/
-                       vlr= RE_findOrAddVlak(re, UVTOINDEX(sizeu - 1, v));
-                       vlr1= RE_findOrAddVlak(re, UVTOINDEX(0, v));
-                       VecAddf(vlr1->v1->n, vlr1->v1->n, vlr->n);
-                       VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
-                       VecAddf(vlr->v3->n, vlr->v3->n, vlr1->n);
-                       VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
-               }
-       }
-       if (dl->flag & DL_CYCL_U) {
-               
-               for (u = 0; u < sizeu; u++)
-               {
-                       /* optimize! :*/
-                       vlr= RE_findOrAddVlak(re, UVTOINDEX(u, 0));
-                       vlr1= RE_findOrAddVlak(re, UVTOINDEX(u, sizev-1));
-                       VecAddf(vlr1->v2->n, vlr1->v2->n, vlr->n);
-                       VecAddf(vlr1->v3->n, vlr1->v3->n, vlr->n);
-                       VecAddf(vlr->v1->n, vlr->v1->n, vlr1->n);
-                       VecAddf(vlr->v4->n, vlr->v4->n, vlr1->n);
-               }
-       }
-       /* last vertex is an extra case: 
-               
-               ^       ()----()----()----()
-               |       |     |     ||     |
-               u       |     |(0,n)||(0,0)|
-               |     |     ||     |
-               ()====()====[]====()
-               |     |     ||     |
-               |     |(m,n)||(m,0)|
-               |     |     ||     |
-               ()----()----()----()
-               v ->
-               
-               vertex [] is no longer shared, therefore distribute
-               normals of the surrounding faces to all of the duplicates of []
-               */
+       if(shb->size<512) shb->size= 512;
+       else if(shb->size > lar->bufsize) shb->size= lar->bufsize;
        
-       if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U))
-       {
-               vlr= RE_findOrAddVlak(re, UVTOINDEX(sizeu - 1, sizev - 1)); /* (m,n) */
-               vlr1= RE_findOrAddVlak(re, UVTOINDEX(0,0));  /* (0,0) */
-               VecAddf(n1, vlr->n, vlr1->n);
-               vlr2= RE_findOrAddVlak(re, UVTOINDEX(0, sizev-1)); /* (0,n) */
-               VecAddf(n1, n1, vlr2->n);
-               vlr3= RE_findOrAddVlak(re, UVTOINDEX(sizeu-1, 0)); /* (m,0) */
-               VecAddf(n1, n1, vlr3->n);
-               VECCOPY(vlr->v3->n, n1);
-               VECCOPY(vlr1->v1->n, n1);
-               VECCOPY(vlr2->v2->n, n1);
-               VECCOPY(vlr3->v4->n, n1);
-       }
-       for(a = startvert; a < re->totvert; a++) {
-               ver= RE_findOrAddVert(re, a);
-               Normalize(ver->n);
-       }
+       shb->size &= ~15;       /* make sure its multiples of 16 */
        
+       shb->samp= lar->samp;
+       shb->soft= lar->soft;
+       shb->shadhalostep= lar->shadhalostep;
+       
+       MTC_Mat4Ortho(mat);
+       MTC_Mat4Invert(shb->winmat, mat);       /* winmat is temp */
+       
+       /* matrix: combination of inverse view and lampmat */
+       /* calculate again: the ortho-render has no correct viewinv */
+       MTC_Mat4Invert(viewinv, re->viewmat);
+       MTC_Mat4MulMat4(shb->viewmat, viewinv, shb->winmat);
+       
+       /* projection */
+       shb->d= lar->clipsta;
+       shb->clipend= lar->clipend;
+       
+       /* bias is percentage, made 2x larger because of correction for angle of incidence */
+       /* when a ray is closer to parallel of a face, bias value is increased during render */
+       shb->bias= (0.02*lar->bias)*0x7FFFFFFF;
+       shb->bias= shb->bias*(100/re->r.size);
+       
+       /* halfway method (average of first and 2nd z) reduces bias issues */
+       if(lar->buftype==LA_SHADBUF_HALFWAY)
+               shb->bias= 0.1f*shb->bias;
        
-       return orcoret;
 }
 
-static void init_render_surf(Render *re, Object *ob)
+static void area_lamp_vectors(LampRen *lar)
 {
-       Nurb *nu=0;
-       Curve *cu;
-       ListBase displist;
-       DispList *dl;
-       Material *matar[32];
-       float *orco=NULL, *orcobase=NULL, mat[4][4];
-       int a, need_orco=0;
-
-       cu= ob->data;
-       nu= cu->nurb.first;
-       if(nu==0) return;
-
-       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-       MTC_Mat4Invert(ob->imat, mat);
-
-       /* material array */
-       memset(matar, 0, 4*32);
-       matar[0]= give_render_material(re, ob, 0);
-       for(a=0; a<ob->totcol; a++) {
-               matar[a]= give_render_material(re, ob, a+1);
-               if(matar[a] && matar[a]->texco & TEXCO_ORCO) {
-                       need_orco= 1;
-               }
-       }
-
-       if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
+       float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
 
-       if(need_orco) orcobase= orco= get_object_orco(re, ob);
+       /* make it smaller, so area light can be multisampled */
+       multifac= 1.0f/sqrt((float)lar->ray_totsamp);
+       xsize *= multifac;
+       ysize *= multifac;
+       
+       /* corner vectors */
+       lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
+       lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
+       lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
 
-       displist.first= displist.last= 0;
-       makeDispListSurf(ob, &displist, 1);
+       /* corner vectors */
+       lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
+       lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
+       lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
 
-       dl= displist.first;
-       /* walk along displaylist and create rendervertices/-faces */
-       while(dl) {
-                       /* watch out: u ^= y, v ^= x !! */
-               if(dl->type==DL_SURF) {
-                       orco+= 3*dl_surf_to_renderdata(re, ob, dl, matar, orco, mat);
-               }
+       /* corner vectors */
+       lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
+       lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
+       lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];      
 
-               dl= dl->next;
-       }
-       freedisplist(&displist);
+       /* corner vectors */
+       lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
+       lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
+       lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];      
+       /* only for correction button size, matrix size works on energy */
+       lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
 }
 
-static void init_render_curve(Render *re, Object *ob, int only_verts)
-{
-       Curve *cu;
-       VertRen *ver;
-       VlakRen *vlr;
-       DispList *dl;
-       ListBase olddl={NULL, NULL};
-       Material *matar[32];
-       float len, *data, *fp, *orco=NULL, *orcobase= NULL;
-       float n[3], mat[4][4];
-       int nr, startvert, startvlak, a, b;
-       int frontside, need_orco=0;
-
-       cu= ob->data;
-       if(cu->nurb.first==NULL) return;
-
-       /* no modifier call here, is in makedisp */
+/* If lar takes more lamp data, the decoupling will be better. */
+static GroupObject *add_render_lamp(Render *re, Object *ob)
+{
+       Lamp *la= ob->data;
+       LampRen *lar;
+       GroupObject *go;
+       float mat[4][4], angle, xn, yn;
+       int c;
 
-       if(cu->resolu_ren) 
-               SWAP(ListBase, olddl, cu->disp);
+       /* previewrender sets this to zero... prevent accidents */
+       if(la==NULL) return NULL;
        
-       /* test displist */
-       if(cu->disp.first==NULL) 
-               makeDispListCurveTypes(ob, 0);
-       dl= cu->disp.first;
-       if(cu->disp.first==NULL) return;
+       /* prevent only shadow from rendering light */
+       if(la->mode & LA_ONLYSHADOW)
+               if((re->r.mode & R_SHADOW)==0)
+                       return NULL;
+       
+       re->totlamp++;
        
+       /* groups is used to unify support for lightgroups, this is the global lightgroup */
+       go= MEM_callocN(sizeof(GroupObject), "groupobject");
+       BLI_addtail(&re->lights, go);
+       go->ob= ob;
+       /* lamprens are in own list, for freeing */
+       lar= (LampRen *)MEM_callocN(sizeof(LampRen),"lampren");
+       BLI_addtail(&re->lampren, lar);
+       go->lampren= lar;
+
        MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
        MTC_Mat4Invert(ob->imat, mat);
 
-       /* material array */
-       memset(matar, 0, 4*32);
-       matar[0]= give_render_material(re, ob, 0);
-       for(a=0; a<ob->totcol; a++) {
-               matar[a]= give_render_material(re, ob, a+1);
-               if(matar[a]->texco & TEXCO_ORCO) {
-                       need_orco= 1;
-               }
-       }
-
-       if(need_orco) orcobase=orco= get_object_orco(re, ob);
-
-       dl= cu->disp.first;
-       while(dl) {
-               if(dl->type==DL_INDEX3) {
-                       int *index;
+       MTC_Mat3CpyMat4(lar->mat, mat);
+       MTC_Mat3CpyMat4(lar->imat, ob->imat);
 
-                       startvert= re->totvert;
-                       data= dl->verts;
+       lar->bufsize = la->bufsize;
+       lar->samp = la->samp;
+       lar->buffers= la->buffers;
+       if(lar->buffers==0) lar->buffers= 1;
+       lar->buftype= la->buftype;
+       lar->filtertype= la->filtertype;
+       lar->soft = la->soft;
+       lar->shadhalostep = la->shadhalostep;
+       lar->clipsta = la->clipsta;
+       lar->clipend = la->clipend;
+       
+       lar->bias = la->bias;
 
-                       n[0]= ob->imat[0][2];
-                       n[1]= ob->imat[1][2];
-                       n[2]= ob->imat[2][2];
-                       Normalize(n);
+       lar->type= la->type;
+       lar->mode= la->mode;
 
-                       for(a=0; a<dl->nr; a++, data+=3) {
-                               ver= RE_findOrAddVert(re, re->totvert++);
-                               VECCOPY(ver->co, data);
+       lar->energy= la->energy;
+       if(la->mode & LA_NEG) lar->energy= -lar->energy;
 
-                               /* flip normal if face is backfacing, also used in face loop below */
-                               if(ver->co[2] < 0.0) {
-                                       VECCOPY(ver->n, n);
-                                       ver->flag = 1;
-                               }
-                               else {
-                                       ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2];
-                                       ver->flag = 0;
-                               }
+       lar->vec[0]= -mat[2][0];
+       lar->vec[1]= -mat[2][1];
+       lar->vec[2]= -mat[2][2];
+       Normalize(lar->vec);
+       lar->co[0]= mat[3][0];
+       lar->co[1]= mat[3][1];
+       lar->co[2]= mat[3][2];
+       lar->dist= la->dist;
+       lar->haint= la->haint;
+       lar->distkw= lar->dist*lar->dist;
+       lar->r= lar->energy*la->r;
+       lar->g= lar->energy*la->g;
+       lar->b= lar->energy*la->b;
+       lar->k= la->k;
 
-                               MTC_Mat4MulVecfl(mat, ver->co);
-                               
-                               if (orco) {
-                                       ver->orco = orco;
-                                       orco += 3;
-                               }
-                       }
-                       
-                       if(only_verts==0) {
-                               startvlak= re->totvlak;
-                               index= dl->index;
-                               for(a=0; a<dl->parts; a++, index+=3) {
+       // area
+       lar->ray_samp= la->ray_samp;
+       lar->ray_sampy= la->ray_sampy;
+       lar->ray_sampz= la->ray_sampz;
+       
+       lar->area_size= la->area_size;
+       lar->area_sizey= la->area_sizey;
+       lar->area_sizez= la->area_sizez;
 
-                                       vlr= RE_findOrAddVlak(re, re->totvlak++);
-                                       vlr->ob = ob;
-                                       vlr->v1= RE_findOrAddVert(re, startvert+index[0]);
-                                       vlr->v2= RE_findOrAddVert(re, startvert+index[1]);
-                                       vlr->v3= RE_findOrAddVert(re, startvert+index[2]);
-                                       vlr->v4= NULL;
-                                       
-                                       if(vlr->v1->flag) {
-                                               VECCOPY(vlr->n, n);
-                                       }
-                                       else {
-                                               vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2];
-                                       }
-                                       
-                                       vlr->mat= matar[ dl->col ];
-                                       vlr->flag= 0;
-                                       if( (cu->flag & CU_NOPUNOFLIP) ) {
-                                               vlr->flag |= R_NOPUNOFLIP;
-                                       }
-                                       vlr->ec= 0;
-                                       vlr->lay= ob->lay;
-                               }
-                       }
+       lar->area_shape= la->area_shape;
+       lar->ray_samp_method= la->ray_samp_method;
+       lar->ray_samp_type= la->ray_samp_type;
+       
+       lar->adapt_thresh= la->adapt_thresh;
+       
+       if( ELEM3(lar->type, LA_SPOT, LA_SUN, LA_LOCAL)) {
+               lar->ray_totsamp= lar->ray_samp*lar->ray_samp;
+               lar->area_shape = LA_AREA_SQUARE;
+               lar->area_sizey= lar->area_size;
+       }
+       else if(lar->type==LA_AREA) {
+               switch(lar->area_shape) {
+               case LA_AREA_SQUARE:
+                       lar->ray_totsamp= lar->ray_samp*lar->ray_samp;
+                       lar->ray_sampy= lar->ray_samp;
+                       lar->area_sizey= lar->area_size;
+                       break;
+               case LA_AREA_RECT:
+                       lar->ray_totsamp= lar->ray_samp*lar->ray_sampy;
+                       break;
+               case LA_AREA_CUBE:
+                       lar->ray_totsamp= lar->ray_samp*lar->ray_samp*lar->ray_samp;
+                       lar->ray_sampy= lar->ray_samp;
+                       lar->ray_sampz= lar->ray_samp;
+                       lar->area_sizey= lar->area_size;
+                       lar->area_sizez= lar->area_size;
+                       break;
+               case LA_AREA_BOX:
+                       lar->ray_totsamp= lar->ray_samp*lar->ray_sampy*lar->ray_sampz;
+                       break;
                }
-               else if (dl->type==DL_SURF) {
-                       
-                       /* cyclic U means an extruded full circular curve, we skip bevel splitting then */
-                       if (dl->flag & DL_CYCL_U) {
-                               orco+= 3*dl_surf_to_renderdata(re, ob, dl, matar, orco, mat);
-                       }
-                       else {
-                               int p1,p2,p3,p4;
 
-                               fp= dl->verts;
-                               startvert= re->totvert;
-                               nr= dl->nr*dl->parts;
+               area_lamp_vectors(lar);
+               init_jitter_plane(lar); // subsamples
+       }
+       else lar->ray_totsamp= 0;
+       
+#ifndef DISABLE_YAFRAY
+       /* yafray: photonlight and other params */
+       if (re->r.renderer==R_YAFRAY) {
+               lar->YF_numphotons = la->YF_numphotons;
+               lar->YF_numsearch = la->YF_numsearch;
+               lar->YF_phdepth = la->YF_phdepth;
+               lar->YF_useqmc = la->YF_useqmc;
+               lar->YF_causticblur = la->YF_causticblur;
+               lar->YF_ltradius = la->YF_ltradius;
+               lar->YF_bufsize = la->YF_bufsize;
+               lar->YF_glowint = la->YF_glowint;
+               lar->YF_glowofs = la->YF_glowofs;
+               lar->YF_glowtype = la->YF_glowtype;
+       }
+#endif /* disable yafray */
 
-                               while(nr--) {
-                                       ver= RE_findOrAddVert(re, re->totvert++);
-                                               
-                                       VECCOPY(ver->co, fp);
-                                       MTC_Mat4MulVecfl(mat, ver->co);
-                                       fp+= 3;
+       lar->spotsi= la->spotsize;
+       if(lar->mode & LA_HALO) {
+               if(lar->spotsi>170.0) lar->spotsi= 170.0;
+       }
+       lar->spotsi= cos( M_PI*lar->spotsi/360.0 );
+       lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
 
-                                       if (orco) {
-                                               ver->orco = orco;
-                                               orco += 3;
-                                       }
-                               }
+       memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *));
 
-                               if(dl->bevelSplitFlag || only_verts==0) {
-                                       startvlak= re->totvlak;
+       lar->lay= ob->lay & 0xFFFFFF;   // higher 8 bits are localview layers
 
-                                       for(a=0; a<dl->parts; a++) {
+       lar->falloff_type = la->falloff_type;
+       lar->ld1= la->att1;
+       lar->ld2= la->att2;
+       lar->curfalloff = curvemapping_copy(la->curfalloff);
 
-                                               frontside= (a >= dl->nr/2);
+       if(lar->type==LA_SPOT) {
 
-                                               DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
-                                               p1+= startvert;
-                                               p2+= startvert;
-                                               p3+= startvert;
-                                               p4+= startvert;
+               Normalize(lar->imat[0]);
+               Normalize(lar->imat[1]);
+               Normalize(lar->imat[2]);
 
-                                               for(; b<dl->nr; b++) {
-                                                       vlr= RE_findOrAddVlak(re, re->totvlak++);
-                                                       vlr->ob= ob;
-                                                       vlr->v1= RE_findOrAddVert(re, p2);
-                                                       vlr->v2= RE_findOrAddVert(re, p1);
-                                                       vlr->v3= RE_findOrAddVert(re, p3);
-                                                       vlr->v4= RE_findOrAddVert(re, p4);
-                                                       vlr->ec= ME_V2V3+ME_V3V4;
-                                                       if(a==0) vlr->ec+= ME_V1V2;
+               xn= saacos(lar->spotsi);
+               xn= sin(xn)/cos(xn);
+               lar->spottexfac= 1.0/(xn);
 
-                                                       vlr->flag= dl->rt;
-                                                       vlr->lay= ob->lay;
+               if(lar->mode & LA_ONLYSHADOW) {
+                       if((lar->mode & (LA_SHAD_BUF|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW;
+               }
 
-                                                       /* this is not really scientific: the vertices
-                                                               * 2, 3 en 4 seem to give better vertexnormals than 1 2 3:
-                                                               * front and backside treated different!!
-                                                               */
+       }
 
-                                                       if(frontside)
-                                                               CalcNormFloat(vlr->v2->co, vlr->v3->co, vlr->v4->co, vlr->n);
-                                                       else 
-                                                               CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->n);
+       /* set flag for spothalo en initvars */
+       if(la->type==LA_SPOT && (la->mode & LA_HALO)) {
+               if(la->haint>0.0) {
+                       re->flag |= R_LAMPHALO;
 
-                                                       vlr->mat= matar[ dl->col ];
+                       /* camera position (0,0,0) rotate around lamp */
+                       lar->sh_invcampos[0]= -lar->co[0];
+                       lar->sh_invcampos[1]= -lar->co[1];
+                       lar->sh_invcampos[2]= -lar->co[2];
+                       MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
 
-                                                       p4= p3;
-                                                       p3++;
-                                                       p2= p1;
-                                                       p1++;
-                                               }
-                                       }
+                       /* z factor, for a normalized volume */
+                       angle= saacos(lar->spotsi);
+                       xn= lar->spotsi;
+                       yn= sin(angle);
+                       lar->sh_zfac= yn/xn;
+                       /* pre-scale */
+                       lar->sh_invcampos[2]*= lar->sh_zfac;
 
-                                       if (dl->bevelSplitFlag) {
-                                               for(a=0; a<dl->parts-1+!!(dl->flag&DL_CYCL_V); a++)
-                                                       if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F)))
-                                                               split_v_renderfaces(re, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U);
-                                       }
+               }
+       }
+       else if(la->type==LA_HEMI) {
+               lar->mode &= ~(LA_SHAD_RAY|LA_SHAD_BUF);
+       }
 
-                                       /* vertex normals */
-                                       for(a= startvlak; a<re->totvlak; a++) {
-                                               vlr= RE_findOrAddVlak(re, a);
+       for(c=0; c<MAX_MTEX; c++) {
+               if(la->mtex[c] && la->mtex[c]->tex) {
+                       lar->mode |= LA_TEXTURE;
 
-                                               VecAddf(vlr->v1->n, vlr->v1->n, vlr->n);
-                                               VecAddf(vlr->v3->n, vlr->v3->n, vlr->n);
-                                               VecAddf(vlr->v2->n, vlr->v2->n, vlr->n);
-                                               VecAddf(vlr->v4->n, vlr->v4->n, vlr->n);
-                                       }
-                                       for(a=startvert; a<re->totvert; a++) {
-                                               ver= RE_findOrAddVert(re, a);
-                                               len= Normalize(ver->n);
-                                               if(len==0.0) ver->flag= 1;      /* flag abuse, its only used in zbuf now  */
-                                               else ver->flag= 0;
-                                       }
-                                       for(a= startvlak; a<re->totvlak; a++) {
-                                               vlr= RE_findOrAddVlak(re, a);
-                                               if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n);
-                                               if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n);
-                                               if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n);
-                                               if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n);
-                                       }
+                       if(G.rendering) {
+                               if(re->osa) {
+                                       if(la->mtex[c]->tex->type==TEX_IMAGE) lar->mode |= LA_OSATEX;
                                }
                        }
                }
-
-               dl= dl->next;
        }
+       /* yafray: shadow flag should not be cleared, only used with internal renderer */
+       if (re->r.renderer==R_INTERN) {
+               /* to make sure we can check ray shadow easily in the render code */
+               if(lar->mode & LA_SHAD_RAY) {
+                       if( (re->r.mode & R_RAYTRACE)==0)
+                               lar->mode &= ~LA_SHAD_RAY;
+               }
        
-       /* not very elegant... but we want original displist in UI */
-       if(cu->resolu_ren) {
-               freedisplist(&cu->disp);
-               SWAP(ListBase, olddl, cu->disp);
-       }
-}
 
-/* prevent phong interpolation for giving ray shadow errors (terminator problem) */
-static void set_phong_threshold(Render *re, Object *ob, int startface, int numface, int startvert, int numvert )
-{
-//     VertRen *ver;
-       VlakRen *vlr;
-       float thresh= 0.0, dot;
-       int tot=0, i;
-       
-       /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger 
-          are taken into account. This threshold is meant to work on smooth geometry, not
-          for extreme cases (ton) */
-       
-       for(i=startface; i<startface+numface; i++) {
-               vlr= RE_findOrAddVlak(re, i);
-               if(vlr->flag & R_SMOOTH) {
-                       dot= INPR(vlr->n, vlr->v1->n);
-                       dot= ABS(dot);
-                       if(dot>0.9) {
-                               thresh+= dot; tot++;
+               if(re->r.mode & R_SHADOW) {
+                       
+                       if ((lar->mode & LA_SHAD_RAY) && (lar->ray_samp_method == LA_SAMP_HAMMERSLEY)) {
+                               init_lamp_hammersley(lar);
                        }
-                       dot= INPR(vlr->n, vlr->v2->n);
-                       dot= ABS(dot);
-                       if(dot>0.9) {
-                               thresh+= dot; tot++;
+                       if(la->type==LA_AREA && (lar->mode & LA_SHAD_RAY) && (lar->ray_samp_method == LA_SAMP_CONSTANT)) {
+                               init_jitter_plane(lar);
                        }
-
-                       dot= INPR(vlr->n, vlr->v3->n);
-                       dot= ABS(dot);
-                       if(dot>0.9) {
-                               thresh+= dot; tot++;
+                       else if (la->type==LA_SPOT && (lar->mode & LA_SHAD_BUF) ) {
+                               /* Per lamp, one shadow buffer is made. */
+                               lar->bufflag= la->bufflag;
+                               Mat4CpyMat4(mat, ob->obmat);
+                               initshadowbuf(re, lar, mat);    // mat is altered
                        }
-
-                       if(vlr->v4) {
-                               dot= INPR(vlr->n, vlr->v4->n);
-                               dot= ABS(dot);
-                               if(dot>0.9) {
-                                       thresh+= dot; tot++;
+                       
+                       
+                       /* this is the way used all over to check for shadow */
+                       if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
+                               LampShadowSubSample *lss;
+                               int a, b, tot= re->r.threads*re->r.osa;
+                               
+                               lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample");
+                               lss= lar->shadsamp[0].s;
+                               /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */
+                               for(a=0; a<tot; a++, lss++) {
+                                       for(b=0; b<4; b++) {
+                                               lss->samplenr= -1;      /* used to detect whether we store or read */
+                                               lss->shadfac[b]= 1.0f;
+                                       }
                                }
                        }
                }
        }
        
-       if(tot) {
-               thresh/= (float)tot;
-               ob->smoothresh= cos(0.5*M_PI-saacos(thresh));
-       }
+       return go;
 }
 
-/* par = pointer to duplicator parent, needed for object lookup table */
-/* index = when duplicater copies same object (particle), the counter */
-static void init_render_object(Render *re, Object *ob, Object *par, int index, int only_verts)
+/* layflag: allows material group to ignore layerflag */
+static void add_lightgroup(Render *re, Group *group, int exclusive)
 {
-       static double lasttime= 0.0;
-       double time;
-       float mat[4][4];
-       int startface, startvert, startstrand, allow_render=1;
+       GroupObject *go, *gol;
        
-       startface=re->totvlak;
-       startvert=re->totvert;
-       startstrand=re->totstrand;
-
-       ob->flag |= OB_DONE;
-
-       /* the emitter has to be processed first (render levels of modifiers) */
-       /* so here we only check if the emitter should be rendered */
-       if(ob->particlesystem.first) {
-               ParticleSystem *psys = ob->particlesystem.first;
-               int showe = 0;
-               for(; psys; psys=psys->next)
-                       showe += psys->part->draw & PART_DRAW_EMITTER;
-
-               /* if no psys has "show emitter" selected don't render emitter */
-               if(showe==0) allow_render = 0;
-       }
+       group->id.flag &= ~LIB_DOIT;
 
-       if(allow_render) {
-               if(ob->type==OB_LAMP)
-                       add_render_lamp(re, ob);
-               else if ELEM(ob->type, OB_FONT, OB_CURVE)
-                       init_render_curve(re, ob, only_verts);
-               else if(ob->type==OB_SURF)
-                       init_render_surf(re, ob);
-               else if(ob->type==OB_MESH)
-                       init_render_mesh(re, ob, par, only_verts);
-               else if(ob->type==OB_MBALL)
-                       init_render_mball(re, ob);
-               else {
-                       MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
-                       MTC_Mat4Invert(ob->imat, mat);
+       /* it's a bit too many loops in loops... but will survive */
+       /* note that 'exclusive' will remove it from the global list */
+       for(go= group->gobject.first; go; go= go->next) {
+               go->lampren= NULL;
+               
+               if(go->ob->lay & re->scene->lay) {
+                       if(go->ob && go->ob->type==OB_LAMP) {
+                               for(gol= re->lights.first; gol; gol= gol->next) {
+                                       if(gol->ob==go->ob) {
+                                               go->lampren= gol->lampren;
+                                               break;
+                                       }
+                               }
+                               if(go->lampren==NULL) 
+                                       gol= add_render_lamp(re, go->ob);
+                               if(gol && exclusive) {
+                                       BLI_remlink(&re->lights, gol);
+                                       MEM_freeN(gol);
+                               }
+                       }
                }
        }
+}
 
-       if(ob->particlesystem.first) {
-               ParticleSystem *psys = ob->particlesystem.first;
-               DerivedMesh *dm = 0;
-
-               /* the emitter mesh wasn't rendered so the modifier stack wasn't evaluated with render settings */
-               if(allow_render==0 && ob->type==OB_MESH)
-                       dm = mesh_create_derived_render(ob,     CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
-
-               for(; psys; psys=psys->next) {
-                       render_new_particle_system(re, ob, psys);
-                       psys_free_render_memory(ob, psys);
-               }
-
-               if(dm)
-                       dm->release(dm);
-       }
+static void set_material_lightgroups(Render *re)
+{
+       Group *group;
+       Material *ma;
        
-       /* generic post process here */
-       if(startvert!=re->totvert || startstrand!=re->totstrand)
-               RE_addRenderObject(re, ob, par, index, startvert, re->totvert, startface, re->totvlak, startstrand, re->totstrand);
-               
-       if(startvert!=re->totvert) {
-               /* the exception below is because displace code now is in init_render_mesh call, 
-               I will look at means to have autosmooth enabled for all object types 
-               and have it as general postprocess, like displace */
-               if (ob->type!=OB_MESH && test_for_displace(re, ob ) ) 
-                       do_displacement(re, ob, startface, re->totvlak-startface, startvert, re->totvert-startvert);
+       /* not for preview render */
+       if(re->scene->r.scemode & R_PREVIEWBUTS)
+               return;
        
-               /* phong normal interpolation can cause error in tracing (terminator prob) */
-               ob->smoothresh= 0.0;
-               if( (re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW) ) 
-                       set_phong_threshold(re, ob, startface, re->totvlak-startface, startvert, re->totvert-startvert);
-       }
+       for(group= G.main->group.first; group; group=group->id.next)
+               group->id.flag |= LIB_DOIT;
        
-       time= PIL_check_seconds_timer();
-       if(time - lasttime > 1.0) {
-               lasttime= time;
-               /* clumsy copying still */
-               re->i.totvert= re->totvert;
-               re->i.totface= re->totvlak;
-               re->i.totstrand= re->totstrand;
-               re->i.tothalo= re->tothalo;
-               re->i.totlamp= re->totlamp;
-               re->stats_draw(&re->i);
+       /* it's a bit too many loops in loops... but will survive */
+       /* hola! materials not in use...? */
+       for(ma= G.main->mat.first; ma; ma=ma->id.next) {
+               if(ma->group && (ma->group->id.flag & LIB_DOIT))
+                       add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY);
        }
 }
 
-void RE_Database_Free(Render *re)
+static void set_renderlayer_lightgroups(Render *re, Scene *sce)
 {
-       Object *ob = NULL;
-       LampRen *lar;
-
-       /* FREE */
-       
-       for(lar= re->lampren.first; lar; lar= lar->next) {
-               freeshadowbuf(lar);
-               if(lar->jitter) MEM_freeN(lar->jitter);
-               if(lar->shadsamp) MEM_freeN(lar->shadsamp);
-               if(lar->qsa) free_lamp_qmcsampler(lar);
-               curvemapping_free(lar->curfalloff);
-       }
-       
-       BLI_freelistN(&re->lampren);
-       BLI_freelistN(&re->lights);
-
-       free_renderdata_tables(re);
+       SceneRenderLayer *srl;
        
-       /* free orco. check all objects because of duplis and sets */
-       ob= G.main->object.first;
-       while(ob) {
-               if(ob->type==OB_MBALL) {
-                       if(ob->disp.first && ob->disp.first!=ob->disp.last) {
-                               DispList *dl= ob->disp.first;
-                               BLI_remlink(&ob->disp, dl);
-                               freedisplist(&ob->disp);
-                               BLI_addtail(&ob->disp, dl);
-                       }
-               }
-               ob= ob->id.next;
+       for(srl= sce->r.layers.first; srl; srl= srl->next) {
+               if(srl->light_override)
+                       add_lightgroup(re, srl->light_override, 0);
        }
+}
 
-       free_mesh_orco_hash(re);
+/* ------------------------------------------------------------------------- */
+/* World                                                                                                                                        */
+/* ------------------------------------------------------------------------- */
 
-       end_radio_render();
-       end_render_materials();
+void init_render_world(Render *re)
+{
+       int a;
+       char *cp;
        
-       if(re->wrld.aosphere) {
-               MEM_freeN(re->wrld.aosphere);
-               re->wrld.aosphere= NULL;
-               re->scene->world->aosphere= NULL;
+       if(re->scene && re->scene->world) {
+               re->wrld= *(re->scene->world);
+               
+               cp= (char *)&re->wrld.fastcol;
+               
+               cp[0]= 255.0*re->wrld.horr;
+               cp[1]= 255.0*re->wrld.horg;
+               cp[2]= 255.0*re->wrld.horb;
+               cp[3]= 1;
+               
+               VECCOPY(re->grvec, re->viewmat[2]);
+               Normalize(re->grvec);
+               Mat3CpyMat4(re->imat, re->viewinv);
+               
+               for(a=0; a<MAX_MTEX; a++) 
+                       if(re->wrld.mtex[a] && re->wrld.mtex[a]->tex) re->wrld.skytype |= WO_SKYTEX;
+               
+               /* AO samples should be OSA minimum */
+               if(re->osa)
+                       while(re->wrld.aosamp*re->wrld.aosamp < re->osa) 
+                               re->wrld.aosamp++;
+               if(!(re->r.mode & R_RAYTRACE))
+                       re->wrld.mode &= ~WO_AMB_OCC;
        }
-       if(re->wrld.aotables) {
-               MEM_freeN(re->wrld.aotables);
-               re->wrld.aotables= NULL;
-               re->scene->world->aotables= NULL;
+       else {
+               memset(&re->wrld, 0, sizeof(World));
+               re->wrld.exp= 0.0;
+               re->wrld.range= 1.0;
        }
-       if((re->r.mode & R_RAYTRACE) && (re->wrld.mode & WO_AMB_OCC) &&
-           (re->wrld.ao_samp_method == WO_AOSAMP_HAMMERSLEY) && (re->qsa))
-               free_render_qmcsampler(re);
        
-       if(re->r.mode & R_RAYTRACE) freeraytree(re);
+       re->wrld.linfac= 1.0 + pow((2.0*re->wrld.exp + 0.5), -10);
+       re->wrld.logfac= log( (re->wrld.linfac-1.0)/re->wrld.linfac )/re->wrld.range;
+}
 
-       free_sss(re);
+
+
+/* ------------------------------------------------------------------------- */
+/* Object Finalization                                                                                                          */
+/* ------------------------------------------------------------------------- */
+
+/* prevent phong interpolation for giving ray shadow errors (terminator problem) */
+static void set_phong_threshold(ObjectRen *obr)
+{
+//     VertRen *ver;
+       VlakRen *vlr;
+       float thresh= 0.0, dot;
+       int tot=0, i;
        
-       re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
-       re->i.convertdone= 0;
+       /* Added check for 'pointy' situations, only dotproducts of 0.9 and larger 
+          are taken into account. This threshold is meant to work on smooth geometry, not
+          for extreme cases (ton) */
        
-       if(re->scene)
-               if(re->scene->r.scemode & R_FREE_IMAGE)
-                       if((re->r.scemode & R_PREVIEWBUTS)==0)
-                               BKE_image_free_all_textures();
+       for(i=0; i<obr->totvlak; i++) {
+               vlr= RE_findOrAddVlak(obr, i);
+               if(vlr->flag & R_SMOOTH) {
+                       dot= INPR(vlr->n, vlr->v1->n);
+                       dot= ABS(dot);
+                       if(dot>0.9) {
+                               thresh+= dot; tot++;
+                       }
+                       dot= INPR(vlr->n, vlr->v2->n);
+                       dot= ABS(dot);
+                       if(dot>0.9) {
+                               thresh+= dot; tot++;
+                       }
 
-       if(re->memArena) {
-               BLI_memarena_free(re->memArena);
-               re->memArena = NULL;
+                       dot= INPR(vlr->n, vlr->v3->n);
+                       dot= ABS(dot);
+                       if(dot>0.9) {
+                               thresh+= dot; tot++;
+                       }
+
+                       if(vlr->v4) {
+                               dot= INPR(vlr->n, vlr->v4->n);
+                               dot= ABS(dot);
+                               if(dot>0.9) {
+                                       thresh+= dot; tot++;
+                               }
+                       }
+               }
+       }
+       
+       if(tot) {
+               thresh/= (float)tot;
+               obr->ob->smoothresh= cos(0.5*M_PI-saacos(thresh));
        }
 }
 
 /* per face check if all samples should be taken.
    if raytrace, do always for raytraced material, or when material full_osa set */
-static void set_fullsample_flag(Render *re)
+static void set_fullsample_flag(Render *re, ObjectRen *obr)
 {
        VlakRen *vlr;
        int a, trace;
@@ -3973,8 +3680,8 @@ static void set_fullsample_flag(Render *re)
        
        trace= re->r.mode & R_RAYTRACE;
        
-       for(a=re->totvlak-1; a>=0; a--) {
-               vlr= RE_findOrAddVlak(re, a);
+       for(a=obr->totvlak-1; a>=0; a--) {
+               vlr= RE_findOrAddVlak(obr, a);
                
                if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA;
                else if(trace) {
@@ -3988,15 +3695,15 @@ static void set_fullsample_flag(Render *re)
        }
 }
 
-static void check_non_flat_quads(Render *re)
+static void check_non_flat_quads(ObjectRen *obr)
 {
        VlakRen *vlr, *vlr1;
        VertRen *v1, *v2, *v3, *v4;
        float nor[3], xn, flen;
        int a;
 
-       for(a=re->totvlak-1; a>=0; a--) {
-               vlr= RE_findOrAddVlak(re, a);
+       for(a=obr->totvlak-1; a>=0; a--) {
+               vlr= RE_findOrAddVlak(obr, a);
                
                /* test if rendering as a quad or triangle, skip wire */
                if(vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->mode & MA_WIRE)==0) {
@@ -4052,7 +3759,7 @@ static void check_non_flat_quads(Render *re)
                                if(ABS(xn) < 0.999995 ) {       // checked on noisy fractal grid
                                        float d1, d2;
 
-                                       vlr1= RE_vlakren_copy(re, vlr);
+                                       vlr1= RE_vlakren_copy(obr, vlr);
                                        vlr1->flag |= R_FACE_SPLIT;
                                        
                                        /* split direction based on vnorms */
@@ -4095,112 +3802,362 @@ static void check_non_flat_quads(Render *re)
        }
 }
 
-/* layflag: allows material group to ignore layerflag */
-static void add_lightgroup(Render *re, Group *group, int exclusive)
+static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts)
 {
-       GroupObject *go, *gol;
+       Object *ob= obr->ob;
+
+       if(obr->totvert || obr->totvlak || obr->tothalo || obr->totstrand) {
+               /* the exception below is because displace code now is in init_render_mesh call, 
+               I will look at means to have autosmooth enabled for all object types 
+               and have it as general postprocess, like displace */
+               if(ob->type!=OB_MESH && test_for_displace(re, ob)) 
+                       do_displacement(re, obr);
        
-       group->id.flag &= ~LIB_DOIT;
+               if(!only_verts) {
+                       /* phong normal interpolation can cause error in tracing
+                        * (terminator problem) */
+                       ob->smoothresh= 0.0;
+                       if((re->r.mode & R_RAYTRACE) && (re->r.mode & R_SHADOW)) 
+