diff options
Diffstat (limited to 'source/blender/blenkernel/intern/anim.c')
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 552 |
1 files changed, 414 insertions, 138 deletions
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 08648aa6e10..aeddabf8c1b 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -44,6 +44,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" @@ -51,6 +52,7 @@ #include "DNA_vfont_types.h" #include "BKE_anim.h" +#include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -61,6 +63,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_main.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_utildefines.h" @@ -69,6 +72,8 @@ #include <config.h> #endif +static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated); + void free_path(Path *path) { if(path->data) MEM_freeN(path->data); @@ -112,7 +117,7 @@ void calc_curvepath(Object *ob) path->len= tot+1; /* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */ - if(path->len<nu->resolu*nu->pntsu) path->len= nu->resolu*nu->pntsu; + if(path->len<nu->resolu*SEGMENTSU(nu)) path->len= nu->resolu*SEGMENTSU(nu); dist= (float *)MEM_mallocN((tot+1)*4, "calcpathdist"); @@ -275,7 +280,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK /* ****************** DUPLICATOR ************** */ -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index) +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int type, int animated) { DupliObject *dob= MEM_callocN(sizeof(DupliObject), "dupliobject"); @@ -285,50 +290,66 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i Mat4CpyMat4(dob->omat, ob->obmat); dob->origlay= ob->lay; dob->index= index; + dob->type= type; + dob->animated= (type == OB_DUPLIGROUP) && animated; ob->lay= lay; return dob; } -static void group_duplilist(ListBase *lb, Object *ob, int level) +static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) { DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4]; + float mat[4][4], tmat[4][4]; if(ob->dup_group==NULL) return; group= ob->dup_group; /* simple preventing of too deep nested groups */ - if(level>4) return; + if(level>MAX_DUPLI_RECUR) return; /* handles animated groups, and */ /* we need to check update for objects that are not in scene... */ group_handle_recalc_and_update(ob, group); + animated= animated || group_is_animated(ob, group); for(go= group->gobject.first; go; go= go->next) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if(go->ob!=ob) { - Mat4MulMat4(mat, go->ob->obmat, ob->obmat); - dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0); + + /* Group Dupli Offset, should apply after everything else */ + if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) { + Mat4CpyMat4(tmat, go->ob->obmat); + VecSubf(tmat[3], tmat[3], group->dupli_ofs); + Mat4MulMat4(mat, tmat, ob->obmat); + } else { + Mat4MulMat4(mat, go->ob->obmat, ob->obmat); + } + + dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); dob->no_draw= (dob->origlay & group->layer)==0; - if(go->ob->dup_group && (go->ob->transflag & OB_DUPLIGROUP)) { + if(go->ob->transflag & OB_DUPLI) { Mat4CpyMat4(dob->ob->obmat, dob->mat); - group_duplilist(lb, go->ob, level+1); + object_duplilist_recursive((ID *)group, go->ob, lb, ob->obmat, level+1, animated); Mat4CpyMat4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Object *ob) +static void frames_duplilist(ListBase *lb, Object *ob, int level, int animated) { extern int enable_cu_speed; /* object.c */ Object copyob; + DupliObject *dob; int cfrao, ok; + /* simple preventing of too deep nested groups */ + if(level>MAX_DUPLI_RECUR) return; + cfrao= G.scene->r.cfra; if(ob->parent==NULL && ob->track==NULL && ob->ipo==NULL && ob->constraints.first==NULL) return; @@ -347,7 +368,8 @@ static void frames_duplilist(ListBase *lb, Object *ob) if(ok) { do_ob_ipo(ob); where_is_object_time(ob, (float)G.scene->r.cfra); - new_dupli_object(lb, ob, ob->obmat, ob->lay, G.scene->r.cfra); + dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, G.scene->r.cfra, OB_DUPLIFRAMES, animated); + Mat4CpyMat4(dob->omat, copyob.obmat); } } @@ -357,22 +379,28 @@ static void frames_duplilist(ListBase *lb, Object *ob) } struct vertexDupliData { + ID *id; /* scene or group, for recursive loops */ + int level; + int animated; ListBase *lb; float pmat[4][4]; + float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */ Object *ob, *par; + float (*orco)[3]; }; static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { + DupliObject *dob; struct vertexDupliData *vdd= userData; - float vec[3], *q2, mat[3][3], tmat[4][4], obmat[4][4]; + float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4]; VECCOPY(vec, co); Mat4MulVecfl(vdd->pmat, vec); VecSubf(vec, vec, vdd->pmat[3]); - VecAddf(vec, vec, vdd->ob->obmat[3]); + VecAddf(vec, vec, vdd->obmat[3]); - Mat4CpyMat4(obmat, vdd->ob->obmat); + Mat4CpyMat4(obmat, vdd->obmat); VECCOPY(obmat[3], vec); if(vdd->par->transflag & OB_DUPLIROT) { @@ -383,44 +411,98 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n vec[0]= -no_s[0]; vec[1]= -no_s[1]; vec[2]= -no_s[2]; } - q2= vectoquat(vec, vdd->ob->trackflag, vdd->ob->upflag); + vectoquat(vec, vdd->ob->trackflag, vdd->ob->upflag, q2); QuatToMat3(q2, mat); Mat4CpyMat4(tmat, obmat); Mat4MulMat43(obmat, tmat, mat); } - new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index); + dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated); + if(vdd->orco) + VECCOPY(dob->orco, vdd->orco[index]); + + if(vdd->ob->transflag & OB_DUPLI) { + 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, vdd->animated); + Mat4CpyMat4(vdd->ob->obmat, tmpmat); + } } -static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par) +static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level, int animated) { - Object *ob; - Base *base; + Object *ob, *ob_iter; + Mesh *me; + Base *base = NULL; float vec[3], no[3], pmat[4][4]; - int lay, totvert, a; + int lay, totvert, a, oblay; DerivedMesh *dm; + struct vertexDupliData vdd; + Scene *sce = NULL; + Group *group = NULL; + GroupObject * go = NULL; Mat4CpyMat4(pmat, par->obmat); - lay= G.scene->lay; - + /* simple preventing of too deep nested groups */ + if(level>MAX_DUPLI_RECUR) return; + if(par==G.obedit) dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); else - dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH); + dm= mesh_get_derived_deform(par, CD_MASK_BAREMESH); + + if(G.rendering) { + me= par->data; + vdd.orco= (float(*)[3])get_mesh_orco_verts(par); + transform_mesh_orco_verts(me, vdd.orco, me->totvert, 0); + } + else + vdd.orco= NULL; totvert = dm->getNumVerts(dm); - base= sce->base.first; - while(base) { - - if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) { - ob= base->object->parent; + /* having to loop on scene OR group objects is NOT FUN */ + if (GS(id->name) == ID_SCE) { + sce = (Scene *)id; + lay= sce->lay; + base= sce->base.first; + } else { + group = (Group *)id; + lay= group->layer; + go = group->gobject.first; + } + + /* Start looping on Scene OR Group objects */ + while (base || go) { + if (sce) { + ob_iter= base->object; + oblay = base->lay; + } else { + ob_iter= go->ob; + oblay = ob_iter->lay; + } + + if (lay & oblay && G.obedit!=ob_iter) { + ob=ob_iter->parent; while(ob) { if(ob==par) { - struct vertexDupliData vdd; + ob = ob_iter; + /* End Scene/Group object loop, below is generic */ - ob= base->object; + + /* 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 + Mat4CpyMat4(vdd.obmat, ob->obmat); + + vdd.id= id; + vdd.level= level; + vdd.animated= animated; vdd.lb= lb; vdd.ob= ob; vdd.par= par; @@ -446,26 +528,37 @@ static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par) ob= ob->parent; } } - base= base->next; + if (sce) base= base->next; /* scene loop */ + else go= go->next; /* group loop */ } + if(vdd.orco) + MEM_freeN(vdd.orco); dm->release(dm); } -static void face_duplilist(ListBase *lb, Scene *sce, Object *par) +static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level, int animated) { - Object *ob; - Base *base; + Object *ob, *ob_iter; + Base *base = NULL; + DupliObject *dob; DerivedMesh *dm; + Mesh *me; + MTFace *mtface; MFace *mface; MVert *mvert; - float pmat[4][4], imat[3][3]; - int lay, totface, a; - - Mat4CpyMat4(pmat, par->obmat); + float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w; + int lay, oblay, totface, a; + Scene *sce = NULL; + Group *group = NULL; + GroupObject *go = NULL; + float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ - lay= G.scene->lay; + /* simple preventing of too deep nested groups */ + if(level>MAX_DUPLI_RECUR) return; + Mat4CpyMat4(pmat, par->obmat); + if(par==G.obedit) { int totvert; dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); @@ -484,26 +577,69 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par) mface= dm->getFaceArray(dm); mvert= dm->getVertArray(dm); } + + if(G.rendering) { + me= (Mesh*)par->data; + + orco= (float(*)[3])get_mesh_orco_verts(par); + transform_mesh_orco_verts(me, orco, me->totvert, 0); + mtface= me->mtface; + } + else { + orco= NULL; + mtface= NULL; + } + /* having to loop on scene OR group objects is NOT FUN */ + if (GS(id->name) == ID_SCE) { + sce = (Scene *)id; + lay= sce->lay; + base= sce->base.first; + } else { + group = (Group *)id; + lay= group->layer; + go = group->gobject.first; + } - for(base= sce->base.first; base; base= base->next) { + /* Start looping on Scene OR Group objects */ + while (base || go) { + if (sce) { + ob_iter= base->object; + oblay = base->lay; + } else { + ob_iter= go->ob; + oblay = ob_iter->lay; + } - if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) { - ob= base->object->parent; + if (lay & oblay && G.obedit!=ob_iter) { + ob=ob_iter->parent; while(ob) { if(ob==par) { + ob = ob_iter; + /* End Scene/Group object loop, below is generic */ - ob= base->object; - Mat3CpyMat4(imat, ob->parentinv); + /* 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 + Mat4CpyMat4(ob__obmat, ob->obmat); + Mat3CpyMat4(imat, ob->parentinv); + /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ for(a=0; a<totface; a++) { - float *v1= mvert[ mface[a].v1 ].co; - float *v2= mvert[ mface[a].v2 ].co; - float *v3= mvert[ mface[a].v3 ].co; - float *v4= mface[a].v4?mvert[ mface[a].v4 ].co:NULL; + int mv1 = mface[a].v1; + int mv2 = mface[a].v2; + int mv3 = mface[a].v3; + int mv4 = mface[a].v4; + float *v1= mvert[mv1].co; + float *v2= mvert[mv2].co; + float *v3= mvert[mv3].co; + float *v4= (mv4)? mvert[mv4].co: NULL; float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; /* translation */ @@ -514,9 +650,10 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par) Mat4MulVecfl(pmat, cent); VecSubf(cent, cent, pmat[3]); - VecAddf(cent, cent, ob->obmat[3]); + VecAddf(cent, cent, ob__obmat[3]); + + Mat4CpyMat4(obmat, ob__obmat); - Mat4CpyMat4(obmat, ob->obmat); VECCOPY(obmat[3], cent); /* rotation */ @@ -536,8 +673,40 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par) Mat4CpyMat4(tmat, obmat); Mat4MulMat43(obmat, tmat, mat); - new_dupli_object(lb, ob, obmat, lay, a); - + dob= new_dupli_object(lb, ob, obmat, lay, a, OB_DUPLIFACES, animated); + if(G.rendering) { + w= (mv4)? 0.25f: 1.0f/3.0f; + + if(orco) { + VECADDFAC(dob->orco, dob->orco, orco[mv1], w); + VECADDFAC(dob->orco, dob->orco, orco[mv2], w); + VECADDFAC(dob->orco, dob->orco, orco[mv3], w); + if(mv4) + VECADDFAC(dob->orco, dob->orco, orco[mv4], w); + } + + if(mtface) { + dob->uv[0] += w*mtface[a].uv[0][0]; + dob->uv[1] += w*mtface[a].uv[0][1]; + dob->uv[0] += w*mtface[a].uv[1][0]; + dob->uv[1] += w*mtface[a].uv[1][1]; + dob->uv[0] += w*mtface[a].uv[2][0]; + dob->uv[1] += w*mtface[a].uv[2][1]; + + if(mv4) { + dob->uv[0] += w*mtface[a].uv[3][0]; + dob->uv[1] += w*mtface[a].uv[3][1]; + } + } + } + + if(ob->transflag & OB_DUPLI) { + 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, animated); + Mat4CpyMat4(ob->obmat, tmpmat); + } } break; @@ -545,34 +714,51 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par) ob= ob->parent; } } + if (sce) base= base->next; /* scene loop */ + else go= go->next; /* group loop */ } if(par==G.obedit) { MEM_freeN(mface); MEM_freeN(mvert); } + + if(orco) + MEM_freeN(orco); dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, ParticleSystem *psys) +static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; - Object *ob, **oblist=0; + Object *ob=0, **oblist=0, obcopy, *obcopylist=0; + DupliObject *dob; ParticleSettings *part; ParticleData *pa; + ChildParticle *cpa=0; ParticleKey state; - float ctime, pa_time; - float tmat[4][4], mat[3][3], obrotmat[3][3], parotmat[3][3], size=0.0; - float xvec[3] = {-1.0, 0.0, 0.0}, *q; - int lay, a, k, step_nbr = 0, counter; + ParticleCacheKey *cache; + ParticleSystemModifierData *psmd; + float ctime, pa_time, scale = 1.0f; + float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; + float (*obmat)[4], (*oldobmat)[4]; + int lay, a, b, k, step_nbr = 0, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; if(psys==0) return; + /* simple preventing of too deep nested groups */ + if(level>MAX_DUPLI_RECUR) return; + part=psys->part; + psmd= psys_get_modifier(par, psys); + + if(part==0) + return; - if(part==0) return; + if(!psys_check_enabled(par, psys)) + return; ctime = bsystem_time(par, (float)G.scene->r.cfra, 0.0); @@ -580,7 +766,7 @@ static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, Partic totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); - + lay= G.scene->lay; if((part->draw_as == PART_DRAW_OB && part->dup_ob) || (part->draw_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first)) { @@ -590,103 +776,171 @@ static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, Partic else step_nbr = 0; + /* if we have a hair particle system, use the path cache */ + if(part->type == PART_HAIR) { + if(psys->flag & PSYS_HAIR_DONE) + hair= (totchild == 0 || psys->childcache) && psys->pathcache; + if(!hair) + return; + + /* we use cache, update totchild according to cached data */ + totchild = psys->totchildcache; + totpart = psys->totcached; + } + psys->lattice = psys_get_lattice(par, psys); + /* gather list of objects or single object */ if(part->draw_as==PART_DRAW_GR) { group_handle_recalc_and_update(par, part->dup_group); - go= part->dup_group->gobject.first; - while(go) { - go=go->next; + for(go=part->dup_group->gobject.first; go; go=go->next) totgroup++; - } - oblist= MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); - go= part->dup_group->gobject.first; - for(a=0; a<totgroup; a++, go=go->next) - oblist[a]=go->ob; + /* we also copy the actual objects to restore afterwards, since + * where_is_object_time will change the object which breaks transform */ + oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); + obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list"); + + go = part->dup_group->gobject.first; + for(a=0; a<totgroup; a++, go=go->next) { + oblist[a] = go->ob; + obcopylist[a] = *go->ob; + } + } + else { + ob = part->dup_ob; + obcopy = *ob; } if(totchild==0 || part->draw & PART_DRAW_PARENT) - a=0; + a = 0; else - a=totpart; + a = totpart; for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if(a<totpart) { - if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; - - pa_num=pa->num; + /* handle parent particle */ + if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) + continue; - pa_time=pa->time; - - size=pa->size; + pa_num = pa->num; + pa_time = pa->time; + size = pa->size; } else { - /* TODO: figure these two out */ - pa_num = a; - pa_time = psys->particles[psys->child[a - totpart].parent].time; + /* handle child particle */ + cpa = &psys->child[a - totpart]; - size=psys_get_child_size(psys, &psys->child[a - totpart], ctime, 0); + pa_num = a; + pa_time = psys->particles[cpa->parent].time; + size = psys_get_child_size(psys, cpa, ctime, 0); } if(part->draw_as==PART_DRAW_GR) { + /* for groups, pick the object based on settings */ 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]; + obmat = oblist[b]->obmat; + oldobmat = obcopylist[b].obmat; + } + else { + obmat= ob->obmat; + oldobmat= obcopy.obmat; } - else - ob = part->dup_ob; for(k=0; k<=step_nbr; k++, counter++) { - if(step_nbr) { + if(hair) { + /* hair we handle separate and compute transform based on hair keys */ + if(a < totpart) { + cache = psys->pathcache[a]; + psys_get_dupli_path_transform(par, psys, psmd, pa, 0, cache, pamat, &scale); + } + else { + cache = psys->childcache[a-totpart]; + psys_get_dupli_path_transform(par, psys, psmd, 0, cpa, cache, pamat, &scale); + } + + VECCOPY(pamat[3], cache->co); + pamat[3][3]= 1.0f; + + } + else if(step_nbr) { + /* other keys */ 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 { + /* first key */ 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) { - - Mat4CpyMat4(tmat, go->ob->obmat); - Mat4MulMat43(tmat, go->ob->obmat, parotmat); - Mat4MulFloat3((float *)tmat, size); - - VECADD(tmat[3], go->ob->obmat[3], state.co); + for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { + Mat4MulMat4(tmat, oblist[b]->obmat, pamat); + Mat4MulFloat3((float *)tmat, size*scale); + if(par_space_mat) + Mat4MulMat4(mat, tmat, par_space_mat); + else + Mat4CpyMat4(mat, tmat); - new_dupli_object(lb, go->ob, tmat, par->lay, counter); + dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); + Mat4CpyMat4(dob->omat, obcopylist[b].obmat); + if(G.rendering) + psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); } } 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); - - Mat3MulMat3(mat, parotmat, obrotmat); - Mat4CpyMat4(tmat, ob->obmat); - Mat4MulMat43(tmat, ob->obmat, mat); - Mat4MulFloat3((float *)tmat, size); + Mat4CpyMat4(mat, pamat); - VECCOPY(tmat[3], state.co); + Mat4MulMat4(tmat, obmat, mat); + Mat4MulFloat3((float *)tmat, size*scale); + if(par_space_mat) + Mat4MulMat4(mat, tmat, par_space_mat); + else + Mat4CpyMat4(mat, tmat); - new_dupli_object(lb, ob, tmat, par->lay, counter); + dob= new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); + Mat4CpyMat4(dob->omat, oldobmat); + if(G.rendering) + psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); } } } + + /* restore objects since they were changed in where_is_object_time */ + if(part->draw_as==PART_DRAW_GR) { + for(a=0; a<totgroup; a++) + *(oblist[a])= obcopylist[a]; + } + else + *ob= obcopy; } + + /* clean up */ if(oblist) MEM_freeN(oblist); + if(obcopylist) + MEM_freeN(obcopylist); if(psys->lattice) { end_latt_deform(); @@ -717,7 +971,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Object *par) +static void font_duplilist(ListBase *lb, Object *par, int level, int animated) { Object *ob, *obar[256]; Curve *cu; @@ -725,6 +979,9 @@ static void font_duplilist(ListBase *lb, Object *par) float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof; int slen, a; + /* simple preventing of too deep nested groups */ + if(level>MAX_DUPLI_RECUR) return; + Mat4CpyMat4(pmat, par->obmat); /* in par the family name is stored, use this to find the other objects */ @@ -755,54 +1012,73 @@ static void font_duplilist(ListBase *lb, Object *par) Mat4CpyMat4(obmat, par->obmat); VECCOPY(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a); + new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIVERTS, animated); } - } MEM_freeN(chartransdata); } /* ***************************** */ +static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated) +{ + if((ob->transflag & OB_DUPLI)==0) + return; + + /* Should the dupli's be generated for this object? - Respect restrict flags */ + if (G.rendering) { + if (ob->restrictflag & OB_RESTRICT_RENDER) { + return; + } + } else { + if (ob->restrictflag & OB_RESTRICT_VIEW) { + return; + } + } -/* note; group dupli's already set transform matrix. see note in group_duplilist() */ -ListBase *object_duplilist(Scene *sce, Object *ob) -{ - ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); - duplilist->first= duplilist->last= NULL; - - if(ob->transflag & OB_DUPLI) { - if(ob->transflag & OB_DUPLIPARTS) { - ParticleSystem *psys = ob->particlesystem.first; - for(; psys; psys=psys->next) - new_particle_duplilist(duplilist, sce, ob, psys); + if(ob->transflag & OB_DUPLIPARTS) { + ParticleSystem *psys = ob->particlesystem.first; + for(; psys; psys=psys->next) + new_particle_duplilist(duplilist, id, ob, par_space_mat, psys, level+1, animated); + } + else if(ob->transflag & OB_DUPLIVERTS) { + if(ob->type==OB_MESH) { + vertex_duplilist(duplilist, id, ob, par_space_mat, level+1, animated); } - else if(ob->transflag & OB_DUPLIVERTS) { - if(ob->type==OB_MESH) { - vertex_duplilist(duplilist, sce, ob); - } - else if(ob->type==OB_FONT) { - font_duplilist(duplilist, ob); + else if(ob->type==OB_FONT) { + if (GS(id->name)==ID_SCE) { /* TODO - support dupligroups */ + font_duplilist(duplilist, ob, level+1, animated); } } - else if(ob->transflag & OB_DUPLIFACES) { - if(ob->type==OB_MESH) - face_duplilist(duplilist, sce, ob); + } + else if(ob->transflag & OB_DUPLIFACES) { + if(ob->type==OB_MESH) + face_duplilist(duplilist, id, ob, par_space_mat, level+1, animated); + } + else if(ob->transflag & OB_DUPLIFRAMES) { + if (GS(id->name)==ID_SCE) { /* TODO - support dupligroups */ + frames_duplilist(duplilist, ob, level+1, animated); } - else if(ob->transflag & OB_DUPLIFRAMES) - frames_duplilist(duplilist, ob); - else if(ob->transflag & OB_DUPLIGROUP) { - DupliObject *dob; - - group_duplilist(duplilist, ob, 0); /* now recursive */ + } else if(ob->transflag & OB_DUPLIGROUP) { + DupliObject *dob; + + group_duplilist(duplilist, ob, level+1, animated); /* now recursive */ - /* make copy already, because in group dupli's deform displists can be made, requiring parent matrices */ + if (level==0) { for(dob= duplilist->first; dob; dob= dob->next) - Mat4CpyMat4(dob->ob->obmat, dob->mat); + if(dob->type == OB_DUPLIGROUP) + Mat4CpyMat4(dob->ob->obmat, dob->mat); } - } - +} + +/* Returns a list of DupliObject + * note; group dupli's already set transform matrix. see note in group_duplilist() */ +ListBase *object_duplilist(Scene *sce, Object *ob) +{ + ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); + duplilist->first= duplilist->last= NULL; + object_duplilist_recursive((ID *)sce, ob, duplilist, NULL, 0, 0); return duplilist; } |