Particle object and group visualization now also work for hair, to
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 7 Jan 2008 16:26:41 +0000 (16:26 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 7 Jan 2008 16:26:41 +0000 (16:26 +0000)
make for example feathers. Also made dupliparts work within groups.

One issue still is that in particle editmode, the duplis can interfere
with brushes and selection, though tweaking the dupli object position
can alleviate the problem.

source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/particle_system.c
source/blender/src/drawobject.c
source/blender/src/editparticle.c

index 8651996515b310663220f880cd73e6a6d012faab..bfc0779368acb6d584ba98ee0b3b7eaae08ac21b 100644 (file)
@@ -47,6 +47,7 @@
 #include "DNA_key_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_scene_types.h"
@@ -76,7 +77,7 @@
 
 #define MAX_DUPLI_RECUR 4
 
-static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level);
+static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level);
 
 void free_path(Path *path)
 {
@@ -327,7 +328,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level)
                        
                        if(go->ob->transflag & OB_DUPLI) {
                                Mat4CpyMat4(dob->ob->obmat, dob->mat);
-                               object_duplilist_recursive((ID *)group, go->ob, lb, &ob->obmat, level+1);
+                               object_duplilist_recursive((ID *)group, go->ob, lb, ob->obmat, level+1);
                                Mat4CpyMat4(dob->ob->obmat, dob->omat);
                        }
                }
@@ -412,12 +413,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
                float tmpmat[4][4];
                Mat4CpyMat4(tmpmat, vdd->ob->obmat);
                Mat4CpyMat4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
-               object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, &obmat, vdd->level+1);
+               object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, obmat, vdd->level+1);
                Mat4CpyMat4(vdd->ob->obmat, tmpmat);
        }
 }
 
-static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level)
+static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level)
 {
        Object *ob, *ob_iter;
        Base *base = NULL;
@@ -473,11 +474,11 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_spac
                                        /* par_space_mat - only used for groups so we can modify the space dupli's are in
                                           when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
                                        */
-                                       if (par_space_mat) {
-                                               Mat4MulMat4(vdd.obmat, ob->obmat, *par_space_mat);
-                                       } else {
+                                       if(par_space_mat)
+                                               Mat4MulMat4(vdd.obmat, ob->obmat, par_space_mat);
+                                       else
                                                Mat4CpyMat4(vdd.obmat, ob->obmat);
-                                       }
+
                                        vdd.id= id;
                                        vdd.level= level;
                                        vdd.lb= lb;
@@ -512,7 +513,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_spac
        dm->release(dm);
 }
 
-static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level)
+static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level)
 {
        Object *ob, *ob_iter;
        Base *base = NULL;
@@ -583,11 +584,10 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_
                                        /* par_space_mat - only used for groups so we can modify the space dupli's are in
                                           when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
                                        */
-                                       if (par_space_mat) {
-                                               Mat4MulMat4(ob__obmat, ob->obmat, *par_space_mat);
-                                       } else {
+                                       if(par_space_mat)
+                                               Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat);
+                                       else
                                                Mat4CpyMat4(ob__obmat, ob->obmat);
-                                       }
                                        
                                        Mat3CpyMat4(imat, ob->parentinv);
                                                
@@ -638,7 +638,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_
                                                        float tmpmat[4][4];
                                                        Mat4CpyMat4(tmpmat, ob->obmat);
                                                        Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */
-                                                       object_duplilist_recursive((ID *)id, ob, lb, &ob->obmat, level+1);
+                                                       object_duplilist_recursive((ID *)id, ob, lb, ob->obmat, level+1);
                                                        Mat4CpyMat4(ob->obmat, tmpmat);
                                                }
                                        }
@@ -660,17 +660,44 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_
        dm->release(dm);
 }
 
-static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSystem *psys, int level)
+static void particle_dupli_path_rotation(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4])
+{
+       float loc[3], nor[3], vec[3], side[3];
+
+       VecSubf(vec, (cache+1)->co, cache->co);
+       Normalize(vec);
+
+       if(pa)
+               psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
+       else
+               psys_particle_on_emitter(ob, psmd,
+                       (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
+                       cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
+       
+       Crossf(side, nor, vec);
+       Normalize(side);
+       Crossf(nor, vec, side);
+
+       Mat4One(mat);
+       VECCOPY(mat[0], vec);
+       VECCOPY(mat[1], side);
+       VECCOPY(mat[2], nor);
+}
+
+static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level)
 {
        GroupObject *go;
-       Object *ob, **oblist=0;
+       Object *ob=0, **oblist=0;
        ParticleSettings *part;
        ParticleData *pa;
        ParticleKey state;
+       ParticleCacheKey *cache;
+       ParticleSystemModifierData *psmd;
        float ctime, pa_time;
-       float tmat[4][4], mat[3][3], obrotmat[3][3], parotmat[3][3], size=0.0;
+       float tmat[4][4], mat[4][4], obrotmat[4][4], pamat[4][4], size=0.0;
+       float obmat[4][4], (*obmatlist)[4][4]=0;
        float xvec[3] = {-1.0, 0.0, 0.0}, *q;
-       int lay, a, k, step_nbr = 0, counter;
+       int lay, a, b, k, step_nbr = 0, counter, hair = 0;
        int totpart, totchild, totgroup=0, pa_num;
 
        if(psys==0) return;
@@ -678,9 +705,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
        /* simple preventing of too deep nested groups */
        if(level>MAX_DUPLI_RECUR) return;
        
-       if (GS(id->name)!=ID_SCE) return; /* No support for groups YET! TODO */
-       
        part=psys->part;
+       psmd= psys_get_modifier(par, psys);
 
        if(part==0) return;
 
@@ -700,6 +726,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
                else
                        step_nbr = 0;
 
+               if(psys->flag & PSYS_HAIR_DONE)
+                       hair= (totchild == 0 || psys->childcache) && psys->pathcache;
+
                psys->lattice = psys_get_lattice(par, psys);
 
                if(part->draw_as==PART_DRAW_GR) {
@@ -712,9 +741,16 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
                        }
 
                        oblist= MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list");
+                       obmatlist= MEM_callocN(totgroup*sizeof(float)*4*4, "dupgroup obmat list");
                        go= part->dup_group->gobject.first;
-                       for(a=0; a<totgroup; a++, go=go->next)
+                       for(a=0; a<totgroup; a++, go=go->next) {
                                oblist[a]=go->ob;
+                               Mat4CpyMat4(obmatlist[a], go->ob->obmat);
+                       }
+               }
+               else {
+                       ob = part->dup_ob;
+                       Mat4CpyMat4(obmat, ob->obmat);
                }
 
                if(totchild==0 || part->draw & PART_DRAW_PARENT)
@@ -724,7 +760,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
 
                for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) {
                        if(a<totpart) {
-                               if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
+                               if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP))
+                                       continue;
 
                                pa_num=pa->num;
 
@@ -742,61 +779,91 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy
 
                        if(part->draw_as==PART_DRAW_GR) {
                                if(part->draw&PART_DRAW_RAND_GR)
-                                       ob = oblist[BLI_rand() % totgroup];
+                                       b= BLI_rand() % totgroup;
                                else if(part->from==PART_FROM_PARTICLE)
-                                       ob = oblist[pa_num % totgroup];
+                                       b= pa_num % totgroup;
                                else
-                                       ob = oblist[a % totgroup];
+                                       b= a % totgroup;
+
+                               ob = oblist[b];
+                               Mat4CpyMat4(obmat, obmatlist[b]);
                        }
-                       else
-                               ob = part->dup_ob;
 
                        for(k=0; k<=step_nbr; k++, counter++) {
-                               if(step_nbr) {
+                               if(hair) {
+                                       if(a < totpart) {
+                                               cache = psys->pathcache[a];
+                                               particle_dupli_path_rotation(par, part, psmd, pa, 0, cache, pamat);
+                                       }
+                                       else {
+                                               ChildParticle *cpa= psys->child+(a-totpart);
+                                               cache = psys->childcache[a-totpart];
+                                               particle_dupli_path_rotation(par, part, psmd, 0, cpa, cache, pamat);
+                                       }
+
+                                       VECCOPY(pamat[3], cache->co);
+                               }
+                               else if(step_nbr) {
                                        state.time = (float)k / (float)step_nbr;
                                        psys_get_particle_on_path(par, psys, a, &state, 0);
+
+                                       QuatToMat4(state.rot, pamat);
+                                       VECCOPY(pamat[3], state.co);
+                                       pamat[3][3]= 1.0f;
                                }
                                else {
                                        state.time = -1.0;
                                        if(psys_get_particle_state(par, psys, a, &state, 0) == 0)
                                                continue;
-                               }
 
-                               QuatToMat3(state.rot, parotmat);
+                                       QuatToMat4(state.rot, pamat);
+                                       VECCOPY(pamat[3], state.co);
+                                       pamat[3][3]= 1.0f;
+                               }
 
                                if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
-                                       for(go= part->dup_group->gobject.first; go; go= go->next) {
+                                       for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) {
 
-                                               Mat4CpyMat4(tmat, go->ob->obmat);
-                                               Mat4MulMat43(tmat, go->ob->obmat, parotmat);
+                                               Mat4MulMat4(tmat, obmatlist[b], pamat);
                                                Mat4MulFloat3((float *)tmat, size);
+                                               if(par_space_mat)
+                                                       Mat4MulMat4(mat, tmat, par_space_mat);
+                                               else
+                                                       Mat4CpyMat4(mat, tmat);
 
-                                               VECADD(tmat[3], go->ob->obmat[3], state.co);
-
-                                               new_dupli_object(lb, go->ob, tmat, par->lay, counter, OB_DUPLIPARTS);
+                                               new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS);
                                        }
                                }
                                else {
                                        /* to give ipos in object correct offset */
                                        where_is_object_time(ob, ctime-pa_time);
                                        
-                                       q = vectoquat(xvec, ob->trackflag, ob->upflag);
-                                       QuatToMat3(q, obrotmat);
+                                       if(!hair) {
+                                               q = vectoquat(xvec, ob->trackflag, ob->upflag);
+                                               QuatToMat4(q, obrotmat);
+                                               obrotmat[3][3]= 1.0f;
 
-                                       Mat3MulMat3(mat, parotmat, obrotmat);
-                                       Mat4CpyMat4(tmat, ob->obmat);
-                                       Mat4MulMat43(tmat, ob->obmat, mat);
-                                       Mat4MulFloat3((float *)tmat, size);
+                                               Mat4MulMat4(mat, obrotmat, pamat);
+                                       }
+                                       else
+                                               Mat4CpyMat4(mat, pamat);
 
-                                       VECCOPY(tmat[3], state.co);
+                                       Mat4MulMat4(tmat, obmat, mat);
+                                       Mat4MulFloat3((float *)tmat, size);
+                                       if(par_space_mat)
+                                               Mat4MulMat4(mat, tmat, par_space_mat);
+                                       else
+                                               Mat4CpyMat4(mat, tmat);
 
-                                       new_dupli_object(lb, ob, tmat, par->lay, counter, OB_DUPLIPARTS);
+                                       new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS);
                                }
                        }
                }
        }
        if(oblist)
                MEM_freeN(oblist);
+       if(obmatlist)
+               MEM_freeN(obmatlist);
 
        if(psys->lattice) {
                end_latt_deform();
@@ -877,7 +944,7 @@ static void font_duplilist(ListBase *lb, Object *par, int level)
 }
 
 /* ***************************** */
-static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level)
+static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level)
 {      
        if((ob->transflag & OB_DUPLI)==0)
                return;
@@ -896,7 +963,7 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist,
        if(ob->transflag & OB_DUPLIPARTS) {
                ParticleSystem *psys = ob->particlesystem.first;
                for(; psys; psys=psys->next)
-                       new_particle_duplilist(duplilist, id, ob, psys, level+1);
+                       new_particle_duplilist(duplilist, id, ob, par_space_mat, psys, level+1);
        }
        else if(ob->transflag & OB_DUPLIVERTS) {
                if(ob->type==OB_MESH) {
index 1235d9f539121a959db44e13e119f10ddd09dd69..436d4d2210d6edeffc054899d8fa579772fbb51c 100644 (file)
@@ -1533,10 +1533,10 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
        ParticleTexture ptex;
        ParticleKey state;
        IpoCurve *icu=0;
-       float fac, rotfac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0;
+       float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0;
        float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
        float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
-       float q_one[4]={1.0,0.0,0.0,0.0}, q_phase[4];
+       float q_phase[4];
        part=psys->part;
 
        ptex.ivel=1.0;
@@ -4241,7 +4241,7 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
        }
 
        if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && (psys_in_edit_mode(psys)
-               || part->draw_as==PART_DRAW_PATH || part->draw&PART_DRAW_KEYS)){
+               || (part->type==PART_HAIR || part->draw_as==PART_DRAW_PATH) || part->draw&PART_DRAW_KEYS)){
                psys_cache_paths(ob, psys, cfra, 0);
 
                /* for render, child particle paths are computed on the fly */
index db2225f4823ef11247aa7247afd424a44513e86a..2ae272cd5bad7f71fb92bf4fd65acc5040e1c0f6 100644 (file)
@@ -3580,8 +3580,8 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
                if(psys->childcache==0)
                        psys_cache_child_paths(ob, psys, CFRA, 0);
        }
-       else if(psys->childcache)
-                       free_child_path_cache(psys);
+       else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache)
+               free_child_path_cache(psys);
 
        if((G.vd->flag & V3D_ZBUF_SELECT)==0)
                glDisable(GL_DEPTH_TEST);
@@ -3625,13 +3625,14 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys)
        }
 
        glEnable(GL_LIGHTING);
+       if(psys->part->draw_as == PART_DRAW_PATH) {
+               for(i=0, path=psys->childcache; i<totchild; i++,path++){
+                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
+                       glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
 
-       for(i=0, path=psys->childcache; i<totchild; i++,path++){
-               glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
-               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
-               glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
-
-               glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+                       glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+               }
        }
 
        glDisable(GL_COLOR_MATERIAL);
index 9e9fc5aa236051d07a2af540fa6c0418aab787eb..0a2158faf33f2da6a550d00e9e1d9f25a53a0085 100644 (file)
@@ -2392,6 +2392,7 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe
                                ekey->time = &hkey->time;
                        }
                        
+                       pa->size= 1.0f;
                        initialize_particle(pa,i,ob,psys,psmd);
                        reset_particle(pa,psys,psmd,ob,0.0,1.0,0,0,0);
                        pa->flag |= PARS_EDIT_RECALC;