static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent) { Base *base; scene->customdata_mask = scene_parent->customdata_mask; /* sets first, we allow per definition current scene to have * dependencies on sets, but not the other way around. */ if (scene->set) scene_update_tagged_recursive(bmain, scene->set, scene_parent); /* scene objects */ for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; BKE_object_handle_update(scene_parent, ob); if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); /* always update layer, so that animating layers works */ base->lay = ob->lay; } /* scene drivers... */ scene_update_drivers(bmain, scene); /* update sound system animation */ sound_update_scene(scene); }
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { DupliObject *dob; Group *group; GroupObject *go; float mat[4][4], tmat[4][4], id; if (ob->dup_group == NULL) return; group = ob->dup_group; /* simple preventing of too deep nested groups */ if (level > MAX_DUPLI_RECUR) return; /* handles animated groups, and */ /* we need to check update for objects that are not in scene... */ if (flag & DUPLILIST_DO_UPDATE) { /* note: update is optional because we don't always need object * transformations to be correct. Also fixes bug [#29616]. */ group_handle_recalc_and_update(scene, ob, group); } if (group_is_animated(ob, group)) flag |= DUPLILIST_ANIMATED; for (go = group->gobject.first, id = 0; go; go = go->next, id++) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if (go->ob != ob) { /* group dupli offset, should apply after everything else */ if (!is_zero_v3(group->dupli_ofs)) { copy_m4_m4(tmat, go->ob->obmat); sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs); mult_m4_m4m4(mat, ob->obmat, tmat); } else { mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || ((G.is_rendering == FALSE) && dob->ob->restrictflag & OB_RESTRICT_VIEW) || ((G.is_rendering == TRUE) && dob->ob->restrictflag & OB_RESTRICT_RENDER)) { dob->no_draw = TRUE; } if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag); copy_m4_m4(dob->ob->obmat, dob->omat); } } } }
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) { DupliObject *dob; Group *group; GroupObject *go; 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>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(scene, 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) { /* group dupli offset, should apply after everything else */ if (!is_zero_v3(group->dupli_ofs)) { copy_m4_m4(tmat, go->ob->obmat); sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs); mult_m4_m4m4(mat, ob->obmat, tmat); } else { mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ( (dob->origlay & group->layer)==0 || (G.rendering==0 && dob->ob->restrictflag & OB_RESTRICT_VIEW) || (G.rendering && dob->ob->restrictflag & OB_RESTRICT_RENDER) ) { dob->no_draw= 1; } else { dob->no_draw= 0; } if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, level+1, animated); copy_m4_m4(dob->ob->obmat, dob->omat); } } } }
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) { DupliObject *dob; Group *group; GroupObject *go; 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>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(scene, 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) { /* 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->transflag & OB_DUPLI) { Mat4CpyMat4(dob->ob->obmat, dob->mat); object_duplilist_recursive((ID *)group, scene, go->ob, lb, ob->obmat, level+1, animated); Mat4CpyMat4(dob->ob->obmat, dob->omat); } } } }
/* deps hack - do extra recalcs at end */ static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent) { Base *base; scene->customdata_mask = scene_parent->customdata_mask; /* sets first, we allow per definition current scene to have * dependencies on sets, but not the other way around. */ if (scene->set) scene_depsgraph_hack(scene->set, scene_parent); for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; if (ob->depsflag) { int recalc = 0; // printf("depshack %s\n", ob->id.name+2); if (ob->depsflag & OB_DEPS_EXTRA_OB_RECALC) recalc |= OB_RECALC_OB; if (ob->depsflag & OB_DEPS_EXTRA_DATA_RECALC) recalc |= OB_RECALC_DATA; ob->recalc |= recalc; BKE_object_handle_update(scene_parent, ob); if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) { GroupObject *go; for (go = ob->dup_group->gobject.first; go; go = go->next) { if (go->ob) go->ob->recalc |= recalc; } group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); } } } }
static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent) { Base *base; scene->customdata_mask = scene_parent->customdata_mask; /* sets first, we allow per definition current scene to have * dependencies on sets, but not the other way around. */ if (scene->set) scene_update_tagged_recursive(bmain, scene->set, scene_parent); /* scene objects */ for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; BKE_object_handle_update(scene_parent, ob); if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); /* always update layer, so that animating layers works (joshua july 2010) */ /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ // base->lay = ob->lay; } /* scene drivers... */ scene_update_drivers(bmain, scene); /* update sound system animation */ sound_update_scene(scene); /* update masking curves */ BKE_mask_update_scene(bmain, scene, FALSE); }
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob=NULL, **oblist=NULL, obcopy, *obcopylist=NULL; DupliObject *dob; ParticleDupliWeight *dw; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=NULL; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int a, b, counter, hair = 0; int totpart, totchild, totgroup=0 /*, pa_num */; int no_draw_flag = PARS_UNEXIST; if (psys==NULL) return; /* simple preventing of too deep nested groups */ if (level>MAX_DUPLI_RECUR) return; part=psys->part; if (part==NULL) return; if (!psys_check_enabled(par, psys)) return; if (G.rendering == 0) no_draw_flag |= PARS_NO_DISP; ctime = BKE_curframe(scene); /* NOTE: in old animsys, used parent object's timeoffset... */ totpart = psys->totpart; totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); if ((psys->renderdata || part->draw_as==PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim= {NULL}; sim.scene= scene; sim.ob= par; sim.psys= psys; sim.psmd= psys_get_modifier(par, psys); /* make sure emitter imat is in global coordinates instead of render view coordinates */ invert_m4_m4(par->imat, par->obmat); /* first check for loops (particle system object used as dupli object) */ if (part->ren_as == PART_DRAW_OB) { if (ELEM(part->dup_ob, NULL, par)) return; } else { /*PART_DRAW_GR */ if (part->dup_group == NULL || part->dup_group->gobject.first == NULL) return; for (go=part->dup_group->gobject.first; go; go=go->next) if (go->ob == par) return; } /* 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_check_group_weights(part); psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if (part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); if (part->draw & PART_DRAW_COUNT_GR) { for (dw=part->dupliweights.first; dw; dw=dw->next) totgroup += dw->count; } else { for (go=part->dup_group->gobject.first; go; go=go->next) totgroup++; } /* 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"); if (part->draw & PART_DRAW_COUNT_GR && totgroup) { dw = part->dupliweights.first; for (a=0; a<totgroup; dw=dw->next) { for (b=0; b<dw->count; b++, a++) { oblist[a] = dw->ob; obcopylist[a] = *dw->ob; } } } else { 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; else a = totpart; for (pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if (a<totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) continue; /* pa_num = pa->num; */ /* UNUSED */ pa_time = pa->time; size = pa->size; } else { /* handle child particle */ cpa = &psys->child[a - totpart]; /* pa_num = a; */ /* UNUSED */ pa_time = psys->particles[cpa->parent].time; size = psys_get_child_size(psys, cpa, ctime, NULL); } /* some hair paths might be non-existent so they can't be used for duplication */ if (hair && ((a < totpart && psys->pathcache[a]->steps < 0) || (a >= totpart && psys->childcache[a-totpart]->steps < 0))) continue; if (part->ren_as==PART_DRAW_GR) { /* prevent divide by zero below [#28336] */ if (totgroup == 0) continue; /* for groups, pick the object based on settings */ if (part->draw&PART_DRAW_RAND_GR) b= BLI_rand() % totgroup; else b= a % totgroup; ob = oblist[b]; obmat = oblist[b]->obmat; oldobmat = obcopylist[b].obmat; } else { obmat= ob->obmat; oldobmat= obcopy.obmat; } 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(&sim, pa, NULL, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale); } copy_v3_v3(pamat[3], cache->co); pamat[3][3]= 1.0f; } else { /* first key */ state.time = ctime; if (psys_get_particle_state(&sim, a, &state, 0) == 0) { continue; } else { float tquat[4]; normalize_qt_qt(tquat, state.rot); quat_to_mat4(pamat, tquat); copy_v3_v3(pamat[3], state.co); pamat[3][3]= 1.0f; } } if (part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { for (go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { copy_m4_m4(tmat, oblist[b]->obmat); /* apply particle scale */ mul_mat3_m4_fl(tmat, size*scale); mul_v3_fl(tmat[3], size*scale); /* group dupli offset, should apply after everything else */ if (!is_zero_v3(part->dup_group->dupli_ofs)) sub_v3_v3v3(tmat[3], tmat[3], part->dup_group->dupli_ofs); /* individual particle transform */ mult_m4_m4m4(tmat, pamat, tmat); if (par_space_mat) mult_m4_m4m4(mat, par_space_mat, tmat); else copy_m4_m4(mat, tmat); dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, obcopylist[b].obmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */ if ((part->draw & PART_DRAW_ROTATE_OB) == 0) { float xvec[3], q[4]; xvec[0] = -1.f; xvec[1] = xvec[2] = 0; vec_to_quat(q, xvec, ob->trackflag, ob->upflag); quat_to_mat4(obmat, q); obmat[3][3]= 1.0f; } /* Normal particles and cached hair live in global space so we need to * remove the real emitter's transformation before 2nd order duplication. */ if (par_space_mat && GS(id->name) != ID_GR) mult_m4_m4m4(mat, psys->imat, pamat); else copy_m4_m4(mat, pamat); mult_m4_m4m4(tmat, mat, obmat); mul_mat3_m4_fl(tmat, size*scale); if (par_space_mat) mult_m4_m4m4(mat, par_space_mat, tmat); else copy_m4_m4(mat, tmat); if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, oldobmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } /* restore objects since they were changed in where_is_object_time */ if (part->ren_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(psys->lattice); psys->lattice = NULL; } }
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; ParticleDupliWeight *dw; ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=0; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int lay, a, b, 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; if(part==0) return; if(!psys_check_enabled(par, psys)) return; ctime = bsystem_time(scene, par, (float)scene->r.cfra, 0.0); totpart = psys->totpart; totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); lay= scene->lay; if((psys->renderdata || part->draw_as==PART_DRAW_REND) && ((part->ren_as == PART_DRAW_OB && part->dup_ob) || (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) { psys_check_group_weights(part); /* 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(&sim); /* gather list of objects or single object */ if(part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); if(part->draw & PART_DRAW_COUNT_GR) { for(dw=part->dupliweights.first; dw; dw=dw->next) totgroup += dw->count; } else { for(go=part->dup_group->gobject.first; go; go=go->next) totgroup++; } /* 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"); if(part->draw & PART_DRAW_COUNT_GR && totgroup) { dw = part->dupliweights.first; for(a=0; a<totgroup; dw=dw->next) { for(b=0; b<dw->count; b++, a++) { oblist[a] = dw->ob; obcopylist[a] = *dw->ob; } } } else { 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; else a = totpart; for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if(a<totpart) { /* handle parent particle */ if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; pa_num = pa->num; pa_time = pa->time; size = pa->size; } else { /* handle child particle */ cpa = &psys->child[a - totpart]; pa_num = a; pa_time = psys->particles[cpa->parent].time; size = psys_get_child_size(psys, cpa, ctime, 0); } if(part->ren_as==PART_DRAW_GR) { /* for groups, pick the object based on settings */ if(part->draw&PART_DRAW_RAND_GR) b= BLI_rand() % totgroup; else if(part->from==PART_FROM_PARTICLE) b= pa_num % totgroup; else b= a % totgroup; ob = oblist[b]; obmat = oblist[b]->obmat; oldobmat = obcopylist[b].obmat; } else { obmat= ob->obmat; oldobmat= obcopy.obmat; } 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(&sim, pa, 0, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); pamat[3][3]= 1.0f; } else { /* first key */ state.time = ctime; if(psys_get_particle_state(&sim, a, &state, 0) == 0) continue; QuatToMat4(state.rot, pamat); VECCOPY(pamat[3], state.co); pamat[3][3]= 1.0f; } if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { 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); 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, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); VECCOPY(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; Mat4CpyMat4(mat, pamat); Mat4MulMat4(tmat, obmat, mat); Mat4MulFloat3((float *)tmat, size*scale); if(part->draw & PART_DRAW_GLOBAL_OB) VECADD(tmat[3], tmat[3], vec); if(par_space_mat) Mat4MulMat4(mat, tmat, par_space_mat); else Mat4CpyMat4(mat, tmat); dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, oldobmat); if(G.rendering) psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } /* restore objects since they were changed in where_is_object_time */ if(part->ren_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(psys->lattice); psys->lattice = NULL; } }