/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], bool use_normals, bool use_orco) { if (dm) { /* pass */ } else if (ob->type == OB_MESH) { if (em) dm = CDDM_from_editbmesh(em, false, false); else dm = CDDM_from_mesh((struct Mesh *)(ob->data)); if (vertexCos) { CDDM_apply_vert_coords(dm, vertexCos); dm->dirty |= DM_DIRTY_NORMALS; } if (use_orco) { DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob)); } } else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { dm = CDDM_from_curve(ob); } if (use_normals) { if (LIKELY(dm)) { DM_ensure_normals(dm); } } return dm; }
/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco) { if (dm) return dm; if (ob->type == OB_MESH) { if (em) dm = CDDM_from_editbmesh(em, FALSE, FALSE); else dm = CDDM_from_mesh((struct Mesh *)(ob->data), ob); if (vertexCos) { CDDM_apply_vert_coords(dm, vertexCos); //CDDM_calc_normals(dm); } if (orco) DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob)); } else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { dm = CDDM_from_curve(ob); } return dm; }
static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; Mesh *me = par->data; Base *base = NULL; DerivedMesh *dm; vertexDupliData vdd; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; BMEditMesh *em; float vec[3], no[3], pmat[4][4]; int totvert, a, oblay; unsigned int lay; copy_m4_m4(pmat, par->obmat); /* simple preventing of too deep nested groups */ if (level > MAX_DUPLI_RECUR) return; em = me->edit_btmesh; if (em) { dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); } else dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); if (G.rendering) { vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par); BKE_mesh_orco_verts_transform(me, vdd.orco, me->totvert, 0); } else vdd.orco = NULL; totvert = dm->getNumVerts(dm); /* 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 && scene->obedit != ob_iter) { ob = ob_iter->parent; while (ob) { if (ob == par) { ob = ob_iter; /* End Scene/Group object loop, below is generic */ /* 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) mult_m4_m4m4(vdd.obmat, par_space_mat, ob->obmat); else copy_m4_m4(vdd.obmat, ob->obmat); vdd.id = id; vdd.level = level; vdd.animated = animated; vdd.lb = lb; vdd.ob = ob; vdd.scene = scene; vdd.par = par; copy_m4_m4(vdd.pmat, pmat); /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ if (me->edit_btmesh) { dm->foreachMappedVert(dm, vertex_dupli__mapFunc, (void *) &vdd); } else { for (a = 0; a < totvert; a++) { dm->getVertCo(dm, a, vec); dm->getVertNo(dm, a, no); vertex_dupli__mapFunc(&vdd, a, vec, no, NULL); } } if (sce) { /* Set proper layer in case of scene looping, * in case of groups the object layer will be * changed when it's duplicated due to the * group duplication. */ ob->lay = vdd.par->lay; } break; } ob = ob->parent; } } 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, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; Base *base = NULL; DupliObject *dob; DerivedMesh *dm; Mesh *me = par->data; MLoopUV *mloopuv; MPoly *mpoly, *mp; MLoop *mloop; MVert *mvert; 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; BMEditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if (level > MAX_DUPLI_RECUR) return; copy_m4_m4(pmat, par->obmat); em = me->edit_btmesh; if (em) { dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); } else { dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); } totface = dm->getNumPolys(dm); mpoly = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); mvert = dm->getVertArray(dm); if (G.rendering) { orco = (float(*)[3])BKE_mesh_orco_verts_get(par); BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0); mloopuv = me->mloopuv; } else { orco = NULL; mloopuv = 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; } /* 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 && scene->obedit != ob_iter) { ob = ob_iter->parent; while (ob) { if (ob == par) { ob = ob_iter; /* End Scene/Group object loop, below is generic */ /* 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) mult_m4_m4m4(ob__obmat, par_space_mat, ob->obmat); else copy_m4_m4(ob__obmat, ob->obmat); copy_m3_m4(imat, ob->parentinv); /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ for (a = 0, mp = mpoly; a < totface; a++, mp++) { int mv1; int mv2; int mv3; /* int mv4; */ /* UNUSED */ float *v1; float *v2; float *v3; /* float *v4; */ /* UNUSED */ float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; MLoop *loopstart = mloop + mp->loopstart; if (mp->totloop < 3) { /* highly unlikely but to be safe */ continue; } else { v1 = mvert[(mv1 = loopstart[0].v)].co; v2 = mvert[(mv2 = loopstart[1].v)].co; v3 = mvert[(mv3 = loopstart[2].v)].co; #if 0 if (mp->totloop > 3) { v4 = mvert[(mv4 = loopstart[3].v)].co; } #endif } /* translation */ BKE_mesh_calc_poly_center(mp, loopstart, mvert, cent); mul_m4_v3(pmat, cent); sub_v3_v3v3(cent, cent, pmat[3]); add_v3_v3(cent, ob__obmat[3]); copy_m4_m4(obmat, ob__obmat); copy_v3_v3(obmat[3], cent); /* rotation */ tri_to_quat(quat, v1, v2, v3); quat_to_mat3(mat, quat); /* scale */ if (par->transflag & OB_DUPLIFACES_SCALE) { float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, NULL); size = sqrtf(size) * par->dupfacesca; mul_m3_fl(mat, size); } copy_m3_m3(mat3, mat); mul_m3_m3m3(mat, imat, mat3); copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); dob = new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIFACES, animated); if (G.rendering) { w = 1.0f / (float)mp->totloop; if (orco) { int j; for (j = 0; j < mpoly->totloop; j++) { madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); } } if (mloopuv) { int j; for (j = 0; j < mpoly->totloop; j++) { madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w); } } } if (ob->transflag & OB_DUPLI) { float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level + 1, animated); copy_m4_m4(ob->obmat, tmpmat); } } break; } ob = ob->parent; } } if (sce) base = base->next; /* scene loop */ else go = go->next; /* group loop */ } if (orco) MEM_freeN(orco); dm->release(dm); }