Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/mesh.c')
-rw-r--r--source/blender/blenkernel/intern/mesh.c285
1 files changed, 271 insertions, 14 deletions
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 419f907d786..c8223657a05 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -61,6 +61,7 @@
#include "BKE_object.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
enum {
MESHCMP_DVERT_WEIGHTMISMATCH = 1,
@@ -463,7 +464,7 @@ void BKE_mesh_free(Mesh *me, int unlink)
CustomData_free(&me->pdata, me->totpoly);
if (me->adt) {
- BKE_free_animdata(&me->id);
+ BKE_animdata_free(&me->id);
me->adt = NULL;
}
@@ -1265,7 +1266,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
dl = dispbase->first;
while (dl) {
- int smooth = dl->rt & CU_SMOOTH ? 1 : 0;
+ const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
if (dl->type == DL_SEGM) {
startvert = vertcount;
@@ -1344,7 +1345,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
}
- if (smooth) mpoly->flag |= ME_SMOOTH;
+ if (is_smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 3;
index += 3;
@@ -1423,7 +1424,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
}
- if (smooth) mpoly->flag |= ME_SMOOTH;
+ if (is_smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 4;
@@ -1773,6 +1774,36 @@ void BKE_mesh_material_index_clear(Mesh *me)
}
}
+void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len)
+{
+ const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+ if (n < remap_len_short) { \
+ BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+ n = remap[n]; \
+ } ((void)0)
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ MAT_NR_REMAP(efa->mat_nr);
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < me->totpoly; i++) {
+ MAT_NR_REMAP(me->mpoly[i].mat_nr);
+ }
+ }
+
+#undef MAT_NR_REMAP
+
+}
+
void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
{
Mesh *me = meshOb->data;
@@ -1805,7 +1836,7 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
* Return a newly MEM_malloc'd array of all the mesh vertex locations
* \note \a r_numVerts may be NULL
*/
-float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3]
+float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_numVerts))[3]
{
int i, numVerts = me->totvert;
float (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "vertexcos1");
@@ -1821,8 +1852,9 @@ float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3]
* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found
*/
-int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
- unsigned vert)
+int poly_find_loop_from_vert(
+ const MPoly *poly, const MLoop *loopstart,
+ unsigned vert)
{
int j;
for (j = 0; j < poly->totloop; j++, loopstart++) {
@@ -1838,20 +1870,22 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
* vertex. Returns the index of the loop matching vertex, or -1 if the
* vertex is not in \a poly
*/
-int poly_get_adj_loops_from_vert(unsigned r_adj[3], const MPoly *poly,
- const MLoop *mloop, unsigned vert)
+int poly_get_adj_loops_from_vert(
+ unsigned r_adj[2], const MPoly *poly,
+ const MLoop *mloop, unsigned vert)
{
int corner = poly_find_loop_from_vert(poly,
&mloop[poly->loopstart],
vert);
if (corner != -1) {
+#if 0 /* unused - this loop */
const MLoop *ml = &mloop[poly->loopstart + corner];
+#endif
/* vertex was found */
r_adj[0] = ME_POLY_LOOP_PREV(mloop, poly, corner)->v;
- r_adj[1] = ml->v;
- r_adj[2] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v;
+ r_adj[1] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v;
}
return corner;
@@ -1887,6 +1921,7 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
{
int i;
MVert *mvert = me->mvert;
+ float (*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL);
for (i = 0; i < me->totvert; i++, mvert++)
mul_m4_v3(mat, mvert->co);
@@ -1901,7 +1936,17 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
}
}
- /* don't update normals, caller can do this explicitly */
+ /* don't update normals, caller can do this explicitly.
+ * We do update loop normals though, those may not be auto-generated (see e.g. STL import script)! */
+ if (lnors) {
+ float m3[3][3];
+
+ copy_m3_m4(m3, mat);
+ normalize_m3(m3);
+ for (i = 0; i < me->totloop; i++, lnors++) {
+ mul_m3_v3(m3, *lnors);
+ }
+ }
}
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
@@ -2124,6 +2169,146 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
(me->mselect[me->totselect - 1].type == type));
}
+void BKE_mesh_calc_normals_split(Mesh *mesh)
+{
+ float (*r_loopnors)[3];
+ float (*polynors)[3];
+ short (*clnors)[2] = NULL;
+ bool free_polynors = false;
+
+ if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
+ r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
+ }
+ else {
+ r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop);
+ CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+
+ /* may be NULL */
+ clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+
+ if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
+ /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */
+ polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ free_polynors = false;
+ }
+ else {
+ polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
+ BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
+ polynors, false);
+ free_polynors = true;
+ }
+
+ BKE_mesh_normals_loop_split(
+ mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
+ mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly,
+ (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL);
+
+ if (free_polynors) {
+ MEM_freeN(polynors);
+ }
+}
+
+/* Spli faces based on the edge angle.
+ * Matches behavior of face splitting in render engines.
+ */
+void BKE_mesh_split_faces(Mesh *mesh)
+{
+ const int num_verts = mesh->totvert;
+ const int num_edges = mesh->totedge;
+ const int num_polys = mesh->totpoly;
+ MVert *mvert = mesh->mvert;
+ MEdge *medge = mesh->medge;
+ MLoop *mloop = mesh->mloop;
+ MPoly *mpoly = mesh->mpoly;
+ float (*lnors)[3];
+ int poly, num_new_verts = 0;
+ if ((mesh->flag & ME_AUTOSMOOTH) == 0) {
+ return;
+ }
+ BKE_mesh_tessface_clear(mesh);
+ /* Compute loop normals if needed. */
+ if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
+ BKE_mesh_calc_normals_split(mesh);
+ }
+ lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ /* Count. */
+ for (poly = 0; poly < num_polys; poly++) {
+ MPoly *mp = &mpoly[poly];
+ int loop;
+ for (loop = 0; loop < mp->totloop; loop++) {
+ MLoop *ml = &mloop[mp->loopstart + loop];
+ MVert *mv = &mvert[ml->v];
+ float vn[3];
+ normal_short_to_float_v3(vn, mv->no);
+ if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
+ num_new_verts++;
+ }
+ }
+ }
+ if (num_new_verts == 0) {
+ /* No new vertices are to be added, can do early exit. */
+ return;
+ }
+ /* Actual split. */
+ mesh->totvert += num_new_verts;
+ mesh->totedge += 2 * num_new_verts;
+ mvert = mesh->mvert = MEM_reallocN(mesh->mvert,
+ sizeof(MVert) * mesh->totvert);
+ medge = mesh->medge = MEM_reallocN(mesh->medge,
+ sizeof(MEdge) * mesh->totedge);
+ CustomData_set_layer(&mesh->vdata, CD_MVERT, mesh->mvert);
+ CustomData_set_layer(&mesh->edata, CD_MEDGE, mesh->medge);
+ num_new_verts = 0;
+ for (poly = 0; poly < num_polys; poly++) {
+ MPoly *mp = &mpoly[poly];
+ int loop;
+ for (loop = 0; loop < mp->totloop; loop++) {
+ int poly_loop = mp->loopstart + loop;
+ MLoop *ml = &mloop[poly_loop];
+ MVert *mv = &mvert[ml->v];
+ float vn[3];
+ normal_short_to_float_v3(vn, mv->no);
+ if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
+ int poly_loop_prev = mp->loopstart + (loop + mp->totloop - 1) % mp->totloop;
+ MLoop *ml_prev = &mloop[poly_loop_prev];
+ int new_edge_prev, new_edge;
+ /* Cretae new vertex. */
+ int new_vert = num_verts + num_new_verts;
+ CustomData_copy_data(&mesh->vdata, &mesh->vdata,
+ ml->v, new_vert, 1);
+ normal_float_to_short_v3(mvert[new_vert].no,
+ lnors[poly_loop]);
+ /* Create new edges. */
+ new_edge_prev = num_edges + 2 * num_new_verts;
+ new_edge = num_edges + 2 * num_new_verts + 1;
+ CustomData_copy_data(&mesh->edata, &mesh->edata,
+ ml_prev->e, new_edge_prev, 1);
+ CustomData_copy_data(&mesh->edata, &mesh->edata,
+ ml->e, new_edge, 1);
+ if (medge[new_edge_prev].v1 == ml->v) {
+ medge[new_edge_prev].v1 = new_vert;
+ }
+ else {
+ medge[new_edge_prev].v2 = new_vert;
+ }
+ if (medge[new_edge].v1 == ml->v) {
+ medge[new_edge].v1 = new_vert;
+ }
+ else {
+ medge[new_edge].v2 = new_vert;
+ }
+
+ ml->v = new_vert;
+ ml_prev->e = new_edge_prev;
+ ml->e = new_edge;
+ num_new_verts++;
+ }
+ }
+ }
+}
+
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
Main *bmain, Scene *sce, Object *ob,
@@ -2213,8 +2398,8 @@ Mesh *BKE_mesh_new_from_object(
* only contains for_render flag. As soon as CoW is
* implemented, this is to be rethinked.
*/
- EvaluationContext eval_ctx = {0};
- eval_ctx.mode = DAG_EVAL_RENDER;
+ EvaluationContext eval_ctx;
+ DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER);
BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);
@@ -2339,3 +2524,75 @@ Mesh *BKE_mesh_new_from_object(
return tmpmesh;
}
+/* settings: 1 - preview, 2 - render */
+Mesh *BKE_mesh_new_from_dupli_data(
+ Main *bmain, DupliObjectData *data,
+ bool calc_tessface, bool calc_undeformed)
+{
+ Object *ob = data->ob;
+ DerivedMesh *dm = data->dm;
+ CustomDataMask mask;
+
+ Mesh *tmpmesh;
+
+ if (!ob || !dm)
+ return NULL;
+
+ mask = CD_MASK_MESH; /* this seems more suitable, exporter,
+ * for example, needs CD_MASK_MDEFORMVERT */
+ if (calc_undeformed)
+ mask |= CD_MASK_ORCO;
+
+ tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ DM_to_mesh(dm, tmpmesh, ob, mask, true);
+
+ /* BKE_mesh_add/copy gives us a user count we don't need */
+ tmpmesh->id.us--;
+
+ /* Copy materials to new mesh */
+ switch (ob->type) {
+ case OB_MESH: {
+ Mesh *origmesh = ob->data;
+ int i;
+
+ tmpmesh->flag = origmesh->flag;
+ tmpmesh->mat = MEM_dupallocN(origmesh->mat);
+ tmpmesh->totcol = origmesh->totcol;
+ tmpmesh->smoothresh = origmesh->smoothresh;
+ if (origmesh->mat) {
+ for (i = origmesh->totcol; i-- > 0; ) {
+ /* are we an object material or data based? */
+ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i];
+
+ if (tmpmesh->mat[i]) {
+ tmpmesh->mat[i]->id.us++;
+ }
+ }
+ }
+ break;
+ }
+ } /* end copy materials */
+
+ if (calc_tessface) {
+ /* cycles and exporters rely on this still */
+ BKE_mesh_tessface_ensure(tmpmesh);
+ }
+
+ /* make sure materials get updated in objects */
+ test_object_materials(bmain, &tmpmesh->id);
+
+ return tmpmesh;
+}
+
+/* **** Depsgraph evaluation **** */
+
+void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+ Mesh *mesh)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s\n", __func__, mesh->id.name);
+ }
+ if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_mesh_texspace_calc(mesh);
+ }
+}