diff options
Diffstat (limited to 'source/blender/blenkernel/intern/mesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 492 |
1 files changed, 369 insertions, 123 deletions
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 5758e00a28d..6a00aaf576b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -32,8 +32,10 @@ #include "DNA_object_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "BLI_utildefines.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_linklist.h" #include "BLI_memarena.h" @@ -41,15 +43,15 @@ #include "BLI_string.h" #include "BKE_animsys.h" +#include "BKE_idcode.h" #include "BKE_main.h" -#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" #include "BKE_library.h" #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_multires.h" -#include "BKE_depsgraph.h" #include "BKE_object.h" #include "BKE_editmesh.h" @@ -109,7 +111,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 for (i = 0; i < c1->totlayer; i++) { if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i1++; } @@ -117,7 +119,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 for (i = 0; i < c2->totlayer; i++) { if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i2++; } @@ -131,14 +133,14 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 i1 = 0; i2 = 0; for (i = 0; i < tot; i++) { while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i1++; l1++; } while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i2++; l2++; @@ -306,7 +308,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) * Callers could also check but safer to do here - campbell */ } else { - const int tottex_original = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE); @@ -317,16 +319,16 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) { BKE_mesh_tessface_clear(me); - CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface); + CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface); /* TODO - add some --debug-mesh option */ if (G.debug & G_DEBUG) { /* note: this warning may be un-called for if we are initializing the mesh for the * first time from bmesh, rather then giving a warning about this we could be smarter * and check if there was any data to begin with, for now just print the warning with - * some info to help troubleshoot whats going on - campbell */ + * some info to help troubleshoot what's going on - campbell */ printf("%s: warning! Tessellation uvs or vcol data got out of sync, " - "had to reset!\n CD_MTFACE: %d != CD_MTEXPOLY: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n", + "had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n", __func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original); } } @@ -372,6 +374,49 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) } } +bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me) +{ + BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL; + bool changed = false; + if (bm) { + if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) { + BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP); + changed = true; + } + } + else { + if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + CustomData_add_layer( + &me->pdata, + CD_FACEMAP, + CD_DEFAULT, + NULL, + me->totpoly); + changed = true; + } + } + return changed; +} + +bool BKE_mesh_clear_facemap_customdata(struct Mesh *me) +{ + BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL; + bool changed = false; + if (bm) { + if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) { + BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP); + changed = true; + } + } + else { + if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly); + changed = true; + } + } + return changed; +} + /* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or * mloopcol and mcol) have the same relative active/render/clone/mask indices. * @@ -380,14 +425,11 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) * versions of the mesh. - campbell*/ static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd) { - if (me->edit_btmesh) - BKE_editmesh_update_linked_customdata(me->edit_btmesh); - if (do_ensure_tess_cd) { mesh_ensure_tessellation_customdata(me); } - CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata); + CustomData_bmesh_update_active_layers(&me->fdata, &me->ldata); } void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd) @@ -406,7 +448,6 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd) me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); - me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY); me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); } @@ -426,6 +467,8 @@ void BKE_mesh_free(Mesh *me) { BKE_animdata_free(&me->id, false); + BKE_mesh_runtime_clear_cache(me); + CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); @@ -460,12 +503,7 @@ void BKE_mesh_init(Mesh *me) me->size[0] = me->size[1] = me->size[2] = 1.0; me->smoothresh = DEG2RADF(30); me->texflag = ME_AUTOSPACE; - - /* disable because its slow on many GPU's, see [#37518] */ -#if 0 - me->flag = ME_TWOSIDED; -#endif - me->drawflag = ME_DRAWEDGES | ME_DRAWFACES | ME_DRAWCREASES; + me->drawflag = 0; CustomData_reset(&me->vdata); CustomData_reset(&me->edata); @@ -496,15 +534,22 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name) void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int flag) { const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0)); /* only do tessface if we have no polys */ + CustomDataMask mask = CD_MASK_MESH; + + if (me_src->id.tag & LIB_TAG_NO_MAIN) { + /* For copies in depsgraph, keep data like origindex and orco. */ + mask |= CD_MASK_DERIVEDMESH; + } me_dst->mat = MEM_dupallocN(me_src->mat); - CustomData_copy(&me_src->vdata, &me_dst->vdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totvert); - CustomData_copy(&me_src->edata, &me_dst->edata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totedge); - CustomData_copy(&me_src->ldata, &me_dst->ldata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totloop); - CustomData_copy(&me_src->pdata, &me_dst->pdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totpoly); + const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; + CustomData_copy(&me_src->vdata, &me_dst->vdata, mask, alloc_type, me_dst->totvert); + CustomData_copy(&me_src->edata, &me_dst->edata, mask, alloc_type, me_dst->totedge); + CustomData_copy(&me_src->ldata, &me_dst->ldata, mask, alloc_type, me_dst->totloop); + CustomData_copy(&me_src->pdata, &me_dst->pdata, mask, alloc_type, me_dst->totpoly); if (do_tessface) { - CustomData_copy(&me_src->fdata, &me_dst->fdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totface); + CustomData_copy(&me_src->fdata, &me_dst->fdata, mask, alloc_type, me_dst->totface); } else { mesh_tessface_clear_intern(me_dst, false); @@ -514,37 +559,223 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int me_dst->edit_btmesh = NULL; + /* Call BKE_mesh_runtime_reset? */ + me_dst->runtime.batch_cache = NULL; + me_dst->runtime.looptris.array = NULL; + me_dst->runtime.bvh_cache = NULL; + me_dst->runtime.shrinkwrap_data = NULL; + + if (me_src->id.tag & LIB_TAG_NO_MAIN) { + me_dst->runtime.deformed_only = me_src->runtime.deformed_only; + } + else { + /* This is a direct copy of a main mesh, so for now it has the same topology. */ + me_dst->runtime.deformed_only = 1; + } + me_dst->runtime.is_original = false; + me_dst->mselect = MEM_dupallocN(me_dst->mselect); me_dst->bb = MEM_dupallocN(me_dst->bb); /* TODO Do we want to add flag to prevent this? */ - if (me_src->key) { + if (me_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) { BKE_id_copy_ex(bmain, &me_src->key->id, (ID **)&me_dst->key, flag, false); } } +/* Custom data layer functions; those assume that totXXX are set correctly. */ +static void mesh_ensure_cdlayers_primary(Mesh *mesh, bool do_tessface) +{ + if (!CustomData_get_layer(&mesh->vdata, CD_MVERT)) + CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert); + if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) + CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge); + if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) + CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop); + if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) + CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly); + + if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) + CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface); +} +static void mesh_ensure_cdlayers_origindex(Mesh *mesh, bool do_tessface) +{ + if (!CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX)) + CustomData_add_layer(&mesh->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert); + if (!CustomData_get_layer(&mesh->edata, CD_ORIGINDEX)) + CustomData_add_layer(&mesh->edata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge); + if (!CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX)) + CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totpoly); + + if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_ORIGINDEX)) + CustomData_add_layer(&mesh->fdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface); +} + +Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len) +{ + Mesh *mesh = BKE_libblock_alloc( + NULL, ID_ME, + BKE_idcode_to_name(ID_ME), + LIB_ID_CREATE_NO_MAIN | + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_DEG_TAG); + BKE_libblock_init_empty(&mesh->id); + + /* don't use CustomData_reset(...); because we dont want to touch customdata */ + copy_vn_i(mesh->vdata.typemap, CD_NUMTYPES, -1); + copy_vn_i(mesh->edata.typemap, CD_NUMTYPES, -1); + copy_vn_i(mesh->fdata.typemap, CD_NUMTYPES, -1); + copy_vn_i(mesh->ldata.typemap, CD_NUMTYPES, -1); + copy_vn_i(mesh->pdata.typemap, CD_NUMTYPES, -1); + + mesh->totvert = verts_len; + mesh->totedge = edges_len; + mesh->totface = tessface_len; + mesh->totloop = loops_len; + mesh->totpoly = polys_len; + + mesh_ensure_cdlayers_primary(mesh, true); + mesh_ensure_cdlayers_origindex(mesh, true); + BKE_mesh_update_customdata_pointers(mesh, false); + + return mesh; +} + +static Mesh *mesh_new_nomain_from_template_ex( + const Mesh *me_src, + int verts_len, int edges_len, int tessface_len, + int loops_len, int polys_len, + CustomDataMask mask) +{ + /* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */ + const bool do_tessface = (tessface_len || + ((me_src->totface != 0) && (me_src->totpoly == 0))); + + Mesh *me_dst = BKE_id_new_nomain(ID_ME, NULL); + + me_dst->mat = MEM_dupallocN(me_src->mat); + me_dst->mselect = MEM_dupallocN(me_dst->mselect); + + me_dst->totvert = verts_len; + me_dst->totedge = edges_len; + me_dst->totface = tessface_len; + me_dst->totloop = loops_len; + me_dst->totpoly = polys_len; + + CustomData_copy(&me_src->vdata, &me_dst->vdata, mask, CD_CALLOC, verts_len); + CustomData_copy(&me_src->edata, &me_dst->edata, mask, CD_CALLOC, edges_len); + CustomData_copy(&me_src->ldata, &me_dst->ldata, mask, CD_CALLOC, loops_len); + CustomData_copy(&me_src->pdata, &me_dst->pdata, mask, CD_CALLOC, polys_len); + if (do_tessface) { + CustomData_copy(&me_src->fdata, &me_dst->fdata, mask, CD_CALLOC, tessface_len); + } + else { + mesh_tessface_clear_intern(me_dst, false); + } + + /* The destination mesh should at least have valid primary CD layers, + * even in cases where the source mesh does not. */ + mesh_ensure_cdlayers_primary(me_dst, do_tessface); + mesh_ensure_cdlayers_origindex(me_dst, false); + BKE_mesh_update_customdata_pointers(me_dst, false); + + return me_dst; +} + +Mesh *BKE_mesh_new_nomain_from_template( + const Mesh *me_src, + int verts_len, int edges_len, int tessface_len, + int loops_len, int polys_len) +{ + return mesh_new_nomain_from_template_ex( + me_src, + verts_len, edges_len, tessface_len, + loops_len, polys_len, + CD_MASK_EVERYTHING); +} + +Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference) +{ + int flags = (LIB_ID_CREATE_NO_MAIN | + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_DEG_TAG | + LIB_ID_COPY_NO_PREVIEW); + + if (reference) { + flags |= LIB_ID_COPY_CD_REFERENCE; + } + + Mesh *result; + BKE_id_copy_ex(NULL, &source->id, (ID **)&result, flags, false); + return result; +} + Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) { Mesh *me_copy; - BKE_id_copy_ex(bmain, &me->id, (ID **)&me_copy, 0, false); + BKE_id_copy_ex(bmain, &me->id, (ID **)&me_copy, LIB_ID_COPY_SHAPEKEY, false); return me_copy; } +BMesh *BKE_mesh_to_bmesh_ex( + Mesh *me, + const struct BMeshCreateParams *create_params, + const struct BMeshFromMeshParams *convert_params) +{ + BMesh *bm; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me); + + bm = BM_mesh_create(&allocsize, create_params); + BM_mesh_bm_from_me(bm, me, convert_params); + + return bm; +} + BMesh *BKE_mesh_to_bmesh( Mesh *me, Object *ob, const bool add_key_index, const struct BMeshCreateParams *params) { - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me); + return BKE_mesh_to_bmesh_ex( + me, params, + &(struct BMeshFromMeshParams){ + .calc_face_normal = false, + .add_key_index = add_key_index, + .use_shapekey = true, + .active_shapekey = ob->shapenr, + }); +} - bm = BM_mesh_create(&allocsize, params); +Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm, const struct BMeshToMeshParams *params) +{ + BLI_assert(params->calc_object_remap == false); + Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL); + BM_mesh_bm_to_me(NULL, bm, mesh, params); + return mesh; +} - BM_mesh_bm_from_me( - bm, me, (&(struct BMeshFromMeshParams){ - .add_key_index = add_key_index, .use_shapekey = true, .active_shapekey = ob->shapenr, - })); +Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const int64_t cd_mask_extra) +{ + Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL); + BM_mesh_bm_to_me_for_eval(bm, mesh, cd_mask_extra); + return mesh; +} - return bm; +/** + * TODO(campbell): support mesh with only an edit-mesh which is lazy initialized. + */ +Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap( + BMEditMesh *em, CustomDataMask data_mask, float (*vertexCos)[3]) +{ + Mesh *me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, data_mask); + /* Use editmesh directly where possible. */ + me->runtime.is_original = true; + if (vertexCos) { + /* We will own this array in the future. */ + BKE_mesh_apply_vert_coords(me, vertexCos); + MEM_freeN(vertexCos); + me->runtime.is_original = false; + } + return me; } void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local) @@ -553,121 +784,82 @@ void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local) } bool BKE_mesh_uv_cdlayer_rename_index( - Mesh *me, const int poly_index, const int loop_index, const int face_index, + Mesh *me, const int loop_index, const int face_index, const char *new_name, const bool do_tessface) { - CustomData *pdata, *ldata, *fdata; - CustomDataLayer *cdlp, *cdlu, *cdlf; - const int step = do_tessface ? 3 : 2; - int i; + CustomData *ldata, *fdata; + CustomDataLayer *cdlu, *cdlf; if (me->edit_btmesh) { - pdata = &me->edit_btmesh->bm->pdata; ldata = &me->edit_btmesh->bm->ldata; fdata = NULL; /* No tessellated data in BMesh! */ } else { - pdata = &me->pdata; ldata = &me->ldata; fdata = &me->fdata; } - cdlp = &pdata->layers[poly_index]; + cdlu = &ldata->layers[loop_index]; - cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL; + cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL; - if (cdlp->name != new_name) { + if (cdlu->name != new_name) { /* Mesh validate passes a name from the CD layer as the new name, * Avoid memcpy from self to self in this case. */ - BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name)); - CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers); + BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name)); + CustomData_set_layer_unique_name(ldata, loop_index); } - /* Loop until we do have exactly the same name for all layers! */ - for (i = 1; !STREQ(cdlp->name, cdlu->name) || (cdlf && !STREQ(cdlp->name, cdlf->name)); i++) { - switch (i % step) { - case 0: - BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name)); - CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers); - break; - case 1: - BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name)); - CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers); - break; - case 2: - if (cdlf) { - BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name)); - CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers); - } - break; - } + if (cdlf == NULL) { + return false; } + BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name)); + CustomData_set_layer_unique_name(fdata, face_index); + return true; } bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface) { - CustomData *pdata, *ldata, *fdata; + CustomData *ldata, *fdata; if (me->edit_btmesh) { - pdata = &me->edit_btmesh->bm->pdata; ldata = &me->edit_btmesh->bm->ldata; /* No tessellated data in BMesh! */ fdata = NULL; do_tessface = false; } else { - pdata = &me->pdata; ldata = &me->ldata; fdata = &me->fdata; do_tessface = (do_tessface && fdata->totlayer); } { - const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY); const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV); const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1; - int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name); int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name); int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1; /* None of those cases should happen, in theory! * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers! */ - if (pidx == -1) { - if (lidx == -1) { - if (fidx == -1) { - /* No layer found with this name! */ - return false; - } - else { - lidx = fidx; - } - } - pidx = lidx; - } - else { - if (lidx == -1) { - lidx = pidx; + if (lidx == -1) { + if (fidx == -1) { + /* No layer found with this name! */ + return false; } - if (fidx == -1 && do_tessface) { - fidx = pidx; + else { + lidx = fidx; } } -#if 0 - /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */ - else if (pidx != lidx) { - lidx = pidx; - } -#endif /* Go back to absolute indices! */ - pidx += pidx_start; lidx += lidx_start; if (fidx != -1) fidx += fidx_start; - return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface); + return BKE_mesh_uv_cdlayer_rename_index(me, lidx, fidx, new_name, do_tessface); } } @@ -745,6 +937,18 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_siz if (r_size) copy_v3_v3(r_size, me->size); } +void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size) +{ + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { + BKE_mesh_texspace_calc(me); + } + + if (r_texflag != NULL) *r_texflag = &me->texflag; + if (r_loc != NULL) *r_loc = me->loc; + if (r_rot != NULL) *r_rot = me->rot; + if (r_size != NULL) *r_size = me->size; +} + void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob) { float *texloc, *texrot, *texsize; @@ -904,7 +1108,6 @@ void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me) test_object_modifiers(ob); } - void BKE_mesh_material_index_remove(Mesh *me, short index) { MPoly *mp; @@ -999,15 +1202,15 @@ 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 + * \note \a r_verts_len may be NULL */ -float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_numVerts))[3] +float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_verts_len))[3] { - int i, numVerts = me->totvert; - float (*cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(*cos), "vertexcos1"); + int i, verts_len = me->totvert; + float (*cos)[3] = MEM_malloc_arrayN(verts_len, sizeof(*cos), "vertexcos1"); - if (r_numVerts) *r_numVerts = numVerts; - for (i = 0; i < numVerts; i++) + if (r_verts_len) *r_verts_len = verts_len; + for (i = 0; i < verts_len; i++) copy_v3_v3(cos[i], me->mvert[i].co); return cos; @@ -1046,10 +1249,6 @@ int poly_get_adj_loops_from_vert( 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] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v; @@ -1072,6 +1271,21 @@ int BKE_mesh_edge_other_vert(const MEdge *e, int v) return -1; } +/** + * Sets each output array element to the edge index if it is a real edge, or -1. + */ +void BKE_mesh_looptri_get_real_edges(const Mesh *mesh, const MLoopTri *looptri, int r_edges[3]) +{ + for (int i = 2, i_next = 0; i_next < 3; i = i_next++) { + const MLoop *l1 = &mesh->mloop[looptri->tri[i]], *l2 = &mesh->mloop[looptri->tri[i_next]]; + const MEdge *e = &mesh->medge[l1->e]; + + bool is_real = (l1->v == e->v1 && l2->v == e->v2) || (l1->v == e->v2 && l2->v == e->v1); + + r_edges[i] = is_real ? l1->e : -1; + } +} + /* basic vertex data functions */ bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3]) { @@ -1139,13 +1353,13 @@ void BKE_mesh_ensure_navmesh(Mesh *me) { if (!CustomData_has_layer(&me->pdata, CD_RECAST)) { int i; - int numFaces = me->totpoly; + int polys_len = me->totpoly; int *recastData; - recastData = (int *)MEM_malloc_arrayN(numFaces, sizeof(int), __func__); - for (i = 0; i < numFaces; i++) { + recastData = (int *)MEM_malloc_arrayN(polys_len, sizeof(int), __func__); + for (i = 0; i < polys_len; i++) { recastData[i] = i + 1; } - CustomData_add_layer_named(&me->pdata, CD_RECAST, CD_ASSIGN, recastData, numFaces, "recastData"); + CustomData_add_layer_named(&me->pdata, CD_RECAST, CD_ASSIGN, recastData, polys_len, "recastData"); } } @@ -1337,6 +1551,37 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type) (me->mselect[me->totselect - 1].type == type)); } + +void BKE_mesh_apply_vert_coords(Mesh *mesh, float (*vertCoords)[3]) +{ + MVert *vert; + int i; + + /* this will just return the pointer if it wasn't a referenced layer */ + vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + mesh->mvert = vert; + + for (i = 0; i < mesh->totvert; ++i, ++vert) + copy_v3_v3(vert->co, vertCoords[i]); + + mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; +} + +void BKE_mesh_apply_vert_normals(Mesh *mesh, short (*vertNormals)[3]) +{ + MVert *vert; + int i; + + /* this will just return the pointer if it wasn't a referenced layer */ + vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); + mesh->mvert = vert; + + for (i = 0; i < mesh->totvert; ++i, ++vert) + copy_v3_v3_short(vert->no, vertNormals[i]); + + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; +} + /** * Compute 'split' (aka loop, or per face corner's) normals. * @@ -1388,6 +1633,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac if (free_polynors) { MEM_freeN(polynors); } + + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; } void BKE_mesh_calc_normals_split(Mesh *mesh) @@ -1421,25 +1668,25 @@ static int split_faces_prepare_new_verts( * dealing with smooth/flat faces one can find cases that no simple algorithm can handle properly. */ BLI_assert(lnors_spacearr != NULL); - const int num_loops = mesh->totloop; - int num_verts = mesh->totvert; + const int loops_len = mesh->totloop; + int verts_len = mesh->totvert; MVert *mvert = mesh->mvert; MLoop *mloop = mesh->mloop; - BLI_bitmap *verts_used = BLI_BITMAP_NEW(num_verts, __func__); - BLI_bitmap *done_loops = BLI_BITMAP_NEW(num_loops, __func__); + BLI_bitmap *verts_used = BLI_BITMAP_NEW(verts_len, __func__); + BLI_bitmap *done_loops = BLI_BITMAP_NEW(loops_len, __func__); MLoop *ml = mloop; MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr; BLI_assert(lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX); - for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) { + for (int loop_idx = 0; loop_idx < loops_len; loop_idx++, ml++, lnor_space++) { if (!BLI_BITMAP_TEST(done_loops, loop_idx)) { const int vert_idx = ml->v; const bool vert_used = BLI_BITMAP_TEST_BOOL(verts_used, vert_idx); /* If vert is already used by another smooth fan, we need a new vert for this one. */ - const int new_vert_idx = vert_used ? num_verts++ : vert_idx; + const int new_vert_idx = vert_used ? verts_len++ : vert_idx; BLI_assert(*lnor_space); @@ -1484,7 +1731,7 @@ static int split_faces_prepare_new_verts( MEM_freeN(done_loops); MEM_freeN(verts_used); - return num_verts - mesh->totvert; + return verts_len - mesh->totvert; } /* Detect needed new edges, and update accordingly loops' edge indices. @@ -1552,12 +1799,12 @@ static int split_faces_prepare_new_edges( static void split_faces_split_new_verts( Mesh *mesh, SplitFaceNewVert *new_verts, const int num_new_verts) { - const int num_verts = mesh->totvert - num_new_verts; + const int verts_len = mesh->totvert - num_new_verts; MVert *mvert = mesh->mvert; /* Remember new_verts is a single linklist, so its items are in reversed order... */ MVert *new_mv = &mvert[mesh->totvert - 1]; - for (int i = mesh->totvert - 1; i >= num_verts ; i--, new_mv--, new_verts = new_verts->next) { + for (int i = mesh->totvert - 1; i >= verts_len ; i--, new_mv--, new_verts = new_verts->next) { BLI_assert(new_verts->new_index == i); BLI_assert(new_verts->new_index != new_verts->orig_index); CustomData_copy_data(&mesh->vdata, &mesh->vdata, new_verts->orig_index, i, 1); @@ -1652,14 +1899,13 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) #endif } - /* **** Depsgraph evaluation **** */ void BKE_mesh_eval_geometry( - EvaluationContext *UNUSED(eval_ctx), + Depsgraph *depsgraph, Mesh *mesh) { - DEG_debug_print_eval(__func__, mesh->id.name, mesh); + DEG_debug_print_eval(depsgraph, __func__, mesh->id.name, mesh); if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(mesh); } |