Major cleanup of particle render & drawing code. No new features and hopefully no...
authorJanne Karhu <jhkarh@gmail.com>
Fri, 3 Apr 2009 14:50:54 +0000 (14:50 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Fri, 3 Apr 2009 14:50:54 +0000 (14:50 +0000)
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/particle.c
source/blender/render/intern/source/convertblender.c
source/blender/src/drawobject.c

index ecc97dd5d3befa22dd30e4f4a10780306cea9d73..5dbfe2fe520ecbb9a5775dedc474314828d12eeb 100644 (file)
@@ -188,6 +188,19 @@ typedef struct ParticleThread {
        int num, tot;
 } ParticleThread;
 
+typedef struct ParticleBillboardData
+{
+       struct Object *ob;
+       float vec[3], vel[3];
+       float offset[2];
+       float size, tilt, random, time;
+       int uv[3];
+       int lock, num;
+       int totnum;
+       short align, uv_split, anim, split_offset;
+}
+ParticleBillboardData;
+
 /* ----------- functions needed outside particlesystem ---------------- */
 /* particle.c */
 int count_particles(struct ParticleSystem *psys);
@@ -260,6 +273,8 @@ void psys_threads_free(ParticleThread *threads);
 void psys_thread_distribute_particle(ParticleThread *thread, struct ParticleData *pa, struct ChildParticle *cpa, int p);
 void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i);
 
+void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
+
 /* particle_system.c */
 int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
 void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys);
index b1ed165fedd9e4567a57e46d07384dd3a0fc5625..4eabb82f6cb9dde4b791a175647abe5cd0cbe87e 100644 (file)
@@ -3868,3 +3868,76 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys
 
        *scale= len;
 }
+
+void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3])
+{
+       float onevec[3] = {0.0f,0.0f,0.0f}, tvec[3], tvec2[3];
+
+       xvec[0] = 1.0f; xvec[1] = 0.0f; xvec[2] = 0.0f;
+       yvec[0] = 0.0f; yvec[1] = 1.0f; yvec[2] = 0.0f;
+
+       if(bb->align < PART_BB_VIEW)
+               onevec[bb->align]=1.0f;
+
+       if(bb->lock && (bb->align == PART_BB_VIEW)) {
+               VECCOPY(xvec, bb->ob->obmat[0]);
+               Normalize(xvec);
+
+               VECCOPY(yvec, bb->ob->obmat[1]);
+               Normalize(yvec);
+
+               VECCOPY(zvec, bb->ob->obmat[2]);
+               Normalize(zvec);
+       }
+       else if(bb->align == PART_BB_VEL) {
+               float temp[3];
+
+               VECCOPY(temp, bb->vel);
+               Normalize(temp);
+
+               VECSUB(zvec, bb->ob->obmat[3], bb->vec);
+
+               if(bb->lock) {
+                       float fac = -Inpf(zvec, temp);
+
+                       VECADDFAC(zvec, zvec, temp, fac);
+               }
+               Normalize(zvec);
+
+               Crossf(xvec,temp,zvec);
+               Normalize(xvec);
+
+               Crossf(yvec,zvec,xvec);
+       }
+       else {
+               VECSUB(zvec, bb->ob->obmat[3], bb->vec);
+               if(bb->lock)
+                       zvec[bb->align] = 0.0f;
+               Normalize(zvec);
+
+               if(bb->align < PART_BB_VIEW)
+                       Crossf(xvec, onevec, zvec);
+               else
+                       Crossf(xvec, bb->ob->obmat[1], zvec);
+               Normalize(xvec);
+
+               Crossf(yvec,zvec,xvec);
+       }
+
+       VECCOPY(tvec, xvec);
+       VECCOPY(tvec2, yvec);
+
+       VecMulf(xvec, cos(bb->tilt * (float)M_PI));
+       VecMulf(tvec2, sin(bb->tilt * (float)M_PI));
+       VECADD(xvec, xvec, tvec2);
+
+       VecMulf(yvec, cos(bb->tilt * (float)M_PI));
+       VecMulf(tvec, -sin(bb->tilt * (float)M_PI));
+       VECADD(yvec, yvec, tvec);
+
+       VecMulf(xvec, bb->size);
+       VecMulf(yvec, bb->size);
+
+       VECADDFAC(center, bb->vec, xvec, bb->offset[0]);
+       VECADDFAC(center, center, yvec, bb->offset[1]);
+}
\ No newline at end of file
index 601acc881de8ec8d5f21ebea0a59da5d62099439..9e474c1961910fd1e98af3d980eefac1f2b9669c 100644 (file)
@@ -947,11 +947,17 @@ static Material *give_render_material(Render *re, Object *ob, int nr)
 /* ------------------------------------------------------------------------- */
 /* Particles                                                                 */
 /* ------------------------------------------------------------------------- */
-
+typedef struct ParticleStrandData
+{
+       struct MCol *mcol;
+       float *orco, *uvco, *surfnor;
+       float time, adapt_angle, adapt_pix, size;
+       int totuv, totcol;
+       int first, line, adapt, override_uv;
+}
+ParticleStrandData;
 /* future thread problem... */
-static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, float *orco, float *surfnor,
-                                                                  float *uvco, int totuv, MCol *mcol, int totcol, float *vec, float *vec1, float ctime,
-                                                                  int first, int line, int adapt, float adapt_angle, float adapt_pix, int override_uv)
+static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, float *vec, float *vec1)
 {
        static VertRen *v1= NULL, *v2= NULL;
        VlakRen *vlr;
@@ -974,11 +980,11 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                float fac;
                if(ma->strand_ease!=0.0f) {
                        if(ma->strand_ease<0.0f)
-                               fac= pow(ctime, 1.0+ma->strand_ease);
+                               fac= pow(sd->time, 1.0+ma->strand_ease);
                        else
-                               fac= pow(ctime, 1.0/(1.0f-ma->strand_ease));
+                               fac= pow(sd->time, 1.0/(1.0f-ma->strand_ease));
                }
-               else fac= ctime;
+               else fac= sd->time;
 
                width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end);
 
@@ -1010,7 +1016,7 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                flag |= R_STRAND;
        
        /* single face line */
-       if(line) {
+       if(sd->line) {
                vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                vlr->flag= flag;
                vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
@@ -1021,25 +1027,25 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                VECCOPY(vlr->v1->co, vec);
                VecAddf(vlr->v1->co, vlr->v1->co, cross);
                VECCOPY(vlr->v1->n, nor);
-               vlr->v1->orco= orco;
+               vlr->v1->orco= sd->orco;
                vlr->v1->accum= -1.0f;  // accum abuse for strand texco
                
                VECCOPY(vlr->v2->co, vec);
                VecSubf(vlr->v2->co, vlr->v2->co, cross);
                VECCOPY(vlr->v2->n, nor);
-               vlr->v2->orco= orco;
+               vlr->v2->orco= sd->orco;
                vlr->v2->accum= vlr->v1->accum;
 
                VECCOPY(vlr->v4->co, vec1);
                VecAddf(vlr->v4->co, vlr->v4->co, cross);
                VECCOPY(vlr->v4->n, nor);
-               vlr->v4->orco= orco;
+               vlr->v4->orco= sd->orco;
                vlr->v4->accum= 1.0f;   // accum abuse for strand texco
                
                VECCOPY(vlr->v3->co, vec1);
                VecSubf(vlr->v3->co, vlr->v3->co, cross);
                VECCOPY(vlr->v3->n, nor);
-               vlr->v3->orco= orco;
+               vlr->v3->orco= sd->orco;
                vlr->v3->accum= vlr->v4->accum;
 
                CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
@@ -1047,23 +1053,23 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                vlr->mat= ma;
                vlr->ec= ME_V2V3;
 
-               if(surfnor) {
+               if(sd->surfnor) {
                        float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
-                       VECCOPY(snor, surfnor);
+                       VECCOPY(snor, sd->surfnor);
                }
 
-               if(uvco){
-                       for(i=0; i<totuv; i++){
+               if(sd->uvco){
+                       for(i=0; i<sd->totuv; i++){
                                MTFace *mtf;
                                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[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
                                mtf->uv[0][1]=mtf->uv[1][1]=
-                               mtf->uv[2][1]=mtf->uv[3][1]=(uvco+2*i)[1];
+                               mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
                        }
-                       if(override_uv>=0){
+                       if(sd->override_uv>=0){
                                MTFace *mtf;
-                               mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0);
+                               mtf=RE_vlakren_get_tface(obr,vlr,sd->override_uv,NULL,0);
                                
                                mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
                                mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
@@ -1072,18 +1078,18 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                                mtf->uv[2][1]=mtf->uv[3][1]=1.0f;
                        }
                }
-               if(mcol){
-                       for(i=0; i<totcol; i++){
+               if(sd->mcol){
+                       for(i=0; i<sd->totcol; i++){
                                MCol *mc;
                                mc=RE_vlakren_get_mcol(obr,vlr,i,NULL,1);
-                               mc[0]=mc[1]=mc[2]=mc[3]=mcol[i];
-                               mc[0]=mc[1]=mc[2]=mc[3]=mcol[i];
+                               mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
+                               mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
                        }
                }
        }
        /* first two vertices of a strand */
-       else if(first) {
-               if(adapt){
+       else if(sd->first) {
+               if(sd->adapt){
                        VECCOPY(anor, nor);
                        VECCOPY(avec, vec);
                        second=1;
@@ -1095,18 +1101,18 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                VECCOPY(v1->co, vec);
                VecAddf(v1->co, v1->co, cross);
                VECCOPY(v1->n, nor);
-               v1->orco= orco;
+               v1->orco= sd->orco;
                v1->accum= -1.0f;       // accum abuse for strand texco
                
                VECCOPY(v2->co, vec);
                VecSubf(v2->co, v2->co, cross);
                VECCOPY(v2->n, nor);
-               v2->orco= orco;
+               v2->orco= sd->orco;
                v2->accum= v1->accum;
        }
        /* more vertices & faces to strand */
        else {
-               if(adapt==0 || second){
+               if(sd->adapt==0 || second){
                        vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                        vlr->flag= flag;
                        vlr->v1= v1;
@@ -1118,14 +1124,14 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                        v2= vlr->v3; // cycle
 
                        
-                       if(adapt){
+                       if(sd->adapt){
                                second=0;
                                VECCOPY(anor,nor);
                                VECCOPY(avec,vec);
                        }
 
                }
-               else if(adapt){
+               else if(sd->adapt){
                        float dvec[3],pvec[3];
                        VecSubf(dvec,avec,vec);
                        Projf(pvec,dvec,vec);
@@ -1135,7 +1141,7 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                        dx= re->winx*dvec[0]*re->winmat[0][0]/w;
                        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){
+                       if(Inpf(anor,nor)<sd->adapt_angle && w>sd->adapt_pix){
                                vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                                vlr->flag= flag;
                                vlr->v1= v1;
@@ -1157,13 +1163,13 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                VECCOPY(vlr->v4->co, vec);
                VecAddf(vlr->v4->co, vlr->v4->co, cross);
                VECCOPY(vlr->v4->n, nor);
-               vlr->v4->orco= orco;
-               vlr->v4->accum= -1.0f + 2.0f*ctime;     // accum abuse for strand texco
+               vlr->v4->orco= sd->orco;
+               vlr->v4->accum= -1.0f + 2.0f*sd->time;  // accum abuse for strand texco
                
                VECCOPY(vlr->v3->co, vec);
                VecSubf(vlr->v3->co, vlr->v3->co, cross);
                VECCOPY(vlr->v3->n, nor);
-               vlr->v3->orco= orco;
+               vlr->v3->orco= sd->orco;
                vlr->v3->accum= vlr->v4->accum;
                
                CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
@@ -1171,23 +1177,23 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                vlr->mat= ma;
                vlr->ec= ME_V2V3;
 
-               if(surfnor) {
+               if(sd->surfnor) {
                        float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
-                       VECCOPY(snor, surfnor);
+                       VECCOPY(snor, sd->surfnor);
                }
 
-               if(uvco){
-                       for(i=0; i<totuv; i++){
+               if(sd->uvco){
+                       for(i=0; i<sd->totuv; i++){
                                MTFace *mtf;
                                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[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
                                mtf->uv[0][1]=mtf->uv[1][1]=
-                               mtf->uv[2][1]=mtf->uv[3][1]=(uvco+2*i)[1];
+                               mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
                        }
-                       if(override_uv>=0){
+                       if(sd->override_uv>=0){
                                MTFace *mtf;
-                               mtf=RE_vlakren_get_tface(obr,vlr,override_uv,NULL,0);
+                               mtf=RE_vlakren_get_tface(obr,vlr,sd->override_uv,NULL,0);
                                
                                mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
                                mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
@@ -1196,12 +1202,12 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, flo
                                mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f;
                        }
                }
-               if(mcol){
-                       for(i=0; i<totcol; i++){
+               if(sd->mcol){
+                       for(i=0; i<sd->totcol; i++){
                                MCol *mc;
                                mc=RE_vlakren_get_mcol(obr,vlr,i,NULL,1);
-                               mc[0]=mc[1]=mc[2]=mc[3]=mcol[i];
-                               mc[0]=mc[1]=mc[2]=mc[3]=mcol[i];
+                               mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
+                               mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
                        }
                }
        }
@@ -1254,17 +1260,13 @@ static void static_particle_wire(ObjectRen *obr, Material *ma, float *vec, float
        }
 
 }
-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])
+
+static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb)
 {
        VlakRen *vlr;
        MTFace *mtf;
-       float xvec[3]={1.0f,0.0f,0.0f}, yvec[3]={0.0f,1.0f,0.0f}, zvec[3];
-       float onevec[3]={0.0f,0.0f,0.0f}, tvec[3],tvec2[3], bb_center[3];
-       float uvx=0.0f, uvy=0.0f, uvdx=1.0f, uvdy=1.0f, time=0.0f;
-
-       if(align<PART_BB_VIEW)
-               onevec[align]=1.0f;
+       float xvec[3], yvec[3], zvec[3], bb_center[3];
+       float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f;
 
        vlr= RE_findOrAddVlak(obr, obr->totvlak++);
        vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
@@ -1272,74 +1274,23 @@ static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, Object
        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]);
-               Normalize(xvec);
-               VECCOPY(yvec,bb_ob->obmat[1]);
-               Normalize(yvec);
-               VECCOPY(zvec,bb_ob->obmat[2]);
-               Normalize(zvec);
-       }
-       else if(align==PART_BB_VEL){
-               float temp[3];
-               VECCOPY(temp,vel);
-               Normalize(temp);
-               VECSUB(zvec,bb_ob->obmat[3],vec);
-               if(lock){
-                       float fac=-Inpf(zvec,temp);
-                       VECADDFAC(zvec,zvec,temp,fac);
-               }
-               Normalize(zvec);
-               Crossf(xvec,temp,zvec);
-               Normalize(xvec);
-               Crossf(yvec,zvec,xvec);
-       }
-       else{
-               VECSUB(zvec,bb_ob->obmat[3],vec);
-               if(lock)
-                       zvec[align]=0.0f;
-               Normalize(zvec);
-
-               if(align<PART_BB_VIEW)
-                       Crossf(xvec,onevec,zvec);
-               else
-                       Crossf(xvec,bb_ob->obmat[1],zvec);
-               Normalize(xvec);
-               Crossf(yvec,zvec,xvec);
-       }
-
-       VECCOPY(tvec,xvec);
-       VECCOPY(tvec2,yvec);
-
-       VecMulf(xvec,cos(tilt*(float)M_PI));
-       VecMulf(tvec2,sin(tilt*(float)M_PI));
-       VECADD(xvec,xvec,tvec2);
-
-       VecMulf(yvec,cos(tilt*(float)M_PI));
-       VecMulf(tvec,-sin(tilt*(float)M_PI));
-       VECADD(yvec,yvec,tvec);
-
-       VecMulf(xvec,size);
-       VecMulf(yvec,size);
+       psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
 
-       VECADDFAC(bb_center,vec,xvec,offset[0]);
-       VECADDFAC(bb_center,bb_center,yvec,offset[1]);
+       VECADD(vlr->v1->co, bb_center, xvec);
+       VECADD(vlr->v1->co, vlr->v1->co, yvec);
+       MTC_Mat4MulVecfl(re->viewmat, vlr->v1->co);
 
-       VECADD(vlr->v1->co,bb_center,xvec);
-       VECADD(vlr->v1->co,vlr->v1->co,yvec);
-       MTC_Mat4MulVecfl(re->viewmat,vlr->v1->co);
+       VECSUB(vlr->v2->co, bb_center, xvec);
+       VECADD(vlr->v2->co, vlr->v2->co, yvec);
+       MTC_Mat4MulVecfl(re->viewmat, vlr->v2->co);
 
-       VECSUB(vlr->v2->co,bb_center,xvec);
-       VECADD(vlr->v2->co,vlr->v2->co,yvec);
-       MTC_Mat4MulVecfl(re->viewmat,vlr->v2->co);
+       VECSUB(vlr->v3->co, bb_center, xvec);
+       VECSUB(vlr->v3->co, vlr->v3->co, yvec);
+       MTC_Mat4MulVecfl(re->viewmat, vlr->v3->co);
 
-       VECSUB(vlr->v3->co,bb_center,xvec);
-       VECSUB(vlr->v3->co,vlr->v3->co,yvec);
-       MTC_Mat4MulVecfl(re->viewmat,vlr->v3->co);
-
-       VECADD(vlr->v4->co,bb_center,xvec);
-       VECSUB(vlr->v4->co,vlr->v4->co,yvec);
-       MTC_Mat4MulVecfl(re->viewmat,vlr->v4->co);
+       VECADD(vlr->v4->co, bb_center, xvec);
+       VECSUB(vlr->v4->co, vlr->v4->co, yvec);
+       MTC_Mat4MulVecfl(re->viewmat, vlr->v4->co);
 
        CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co, vlr->n);
        VECCOPY(vlr->v1->n,vlr->n);
@@ -1350,113 +1301,141 @@ static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, Object
        vlr->mat= ma;
        vlr->ec= ME_V2V3;
 
-       if(uv_split>1){
-               uvdx=uvdy=1.0f/(float)uv_split;
-               if(anim==PART_BB_ANIM_TIME){
-                       if(split_offset==PART_BB_OFF_NONE)
-                               time=pa_time;
-                       else if(split_offset==PART_BB_OFF_LINEAR)
-                               time=(float)fmod(pa_time+(float)p/(float)(uv_split*uv_split),1.0f);
+       if(bb->uv_split > 1){
+               uvdx = uvdy = 1.0f / (float)bb->uv_split;
+               if(bb->anim == PART_BB_ANIM_TIME) {
+                       if(bb->split_offset == PART_BB_OFF_NONE)
+                               time = bb->time;
+                       else if(bb->split_offset == PART_BB_OFF_LINEAR)
+                               time = (float)fmod(bb->time + (float)bb->num / (float)(bb->uv_split * bb->uv_split), 1.0f);
                        else /* split_offset==PART_BB_OFF_RANDOM */
-                               time=(float)fmod(pa_time+random,1.0f);
+                               time = (float)fmod(bb->time + bb->random, 1.0f);
 
                }
-               else if(anim==PART_BB_ANIM_ANGLE){
-                       if(align==PART_BB_VIEW){
-                               time=(float)fmod((tilt+1.0f)/2.0f,1.0);
+               else if(bb->anim == PART_BB_ANIM_ANGLE) {
+                       if(bb->align == PART_BB_VIEW) {
+                               time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0);
                        }
                        else{
-                               float axis1[3]={0.0f,0.0f,0.0f};
-                               float axis2[3]={0.0f,0.0f,0.0f};
-                               axis1[(align+1)%3]=1.0f;
-                               axis2[(align+2)%3]=1.0f;
-                               if(lock==0){
-                                       zvec[align]=0.0f;
+                               float axis1[3] = {0.0f,0.0f,0.0f};
+                               float axis2[3] = {0.0f,0.0f,0.0f};
+                               axis1[(bb->align + 1) % 3] = 1.0f;
+                               axis2[(bb->align + 2) % 3] = 1.0f;
+                               if(bb->lock == 0) {
+                                       zvec[bb->align] = 0.0f;
                                        Normalize(zvec);
                                }
-                               time=saacos(Inpf(zvec,axis1))/(float)M_PI;
-                               if(Inpf(zvec,axis2)<0.0f)
-                                       time=1.0f-time/2.0f;
+                               time = saacos(Inpf(zvec, axis1)) / (float)M_PI;
+                               if(Inpf(zvec, axis2) < 0.0f)
+                                       time = 1.0f - time / 2.0f;
                                else
-                                       time=time/2.0f;
+                                       time = time / 2.0f;
                        }
-                       if(split_offset==PART_BB_OFF_LINEAR)
-                               time=(float)fmod(pa_time+(float)p/(float)(uv_split*uv_split),1.0f);
-                       else if(split_offset==PART_BB_OFF_RANDOM)
-                               time=(float)fmod(pa_time+random,1.0f);
+                       if(bb->split_offset == PART_BB_OFF_LINEAR)
+                               time = (float)fmod(bb->time + (float)bb->num / (float)(bb->uv_split * bb->uv_split), 1.0f);
+                       else if(bb->split_offset == PART_BB_OFF_RANDOM)
+                               time = (float)fmod(bb->time + bb->random, 1.0f);
                }
                else{
-                       if(split_offset==PART_BB_OFF_NONE)
-                               time=0.0f;
-                       else if(split_offset==PART_BB_OFF_LINEAR)
-                               time=(float)fmod((float)p/(float)(uv_split*uv_split),1.0f);
+                       if(bb->split_offset == PART_BB_OFF_NONE)
+                               time = 0.0f;
+                       else if(bb->split_offset == PART_BB_OFF_LINEAR)
+                               time = (float)fmod((float)bb->num /(float)(bb->uv_split * bb->uv_split) , 1.0f);
                        else /* split_offset==PART_BB_OFF_RANDOM */
-                               time=random;
+                               time = bb->random;
                }
-               uvx=uvdx*floor((float)(uv_split*uv_split)*(float)fmod((double)time,(double)uvdx));
-               uvy=uvdy*floor((1.0f-time)*(float)uv_split);
-               if(fmod(time,1.0f/uv_split)==0.0f)
-                       uvy-=uvdy;
+               uvx = uvdx * floor((float)(bb->uv_split * bb->uv_split) * (float)fmod((double)time, (double)uvdx));
+               uvy = uvdy * floor((1.0f - time) * (float)bb->uv_split);
+               if(fmod(time, 1.0f / bb->uv_split) == 0.0f)
+                       uvy -= uvdy;
        }
 
        /* normal UVs */
-       if(uv[0]>=0){
-               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;
-               mtf->uv[1][1]=1.0f;
-               mtf->uv[2][0]=0.0f;
-               mtf->uv[2][1]=0.0f;
-               mtf->uv[3][0]=1.0f;
-               mtf->uv[3][1]=0.0f;
+       if(bb->uv[0] >= 0){
+               mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1);
+               mtf->uv[0][0] = 1.0f;
+               mtf->uv[0][1] = 1.0f;
+               mtf->uv[1][0] = 0.0f;
+               mtf->uv[1][1] = 1.0f;
+               mtf->uv[2][0] = 0.0f;
+               mtf->uv[2][1] = 0.0f;
+               mtf->uv[3][0] = 1.0f;
+               mtf->uv[3][1] = 0.0f;
        }
 
        /* time-index UVs */
-       if(uv[1]>=0){
-               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;
+       if(bb->uv[1] >= 0){
+               mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1);
+               mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time;
+               mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum;
        }
 
        /* split UVs */
-       if(uv_split>1 && uv[2]>=0){
-               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;
-               mtf->uv[1][1]=uvy+uvdy;
-               mtf->uv[2][0]=uvx;
-               mtf->uv[2][1]=uvy;
-               mtf->uv[3][0]=uvx+uvdx;
-               mtf->uv[3][1]=uvy;
+       if(bb->uv_split > 1 && bb->uv[2] >= 0){
+               mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1);
+               mtf->uv[0][0] = uvx + uvdx;
+               mtf->uv[0][1] = uvy + uvdy;
+               mtf->uv[1][0] = uvx;
+               mtf->uv[1][1] = uvy + uvdy;
+               mtf->uv[2][0] = uvx;
+               mtf->uv[2][1] = uvy;
+               mtf->uv[3][0] = uvx + uvdx;
+               mtf->uv[3][1] = uvy;
        }
 }
-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,
-                                                               int totcol, MCol *mcol, float size, int seed, int override_uv,
-                                                               int adapt, float adapt_angle, float adapt_pix)
+static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, float *loc, float *loc1,    int seed)
 {
        HaloRen *har=0;
-       if(path){
-               if(ma->mode&MA_WIRE)
-                       static_particle_wire(obr, ma, loc, loc1, first, line);
-               else if(ma->mode & MA_HALO){
-                       har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, orco, uvco, size, 1.0, seed);
-                       if(har) har->lay= obr->ob->lay;
+
+       if(ma->mode&MA_WIRE)
+               static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
+       else if(ma->mode & MA_HALO){
+               har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed);
+               if(har) har->lay= obr->ob->lay;
+       }
+       else
+               static_particle_strand(re, obr, ma, sd, loc, loc1);
+}
+static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd)
+{
+       int i;
+
+       /* get uvco */
+       if(sd->uvco && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
+               for(i=0; i<sd->totuv; i++) {
+                       if(num != DMCACHE_NOTFOUND) {
+                               MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
+                               MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
+                               mtface += num;
+                               
+                               psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i);
+                       }
+                       else {
+                               sd->uvco[2*i] = 0.0f;
+                               sd->uvco[2*i + 1] = 0.0f;
+                       }
                }
-               else
-                       static_particle_strand(re, obr, ma, orco, surfnor, uvco, totuv, mcol, totcol, loc, loc1, time, first, line, adapt, adapt_angle, adapt_pix, override_uv);
        }
-       else{
-               har= RE_inithalo_particle(re, obr, dm, ma, loc, NULL, orco, uvco, size, 0.0, seed);
-               if(har) har->lay= obr->ob->lay;
+
+       /* get mcol */
+       if(sd->mcol && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
+               for(i=0; i<sd->totcol; i++) {
+                       if(num != DMCACHE_NOTFOUND) {
+                               MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
+                               MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
+                               mc += num * 4;
+
+                               psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i);
+                       }
+                       else
+                               memset(&sd->mcol[i], 0, sizeof(MCol));
+               }
        }
 }
 static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
 {
        Object *ob= obr->ob;
-       Object *tob=0, *bb_ob=re->scene->camera;
+       Object *tob=0;
        Material *ma=0;
        MTFace *mtface;
        ParticleSystemModifierData *psmd;
@@ -1466,19 +1445,20 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        ParticleKey *states=0;
        ParticleKey state;
        ParticleCacheKey *cache=0;
+       ParticleBillboardData bb;
+       ParticleStrandData sd;
        StrandBuffer *strandbuf=0;
        StrandVert *svert=0;
        StrandBound *sbound= 0;
        StrandRen *strand=0;
        RNG *rng= 0;
-       MCol *mcol= 0;
        float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
-       float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f;
+       float strandlen=0.0f, curlen=0.0f;
        float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0);
-       float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2];
-       int i, a, k, max_k=0, totpart, totuv=0, totcol=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0;
-       int path_possible=0, keys_possible=0, baked_keys=0, totchild=0;
-       int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num;
+       float random, simplify[2];
+       int i, a, k, max_k=0, totpart, dosimplify = 0, dosurfacecache = 0;
+       int totchild=0;
+       int seed, path_nbr=0, orco1=0, num;
        int totface, *origindex = 0;
        char **uv_name=0;
 
@@ -1505,6 +1485,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        return 1;
        }
 
+       /* last possibility to bail out! */
        psmd= psys_get_modifier(ob,psys);
        if(!(psmd->modifier.mode & eModifierMode_Render))
                return 0;
@@ -1513,182 +1494,182 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                totchild = (int)((float)totchild * (float)part->disp / 100.0f);
        }
 
-       psys->flag|=PSYS_DRAWING;
+       psys->flag |= PSYS_DRAWING;
 
        rng= rng_new(psys->seed);
-       
-       ma= give_render_material(re, ob, part->omat);
 
-       if(part->bb_ob)
-               bb_ob=part->bb_ob;
+       totpart=psys->totpart;
+
+       memset(&sd, 0, sizeof(ParticleStrandData));
+       sd.override_uv = -1;
+
+/* 2.1 setup material stff */
+       ma= give_render_material(re, ob, part->omat);
        
        if(ma->ipo){
                calc_ipo(ma->ipo, cfra);
                execute_ipo((ID *)ma, ma->ipo);
        }
 
+       hasize = ma->hasize;
+       seed = ma->seed1;
+
+       re->flag |= R_HALO;
+
        RE_set_customdata_names(obr, &psmd->dm->faceData);
-       totuv=CustomData_number_of_layers(&psmd->dm->faceData,CD_MTFACE);
-       totcol=CustomData_number_of_layers(&psmd->dm->faceData,CD_MCOL);
+       sd.totuv = CustomData_number_of_layers(&psmd->dm->faceData, CD_MTFACE);
+       sd.totcol = CustomData_number_of_layers(&psmd->dm->faceData, CD_MCOL);
 
-       if(ma->texco & TEXCO_UV && totuv) {
-               uvco = MEM_callocN(totuv*2*sizeof(float),"particle_uvs");
+       if(ma->texco & TEXCO_UV && sd.totuv) {
+               sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
 
                if(ma->strand_uvname[0]) {
-                       override_uv= CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,ma->strand_uvname);
-                       override_uv-= CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE);
+                       sd.override_uv = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, ma->strand_uvname);
+                       sd.override_uv -= CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
                }
        }
+       else
+               sd.uvco = NULL;
 
-       if(totcol)
-               mcol = MEM_callocN(totcol*sizeof(MCol),"particle_mcols");
+       if(sd.totcol)
+               sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols");
 
-       if(part->draw_as==PART_DRAW_BB){
-               int first_uv=CustomData_get_layer_index(&psmd->dm->faceData,CD_MTFACE);
+/* 2.2 setup billboards */
+       if(part->draw_as == PART_DRAW_BB) {
+               int first_uv = CustomData_get_layer_index(&psmd->dm->faceData, CD_MTFACE);
 
-               uv[0]=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,psys->bb_uvname[0]);
-               if(uv[0]<0)
-                       uv[0]=CustomData_get_active_layer_index(&psmd->dm->faceData,CD_MTFACE);
+               bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[0]);
+               if(bb.uv[0] < 0)
+                       bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm->faceData, CD_MTFACE);
 
-               uv[1]=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,psys->bb_uvname[1]);
-               //if(uv[1]<0)
-               //      uv[1]=CustomData_get_active_layer_index(&psmd->dm->faceData,CD_MTFACE);
+               bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[1]);
 
-               uv[2]=CustomData_get_named_layer_index(&psmd->dm->faceData,CD_MTFACE,psys->bb_uvname[2]);
-               //if(uv[2]<0)
-               //      uv[2]=CustomData_get_active_layer_index(&psmd->dm->faceData,CD_MTFACE);
+               bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm->faceData, CD_MTFACE, psys->bb_uvname[2]);
 
-               if(first_uv>=0){
-                       uv[0]-=first_uv;
-                       uv[1]-=first_uv;
-                       uv[2]-=first_uv;
+               if(first_uv >= 0) {
+                       bb.uv[0] -= first_uv;
+                       bb.uv[1] -= first_uv;
+                       bb.uv[2] -= first_uv;
                }
+
+               bb.align = part->bb_align;
+               bb.anim = part->bb_anim;
+               bb.lock = part->draw & PART_DRAW_BB_LOCK;
+               bb.ob = (part->bb_ob ? part->bb_ob : re->scene->camera);
+               bb.offset[0] = part->bb_offset[0];
+               bb.offset[1] = part->bb_offset[1];
+               bb.split_offset = part->bb_split_offset;
+               bb.totnum = totpart+totchild;
+               bb.uv_split = part->bb_uv_split;
        }
 
-       if(part->flag&PART_ABS_TIME && part->ipo){
+/* 2.3 setup time */
+       if(part->flag&PART_ABS_TIME && part->ipo) {
                calc_ipo(part->ipo, cfra);
                execute_ipo((ID *)part, part->ipo);
        }
 
-       if(part->flag&PART_GLOB_TIME)
-               cfra=bsystem_time(0,(float)CFRA,0.0);
+       if(part->flag & PART_GLOB_TIME)
+               cfra = bsystem_time(0, (float)CFRA, 0.0);
 
-       if(part->type==PART_REACTOR){
+/* 2.4 setup reactors */
+       if(part->type == PART_REACTOR){
                psys_get_reactor_target(ob, psys, &tob, &tpsys);
                if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
-                       psmd=psys_get_modifier(tob,tpsys);
-                       tpart=tpsys->part;
+                       psmd = psys_get_modifier(tob,tpsys);
+                       tpart = tpsys->part;
                }
        }
-
-       hasize = ma->hasize;
-       seed = ma->seed1;
-
-       re->flag |= R_HALO;
        
+/* 2.5 setup matrices */
        MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
        MTC_Mat4Invert(ob->imat, mat);  /* need to be that way, for imat texture */
        Mat3CpyMat4(nmat, ob->imat);
        Mat3Transp(nmat);
 
-       totpart=psys->totpart;
+/* 2.6 setup strand rendering */
+       if(part->draw_as == PART_DRAW_PATH && psys->pathcache){
+               path_nbr=(int)pow(2.0,(double) part->ren_step);
 
-       if(psys->pathcache){
-               path_possible=1;
-               keys_possible=1;
-       }
-       if(part->draw_as==PART_DRAW_PATH){
-               if(path_possible){
-                       path_nbr=(int)pow(2.0,(double) part->ren_step);
-                       //if(part->phystype==PART_PHYS_KEYED && (psys->flag&PSYS_BAKED)==0)
-                       //      path_nbr*=psys->totkeyed;
-
-                       if(path_nbr) {
-                               if((ma->mode & (MA_HALO|MA_WIRE))==0) {
-                                       orco= MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
-                                       set_object_orco(re, psys, orco);
-                               }
-                               path=1;
+               if(path_nbr) {
+                       if((ma->mode & (MA_HALO|MA_WIRE))==0) {
+                               sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
+                               set_object_orco(re, psys, sd.orco);
                        }
+               }
 
-                       if(part->draw&PART_DRAW_REN_ADAPT) {
-                               adapt=1;
-                               adapt_pix=(float)part->adapt_pix;
-                               adapt_angle=cos((float)part->adapt_angle*(float)(M_PI/180.0));
-                       }
+               if(part->draw & PART_DRAW_REN_ADAPT) {
+                       sd.adapt = 1;
+                       sd.adapt_pix = (float)part->adapt_pix;
+                       sd.adapt_angle = cos((float)part->adapt_angle * (float)(M_PI / 180.0));
+               }
 
-                       if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) {
-                               strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
-                               strandbuf->ma= ma;
-                               strandbuf->lay= ob->lay;
-                               Mat4CpyMat4(strandbuf->winmat, re->winmat);
-                               strandbuf->winx= re->winx;
-                               strandbuf->winy= re->winy;
-                               strandbuf->maxdepth= 2;
-                               strandbuf->adaptcos= cos((float)part->adapt_angle*(float)(M_PI/180.0));
-                               strandbuf->overrideuv= override_uv;
-                               strandbuf->minwidth= ma->strand_min;
-
-                               if(ma->strand_widthfade == 0.0f)
-                                       strandbuf->widthfade= 0.0f;
-                               else if(ma->strand_widthfade >= 1.0f)
-                                       strandbuf->widthfade= 2.0f - ma->strand_widthfade;
-                               else
-                                       strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
+               if(re->r.renderer==R_INTERN && part->draw&PART_DRAW_REN_STRAND) {
+                       strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
+                       strandbuf->ma= ma;
+                       strandbuf->lay= ob->lay;
+                       Mat4CpyMat4(strandbuf->winmat, re->winmat);
+                       strandbuf->winx= re->winx;
+                       strandbuf->winy= re->winy;
+                       strandbuf->maxdepth= 2;
+                       strandbuf->adaptcos= cos((float)part->adapt_angle*(float)(M_PI/180.0));
+                       strandbuf->overrideuv= sd.override_uv;
+                       strandbuf->minwidth= ma->strand_min;
+
+                       if(ma->strand_widthfade == 0.0f)
+                               strandbuf->widthfade= 0.0f;
+                       else if(ma->strand_widthfade >= 1.0f)
+                               strandbuf->widthfade= 2.0f - ma->strand_widthfade;
+                       else
+                               strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
 
-                               if(part->flag & PART_HAIR_BSPLINE)
-                                       strandbuf->flag |= R_STRAND_BSPLINE;
-                               if(ma->mode & MA_STR_B_UNITS)
-                                       strandbuf->flag |= R_STRAND_B_UNITS;
+                       if(part->flag & PART_HAIR_BSPLINE)
+                               strandbuf->flag |= R_STRAND_BSPLINE;
+                       if(ma->mode & MA_STR_B_UNITS)
+                               strandbuf->flag |= R_STRAND_B_UNITS;
 
-                               svert= strandbuf->vert;
+                       svert= strandbuf->vert;
 
-                               if(re->r.mode & R_SPEED)
+                       if(re->r.mode & R_SPEED)
+                               dosurfacecache= 1;
+                       else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
+                               if(ma->amb != 0.0f)
                                        dosurfacecache= 1;
-                               else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
-                                       if(ma->amb != 0.0f)
-                                               dosurfacecache= 1;
-
-                               totface= psmd->dm->getNumFaces(psmd->dm);
-                               origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX);
-                               if(origindex) {
-                                       for(a=0; a<totface; a++)
-                                               strandbuf->totbound= MAX2(strandbuf->totbound, origindex[a]);
-                                       strandbuf->totbound++;
-                               }
+
+                       totface= psmd->dm->getNumFaces(psmd->dm);
+                       origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX);
+                       if(origindex) {
+                               for(a=0; a<totface; a++)
+                                       strandbuf->totbound= MAX2(strandbuf->totbound, origindex[a]);
                                strandbuf->totbound++;
-                               strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
-                               sbound= strandbuf->bound;
-                               sbound->start= sbound->end= 0;
                        }
+                       strandbuf->totbound++;
+                       strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
+                       sbound= strandbuf->bound;
+                       sbound->start= sbound->end= 0;
                }
        }
-       else if(keys_possible && part->draw&PART_DRAW_KEYS){
-               path_nbr=part->keys_step;
-               if(path_nbr==0)
-                       baked_keys=1;
-       }
 
-       if(orco==0){
-               orco=MEM_mallocN(3*sizeof(float),"particle orco");
-               orco1=1;
+       if(sd.orco == 0) {
+               sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco");
+               orco1 = 1;
        }
 
-       if(path_nbr==0)
-               psys->lattice=psys_get_lattice(ob,psys);
+       if(path_nbr == 0)
+               psys->lattice = psys_get_lattice(ob, psys);
 
 /* 3. start creating renderable things */
        for(a=0,pa=pars; a<totpart+totchild; a++, pa++, seed++) {
                random = rng_getFloat(rng);
-
+               /* setup per particle individual stuff */
                if(a<totpart){
                        if(pa->flag & PARS_UNEXIST) continue;
 
                        pa_time=(cfra-pa->time)/pa->lifetime;
-                       if((part->flag&PART_ABS_TIME)==0){
-                               if(ma->ipo){
+                       if((part->flag&PART_ABS_TIME) == 0) {
+                               if(ma->ipo) {
                                        /* correction for lifetime */
-                                       calc_ipo(ma->ipo, 100.0f*pa_time);
+                                       calc_ipo(ma->ipo, 100.0f * pa_time);
                                        execute_ipo((ID *)ma, ma->ipo);
                                }
                                if(part->ipo){
@@ -1703,51 +1684,25 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        /* get orco */
                        if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
                                tpa=tpsys->particles+pa->num;
-                               psys_particle_on_emitter(psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,orco,0);
+                               psys_particle_on_emitter(psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,sd.orco,0);
                        }
                        else
-                               psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,0);
+                               psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,sd.orco,0);
 
+                       /* get uvco & mcol */
                        num= pa->num_dmcache;
 
                        if(num == DMCACHE_NOTFOUND)
                                if(pa->num < psmd->dm->getNumFaces(psmd->dm))
                                        num= pa->num;
 
-                       if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
-                               for(i=0; i<totuv; i++){
-                                       if(num != DMCACHE_NOTFOUND) {
-                                               MFace *mface=psmd->dm->getFaceData(psmd->dm,num,CD_MFACE);
-                                               mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
-                                               mtface+=num;
-                                               
-                                               psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i);
-                                       }
-                                       else {
-                                               uvco[2*i]= 0.0f;
-                                               uvco[2*i + 1]= 0.0f;
-                                       }
-                               }
-                       }
-                       if(mcol && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
-                               for(i=0; i<totcol; i++){
-                                       if(num != DMCACHE_NOTFOUND) {
-                                               MFace *mface=psmd->dm->getFaceData(psmd->dm,num,CD_MFACE);
-                                               MCol *mc=(MCol*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MCOL,i);
-                                               mc+=num*4;
-
-                                               psys_interpolate_mcol(mc,mface->v4,pa->fuv,mcol+i);
-                                       }
-                                       else
-                                               memset(&mcol[i], 0, sizeof(MCol));
-                               }
-                       }
+                       get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
 
-                       pa_size=pa->size;
+                       pa_size = pa->size;
 
-                       r_tilt=1.0f+pa->r_ave[0];
+                       r_tilt = 1.0f + pa->r_ave[0];
 
-                       if(path_nbr){
+                       if(path_nbr) {
                                cache = psys->pathcache[a];
                                max_k = (int)cache->steps;
                        }
@@ -1756,123 +1711,67 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                }
                else {
                        ChildParticle *cpa= psys->child+a-totpart;
+
+                       if(path_nbr) {
+                               cache = psys->childcache[a-totpart];
+
+                               if(cache->steps < 0)
+                                       continue;
+
+                               max_k = (int)cache->steps;
+                       }
                        
-                       pa_time=psys_get_child_time(psys, cpa, cfra);
+                       pa_time = psys_get_child_time(psys, cpa, cfra);
 
-                       if((part->flag&PART_ABS_TIME)==0){
-                               if(ma->ipo){
+                       if((part->flag & PART_ABS_TIME) == 0) {
+                               if(ma->ipo) {
                                        /* correction for lifetime */
-                                       calc_ipo(ma->ipo, 100.0f*pa_time);
+                                       calc_ipo(ma->ipo, 100.0f * pa_time);
                                        execute_ipo((ID *)ma, ma->ipo);
                                }
-                               if(part->ipo){
+                               if(part->ipo) {
                                        /* correction for lifetime */
-                                       calc_ipo(part->ipo, 100.0f*pa_time);
+                                       calc_ipo(part->ipo, 100.0f * pa_time);
                                        execute_ipo((ID *)part, part->ipo);
                                }
                        }
 
-                       pa_size=psys_get_child_size(psys, cpa, cfra, &pa_time);
+                       pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);
 
-                       r_tilt=2.0f*cpa->rand[2];
+                       r_tilt = 2.0f * cpa->rand[2];
 
-                       num= cpa->num;
+                       num = cpa->num;
 
                        /* get orco */
                        if(part->childtype == PART_CHILD_FACES) {
                                psys_particle_on_emitter(psmd,
                                        PART_FROM_FACE, cpa->num,DMCACHE_ISCHILD,
-                                       cpa->fuv,cpa->foffset,co,nor,0,0,orco,0);
+                                       cpa->fuv,cpa->foffset,co,nor,0,0,sd.orco,0);
                        }
                        else {
                                ParticleData *par = psys->particles + cpa->parent;
                                psys_particle_on_emitter(psmd, part->from,
                                        par->num,DMCACHE_ISCHILD,par->fuv,
-                                       par->foffset,co,nor,0,0,orco,0);
+                                       par->foffset,co,nor,0,0,sd.orco,0);
                        }
 
-                       if(uvco){
-                               if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
-                                       for(i=0; i<totuv; i++){
-                                               if(part->childtype==PART_CHILD_FACES){
-                                                       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;
-                                                       
-                                                       psys_interpolate_uvs(mtface,mface->v4,cpa->fuv,uvco+2*i);
-                                               }
-                                               else{
-                                                       uvco[2*i]=uvco[2*i+1]=0.0f;
-                                               }
-                                       }
-                               }
-                               else if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
-                                       ParticleData *parent = psys->particles + cpa->parent;
-                                       num= parent->num_dmcache;
-
-                                       if(num == DMCACHE_NOTFOUND)
-                                               if(parent->num < psmd->dm->getNumFaces(psmd->dm))
-                                                       num= parent->num;
-
-                                       for(i=0; i<totuv; i++) {
-                                               if(num != DMCACHE_NOTFOUND) {
-                                                       MFace *mface=psmd->dm->getFaceData(psmd->dm,num,CD_MFACE);
-                                                       mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i);
-                                                       mtface+=num;
-                                                       psys_interpolate_uvs(mtface,mface->v4,parent->fuv,uvco+2*i);
-                                               }
-                                               else {
-                                                       uvco[2*i]= 0.0f;
-                                                       uvco[2*i + 1]= 0.0f;
-                                               }
-                                       }
-                               }
-                       }
-
-                       if(mcol){
-                               if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
-                                       for(i=0; i<totcol; i++){
-                                               if(part->childtype==PART_CHILD_FACES){
-                                                       MFace *mface=psmd->dm->getFaceData(psmd->dm,cpa->num,CD_MFACE);
-                                                       MCol *mc=(MCol*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MCOL,i);
-                                                       mc+=cpa->num*4;
-                                                       
-                                                       psys_interpolate_mcol(mc,mface->v4,cpa->fuv,mcol+i);
-                                               }
-                                               else
-                                                       memset(&mcol[i], 0, sizeof(MCol));
-                                       }
-                               }
-                               else if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){
-                                       ParticleData *parent = psys->particles + cpa->parent;
-                                       num= parent->num_dmcache;
-
-                                       if(num == DMCACHE_NOTFOUND)
-                                               if(parent->num < psmd->dm->getNumFaces(psmd->dm))
-                                                       num= parent->num;
-
-                                       for(i=0; i<totcol; i++){
-                                               if(num != DMCACHE_NOTFOUND) {
-                                                       MFace *mface=psmd->dm->getFaceData(psmd->dm,num,CD_MFACE);
-                                                       MCol *mc=(MCol*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MCOL,i);
-                                                       mc+=num*4;
-                                                       
-                                                       psys_interpolate_mcol(mc,mface->v4,parent->fuv,mcol+i);
-                                               }
-                                               else
-                                                       memset(&mcol[i], 0, sizeof(MCol));
-                                       }
-                               }
+                       /* get uvco & mcol */
+                       if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
+                               get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
                        }
+                       else {
+                               ParticleData *parent = psys->particles + cpa->parent;
+                               num = parent->num_dmcache;
 
-                       dosimplify= psys_render_simplify_params(psys, cpa, simplify);
+                               if(num == DMCACHE_NOTFOUND)
+                                       if(parent->num < psmd->dm->getNumFaces(psmd->dm))
+                                               num = parent->num;
 
-                       if(path_nbr && psys->childcache) {
-                               cache = psys->childcache[a-totpart];
-                               max_k = (int)cache->steps;
+                               get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
                        }
 
+                       dosimplify = psys_render_simplify_params(psys, cpa, simplify);
+
                        if(strandbuf) {
                                if(origindex[cpa->num]+1 > sbound - strandbuf->bound) {
                                        sbound= strandbuf->bound + origindex[cpa->num]+1;
@@ -1884,17 +1783,17 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                /* surface normal shading setup */
                if(ma->mode_l & MA_STR_SURFDIFF) {
                        Mat3MulVecfl(nmat, nor);
-                       surfnor= nor;
+                       sd.surfnor= nor;
                }
                else
-                       surfnor= NULL;
+                       sd.surfnor= NULL;
 
                /* strand render setup */
                if(strandbuf) {
                        strand= RE_findOrAddStrand(obr, obr->totstrand++);
                        strand->buffer= strandbuf;
                        strand->vert= svert;
-                       VECCOPY(strand->orco, orco);
+                       VECCOPY(strand->orco, sd.orco);
 
                        if(dosimplify) {
                                float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
@@ -1902,9 +1801,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                ssimplify[1]= simplify[1];
                        }
 
-                       if(surfnor) {
+                       if(sd.surfnor) {
                                float *snor= RE_strandren_get_surfnor(obr, strand, 1);
-                               VECCOPY(snor, surfnor);
+                               VECCOPY(snor, sd.surfnor);
                        }
 
                        if(dosurfacecache && num >= 0) {
@@ -1912,20 +1811,20 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                *facenum= num;
                        }
 
-                       if(uvco) {
-                               for(i=0; i<totuv; i++) {
-                                       if(i != override_uv) {
+                       if(sd.uvco) {
+                               for(i=0; i<sd.totuv; i++) {
+                                       if(i != sd.override_uv) {
                                                float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
 
-                                               uv[0]= uvco[2*i];
-                                               uv[1]= uvco[2*i+1];
+                                               uv[0]= sd.uvco[2*i];
+                                               uv[1]= sd.uvco[2*i+1];
                                        }
                                }
                        }
-                       if(mcol) {
-                               for(i=0; i<totcol; i++) {
+                       if(sd.mcol) {
+                               for(i=0; i<sd.totcol; i++) {
                                        MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1);
-                                       *mc = mcol[i];
+                                       *mc = sd.mcol[i];
                                }
                        }
 
@@ -1941,11 +1840,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                        strandlen += VecLenf((cache+k-1)->co, (cache+k)->co);
                }
 
-               for(k=0; k<=path_nbr; k++){
-                       if(path_nbr){
+               if(path_nbr) {
+                       /* render strands */
+                       for(k=0; k<=path_nbr; k++){
                                if(k<=max_k){
-                                       //bti->convert_bake_key(bsys,cache+k,0,(void*)&state);
-                                       //copy_particle_key(&state,cache+k,0);
                                        VECCOPY(state.co,(cache+k)->co);
                                        VECCOPY(state.vel,(cache+k)->vel);
                                }
@@ -1955,65 +1853,95 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                if(k > 0)
                                        curlen += VecLenf((cache+k-1)->co, (cache+k)->co);
                                time= curlen/strandlen;
-                       }
-                       else{
-                               time=0.0f;
-                               state.time=cfra;
-                               if(psys_get_particle_state(ob,psys,a,&state,0)==0)
-                                       continue;
+
+                               VECCOPY(loc,state.co);
+                               MTC_Mat4MulVecfl(re->viewmat,loc);
+
+                               if(strandbuf) {
+                                       VECCOPY(svert->co, loc);
+                                       svert->strandco= -1.0f + 2.0f*time;
+                                       svert++;
+                                       strand->totvert++;
+                               }
+                               else{
+                                       sd.first = 0;
+                                       sd.time = time;
+                                       sd.size = hasize;
+
+                                       if(k==1){
+                                               sd.first = 1;
+                                               sd.time = 0.0f;
+                                               VECSUB(loc0,loc1,loc);
+                                               VECADD(loc0,loc1,loc0);
+                                       }
+
+                                       if(k)
+                                               render_new_particle(re, obr, psmd->dm, ma, &sd, loc, loc1, seed);
+
+                                       VECCOPY(loc1,loc);
+                               }
                        }
 
+               }
+               else {
+                       /* render normal particles */
+                       time=0.0f;
+                       state.time=cfra;
+                       if(psys_get_particle_state(ob,psys,a,&state,0)==0)
+                               continue;
+
                        VECCOPY(loc,state.co);
                        if(part->draw_as!=PART_DRAW_BB)
                                MTC_Mat4MulVecfl(re->viewmat,loc);
 
-                       if(part->draw_as==PART_DRAW_LINE) {
-                               VECCOPY(vel,state.vel);
-                               //VECADD(vel,vel,state.co);
-                               MTC_Mat4Mul3Vecfl(re->viewmat,vel);
-                               //VECSUB(vel,vel,loc);
-                               Normalize(vel);
-                               if(part->draw & PART_DRAW_VEL_LENGTH)
-                                       VecMulf(vel,VecLength(state.vel));
-                               VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
-                               VECADDFAC(loc1,loc,vel,part->draw_line[1]);
-
-                               render_new_particle(re,obr,psmd->dm,ma,1,0,1,0.0f,loc0,loc1,
-                                                                       orco,surfnor,totuv,uvco,totcol,mcol,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,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);
-                       }
-                       else if(strandbuf) { if(svert) {
-                               VECCOPY(svert->co, loc);
-                               svert->strandco= -1.0f + 2.0f*time;
-                               svert++;
-                               strand->totvert++;
-                       } }
-                       else{
-                               if(k==1){
-                                       VECSUB(loc0,loc1,loc);
-                                       VECADD(loc0,loc1,loc0);
-                                       render_new_particle(re,obr,psmd->dm,ma,path,1,0,0.0f,loc1,loc0,
-                                                                               orco,surfnor,totuv,uvco,totcol,mcol,hasize,seed,override_uv,
-                                                                               adapt,adapt_angle,adapt_pix);
-                               }
+                       switch(part->draw_as) {
+                               case PART_DRAW_LINE:
+                                       sd.line = 1;
+                                       sd.time = 0.0f;
+                                       sd.size = hasize;
+
+                                       VECCOPY(vel,state.vel);
+                                       MTC_Mat4Mul3Vecfl(re->viewmat,vel);
+                                       Normalize(vel);
+
+                                       if(part->draw & PART_DRAW_VEL_LENGTH)
+                                               VecMulf(vel,VecLength(state.vel));
+
+                                       VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
+                                       VECADDFAC(loc1,loc,vel,part->draw_line[1]);
 
-                               if(path_nbr==0 || k)
-                                       render_new_particle(re,obr,psmd->dm,ma,path,0,0,time,loc,loc1,
-                                                                               orco,surfnor,totuv,uvco,totcol,mcol,hasize,seed,override_uv,
-                                                                               adapt,adapt_angle,adapt_pix);
+                                       render_new_particle(re,obr,psmd->dm,ma,&sd,loc0,loc1,seed);
 
-                               VECCOPY(loc1,loc);
+                                       break;
+
+                               case PART_DRAW_BB:
+                                       bb.random = random;
+                                       bb.size = pa_size;
+                                       bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+                                       bb.time = pa_time;
+                                       bb.num = a;
+                                       VECCOPY(bb.vec, loc);
+                                       VECCOPY(bb.vel, state.vel);
+
+                                       particle_billboard(re, obr, ma, &bb);
+
+                                       break;
+
+                               default:
+                               {
+                                       HaloRen *har=0;
+
+                                       har = RE_inithalo_particle(re, obr, psmd->dm, ma, loc, NULL, sd.orco, sd.uvco, hasize, 0.0, seed);
+                                       
+                                       if(har) har->lay= obr->ob->lay;
+
+                                       break;
+                               }
                        }
                }
 
                if(orco1==0)
-                       orco+=3;
+                       sd.orco+=3;
 
                if(re->test_break())
                        break;
@@ -2026,13 +1954,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        if(ma) do_mat_ipo(ma);
 
        if(orco1)
-               MEM_freeN(orco);
+               MEM_freeN(sd.orco);
 
-       if(uvco)
-               MEM_freeN(uvco);
+       if(sd.uvco)
+               MEM_freeN(sd.uvco);
        
-       if(mcol)
-               MEM_freeN(mcol);
+       if(sd.mcol)
+               MEM_freeN(sd.mcol);
 
        if(uv_name)
                MEM_freeN(uv_name);
@@ -2049,7 +1977,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                psys->lattice=0;
        }
 
-       if(path && (ma->mode_l & MA_TANGENT_STR)==0)
+       if(path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
                calc_vertexnormals(re, obr, 0, 0);
 
        return 1;
index 2063ac42bb1b6b385393ce6b4532bcd3e10ec5b9..c9fffa407ee38bc88f8f6974138164f86b1c9a74 100644 (file)
@@ -2910,6 +2910,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
        ParticleData *pars, *pa;
        ParticleKey state, *states=0;
        ParticleCacheKey *cache=0;
+       ParticleBillboardData bb;
        Material *ma;
        Object *bb_ob=0;
        float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
@@ -2917,8 +2918,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
        float cfra=bsystem_time(ob,(float)CFRA,0.0);
        float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
        float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
-       int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
-       int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
+       int a, k, k_max=0, totpart, totpoint=0, draw_as, totchild=0;
        int select=ob->flag&SELECT, create_cdata=0;
        GLint polygonmode[2];
        char val[32];
@@ -3004,18 +3004,9 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
        if(part->flag&PART_GLOB_TIME)
                cfra=bsystem_time(0,(float)CFRA,0.0);
 
-       if(psys->pathcache){
-               path_possible=1;
-               keys_possible=1;
-       }
-       if(draw_as==PART_DRAW_PATH && path_possible==0)
+       if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL)
                draw_as=PART_DRAW_DOT;
 
-       if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
-               path_nbr=part->keys_step;
-               draw_keys=1;
-       }
-
 /* 3. */
        switch(draw_as){
                case PART_DRAW_DOT:
@@ -3064,12 +3055,15 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                                        glPointSize(2.0); /* default dot size */
                        }
                        else if(part->bb_ob)
-                               bb_ob=part->bb_ob;
+                               bb.ob=part->bb_ob;
                        else
-                               bb_ob=G.vd->camera;
+                               bb.ob=G.vd->camera;
 
-                       if(part->bb_align<PART_BB_VIEW)
-                               onevec[part->bb_align]=1.0f;
+                       bb.align = part->bb_align;
+                       bb.anim = part->bb_anim;
+                       bb.lock = part->draw & PART_DRAW_BB_LOCK;
+                       bb.offset[0] = part->bb_offset[0];
+                       bb.offset[1] = part->bb_offset[1];
                        break;
                case PART_DRAW_PATH:
                        break;
@@ -3081,35 +3075,37 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
        }
 
 /* 4. */
-       if(draw_as && draw_as!=PART_DRAW_PATH){
-               if(draw_as!=PART_DRAW_CIRC){
-                       switch(draw_as){
+       if(draw_as && draw_as!=PART_DRAW_PATH) {
+               int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
+
+               if(draw_as!=PART_DRAW_CIRC) {
+                       switch(draw_as) {
                                case PART_DRAW_AXIS:
                                case PART_DRAW_CROSS:
-                                       if(draw_as!=PART_DRAW_CROSS || create_cdata)
-                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
-                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
+                                       if(draw_as != PART_DRAW_CROSS || create_cdata)
+                                               cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
+                                       vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
                                        break;
                                case PART_DRAW_LINE:
                                        if(create_cdata)
-                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
-                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
+                                               cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
+                                       vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
                                        break;
                                case PART_DRAW_BB:
                                        if(create_cdata)
-                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
-                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
-                                       ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
+                                               cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
+                                       vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
+                                       ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
                                        break;
                                default:
                                        if(create_cdata)
-                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
-                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
+                                               cdata=MEM_callocN(tot_vec_size, "particle_cdata");
+                                       vdata=MEM_callocN(tot_vec_size, "particle_vdata");
                        }
                }
 
-               if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
-                       vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
+               if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE)
+                       vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
 
                vd=vdata;
                ved=vedata;
@@ -3122,6 +3118,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
        if(draw_as){
 /* 5. */
                for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
+                       /* setup per particle individual stuff */
                        if(a<totpart){
                                if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
                                if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
@@ -3159,11 +3156,6 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                                }
 
                                r_tilt=1.0f+pa->r_ave[0];
-
-                               if(path_nbr){
-                                       cache=psys->pathcache[a];
-                                       k_max=(int)(cache->steps);
-                               }
                        }
                        else{
                                ChildParticle *cpa= &psys->child[a-totpart];
@@ -3191,47 +3183,23 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                                pa_size=psys_get_child_size(psys,cpa,cfra,0);
 
                                r_tilt=2.0f*cpa->rand[2];
-                               if(path_nbr){
-                                       cache=psys->childcache[a-totpart];
-                                       k_max=(int)(cache->steps);
-                               }
                        }
 
                        if(draw_as!=PART_DRAW_PATH){
-                               int next_pa=0;
-                               for(k=0; k<=path_nbr; k++){
-                                       if(draw_keys){
-                                               state.time=(float)k/(float)path_nbr;
-                                               psys_get_particle_on_path(ob,psys,a,&state,1);
-                                       }
-                                       else if(path_nbr){
-                                               if(k<=k_max){
-                                                       VECCOPY(state.co,(cache+k)->co);
-                                                       VECCOPY(state.vel,(cache+k)->vel);
-                                                       QUATCOPY(state.rot,(cache+k)->rot);
-                                               }
-                                               else
-                                                       continue;       
-                                       }
-                                       else{
-                                               state.time=cfra;
-                                               if(psys_get_particle_state(ob,psys,a,&state,0)==0){
-                                                       next_pa=1;
-                                                       break;
-                                               }
-                                       }
-
+                               state.time=cfra;
+                               if(psys_get_particle_state(ob,psys,a,&state,0)){
+                                       /* create actiual particle data */
                                        switch(draw_as){
                                                case PART_DRAW_DOT:
+                                                       if(vd){
+                                                               VECCOPY(vd,state.co) vd+=3;
+                                                       }
                                                        if(cd) {
                                                                cd[0]=ma_r;
                                                                cd[1]=ma_g;
                                                                cd[2]=ma_b;
                                                                cd+=3;
                                                        }
-                                                       if(vd){
-                                                               VECCOPY(vd,state.co) vd+=3;
-                                                       }
                                                        break;
                                                case PART_DRAW_CROSS:
                                                case PART_DRAW_AXIS:
@@ -3314,59 +3282,15 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                                                                cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
                                                                cd+=12;
                                                        }
-                                                       if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){
-                                                               VECCOPY(xvec,bb_ob->obmat[0]);
-                                                               Normalize(xvec);
-                                                               VECCOPY(yvec,bb_ob->obmat[1]);
-                                                               Normalize(yvec);
-                                                               VECCOPY(zvec,bb_ob->obmat[2]);
-                                                               Normalize(zvec);
-                                                       }
-                                                       else if(part->bb_align==PART_BB_VEL){
-                                                               float temp[3];
-                                                               VECCOPY(temp,state.vel);
-                                                               Normalize(temp);
-                                                               VECSUB(zvec,bb_ob->obmat[3],state.co);
-                                                               if(part->draw&PART_DRAW_BB_LOCK){
-                                                                       float fac=-Inpf(zvec,temp);
-                                                                       VECADDFAC(zvec,zvec,temp,fac);
-                                                               }
-                                                               Normalize(zvec);
-                                                               Crossf(xvec,temp,zvec);
-                                                               Normalize(xvec);
-                                                               Crossf(yvec,zvec,xvec);
-                                                       }
-                                                       else{
-                                                               VECSUB(zvec,bb_ob->obmat[3],state.co);
-                                                               if(part->draw&PART_DRAW_BB_LOCK)
-                                                                       zvec[part->bb_align]=0.0f;
-                                                               Normalize(zvec);
-
-                                                               if(part->bb_align<PART_BB_VIEW)
-                                                                       Crossf(xvec,onevec,zvec);
-                                                               else
-                                                                       Crossf(xvec,bb_ob->obmat[1],zvec);
-                                                               Normalize(xvec);
-                                                               Crossf(yvec,zvec,xvec);
-                                                       }
 
-                                                       VECCOPY(vec,xvec);
-                                                       VECCOPY(vec2,yvec);
-
-                                                       VecMulf(xvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
-                                                       VecMulf(vec2,sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
-                                                       VECADD(xvec,xvec,vec2);
-
-                                                       VecMulf(yvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
-                                                       VecMulf(vec,-sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
-                                                       VECADD(yvec,yvec,vec);
-
-                                                       VecMulf(xvec,pa_size);
-                                                       VecMulf(yvec,pa_size);
-
-                                                       VECADDFAC(bb_center,state.co,xvec,part->bb_offset[0]);
-                                                       VECADDFAC(bb_center,bb_center,yvec,part->bb_offset[1]);
+                                                       bb.size = pa_size;
+                                                       bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+                                                       bb.time = pa_time;
+                                                       VECCOPY(bb.vec, state.co);
+                                                       VECCOPY(bb.vel, state.vel);
 
+                                                       psys_make_billboard(&bb, xvec, yvec, zvec, bb_center);
+                                                       
                                                        VECADD(vd,bb_center,xvec);
                                                        VECADD(vd,vd,yvec); vd+=3;
 
@@ -3386,6 +3310,10 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                                                        break;
                                        }
 
+                                       totpoint++;
+
+                                       /* additional things to draw for each particle  */
+                                       /* (velocity, size and number)                                  */
                                        if(vedata){
                                                VECCOPY(ved,state.co);
                                                ved+=3;
@@ -3401,15 +3329,12 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                                                setlinestyle(0);
                                        }
 
-                                       totpoint++;
-                               }
-                               if(next_pa)
-                                               continue;
-                               if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
-                                       /* in path drawing state.co is the end point */
-                                       glRasterPos3f(state.co[0],  state.co[1],  state.co[2]);
-                                       sprintf(val," %i",a);
-                                       BMF_DrawString(G.font, val);
+                                       if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
+                                               /* in path drawing state.co is the end point */
+                                               glRasterPos3f(state.co[0],  state.co[1],  state.co[2]);
+                                               sprintf(val," %i",a);
+                                               BMF_DrawString(G.font, val);
+                                       }
                                }
                        }
                }
@@ -3418,51 +3343,39 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
                glGetIntegerv(GL_POLYGON_MODE, polygonmode);
                glDisableClientState(GL_NORMAL_ARRAY);
 
-               if(draw_as != PART_DRAW_CIRC){
-                       if(draw_as==PART_DRAW_PATH){
-                               ParticleCacheKey **cache, *path;
-                               float *cd2=0,*cdata2=0;
-
-                               glEnableClientState(GL_VERTEX_ARRAY);
-
-                               if(dt > OB_WIRE) {
-                                       glEnableClientState(GL_NORMAL_ARRAY);
+               if(draw_as==PART_DRAW_PATH){
+                       ParticleCacheKey **cache, *path;
+                       float *cd2=0,*cdata2=0;
 
-                                       if(part->draw&PART_DRAW_MAT_COL)
-                                               glEnableClientState(GL_COLOR_ARRAY);
+                       glEnableClientState(GL_VERTEX_ARRAY);
 
-                                       glEnable(GL_LIGHTING);
-                                       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-                                       glEnable(GL_COLOR_MATERIAL);
-                               }
-                               else {
-                                       glDisableClientState(GL_NORMAL_ARRAY);
+                       /* setup gl flags */
+                       if(dt > OB_WIRE) {
+                               glEnableClientState(GL_NORMAL_ARRAY);
 
-                                       glDisable(GL_COLOR_MATERIAL);
-                                       glDisable(GL_LIGHTING);
-                                       BIF_ThemeColor(TH_WIRE);
-                               }
+                               if(part->draw&PART_DRAW_MAT_COL)
+                                       glEnableClientState(GL_COLOR_ARRAY);
 
-                               if(totchild && (part->draw&PART_DRAW_PARENT)==0)
-                                       totpart=0;
+                               glEnable(GL_LIGHTING);
+                               glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+                               glEnable(GL_COLOR_MATERIAL);
+                       }
+                       else {
+                               glDisableClientState(GL_NORMAL_ARRAY);
 
-                               cache=psys->pathcache;
-                               for(a=0, pa=psys->particles; a<totpart; a++, pa++){
-                                       path=cache[a];
-                                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+                               glDisable(GL_COLOR_MATERIAL);
+                               glDisable(GL_LIGHTING);
+                               BIF_ThemeColor(TH_WIRE);
+                       }
 
-                                       if(dt > OB_WIRE) {
-                                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
-                                               if(part->draw&PART_DRAW_MAT_COL)
-                                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
-                                       }
+                       if(totchild && (part->draw&PART_DRAW_PARENT)==0)
+                               totpart=0;
 
-                                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
-                               }
-                               
-                               cache=psys->childcache;
-                               for(a=0; a<totchild; a++){
-                                       path=cache[a];
+                       /* draw actual/parent particles */
+                       cache=psys->pathcache;
+                       for(a=0, pa=psys->particles; a<totpart; a++, pa++){
+                               path=cache[a];
+                               if(path->steps > 0) {
                                        glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
 
                                        if(dt > OB_WIRE) {
@@ -3473,68 +3386,85 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
 
                                        glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
                                }
+                       }
+                       
+                       /* draw child particles */
+                       cache=psys->childcache;
+                       for(a=0; a<totchild; a++){
+                               path=cache[a];
+                               glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
 
                                if(dt > OB_WIRE) {
+                                       glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
                                        if(part->draw&PART_DRAW_MAT_COL)
-                                               glDisable(GL_COLOR_ARRAY);
-                                       glDisable(GL_COLOR_MATERIAL);
+                                               glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
                                }
 
-                               if(cdata2)
-                                       MEM_freeN(cdata2);
-                               cd2=cdata2=0;
+                               glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+                       }
 
-                               glLineWidth(1.0f);
 
-                               /* draw particle edit mode key points*/
+                       /* restore & clean up */
+                       if(dt > OB_WIRE) {
+                               if(part->draw&PART_DRAW_MAT_COL)
+                                       glDisable(GL_COLOR_ARRAY);
+                               glDisable(GL_COLOR_MATERIAL);
                        }
 
-                       if(draw_as!=PART_DRAW_PATH){
-                               glDisableClientState(GL_COLOR_ARRAY);
+                       if(cdata2)
+                               MEM_freeN(cdata2);
+                       cd2=cdata2=0;
 
-                               if(vdata){
-                                       glEnableClientState(GL_VERTEX_ARRAY);
-                                       glVertexPointer(3, GL_FLOAT, 0, vdata);
-                               }
-                               else
-                                       glDisableClientState(GL_VERTEX_ARRAY);
+                       glLineWidth(1.0f);
+               }
+               else if(draw_as!=PART_DRAW_CIRC){
+                       glDisableClientState(GL_COLOR_ARRAY);
 
-                               if(ndata && dt>OB_WIRE){
-                                       glEnableClientState(GL_NORMAL_ARRAY);
-                                       glNormalPointer(GL_FLOAT, 0, ndata);
-                                       glEnable(GL_LIGHTING);
-                               }
-                               else{
-                                       glDisableClientState(GL_NORMAL_ARRAY);
-                                       glDisable(GL_LIGHTING);
-                               }
+                       /* setup created data arrays */
+                       if(vdata){
+                               glEnableClientState(GL_VERTEX_ARRAY);
+                               glVertexPointer(3, GL_FLOAT, 0, vdata);
+                       }
+                       else
+                               glDisableClientState(GL_VERTEX_ARRAY);
 
-                               if(cdata){
-                                       glEnableClientState(GL_COLOR_ARRAY);
-                                       glColorPointer(3, GL_FLOAT, 0, cdata);
-                               }
+                       if(ndata && dt>OB_WIRE){
+                               glEnableClientState(GL_NORMAL_ARRAY);
+                               glNormalPointer(GL_FLOAT, 0, ndata);
+                               glEnable(GL_LIGHTING);
+                       }
+                       else{
+                               glDisableClientState(GL_NORMAL_ARRAY);
+                               glDisable(GL_LIGHTING);
+                       }
 
-                               switch(draw_as){
-                                       case PART_DRAW_AXIS:
-                                       case PART_DRAW_CROSS:
-                                               glDrawArrays(GL_LINES, 0, 6*totpoint);
-                                               break;
-                                       case PART_DRAW_LINE:
-                                               glDrawArrays(GL_LINES, 0, 2*totpoint);
-                                               break;
-                                       case PART_DRAW_BB:
-                                               if(dt<=OB_WIRE)
-                                                       glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
-
-                                               glDrawArrays(GL_QUADS, 0, 4*totpoint);
-                                               break;
-                                       default:
-                                               glDrawArrays(GL_POINTS, 0, totpoint);
-                                               break;
-                               }
+                       if(cdata){
+                               glEnableClientState(GL_COLOR_ARRAY);
+                               glColorPointer(3, GL_FLOAT, 0, cdata);
                        }
 
+
+                       /* draw created data arrays */
+                       switch(draw_as){
+                               case PART_DRAW_AXIS:
+                               case PART_DRAW_CROSS:
+                                       glDrawArrays(GL_LINES, 0, 6*totpoint);
+                                       break;
+                               case PART_DRAW_LINE:
+                                       glDrawArrays(GL_LINES, 0, 2*totpoint);
+                                       break;
+                               case PART_DRAW_BB:
+                                       if(dt<=OB_WIRE)
+                                               glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+
+                                       glDrawArrays(GL_QUADS, 0, 4*totpoint);
+                                       break;
+                               default:
+                                       glDrawArrays(GL_POINTS, 0, totpoint);
+                                       break;
+                       }
                }
+
                if(vedata){
                        glDisableClientState(GL_COLOR_ARRAY);
                        cpack(0xC0C0C0);