From fe6c98a4d9a25fb66b1036ef3d15174af5eabe09 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 7 Jan 2008 16:26:41 +0000 Subject: [PATCH] Particle object and group visualization now also work for hair, to 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 | 159 +++++++++++++----- .../blenkernel/intern/particle_system.c | 6 +- source/blender/src/drawobject.c | 17 +- source/blender/src/editparticle.c | 1 + 4 files changed, 126 insertions(+), 57 deletions(-) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 8651996515b..bfc0779368a 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -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; anext) + for(a=0; anext) { 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; aflag & (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; + + QuatToMat4(state.rot, pamat); + VECCOPY(pamat[3], state.co); + pamat[3][3]= 1.0f; } - QuatToMat3(state.rot, parotmat); - 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); + Mat4MulMat4(mat, obrotmat, pamat); + } + else + Mat4CpyMat4(mat, pamat); + + Mat4MulMat4(tmat, obmat, mat); Mat4MulFloat3((float *)tmat, size); + if(par_space_mat) + Mat4MulMat4(mat, tmat, par_space_mat); + else + Mat4CpyMat4(mat, tmat); - VECCOPY(tmat[3], state.co); - - 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) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1235d9f5391..436d4d2210d 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -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 */ diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index db2225f4823..2ae272cd5ba 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -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; ico); + glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel); + glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col); - for(i=0, path=psys->childcache; ico); - 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); diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index 9e9fc5aa236..0a2158faf33 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -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;