merge from trunk #37722
[blender-staging.git] / source / blender / render / intern / source / renderdatabase.c
index 1d490637222a168337f054afd1b2bccded7a3b4c..456162d2d30596dd5463a433f6792d07c72f7a15 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -15,7 +15,7 @@
  *
  * 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.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
 
+/** \file blender/render/intern/source/renderdatabase.c
+ *  \ingroup render
+ */
+
+
 /*
  * Storage, retrieval and query of render specific data.
  *
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
-#include "BKE_utildefines.h"
 
-#include "BLI_arithb.h"
+
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
 #include "BLI_memarena.h"
 
 #include "DNA_material_types.h" 
@@ -75,6 +82,7 @@
 
 #include "RE_render_ext.h"     /* externtex */
 
+#include "rayobject.h"
 #include "renderpipeline.h"
 #include "render_types.h"
 #include "renderdatabase.h"
 #define RE_MCOL_ELEMS          4
 #define RE_UV_ELEMS                    2
 #define RE_SURFNOR_ELEMS       3
+#define RE_RADFACE_ELEMS       1
+#define RE_SIMPLIFY_ELEMS      2
+#define RE_FACE_ELEMS          1
+#define RE_NMAP_TANGENT_ELEMS  16
 
-float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
 {
        float *sticky;
        int nr= ver->index>>8;
        
-       sticky= re->vertnodes[nr].sticky;
+       sticky= obr->vertnodes[nr].sticky;
        if(sticky==NULL) {
                if(verify) 
-                       sticky= re->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
+                       sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table");
                else
                        return NULL;
        }
        return sticky + (ver->index & 255)*RE_STICKY_ELEMS;
 }
 
-float *RE_vertren_get_stress(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify)
 {
        float *stress;
        int nr= ver->index>>8;
        
-       stress= re->vertnodes[nr].stress;
+       stress= obr->vertnodes[nr].stress;
        if(stress==NULL) {
                if(verify) 
-                       stress= re->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
+                       stress= obr->vertnodes[nr].stress= MEM_mallocN(256*RE_STRESS_ELEMS*sizeof(float), "stress table");
                else
                        return NULL;
        }
@@ -135,30 +147,30 @@ float *RE_vertren_get_stress(Render *re, VertRen *ver, int verify)
 }
 
 /* this one callocs! */
-float *RE_vertren_get_rad(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_rad(ObjectRen *obr, VertRen *ver, int verify)
 {
        float *rad;
        int nr= ver->index>>8;
        
-       rad= re->vertnodes[nr].rad;
+       rad= obr->vertnodes[nr].rad;
        if(rad==NULL) {
                if(verify) 
-                       rad= re->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
+                       rad= obr->vertnodes[nr].rad= MEM_callocN(256*RE_RAD_ELEMS*sizeof(float), "rad table");
                else
                        return NULL;
        }
        return rad + (ver->index & 255)*RE_RAD_ELEMS;
 }
 
-float *RE_vertren_get_strand(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_strand(ObjectRen *obr, VertRen *ver, int verify)
 {
        float *strand;
        int nr= ver->index>>8;
        
-       strand= re->vertnodes[nr].strand;
+       strand= obr->vertnodes[nr].strand;
        if(strand==NULL) {
                if(verify) 
-                       strand= re->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
+                       strand= obr->vertnodes[nr].strand= MEM_mallocN(256*RE_STRAND_ELEMS*sizeof(float), "strand table");
                else
                        return NULL;
        }
@@ -166,15 +178,15 @@ float *RE_vertren_get_strand(Render *re, VertRen *ver, int verify)
 }
 
 /* needs calloc */
-float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify)
+float *RE_vertren_get_tangent(ObjectRen *obr, VertRen *ver, int verify)
 {
        float *tangent;
        int nr= ver->index>>8;
        
-       tangent= re->vertnodes[nr].tangent;
+       tangent= obr->vertnodes[nr].tangent;
        if(tangent==NULL) {
                if(verify) 
-                       tangent= re->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
+                       tangent= obr->vertnodes[nr].tangent= MEM_callocN(256*RE_TANGENT_ELEMS*sizeof(float), "tangent table");
                else
                        return NULL;
        }
@@ -182,64 +194,62 @@ float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify)
 }
 
 /* needs calloc! not all renderverts have them */
-float *RE_vertren_get_winspeed(Render *re, VertRen *ver, int verify)
+/* also winspeed is exception, it is stored per instance */
+float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
 {
        float *winspeed;
-       int nr= ver->index>>8;
+       int totvector;
        
-       winspeed= re->vertnodes[nr].winspeed;
+       winspeed= obi->vectors;
        if(winspeed==NULL) {
-               if(verify) 
-                       winspeed= re->vertnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
+               if(verify) {
+                       totvector= obi->obr->totvert + obi->obr->totstrand;
+                       winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
+               }
                else
                        return NULL;
        }
-       return winspeed + (ver->index & 255)*RE_WINSPEED_ELEMS;
+       return winspeed + ver->index*RE_WINSPEED_ELEMS;
 }
 
-VertRen *RE_vertren_copy(Render *re, VertRen *ver)
+VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
 {
-       VertRen *v1= RE_findOrAddVert(re, re->totvert++);
+       VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
        float *fp1, *fp2;
        int index= v1->index;
        
        *v1= *ver;
        v1->index= index;
        
-       fp1= RE_vertren_get_sticky(re, ver, 0);
+       fp1= RE_vertren_get_sticky(obr, ver, 0);
        if(fp1) {
-               fp2= RE_vertren_get_sticky(re, v1, 1);
+               fp2= RE_vertren_get_sticky(obr, v1, 1);
                memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float));
        }
-       fp1= RE_vertren_get_stress(re, ver, 0);
+       fp1= RE_vertren_get_stress(obr, ver, 0);
        if(fp1) {
-               fp2= RE_vertren_get_stress(re, v1, 1);
+               fp2= RE_vertren_get_stress(obr, v1, 1);
                memcpy(fp2, fp1, RE_STRESS_ELEMS*sizeof(float));
        }
-       fp1= RE_vertren_get_rad(re, ver, 0);
+       fp1= RE_vertren_get_rad(obr, ver, 0);
        if(fp1) {
-               fp2= RE_vertren_get_rad(re, v1, 1);
+               fp2= RE_vertren_get_rad(obr, v1, 1);
                memcpy(fp2, fp1, RE_RAD_ELEMS*sizeof(float));
        }
-       fp1= RE_vertren_get_strand(re, ver, 0);
+       fp1= RE_vertren_get_strand(obr, ver, 0);
        if(fp1) {
-               fp2= RE_vertren_get_strand(re, v1, 1);
+               fp2= RE_vertren_get_strand(obr, v1, 1);
                memcpy(fp2, fp1, RE_STRAND_ELEMS*sizeof(float));
        }
-       fp1= RE_vertren_get_tangent(re, ver, 0);
+       fp1= RE_vertren_get_tangent(obr, ver, 0);
        if(fp1) {
-               fp2= RE_vertren_get_tangent(re, v1, 1);
+               fp2= RE_vertren_get_tangent(obr, v1, 1);
                memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
        }
-       fp1= RE_vertren_get_winspeed(re, ver, 0);
-       if(fp1) {
-               fp2= RE_vertren_get_winspeed(re, v1, 1);
-               memcpy(fp2, fp1, RE_WINSPEED_ELEMS*sizeof(float));
-       }
        return v1;
 }
 
-VertRen *RE_findOrAddVert(Render *re, int nr)
+VertRen *RE_findOrAddVert(ObjectRen *obr, int nr)
 {
        VertTableNode *temp;
        VertRen *v;
@@ -251,23 +261,23 @@ VertRen *RE_findOrAddVert(Render *re, int nr)
        }
        a= nr>>8;
        
-       if (a>=re->vertnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
-               temp= re->vertnodes;
+       if (a>=obr->vertnodeslen-1) {  /* Need to allocate more columns..., and keep last element NULL for free loop */
+               temp= obr->vertnodes;
                
-               re->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(re->vertnodeslen+TABLEINITSIZE) , "vertnodes");
-               if(temp) memcpy(re->vertnodes, temp, re->vertnodeslen*sizeof(VertTableNode));
-               memset(re->vertnodes+re->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
+               obr->vertnodes= MEM_mallocN(sizeof(VertTableNode)*(obr->vertnodeslen+TABLEINITSIZE) , "vertnodes");
+               if(temp) memcpy(obr->vertnodes, temp, obr->vertnodeslen*sizeof(VertTableNode));
+               memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode));
                
-               re->vertnodeslen+=TABLEINITSIZE; 
+               obr->vertnodeslen+=TABLEINITSIZE; 
                if(temp) MEM_freeN(temp);       
        }
        
-       v= re->vertnodes[a].vert;
+       v= obr->vertnodes[a].vert;
        if(v==NULL) {
                int i;
                
                v= (VertRen *)MEM_callocN(256*sizeof(VertRen),"findOrAddVert");
-               re->vertnodes[a].vert= v;
+               obr->vertnodes[a].vert= v;
                
                for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++) {
                        v[a].index= i;
@@ -279,193 +289,211 @@ VertRen *RE_findOrAddVert(Render *re, int nr)
 
 /* ------------------------------------------------------------------------ */
 
-MTFace *RE_vlakren_get_tface(Render *re, VlakRen *vlr, int n, char **name, int verify)
+MTFace *RE_vlakren_get_tface(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
 {
        VlakTableNode *node;
        int nr= vlr->index>>8, vlakindex= (vlr->index&255);
        int index= (n<<8) + vlakindex;
 
-       node= &re->vlaknodes[nr];
+       node= &obr->vlaknodes[nr];
 
        if(verify) {
                if(n>=node->totmtface) {
-                       MTFace **mtface= node->mtface;
-                       int size= size= (n+1)*256;
+                       MTFace *mtface= node->mtface;
+                       int size= (n+1)*256;
 
-                       node->mtface= MEM_callocN(size*sizeof(MTFace*), "Vlak mtface");
+                       node->mtface= MEM_callocN(size*sizeof(MTFace), "Vlak mtface");
 
                        if(mtface) {
                                size= node->totmtface*256;
-                               memcpy(node->mtface, mtface, size*sizeof(MTFace*));
+                               memcpy(node->mtface, mtface, size*sizeof(MTFace));
                                MEM_freeN(mtface);
                        }
 
                        node->totmtface= n+1;
-
-                       if (!node->names) {
-                               size= sizeof(*node->names)*256;
-                               node->names= MEM_callocN(size, "Vlak names");
-                       }
-               }
-
-               if(node->mtface[index]==NULL) {
-                       node->mtface[index]= BLI_memarena_alloc(re->memArena,
-                               sizeof(MTFace)*RE_MTFACE_ELEMS);
-
-                       node->names[vlakindex]= re->customdata_names.last;
                }
        }
        else {
-               if(n>=node->totmtface || node->mtface[index]==NULL)
+               if(n>=node->totmtface)
                        return NULL;
 
-               if(name) *name= node->names[vlakindex]->mtface[n];
+               if(name) *name= obr->mtface[n];
        }
 
-       return node->mtface[index];
+       return node->mtface + index;
 }
 
-MCol *RE_vlakren_get_mcol(Render *re, VlakRen *vlr, int n, char **name, int verify)
+MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int verify)
 {
        VlakTableNode *node;
        int nr= vlr->index>>8, vlakindex= (vlr->index&255);
        int index= (n<<8) + vlakindex;
 
-       node= &re->vlaknodes[nr];
+       node= &obr->vlaknodes[nr];
 
        if(verify) {
                if(n>=node->totmcol) {
-                       MCol **mcol= node->mcol;
+                       MCol *mcol= node->mcol;
                        int size= (n+1)*256;
 
-                       node->mcol= MEM_callocN(size*sizeof(MCol*), "Vlak mcol");
+                       node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "Vlak mcol");
 
                        if(mcol) {
                                size= node->totmcol*256;
-                               memcpy(node->mcol, mcol, size*sizeof(MCol*));
+                               memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
                                MEM_freeN(mcol);
                        }
 
                        node->totmcol= n+1;
-
-                       if (!node->names) {
-                               size= sizeof(*node->names)*256;
-                               node->names= MEM_callocN(size, "Vlak names");
-                       }
-               }
-
-               if(node->mcol[index]==NULL) {
-                       node->mcol[index]= BLI_memarena_alloc(re->memArena,
-                               sizeof(MCol)*RE_MCOL_ELEMS);
-
-                       node->names[vlakindex]= re->customdata_names.last;
                }
        }
        else {
-               if(n>=node->totmcol || node->mcol[index]==NULL)
+               if(n>=node->totmcol)
                        return NULL;
 
-               if(name) *name= node->names[vlakindex]->mcol[n];
+               if(name) *name= obr->mcol[n];
        }
 
-       return node->mcol[index];
+       return node->mcol + index*RE_MCOL_ELEMS;
 }
 
-float *RE_vlakren_get_surfnor(Render *re, VlakRen *vlak, int verify)
+float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
 {
        float *surfnor;
        int nr= vlak->index>>8;
        
-       surfnor= re->vlaknodes[nr].surfnor;
+       surfnor= obr->vlaknodes[nr].surfnor;
        if(surfnor==NULL) {
                if(verify) 
-                       surfnor= re->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
+                       surfnor= obr->vlaknodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
                else
                        return NULL;
        }
        return surfnor + (vlak->index & 255)*RE_SURFNOR_ELEMS;
 }
 
-VlakRen *RE_vlakren_copy(Render *re, VlakRen *vlr)
+float *RE_vlakren_get_nmap_tangent(ObjectRen *obr, VlakRen *vlak, int verify)
 {
-       VlakRen *vlr1 = RE_findOrAddVlak(re, re->totvlak++);
+       float *tangent;
+       int nr= vlak->index>>8;
+
+       tangent= obr->vlaknodes[nr].tangent;
+       if(tangent==NULL) {
+               if(verify) 
+                       tangent= obr->vlaknodes[nr].tangent= MEM_callocN(256*RE_NMAP_TANGENT_ELEMS*sizeof(float), "tangent table");
+               else
+                       return NULL;
+       }
+       return tangent + (vlak->index & 255)*RE_NMAP_TANGENT_ELEMS;
+}
+
+RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
+{
+       RadFace **radface;
+       int nr= vlak->index>>8;
+       
+       radface= obr->vlaknodes[nr].radface;
+       if(radface==NULL) {
+               if(verify) 
+                       radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
+               else
+                       return NULL;
+       }
+       return radface + (vlak->index & 255)*RE_RADFACE_ELEMS;
+}
+
+VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
+{
+       VlakRen *vlr1 = RE_findOrAddVlak(obr, obr->totvlak++);
        MTFace *mtface, *mtface1;
        MCol *mcol, *mcol1;
-       VlakTableNode *node = &re->vlaknodes[vlr->index>>8];
-       VlakTableNode *node1 = &re->vlaknodes[vlr1->index>>8];
-       float *surfnor, *surfnor1;
+       float *surfnor, *surfnor1, *tangent, *tangent1;
+       RadFace **radface, **radface1;
        int i, index = vlr1->index;
        char *name;
 
        *vlr1= *vlr;
        vlr1->index= index;
 
-       for (i=0; (mtface=RE_vlakren_get_tface(re, vlr, i, &name, 0)) != NULL; i++) {
-               mtface1= RE_vlakren_get_tface(re, vlr1, i, &name, 1);
+       for (i=0; (mtface=RE_vlakren_get_tface(obr, vlr, i, &name, 0)) != NULL; i++) {
+               mtface1= RE_vlakren_get_tface(obr, vlr1, i, &name, 1);
                memcpy(mtface1, mtface, sizeof(MTFace)*RE_MTFACE_ELEMS);
        }
 
-       for (i=0; (mcol=RE_vlakren_get_mcol(re, vlr, i, &name, 0)) != NULL; i++) {
-               mcol1= RE_vlakren_get_mcol(re, vlr1, i, &name, 1);
+       for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)) != NULL; i++) {
+               mcol1= RE_vlakren_get_mcol(obr, vlr1, i, &name, 1);
                memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
        }
 
-       surfnor= RE_vlakren_get_surfnor(re, vlr, 0);
+       surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
        if(surfnor) {
-               surfnor1= RE_vlakren_get_surfnor(re, vlr1, 1);
+               surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
                VECCOPY(surfnor1, surfnor);
        }
 
-       if (node->names && node1->names)
-               node1->names[vlr1->index&255] = node->names[vlr->index&255];
+       tangent= RE_vlakren_get_nmap_tangent(obr, vlr, 0);
+       if(tangent) {
+               tangent1= RE_vlakren_get_nmap_tangent(obr, vlr1, 1);
+               memcpy(tangent1, tangent, sizeof(float)*RE_NMAP_TANGENT_ELEMS);
+       }
+
+       radface= RE_vlakren_get_radface(obr, vlr, 0);
+       if(radface) {
+               radface1= RE_vlakren_get_radface(obr, vlr1, 1);
+               *radface1= *radface;
+       }
 
        return vlr1;
 }
 
-static int vlakren_remap_layer_num(int n, int active)
+void RE_vlakren_get_normal(Render *UNUSED(re), ObjectInstanceRen *obi, VlakRen *vlr, float *nor)
 {
-       /* make the active layer the first */
-       if (n == active) return 0;
-       else if (n < active) return n+1;
-       else return n;
+       float (*nmat)[3]= obi->nmat;
+
+       if(obi->flag & R_TRANSFORMED) {
+               VECCOPY(nor, vlr->n);
+               
+               mul_m3_v3(nmat, nor);
+               normalize_v3(nor);
+       }
+       else
+               VECCOPY(nor, vlr->n);
 }
 
-void RE_vlakren_set_customdata_names(Render *re, CustomData *data)
+void RE_set_customdata_names(ObjectRen *obr, CustomData *data)
 {
        /* CustomData layer names are stored per object here, because the
           DerivedMesh which stores the layers is freed */
        
-       CustomDataNames *cdn= MEM_callocN(sizeof(*cdn), "CustomDataNames");
        CustomDataLayer *layer;
-       int numlayers, i, mtfn, mcn, n;
-
-       BLI_addtail(&re->customdata_names, cdn);
+       int numtf = 0, numcol = 0, i, mtfn, mcn;
 
        if (CustomData_has_layer(data, CD_MTFACE)) {
-               numlayers= CustomData_number_of_layers(data, CD_MTFACE);
-               cdn->mtface= MEM_callocN(sizeof(*cdn->mtface)*numlayers, "mtfacenames");
+               numtf= CustomData_number_of_layers(data, CD_MTFACE);
+               obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames");
        }
 
        if (CustomData_has_layer(data, CD_MCOL)) {
-               numlayers= CustomData_number_of_layers(data, CD_MCOL);
-               cdn->mcol= MEM_callocN(sizeof(*cdn->mcol)*numlayers, "mcolnames");
+               numcol= CustomData_number_of_layers(data, CD_MCOL);
+               obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames");
        }
 
        for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) {
                layer= &data->layers[i];
 
                if (layer->type == CD_MTFACE) {
-                       n= vlakren_remap_layer_num(mtfn++, layer->active_rnd);
-                       strcpy(cdn->mtface[n], layer->name);
+                       strcpy(obr->mtface[mtfn++], layer->name);
+                       obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf);
+                       obr->bakemtface= layer->active;
                }
                else if (layer->type == CD_MCOL) {
-                       n= vlakren_remap_layer_num(mcn++, layer->active_rnd);
-                       strcpy(cdn->mcol[n], layer->name);
+                       strcpy(obr->mcol[mcn++], layer->name);
+                       obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol);
                }
        }
 }
 
-VlakRen *RE_findOrAddVlak(Render *re, int nr)
+VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr)
 {
        VlakTableNode *temp;
        VlakRen *v;
@@ -473,28 +501,28 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr)
 
        if(nr<0) {
                printf("error in findOrAddVlak: %d\n",nr);
-               return re->vlaknodes[0].vlak;
+               return obr->vlaknodes[0].vlak;
        }
        a= nr>>8;
        
-       if (a>=re->vlaknodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
-               temp= re->vlaknodes;
+       if (a>=obr->vlaknodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
+               temp= obr->vlaknodes;
                
-               re->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(re->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
-               if(temp) memcpy(re->vlaknodes, temp, re->vlaknodeslen*sizeof(VlakTableNode));
-               memset(re->vlaknodes+re->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
+               obr->vlaknodes= MEM_mallocN(sizeof(VlakTableNode)*(obr->vlaknodeslen+TABLEINITSIZE) , "vlaknodes");
+               if(temp) memcpy(obr->vlaknodes, temp, obr->vlaknodeslen*sizeof(VlakTableNode));
+               memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode));
 
-               re->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
+               obr->vlaknodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
                if(temp) MEM_freeN(temp);       
        }
 
-       v= re->vlaknodes[a].vlak;
+       v= obr->vlaknodes[a].vlak;
        
        if(v==NULL) {
                int i;
 
                v= (VlakRen *)MEM_callocN(256*sizeof(VlakRen),"findOrAddVlak");
-               re->vlaknodes[a].vlak= v;
+               obr->vlaknodes[a].vlak= v;
 
                for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
                        v[a].index= i;
@@ -505,129 +533,138 @@ VlakRen *RE_findOrAddVlak(Render *re, int nr)
 
 /* ------------------------------------------------------------------------ */
 
-float *RE_strandren_get_winspeed(Render *re, StrandRen *strand, int verify)
-{
-       float *winspeed;
-       int nr= strand->index>>8;
-       
-       winspeed= re->strandnodes[nr].winspeed;
-       if(winspeed==NULL) {
-               if(verify) 
-                       winspeed= re->strandnodes[nr].winspeed= MEM_callocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table");
-               else
-                       return NULL;
-       }
-       return winspeed + (strand->index & 255)*RE_WINSPEED_ELEMS;
-}
-
-float *RE_strandren_get_surfnor(Render *re, StrandRen *strand, int verify)
+float *RE_strandren_get_surfnor(ObjectRen *obr, StrandRen *strand, int verify)
 {
        float *surfnor;
        int nr= strand->index>>8;
        
-       surfnor= re->strandnodes[nr].surfnor;
+       surfnor= obr->strandnodes[nr].surfnor;
        if(surfnor==NULL) {
                if(verify) 
-                       surfnor= re->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor table");
+                       surfnor= obr->strandnodes[nr].surfnor= MEM_callocN(256*RE_SURFNOR_ELEMS*sizeof(float), "surfnor strand table");
                else
                        return NULL;
        }
        return surfnor + (strand->index & 255)*RE_SURFNOR_ELEMS;
 }
 
-float *RE_strandren_get_uv(Render *re, StrandRen *strand, int n, char **name, int verify)
+float *RE_strandren_get_uv(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
 {
        StrandTableNode *node;
        int nr= strand->index>>8, strandindex= (strand->index&255);
        int index= (n<<8) + strandindex;
 
-       node= &re->strandnodes[nr];
+       node= &obr->strandnodes[nr];
 
        if(verify) {
                if(n>=node->totuv) {
-                       float **uv= node->uv;
+                       float *uv= node->uv;
                        int size= (n+1)*256;
 
-                       node->uv= MEM_callocN(size*sizeof(float*), "Strand uv");
+                       node->uv= MEM_callocN(size*sizeof(float)*RE_UV_ELEMS, "strand uv table");
 
                        if(uv) {
                                size= node->totuv*256;
-                               memcpy(node->uv, uv, size*sizeof(float*));
+                               memcpy(node->uv, uv, size*sizeof(float)*RE_UV_ELEMS);
                                MEM_freeN(uv);
                        }
 
                        node->totuv= n+1;
-
-                       if (!node->names) {
-                               size= sizeof(*node->names)*256;
-                               node->names= MEM_callocN(size, "Strand names");
-                       }
-               }
-
-               if(node->uv[index]==NULL) {
-                       node->uv[index]= BLI_memarena_alloc(re->memArena,
-                               sizeof(float)*RE_UV_ELEMS);
-
-                       node->names[strandindex]= re->customdata_names.last;
                }
        }
        else {
-               if(n>=node->totuv || node->uv[index]==NULL)
+               if(n>=node->totuv)
                        return NULL;
 
-               if(name) *name= node->names[strandindex]->mtface[n];
+               if(name) *name= obr->mtface[n];
        }
 
-       return node->uv[index];
+       return node->uv + index*RE_UV_ELEMS;
 }
 
-MCol *RE_strandren_get_mcol(Render *re, StrandRen *strand, int n, char **name, int verify)
+MCol *RE_strandren_get_mcol(ObjectRen *obr, StrandRen *strand, int n, char **name, int verify)
 {
        StrandTableNode *node;
        int nr= strand->index>>8, strandindex= (strand->index&255);
        int index= (n<<8) + strandindex;
 
-       node= &re->strandnodes[nr];
+       node= &obr->strandnodes[nr];
 
        if(verify) {
                if(n>=node->totmcol) {
-                       MCol **mcol= node->mcol;
+                       MCol *mcol= node->mcol;
                        int size= (n+1)*256;
 
-                       node->mcol= MEM_callocN(size*sizeof(MCol*), "Strand mcol");
+                       node->mcol= MEM_callocN(size*sizeof(MCol)*RE_MCOL_ELEMS, "strand mcol table");
 
                        if(mcol) {
                                size= node->totmcol*256;
-                               memcpy(node->mcol, mcol, size*sizeof(MCol*));
+                               memcpy(node->mcol, mcol, size*sizeof(MCol)*RE_MCOL_ELEMS);
                                MEM_freeN(mcol);
                        }
 
                        node->totmcol= n+1;
-
-                       if (!node->names) {
-                               size= sizeof(*node->names)*256;
-                               node->names= MEM_callocN(size, "Strand names");
-                       }
-               }
-
-               if(node->mcol[index]==NULL) {
-                       node->mcol[index]= BLI_memarena_alloc(re->memArena,
-                               sizeof(MCol)*RE_MCOL_ELEMS);
-
-                       node->names[strandindex]= re->customdata_names.last;
                }
        }
        else {
-               if(n>=node->totmcol || node->mcol[index]==NULL)
+               if(n>=node->totmcol)
                        return NULL;
 
-               if(name) *name= node->names[strandindex]->mcol[n];
+               if(name) *name= obr->mcol[n];
        }
 
-       return node->mcol[index];
+       return node->mcol + index*RE_MCOL_ELEMS;
 }
 
-StrandRen *RE_findOrAddStrand(Render *re, int nr)
+float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify)
+{
+       float *simplify;
+       int nr= strand->index>>8;
+       
+       simplify= obr->strandnodes[nr].simplify;
+       if(simplify==NULL) {
+               if(verify) 
+                       simplify= obr->strandnodes[nr].simplify= MEM_callocN(256*RE_SIMPLIFY_ELEMS*sizeof(float), "simplify strand table");
+               else
+                       return NULL;
+       }
+       return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS;
+}
+
+int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify)
+{
+       int *face;
+       int nr= strand->index>>8;
+       
+       face= obr->strandnodes[nr].face;
+       if(face==NULL) {
+               if(verify) 
+                       face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face strand table");
+               else
+                       return NULL;
+       }
+       return face + (strand->index & 255)*RE_FACE_ELEMS;
+}
+
+/* winspeed is exception, it is stored per instance */
+float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify)
+{
+       float *winspeed;
+       int totvector;
+       
+       winspeed= obi->vectors;
+       if(winspeed==NULL) {
+               if(verify) {
+                       totvector= obi->obr->totvert + obi->obr->totstrand;
+                       winspeed= obi->vectors= MEM_callocN(totvector*RE_WINSPEED_ELEMS*sizeof(float), "winspeed strand table");
+               }
+               else
+                       return NULL;
+       }
+       return winspeed + (obi->obr->totvert + strand->index)*RE_WINSPEED_ELEMS;
+}
+
+StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr)
 {
        StrandTableNode *temp;
        StrandRen *v;
@@ -635,28 +672,28 @@ StrandRen *RE_findOrAddStrand(Render *re, int nr)
 
        if(nr<0) {
                printf("error in findOrAddStrand: %d\n",nr);
-               return re->strandnodes[0].strand;
+               return obr->strandnodes[0].strand;
        }
        a= nr>>8;
        
-       if (a>=re->strandnodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
-               temp= re->strandnodes;
+       if (a>=obr->strandnodeslen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
+               temp= obr->strandnodes;
                
-               re->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(re->strandnodeslen+TABLEINITSIZE) , "strandnodes");
-               if(temp) memcpy(re->strandnodes, temp, re->strandnodeslen*sizeof(StrandTableNode));
-               memset(re->strandnodes+re->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
+               obr->strandnodes= MEM_mallocN(sizeof(StrandTableNode)*(obr->strandnodeslen+TABLEINITSIZE) , "strandnodes");
+               if(temp) memcpy(obr->strandnodes, temp, obr->strandnodeslen*sizeof(StrandTableNode));
+               memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode));
 
-               re->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
+               obr->strandnodeslen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
                if(temp) MEM_freeN(temp);       
        }
 
-       v= re->strandnodes[a].strand;
+       v= obr->strandnodes[a].strand;
        
        if(v==NULL) {
                int i;
 
                v= (StrandRen *)MEM_callocN(256*sizeof(StrandRen),"findOrAddStrand");
-               re->strandnodes[a].strand= v;
+               obr->strandnodes[a].strand= v;
 
                for(i= (nr & 0xFFFFFF00), a=0; a<256; a++, i++)
                        v[a].index= i;
@@ -665,36 +702,34 @@ StrandRen *RE_findOrAddStrand(Render *re, int nr)
        return v;
 }
 
-StrandBuffer *RE_addStrandBuffer(Render *re, Object *ob, int totvert)
+StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
 {
        StrandBuffer *strandbuf;
 
        strandbuf= MEM_callocN(sizeof(StrandBuffer), "StrandBuffer");
        strandbuf->vert= MEM_callocN(sizeof(StrandVert)*totvert, "StrandVert");
        strandbuf->totvert= totvert;
-       strandbuf->ob= ob;
+       strandbuf->obr= obr;
 
-       BLI_addtail(&re->strandbufs, strandbuf);
+       obr->strandbuf= strandbuf;
 
        return strandbuf;
 }
 
 /* ------------------------------------------------------------------------ */
 
-void RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int sve, int eve, int sfa, int efa, int sst, int est)
+ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, int psysindex, int lay)
 {
-       ObjectRen *obr= MEM_mallocN(sizeof(ObjectRen), "object render struct");
+       ObjectRen *obr= MEM_callocN(sizeof(ObjectRen), "object render struct");
        
        BLI_addtail(&re->objecttable, obr);
        obr->ob= ob;
        obr->par= par;
        obr->index= index;
-       obr->startvert= sve;
-       obr->endvert= eve;
-       obr->startface= sfa;
-       obr->endface= efa;
-       obr->startstrand= sst;
-       obr->endstrand= est;
+       obr->psysindex= psysindex;
+       obr->lay= lay;
+
+       return obr;
 }
 
 void free_renderdata_vertnodes(VertTableNode *vertnodes)
@@ -738,14 +773,16 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
                        MEM_freeN(vlaknodes[a].mcol);
                if(vlaknodes[a].surfnor)
                        MEM_freeN(vlaknodes[a].surfnor);
-               if(vlaknodes[a].names)
-                       MEM_freeN(vlaknodes[a].names);
+               if(vlaknodes[a].tangent)
+                       MEM_freeN(vlaknodes[a].tangent);
+               if(vlaknodes[a].radface)
+                       MEM_freeN(vlaknodes[a].radface);
        }
        
        MEM_freeN(vlaknodes);
 }
 
-void free_renderdata_strandnodes(StrandTableNode *strandnodes)
+static void free_renderdata_strandnodes(StrandTableNode *strandnodes)
 {
        int a;
        
@@ -762,8 +799,10 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes)
                        MEM_freeN(strandnodes[a].winspeed);
                if(strandnodes[a].surfnor)
                        MEM_freeN(strandnodes[a].surfnor);
-               if(strandnodes[a].names)
-                       MEM_freeN(strandnodes[a].names);
+               if(strandnodes[a].simplify)
+                       MEM_freeN(strandnodes[a].simplify);
+               if(strandnodes[a].face)
+                       MEM_freeN(strandnodes[a].face);
        }
        
        MEM_freeN(strandnodes);
@@ -771,61 +810,98 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes)
 
 void free_renderdata_tables(Render *re)
 {
+       ObjectInstanceRen *obi;
+       ObjectRen *obr;
        StrandBuffer *strandbuf;
-       CustomDataNames *cdn;
        int a=0;
        
-       if(re->bloha) {
-               for(a=0; re->bloha[a]; a++)
-                       MEM_freeN(re->bloha[a]);
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               if(obr->vertnodes) {
+                       free_renderdata_vertnodes(obr->vertnodes);
+                       obr->vertnodes= NULL;
+                       obr->vertnodeslen= 0;
+               }
 
-               MEM_freeN(re->bloha);
-               re->bloha= NULL;
-               re->blohalen= 0;
-       }
+               if(obr->vlaknodes) {
+                       free_renderdata_vlaknodes(obr->vlaknodes);
+                       obr->vlaknodes= NULL;
+                       obr->vlaknodeslen= 0;
+                       obr->totvlak= 0;
+               }
 
-       if(re->vertnodes) {
-               free_renderdata_vertnodes(re->vertnodes);
-               re->vertnodes= NULL;
-               re->vertnodeslen= 0;
-       }
+               if(obr->bloha) {
+                       for(a=0; obr->bloha[a]; a++)
+                               MEM_freeN(obr->bloha[a]);
 
-       if(re->vlaknodes) {
-               free_renderdata_vlaknodes(re->vlaknodes);
-               re->vlaknodes= NULL;
-               re->vlaknodeslen= 0;
-       }
+                       MEM_freeN(obr->bloha);
+                       obr->bloha= NULL;
+                       obr->blohalen= 0;
+               }
 
-       if(re->strandnodes) {
-               free_renderdata_strandnodes(re->strandnodes);
-               re->strandnodes= NULL;
-               re->strandnodeslen= 0;
-       }
+               if(obr->strandnodes) {
+                       free_renderdata_strandnodes(obr->strandnodes);
+                       obr->strandnodes= NULL;
+                       obr->strandnodeslen= 0;
+               }
+
+               strandbuf= obr->strandbuf;
+               if(strandbuf) {
+                       if(strandbuf->vert) MEM_freeN(strandbuf->vert);
+                       if(strandbuf->bound) MEM_freeN(strandbuf->bound);
+                       MEM_freeN(strandbuf);
+               }
 
-       if(re->strandbuckets) {
-               free_buckets(re->strandbuckets);
-               re->strandbuckets= NULL;
+               if(obr->mtface)
+                       MEM_freeN(obr->mtface);
+               if(obr->mcol)
+                       MEM_freeN(obr->mcol);
+                       
+               if(obr->rayfaces)
+               {
+                       MEM_freeN(obr->rayfaces);
+                       obr->rayfaces = NULL;
+               }
+               if(obr->rayprimitives)
+               {
+                       MEM_freeN(obr->rayprimitives);
+                       obr->rayprimitives = NULL;
+               }
+               if(obr->raytree)
+               {
+                       RE_rayobject_free(obr->raytree);
+                       obr->raytree = NULL;
+               }
        }
 
-       for(cdn=re->customdata_names.first; cdn; cdn=cdn->next) {
-               if(cdn->mtface)
-                       MEM_freeN(cdn->mtface);
-               if(cdn->mcol)
-                       MEM_freeN(cdn->mcol);
+       if(re->objectinstance) {
+               for(obi=re->instancetable.first; obi; obi=obi->next)
+               {
+                       if(obi->vectors)
+                               MEM_freeN(obi->vectors);
+
+                       if(obi->raytree)
+                               RE_rayobject_free(obi->raytree);
+               }
+
+               MEM_freeN(re->objectinstance);
+               re->objectinstance= NULL;
+               re->totinstance= 0;
+               re->instancetable.first= re->instancetable.last= NULL;
        }
 
-       for(strandbuf=re->strandbufs.first; strandbuf; strandbuf=strandbuf->next)
-               if(strandbuf->vert) MEM_freeN(strandbuf->vert);
-       BLI_freelistN(&re->strandbufs);
+       if(re->sortedhalos) {
+               MEM_freeN(re->sortedhalos);
+               re->sortedhalos= NULL;
+       }
 
        BLI_freelistN(&re->customdata_names);
        BLI_freelistN(&re->objecttable);
+       BLI_freelistN(&re->instancetable);
 }
 
-
 /* ------------------------------------------------------------------------ */
 
-HaloRen *RE_findOrAddHalo(Render *re, int nr)
+HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
 {
        HaloRen *h, **temp;
        int a;
@@ -836,22 +912,22 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr)
        }
        a= nr>>8;
        
-       if (a>=re->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
+       if (a>=obr->blohalen-1){  /* Need to allocate more columns..., and keep last element NULL for free loop */
                //printf("Allocating %i more halo groups.  %i total.\n", 
-               //      TABLEINITSIZE, re->blohalen+TABLEINITSIZE );
-               temp=re->bloha;
+               //      TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
+               temp=obr->bloha;
                
-               re->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(re->blohalen+TABLEINITSIZE) , "Bloha");
-               if(temp) memcpy(re->bloha, temp, re->blohalen*sizeof(void*));
-               memset(&(re->bloha[re->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
-               re->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
+               obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE) , "Bloha");
+               if(temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
+               memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
+               obr->blohalen+=TABLEINITSIZE;  /*Does this really need to be power of 2?*/
                if(temp) MEM_freeN(temp);       
        }
        
-       h= re->bloha[a];
+       h= obr->bloha[a];
        if(h==NULL) {
                h= (HaloRen *)MEM_callocN(256*sizeof(HaloRen),"findOrAdHalo");
-               re->bloha[a]= h;
+               obr->bloha[a]= h;
        }
        h+= (nr & 255);
        return h;
@@ -859,7 +935,7 @@ HaloRen *RE_findOrAddHalo(Render *re, int nr)
 
 /* ------------------------------------------------------------------------- */
 
-HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1, 
+HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,   float *vec,   float *vec1, 
                                  float *orco,   float hasize,   float vectsize, int seed)
 {
        HaloRen *har;
@@ -876,7 +952,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1,
                if(hoco1[3]==0.0) return NULL;
        }
 
-       har= RE_findOrAddHalo(re, re->tothalo++);
+       har= RE_findOrAddHalo(obr, obr->tothalo++);
        VECCOPY(har->co, vec);
        har->hasize= hasize;
 
@@ -901,12 +977,12 @@ HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1,
 
                har->sin= sin(zn);
                har->cos= cos(zn);
-               zn= VecLenf(vec1, vec);
+               zn= len_v3v3(vec1, vec);
 
                har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
                
-               VecSubf(har->no, vec, vec1);
-               Normalize(har->no);
+               sub_v3_v3v3(har->no, vec, vec1);
+               normalize_v3(har->no);
        }
 
        if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
@@ -929,6 +1005,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1,
        if(ma->mtex[0]) {
 
                if( (ma->mode & MA_HALOTEX) ) har->tex= 1;
+               else if(har->mat->septex & (1<<0));     /* only 1 level textures */
                else {
 
                        mtex= ma->mtex[0];
@@ -941,7 +1018,7 @@ HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1,
                                /* texvec[0]+= imatbase->ivec[0]; */
                                /* texvec[1]+= imatbase->ivec[1]; */
                                /* texvec[2]+= imatbase->ivec[2]; */
-                               /* Mat3MulVecfl(imatbase->imat, texvec); */
+                               /* mul_m3_v3(imatbase->imat, texvec); */
                        }
                        else {
                                if(orco) {
@@ -949,10 +1026,10 @@ HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1,
                                }
                        }
 
-                       externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
+                       externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
 
                        yn= tin*mtex->colfac;
-                       zn= tin*mtex->varfac;
+                       zn= tin*mtex->alphafac;
 
                        if(mtex->mapto & MAP_COL) {
                                zn= 1.0-yn;
@@ -960,23 +1037,25 @@ HaloRen *RE_inithalo(Render *re, Material *ma,   float *vec,   float *vec1,
                                har->g= (yn*tg+ zn*ma->g);
                                har->b= (yn*tb+ zn*ma->b);
                        }
-                       if(mtex->texco & 16) {
+                       if(mtex->texco & TEXCO_UV) {
                                har->alfa= tin;
                        }
+                       if(mtex->mapto & MAP_ALPHA)
+                               har->alfa= tin;
                }
        }
 
        return har;
 }
 
-HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
-                                 float *orco, float *uvco, float hasize, float vectsize, int seed)
+HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma,   float *vec,   float *vec1, 
+                                 float *orco, float *uvco, float hasize, float vectsize, int seed, float *pa_co)
 {
        HaloRen *har;
        MTex *mtex;
        float tin, tr, tg, tb, ta;
        float xn, yn, zn, texvec[3], hoco[4], hoco1[4], in[3],tex[3],out[3];
-       int i;
+       int i, hasrgb;
 
        if(hasize==0.0) return NULL;
 
@@ -987,7 +1066,7 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma,   float
                if(hoco1[3]==0.0) return NULL;
        }
 
-       har= RE_findOrAddHalo(re, re->tothalo++);
+       har= RE_findOrAddHalo(obr, obr->tothalo++);
        VECCOPY(har->co, vec);
        har->hasize= hasize;
 
@@ -1012,12 +1091,12 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma,   float
 
                har->sin= sin(zn);
                har->cos= cos(zn);
-               zn= VecLenf(vec1, vec)*0.5;
+               zn= len_v3v3(vec1, vec)*0.5;
 
                har->hasize= vectsize*zn + (1.0-vectsize)*hasize;
                
-               VecSubf(har->no, vec, vec1);
-               Normalize(har->no);
+               sub_v3_v3v3(har->no, vec, vec1);
+               normalize_v3(har->no);
        }
 
        if(ma->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
@@ -1050,16 +1129,8 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma,   float
                                ;
                        }
                        else if(mtex->texco & TEXCO_OBJECT) {
-                               if(mtex->object){
-                                       float imat[4][4];
-                                       /* imat should really be cached somewhere before this */
-                                       Mat4Invert(imat,mtex->object->obmat);
-                                       Mat4MulVecfl(imat,texvec);
-                               }
-                               /* texvec[0]+= imatbase->ivec[0]; */
-                               /* texvec[1]+= imatbase->ivec[1]; */
-                               /* texvec[2]+= imatbase->ivec[2]; */
-                               /* Mat3MulVecfl(imatbase->imat, texvec); */
+                               if(mtex->object)
+                                       mul_m4_v3(mtex->object->imat_ren,texvec);
                        }
                        else if(mtex->texco & TEXCO_GLOB){
                                VECCOPY(texvec,vec);
@@ -1075,14 +1146,20 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma,   float
                                texvec[1]=2.0f*uvco[2*uv_index+1]-1.0f;
                                texvec[2]=0.0f;
                        }
+                       else if(mtex->texco & TEXCO_PARTICLE) {
+                               /* particle coordinates in range [0,1] */
+                               texvec[0] = 2.f * pa_co[0] - 1.f;
+                               texvec[1] = 2.f * pa_co[1] - 1.f;
+                               texvec[2] = pa_co[2];
+                       }
                        else if(orco) {
                                VECCOPY(texvec, orco);
                        }
 
-                       externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta);
+                       hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
 
                        //yn= tin*mtex->colfac;
-                       //zn= tin*mtex->varfac;
+                       //zn= tin*mtex->alphafac;
                        if(mtex->mapto & MAP_COL) {
                                tex[0]=tr;
                                tex[1]=tg;
@@ -1100,12 +1177,22 @@ HaloRen *RE_inithalo_particle(Render *re, DerivedMesh *dm, Material *ma,   float
                                har->g= in[1];
                                har->b= in[2];
                        }
+
+                       /* alpha returned, so let's use it instead of intensity */
+                       if(hasrgb)
+                               tin = ta;
+
                        if(mtex->mapto & MAP_ALPHA)
-                               har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_ALPHA);
+                               har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->alphafac,mtex->blendtype);
                        if(mtex->mapto & MAP_HAR)
-                               har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_HAR);
+                               har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->hardfac,mtex->blendtype);
                        if(mtex->mapto & MAP_RAYMIRR)
-                               har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_RAYMIRR);
+                               har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->raymirrfac,mtex->blendtype);
+                       if(mtex->mapto & MAP_TRANSLU) {
+                               float add = texture_value_blend(mtex->def_var,(float)har->add/255.0,tin,mtex->translfac,mtex->blendtype);
+                               CLAMP(add, 0.f, 1.f);
+                               har->add = 255.0*add;
+                       }
                        /* now what on earth is this good for?? */
                        //if(mtex->texco & 16) {
                        //      har->alfa= tin;
@@ -1151,10 +1238,9 @@ static int panotestclip(Render *re, int do_pano, float *v)
   - shadow buffering (shadbuf.c)
 */
 
-void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, float xoffs, int do_buckets)
+void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, float xoffs, int UNUSED(do_buckets))
 {
-       VlakRen *vlr = NULL;
-       VertRen *ver = NULL;
+       ObjectRen *obr;
        HaloRen *har = NULL;
        float zn, vec[3], hoco[4];
        int a;
@@ -1165,170 +1251,172 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
                re->panosi= sin(panophi);
                re->panoco= cos(panophi);
        }
-       
-   /* calculate view coordinates (and zbuffer value) */
-       for(a=0; a< re->totvert;a++) {
-               if((a & 255)==0) ver= RE_findOrAddVert(re, a);
-               else ver++;
-
-               if(do_pano) {
-                       vec[0]= re->panoco*ver->co[0] + re->panosi*ver->co[2];
-                       vec[1]= ver->co[1];
-                       vec[2]= -re->panosi*ver->co[0] + re->panoco*ver->co[2];
-               }
-               else {
-                       VECCOPY(vec, ver->co);
-               }
-               /* Go from wcs to hcs ... */
-               projectfunc(vec, re->winmat, ver->ho);
-               /* ... and clip in that system. */
-               ver->clip = testclip(ver->ho);
-               /* 
-                  Because all other ops are performed in other systems, this is 
-                  the only thing that has to be done.
-               */
-       }
-
-   /* calculate view coordinates (and zbuffer value) */
-       for(a=0; a<re->tothalo; a++) {
-               if((a & 255)==0) har= re->bloha[a>>8];
-               else har++;
-
-               if(do_pano) {
-                       vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
-                       vec[1]= har->co[1];
-                       vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
-               }
-               else {
-                       VECCOPY(vec, har->co);
-               }
 
-               projectfunc(vec, re->winmat, hoco);
-               
-               /* we clip halos less critical, but not for the Z */
-               hoco[0]*= 0.5;
-               hoco[1]*= 0.5;
-               
-               if( panotestclip(re, do_pano, hoco) ) {
-                       har->miny= har->maxy= -10000;   /* that way render clips it */
-               }
-               else if(hoco[3]<0.0) {
-                       har->miny= har->maxy= -10000;   /* render clips it */
-               }
-               else /* do the projection...*/
-               {
-                       /* bring back hocos */
-                       hoco[0]*= 2.0;
-                       hoco[1]*= 2.0;
+       for(obr=re->objecttable.first; obr; obr=obr->next) {
+               /* calculate view coordinates (and zbuffer value) */
+               for(a=0; a<obr->tothalo; a++) {
+                       if((a & 255)==0) har= obr->bloha[a>>8];
+                       else har++;
+
+                       if(do_pano) {
+                               vec[0]= re->panoco*har->co[0] + re->panosi*har->co[2];
+                               vec[1]= har->co[1];
+                               vec[2]= -re->panosi*har->co[0] + re->panoco*har->co[2];
+                       }
+                       else {
+                               VECCOPY(vec, har->co);
+                       }
+
+                       projectfunc(vec, re->winmat, hoco);
                        
-                       zn= hoco[3];
-                       har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
-                       har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
-               
-                       /* this should be the zbuffer coordinate */
-                       har->zs= 0x7FFFFF*(hoco[2]/zn);
-                       /* taking this from the face clip functions? seems ok... */
-                       har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+                       /* we clip halos less critical, but not for the Z */
+                       hoco[0]*= 0.5;
+                       hoco[1]*= 0.5;
                        
-                       vec[0]+= har->hasize;
-                       projectfunc(vec, re->winmat, hoco);
-                       vec[0]-= har->hasize;
-                       zn= hoco[3];
-                       har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
-               
-                       /* this clip is not really OK, to prevent stars to become too large */
-                       if(har->type & HA_ONLYSKY) {
-                               if(har->rad>3.0) har->rad= 3.0;
+                       if( panotestclip(re, do_pano, hoco) ) {
+                               har->miny= har->maxy= -10000;   /* that way render clips it */
                        }
-               
-                       har->radsq= har->rad*har->rad;
-               
-                       har->miny= har->ys - har->rad/re->ycor;
-                       har->maxy= har->ys + har->rad/re->ycor;
-               
-                       /* the Zd value is still not really correct for pano */
-               
-                       vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
-                       projectfunc(vec, re->winmat, hoco);
-                       zn= hoco[3];
-                       zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
-                       har->zd= CLAMPIS(zn, 0, INT_MAX);
-               
+                       else if(hoco[3]<0.0) {
+                               har->miny= har->maxy= -10000;   /* render clips it */
+                       }
+                       else /* do the projection...*/
+                       {
+                               /* bring back hocos */
+                               hoco[0]*= 2.0;
+                               hoco[1]*= 2.0;
+                               
+                               zn= hoco[3];
+                               har->xs= 0.5*re->winx*(1.0+hoco[0]/zn); /* the 0.5 negates the previous 2...*/
+                               har->ys= 0.5*re->winy*(1.0+hoco[1]/zn);
+                       
+                               /* this should be the zbuffer coordinate */
+                               har->zs= 0x7FFFFF*(hoco[2]/zn);
+                               /* taking this from the face clip functions? seems ok... */
+                               har->zBufDist = 0x7FFFFFFF*(hoco[2]/zn);
+                               
+                               vec[0]+= har->hasize;
+                               projectfunc(vec, re->winmat, hoco);
+                               vec[0]-= har->hasize;
+                               zn= hoco[3];
+                               har->rad= fabs(har->xs- 0.5*re->winx*(1.0+hoco[0]/zn));
+                       
+                               /* this clip is not really OK, to prevent stars to become too large */
+                               if(har->type & HA_ONLYSKY) {
+                                       if(har->rad>3.0) har->rad= 3.0;
+                               }
+                       
+                               har->radsq= har->rad*har->rad;
+                       
+                               har->miny= har->ys - har->rad/re->ycor;
+                               har->maxy= har->ys + har->rad/re->ycor;
+                       
+                               /* the Zd value is still not really correct for pano */
+                       
+                               vec[2]-= har->hasize;   /* z negative, otherwise it's clipped */
+                               projectfunc(vec, re->winmat, hoco);
+                               zn= hoco[3];
+                               zn= fabs( (float)har->zs - 0x7FFFFF*(hoco[2]/zn));
+                               har->zd= CLAMPIS(zn, 0, INT_MAX);
+                       
+                       }
+                       
                }
-               
        }
+}
 
-       /* set flags at 0 if clipped away */
-       for(a=0; a<re->totvlak; a++) {
-               if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak;
-               else vlr++;
+/* ------------------------------------------------------------------------- */
 
-               if(!re->excludeob || vlr->ob != re->excludeob) {
-                       vlr->flag |= R_VISIBLE;
-                       if(vlr->v4) {
-                               if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE;
-                       }
-                       else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE;
+ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4], int lay)
+{
+       ObjectInstanceRen *obi;
+       float mat3[3][3];
+
+       obi= MEM_callocN(sizeof(ObjectInstanceRen), "ObjectInstanceRen");
+       obi->obr= obr;
+       obi->ob= ob;
+       obi->par= par;
+       obi->index= index;
+       obi->psysindex= psysindex;
+       obi->lay= lay;
+
+       if(mat) {
+               copy_m4_m4(obi->mat, mat);
+               copy_m3_m4(mat3, mat);
+               invert_m3_m3(obi->nmat, mat3);
+               transpose_m3(obi->nmat);
+               obi->flag |= R_DUPLI_TRANSFORMED;
+       }
+
+       BLI_addtail(&re->instancetable, obi);
+
+       return obi;
+}
+
+void RE_makeRenderInstances(Render *re)
+{
+       ObjectInstanceRen *obi, *oldobi;
+       ListBase newlist;
+       int tot;
+
+       /* convert list of object instances to an array for index based lookup */
+       tot= BLI_countlist(&re->instancetable);
+       re->objectinstance= MEM_callocN(sizeof(ObjectInstanceRen)*tot, "ObjectInstance");
+       re->totinstance= tot;
+       newlist.first= newlist.last= NULL;
+
+       obi= re->objectinstance;
+       for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) {
+               *obi= *oldobi;
+
+               if(obi->obr) {
+                       obi->prev= obi->next= NULL;
+                       BLI_addtail(&newlist, obi);
+                       obi++;
                }
                else
-                       vlr->flag &= ~R_VISIBLE;
+                       re->totinstance--;
        }
 
-       project_strands(re, projectfunc, do_pano, do_buckets);
+       BLI_freelistN(&re->instancetable);
+       re->instancetable= newlist;
 }
 
-/* ------------------------------------------------------------------------- */
-
-void set_normalflags(Render *re)
+int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
 {
-       VlakRen *vlr = NULL;
-       float *v1, xn, yn, zn;
-       int a1, doflip;
-       
-       /* switch normal 'snproj' values (define which axis is the optimal one for calculations) */
-       for(a1=0; a1<re->totvlak; a1++) {
-               if((a1 & 255)==0) vlr= re->vlaknodes[a1>>8].vlak;
-               else vlr++;
-               
-               vlr->noflag= 0;
-
-               /* abuse of this flag... this is code that just sets face normal in direction of camera */
-               /* that convention we should get rid of */
-               if((vlr->flag & R_NOPUNOFLIP)==0) {
+       float mat[4][4], vec[4];
+       int a, fl, flag= -1;
+
+       copy_m4_m4(mat, winmat);
+
+       for(a=0; a<8; a++) {
+               vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
+               vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
+               vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
+               vec[3]= 1.0;
+               mul_m4_v4(mat, vec);
+
+               fl= 0;
+               if(bounds) {
+                       if(vec[0] < bounds[0]*vec[3]) fl |= 1;
+                       else if(vec[0] > bounds[1]*vec[3]) fl |= 2;
                        
-                       doflip= 0;
-                       if(re->r.mode & R_ORTHO) {
-                               if(vlr->n[2]>0.0) doflip= 1;
-                       }
-                       else {
-                               v1= vlr->v1->co;
-                               if( (v1[0]*vlr->n[0] +v1[1]*vlr->n[1] +v1[2]*vlr->n[2])<0.0 ) doflip= 1;
-                       }
-                       if(doflip) {
-                               vlr->n[0]= -vlr->n[0];
-                               vlr->n[1]= -vlr->n[1];
-                               vlr->n[2]= -vlr->n[2];
-                               vlr->noflag |= R_FLIPPED_NO;
-                       }
+                       if(vec[1] > bounds[3]*vec[3]) fl |= 4;
+                       else if(vec[1]< bounds[2]*vec[3]) fl |= 8;
                }
-               
-               /* recalculate puno. Displace & flipped matrices can screw up */
-               vlr->puno= 0;
-               if(!(vlr->flag & R_TANGENT)) {
-                       if( Inpf(vlr->n, vlr->v1->n) < 0.0 ) vlr->puno |= ME_FLIPV1;
-                       if( Inpf(vlr->n, vlr->v2->n) < 0.0 ) vlr->puno |= ME_FLIPV2;
-                       if( Inpf(vlr->n, vlr->v3->n) < 0.0 ) vlr->puno |= ME_FLIPV3;
-                       if(vlr->v4 && Inpf(vlr->n, vlr->v4->n) < 0.0 ) vlr->puno |= ME_FLIPV4;
-               }                               
-               xn= fabs(vlr->n[0]);
-               yn= fabs(vlr->n[1]);
-               zn= fabs(vlr->n[2]);
-               if(zn>=xn && zn>=yn) vlr->noflag |= R_SNPROJ_X;
-               else if(yn>=xn && yn>=zn) vlr->noflag |= R_SNPROJ_Y;
-               else vlr->noflag |= R_SNPROJ_Z;
+               else {
+                       if(vec[0] < -vec[3]) fl |= 1;
+                       else if(vec[0] > vec[3]) fl |= 2;
+                       
+                       if(vec[1] > vec[3]) fl |= 4;
+                       else if(vec[1] < -vec[3]) fl |= 8;
+               }
+               if(vec[2] < -vec[3]) fl |= 16;
+               else if(vec[2] > vec[3]) fl |= 32;
 
+               flag &= fl;
+               if(flag==0) return 0;
        }
-}
-
 
+       return flag;
+}