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.
This commit is contained in:
Brecht Van Lommel
2008-01-07 16:26:41 +00:00
parent adc68be1a8
commit fe6c98a4d9
4 changed files with 126 additions and 57 deletions

View 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;
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) {

View 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 */

View 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);

View 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;