static void get_dupliface_transform(MPoly *mpoly, MLoop *mloop, MVert *mvert, bool use_scale, float scale_fac, float mat[4][4]) { float loc[3], quat[4], scale, size[3]; float f_no[3]; /* location */ BKE_mesh_calc_poly_center(mpoly, mloop, mvert, loc); /* rotation */ { const float *v1, *v2, *v3; BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, f_no); v1 = mvert[mloop[0].v].co; v2 = mvert[mloop[1].v].co; v3 = mvert[mloop[2].v].co; tri_to_quat_ex(quat, v1, v2, v3, f_no); } /* scale */ if (use_scale) { float area = BKE_mesh_calc_poly_area(mpoly, mloop, mvert); scale = sqrtf(area) * scale_fac; } else scale = 1.0f; size[0] = size[1] = size[2] = scale; loc_quat_size_to_mat4(mat, loc, quat, size); }
void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me) { std::map<Normal, unsigned int> shared_normal_indices; int last_normal_index = -1; MVert *verts = me->mvert; MLoop *mloops = me->mloop; float(*lnors)[3]; BKE_mesh_calc_normals_split(me); if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); } for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { MPoly *mpoly = &me->mpoly[poly_index]; if (!(mpoly->flag & ME_SMOOTH)) { // For flat faces use face normal as vertex normal: float vector[3]; BKE_mesh_calc_poly_normal(mpoly, mloops+mpoly->loopstart, verts, vector); Normal n = { vector[0], vector[1], vector[2] }; normals.push_back(n); last_normal_index++; } MLoop *mloop = mloops + mpoly->loopstart; BCPolygonNormalsIndices poly_indices; for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { unsigned int loop_idx = mpoly->loopstart + loop_index; if (mpoly->flag & ME_SMOOTH) { float normalized[3]; normalize_v3_v3(normalized, lnors[loop_idx]); Normal n = { normalized[0], normalized[1], normalized[2] }; if (shared_normal_indices.find(n) != shared_normal_indices.end()) { poly_indices.add_index(shared_normal_indices[n]); } else { last_normal_index++; poly_indices.add_index(last_normal_index); shared_normal_indices[n] = last_normal_index; normals.push_back(n); } } else { poly_indices.add_index(last_normal_index); } } polygons_normals.push_back(poly_indices); } }
/** * This function populates an array of verts for the triangles of a mesh * Tangent and Normals are also stored */ static void mesh_calc_tri_tessface( TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm) { int i; MVert *mvert; TSpace *tspace; float *precomputed_normals = NULL; bool calculate_normal; const int tottri = poly_to_tri_count(me->totpoly, me->totloop); MLoopTri *looptri; /* calculate normal for each polygon only once */ unsigned int mpoly_prev = UINT_MAX; float no[3]; mvert = CustomData_get_layer(&me->vdata, CD_MVERT); looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); if (tangent) { DM_ensure_normals(dm); DM_calc_loop_tangents(dm); precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL); calculate_normal = precomputed_normals ? false : true; tspace = dm->getLoopDataArray(dm, CD_TANGENT); BLI_assert(tspace); } BKE_mesh_recalc_looptri( me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); for (i = 0; i < tottri; i++) { MLoopTri *lt = &looptri[i]; MPoly *mp = &me->mpoly[lt->poly]; triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v]; triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v]; triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v]; triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0; if (tangent) { triangles[i].tspace[0] = &tspace[lt->tri[0]]; triangles[i].tspace[1] = &tspace[lt->tri[1]]; triangles[i].tspace[2] = &tspace[lt->tri[2]]; if (calculate_normal) { if (lt->poly != mpoly_prev) { const MPoly *mp = &me->mpoly[lt->poly]; BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no); mpoly_prev = lt->poly; } copy_v3_v3(triangles[i].normal, no); } else { copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]); } } } MEM_freeN(looptri); }
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { 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 = BMEdit_FromObject(par); 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 (flag & DUPLILIST_FOR_RENDER) { 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]; float f_no[3]; MLoop *loopstart = mloop + mp->loopstart; if (UNLIKELY(mp->totloop < 3)) { continue; } else { BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no); v1 = mvert[(mv1 = loopstart[0].v)].co; v2 = mvert[(mv2 = loopstart[1].v)].co; v3 = mvert[(mv3 = loopstart[2].v)].co; } /* 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_ex(quat, v1, v2, v3, f_no); quat_to_mat3(mat, quat); /* scale */ if (par->transflag & OB_DUPLIFACES_SCALE) { float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, f_no); 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, persistent_id, level, a, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); if (flag & DUPLILIST_FOR_RENDER) { 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, persistent_id, level + 1, a, flag); 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); }