Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/object_dupli.c
| Show First 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | |||||
| static const DupliGenerator *get_dupli_generator(const DupliContext *ctx); | static const DupliGenerator *get_dupli_generator(const DupliContext *ctx); | ||||
| /* create initial context for root object */ | /* create initial context for root object */ | ||||
| static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update) | static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update) | ||||
| { | { | ||||
| r_ctx->eval_ctx = eval_ctx; | r_ctx->eval_ctx = eval_ctx; | ||||
| r_ctx->scene = scene; | r_ctx->scene = scene; | ||||
| /* don't allow BKE_object_handle_update for viewport during render, can crash */ | /* don't allow BKE_object_handle_update for viewport during render, can crash */ | ||||
| r_ctx->do_update = update && !(G.is_rendering && !eval_ctx->for_render); | r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER); | ||||
| r_ctx->animated = false; | r_ctx->animated = false; | ||||
| r_ctx->group = NULL; | r_ctx->group = NULL; | ||||
| r_ctx->object = ob; | r_ctx->object = ob; | ||||
| if (space_mat) | if (space_mat) | ||||
| copy_m4_m4(r_ctx->space_mat, space_mat); | copy_m4_m4(r_ctx->space_mat, space_mat); | ||||
| else | else | ||||
| unit_m4(r_ctx->space_mat); | unit_m4(r_ctx->space_mat); | ||||
| ▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /*---- Implementations ----*/ | /*---- Implementations ----*/ | ||||
| /* OB_DUPLIGROUP */ | /* OB_DUPLIGROUP */ | ||||
| static void make_duplis_group(const DupliContext *ctx) | static void make_duplis_group(const DupliContext *ctx) | ||||
| { | { | ||||
| bool for_render = ctx->eval_ctx->for_render; | bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER); | ||||
| Object *ob = ctx->object; | Object *ob = ctx->object; | ||||
| Group *group; | Group *group; | ||||
| GroupObject *go; | GroupObject *go; | ||||
| float group_mat[4][4]; | float group_mat[4][4]; | ||||
| int id; | int id; | ||||
| bool animated, hide; | bool animated, hide; | ||||
| if (ob->dup_group == NULL) return; | if (ob->dup_group == NULL) return; | ||||
| ▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | else { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void make_duplis_verts(const DupliContext *ctx) | static void make_duplis_verts(const DupliContext *ctx) | ||||
| { | { | ||||
| Scene *scene = ctx->scene; | Scene *scene = ctx->scene; | ||||
| Object *parent = ctx->object; | Object *parent = ctx->object; | ||||
| bool for_render = ctx->eval_ctx->for_render; | bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); | ||||
| VertexDupliData vdd; | VertexDupliData vdd; | ||||
| vdd.ctx = ctx; | vdd.ctx = ctx; | ||||
| vdd.use_rotation = parent->transflag & OB_DUPLIROT; | vdd.use_rotation = parent->transflag & OB_DUPLIROT; | ||||
| /* gather mesh info */ | /* gather mesh info */ | ||||
| { | { | ||||
| Mesh *me = parent->data; | Mesh *me = parent->data; | ||||
| BMEditMesh *em = BKE_editmesh_from_object(parent); | BMEditMesh *em = BKE_editmesh_from_object(parent); | ||||
| CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); | CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); | ||||
| if (em) | if (em) | ||||
| vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); | vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); | ||||
| else | else | ||||
| vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); | vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); | ||||
| vdd.edit_btmesh = me->edit_btmesh; | vdd.edit_btmesh = me->edit_btmesh; | ||||
| if (for_render) | if (use_texcoords) | ||||
| vdd.orco = vdd.dm->getVertDataArray(vdd.dm, CD_ORCO); | vdd.orco = vdd.dm->getVertDataArray(vdd.dm, CD_ORCO); | ||||
| else | else | ||||
| vdd.orco = NULL; | vdd.orco = NULL; | ||||
| vdd.totvert = vdd.dm->getNumVerts(vdd.dm); | vdd.totvert = vdd.dm->getNumVerts(vdd.dm); | ||||
| } | } | ||||
| make_child_duplis(ctx, &vdd, make_child_duplis_verts); | make_child_duplis(ctx, &vdd, make_child_duplis_verts); | ||||
| ▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| FaceDupliData *fdd = userdata; | FaceDupliData *fdd = userdata; | ||||
| MPoly *mpoly = fdd->mpoly, *mp; | MPoly *mpoly = fdd->mpoly, *mp; | ||||
| MLoop *mloop = fdd->mloop; | MLoop *mloop = fdd->mloop; | ||||
| MVert *mvert = fdd->mvert; | MVert *mvert = fdd->mvert; | ||||
| float (*orco)[3] = fdd->orco; | float (*orco)[3] = fdd->orco; | ||||
| MLoopUV *mloopuv = fdd->mloopuv; | MLoopUV *mloopuv = fdd->mloopuv; | ||||
| int a, totface = fdd->totface; | int a, totface = fdd->totface; | ||||
| bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); | |||||
| float child_imat[4][4]; | float child_imat[4][4]; | ||||
| DupliObject *dob; | DupliObject *dob; | ||||
| invert_m4_m4(inst_ob->imat, inst_ob->obmat); | invert_m4_m4(inst_ob->imat, inst_ob->obmat); | ||||
| /* relative transform from parent to child space */ | /* relative transform from parent to child space */ | ||||
| mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); | mul_m4_m4m4(child_imat, inst_ob->imat, ctx->object->obmat); | ||||
| for (a = 0, mp = mpoly; a < totface; a++, mp++) { | for (a = 0, mp = mpoly; a < totface; a++, mp++) { | ||||
| Show All 22 Lines | for (a = 0, mp = mpoly; a < totface; a++, mp++) { | ||||
| mul_m4_m4m4(obmat, inst_ob->obmat, obmat); | mul_m4_m4m4(obmat, inst_ob->obmat, obmat); | ||||
| /* space matrix is constructed by removing obmat transform, | /* space matrix is constructed by removing obmat transform, | ||||
| * this yields the worldspace transform for recursive duplis | * this yields the worldspace transform for recursive duplis | ||||
| */ | */ | ||||
| mul_m4_m4m4(space_mat, obmat, inst_ob->imat); | mul_m4_m4m4(space_mat, obmat, inst_ob->imat); | ||||
| dob = make_dupli(ctx, inst_ob, obmat, a, false, false); | dob = make_dupli(ctx, inst_ob, obmat, a, false, false); | ||||
| if (ctx->eval_ctx->for_render) { | if (use_texcoords) { | ||||
| float w = 1.0f / (float)mp->totloop; | float w = 1.0f / (float)mp->totloop; | ||||
| if (orco) { | if (orco) { | ||||
| int j; | int j; | ||||
| for (j = 0; j < mpoly->totloop; j++) { | for (j = 0; j < mpoly->totloop; j++) { | ||||
| madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); | madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); | ||||
| } | } | ||||
| } | } | ||||
| Show All 10 Lines | for (a = 0, mp = mpoly; a < totface; a++, mp++) { | ||||
| make_recursive_duplis(ctx, inst_ob, space_mat, a, false); | make_recursive_duplis(ctx, inst_ob, space_mat, a, false); | ||||
| } | } | ||||
| } | } | ||||
| static void make_duplis_faces(const DupliContext *ctx) | static void make_duplis_faces(const DupliContext *ctx) | ||||
| { | { | ||||
| Scene *scene = ctx->scene; | Scene *scene = ctx->scene; | ||||
| Object *parent = ctx->object; | Object *parent = ctx->object; | ||||
| bool for_render = ctx->eval_ctx->for_render; | bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); | ||||
| FaceDupliData fdd; | FaceDupliData fdd; | ||||
| fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); | fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); | ||||
| /* gather mesh info */ | /* gather mesh info */ | ||||
| { | { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(parent); | BMEditMesh *em = BKE_editmesh_from_object(parent); | ||||
| CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); | CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); | ||||
| if (em) | if (em) | ||||
| fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); | fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); | ||||
| else | else | ||||
| fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); | fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); | ||||
| if (for_render) { | if (use_texcoords) { | ||||
| fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO); | fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO); | ||||
| fdd.mloopuv = fdd.dm->getLoopDataArray(fdd.dm, CD_MLOOPUV); | fdd.mloopuv = fdd.dm->getLoopDataArray(fdd.dm, CD_MLOOPUV); | ||||
| } | } | ||||
| else { | else { | ||||
| fdd.orco = NULL; | fdd.orco = NULL; | ||||
| fdd.mloopuv = NULL; | fdd.mloopuv = NULL; | ||||
| } | } | ||||
| Show All 13 Lines | const DupliGenerator gen_dupli_faces = { | ||||
| make_duplis_faces /* make_duplis */ | make_duplis_faces /* make_duplis */ | ||||
| }; | }; | ||||
| /* OB_DUPLIPARTS */ | /* OB_DUPLIPARTS */ | ||||
| static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys) | static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys) | ||||
| { | { | ||||
| Scene *scene = ctx->scene; | Scene *scene = ctx->scene; | ||||
| Object *par = ctx->object; | Object *par = ctx->object; | ||||
| bool for_render = ctx->eval_ctx->for_render; | bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; | ||||
| bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); | |||||
| GroupObject *go; | GroupObject *go; | ||||
| Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; | Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; | ||||
| DupliObject *dob; | DupliObject *dob; | ||||
| ParticleDupliWeight *dw; | ParticleDupliWeight *dw; | ||||
| ParticleSettings *part; | ParticleSettings *part; | ||||
| ParticleData *pa; | ParticleData *pa; | ||||
| ChildParticle *cpa = NULL; | ChildParticle *cpa = NULL; | ||||
| ▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | for (pa = psys->particles; a < totpart + totchild; a++, pa++) { | ||||
| /* group dupli offset, should apply after everything else */ | /* group dupli offset, should apply after everything else */ | ||||
| if (!is_zero_v3(part->dup_group->dupli_ofs)) | if (!is_zero_v3(part->dup_group->dupli_ofs)) | ||||
| sub_v3_v3(tmat[3], part->dup_group->dupli_ofs); | sub_v3_v3(tmat[3], part->dup_group->dupli_ofs); | ||||
| /* individual particle transform */ | /* individual particle transform */ | ||||
| mul_m4_m4m4(mat, pamat, tmat); | mul_m4_m4m4(mat, pamat, tmat); | ||||
| dob = make_dupli(ctx, go->ob, mat, a, false, false); | dob = make_dupli(ctx, go->ob, mat, a, false, false); | ||||
| dob->particle_system = psys; | dob->particle_system = psys; | ||||
| if (for_render) | if (use_texcoords) | ||||
| psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); | psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* to give ipos in object correct offset */ | /* to give ipos in object correct offset */ | ||||
| BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); | BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); | ||||
| copy_v3_v3(vec, obmat[3]); | copy_v3_v3(vec, obmat[3]); | ||||
| Show All 32 Lines | for (pa = psys->particles; a < totpart + totchild; a++, pa++) { | ||||
| copy_m4_m4(mat, tmat); | copy_m4_m4(mat, tmat); | ||||
| if (part->draw & PART_DRAW_GLOBAL_OB) | if (part->draw & PART_DRAW_GLOBAL_OB) | ||||
| add_v3_v3v3(mat[3], mat[3], vec); | add_v3_v3v3(mat[3], mat[3], vec); | ||||
| dob = make_dupli(ctx, ob, mat, a, false, false); | dob = make_dupli(ctx, ob, mat, a, false, false); | ||||
| dob->particle_system = psys; | dob->particle_system = psys; | ||||
| if (for_render) | if (use_texcoords) | ||||
| psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); | psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); | ||||
| /* XXX blender internal needs this to be set to dupligroup to render | /* XXX blender internal needs this to be set to dupligroup to render | ||||
| * groups correctly, but we don't want this hack for cycles */ | * groups correctly, but we don't want this hack for cycles */ | ||||
| if (dupli_type_hack && ctx->group) | if (dupli_type_hack && ctx->group) | ||||
| dob->type = OB_DUPLIGROUP; | dob->type = OB_DUPLIGROUP; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| int transflag = ctx->object->transflag; | int transflag = ctx->object->transflag; | ||||
| int restrictflag = ctx->object->restrictflag; | int restrictflag = ctx->object->restrictflag; | ||||
| if ((transflag & OB_DUPLI) == 0) | if ((transflag & OB_DUPLI) == 0) | ||||
| return NULL; | return NULL; | ||||
| /* Should the dupli's be generated for this object? - Respect restrict flags */ | /* Should the dupli's be generated for this object? - Respect restrict flags */ | ||||
| if (ctx->eval_ctx->for_render ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW)) | if (ctx->eval_ctx->mode == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW)) | ||||
| return NULL; | return NULL; | ||||
| if (transflag & OB_DUPLIPARTS) { | if (transflag & OB_DUPLIPARTS) { | ||||
| return &gen_dupli_particles; | return &gen_dupli_particles; | ||||
| } | } | ||||
| else if (transflag & OB_DUPLIVERTS) { | else if (transflag & OB_DUPLIVERTS) { | ||||
| if (ctx->object->type == OB_MESH) { | if (ctx->object->type == OB_MESH) { | ||||
| return &gen_dupli_verts; | return &gen_dupli_verts; | ||||
| ▲ Show 20 Lines • Show All 126 Lines • Show Last 20 Lines | |||||