diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/blenkernel/intern/mesh.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/blenkernel/intern/mesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 2792 |
1 files changed, 1410 insertions, 1382 deletions
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 74fb31d0121..5df06e61744 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -52,205 +52,213 @@ #include "DEG_depsgraph.h" enum { - MESHCMP_DVERT_WEIGHTMISMATCH = 1, - MESHCMP_DVERT_GROUPMISMATCH, - MESHCMP_DVERT_TOTGROUPMISMATCH, - MESHCMP_LOOPCOLMISMATCH, - MESHCMP_LOOPUVMISMATCH, - MESHCMP_LOOPMISMATCH, - MESHCMP_POLYVERTMISMATCH, - MESHCMP_POLYMISMATCH, - MESHCMP_EDGEUNKNOWN, - MESHCMP_VERTCOMISMATCH, - MESHCMP_CDLAYERS_MISMATCH, + MESHCMP_DVERT_WEIGHTMISMATCH = 1, + MESHCMP_DVERT_GROUPMISMATCH, + MESHCMP_DVERT_TOTGROUPMISMATCH, + MESHCMP_LOOPCOLMISMATCH, + MESHCMP_LOOPUVMISMATCH, + MESHCMP_LOOPMISMATCH, + MESHCMP_POLYVERTMISMATCH, + MESHCMP_POLYMISMATCH, + MESHCMP_EDGEUNKNOWN, + MESHCMP_VERTCOMISMATCH, + MESHCMP_CDLAYERS_MISMATCH, }; static const char *cmpcode_to_str(int code) { - switch (code) { - case MESHCMP_DVERT_WEIGHTMISMATCH: - return "Vertex Weight Mismatch"; - case MESHCMP_DVERT_GROUPMISMATCH: - return "Vertex Group Mismatch"; - case MESHCMP_DVERT_TOTGROUPMISMATCH: - return "Vertex Doesn't Belong To Same Number Of Groups"; - case MESHCMP_LOOPCOLMISMATCH: - return "Vertex Color Mismatch"; - case MESHCMP_LOOPUVMISMATCH: - return "UV Mismatch"; - case MESHCMP_LOOPMISMATCH: - return "Loop Mismatch"; - case MESHCMP_POLYVERTMISMATCH: - return "Loop Vert Mismatch In Poly Test"; - case MESHCMP_POLYMISMATCH: - return "Loop Vert Mismatch"; - case MESHCMP_EDGEUNKNOWN: - return "Edge Mismatch"; - case MESHCMP_VERTCOMISMATCH: - return "Vertex Coordinate Mismatch"; - case MESHCMP_CDLAYERS_MISMATCH: - return "CustomData Layer Count Mismatch"; - default: - return "Mesh Comparison Code Unknown"; - } + switch (code) { + case MESHCMP_DVERT_WEIGHTMISMATCH: + return "Vertex Weight Mismatch"; + case MESHCMP_DVERT_GROUPMISMATCH: + return "Vertex Group Mismatch"; + case MESHCMP_DVERT_TOTGROUPMISMATCH: + return "Vertex Doesn't Belong To Same Number Of Groups"; + case MESHCMP_LOOPCOLMISMATCH: + return "Vertex Color Mismatch"; + case MESHCMP_LOOPUVMISMATCH: + return "UV Mismatch"; + case MESHCMP_LOOPMISMATCH: + return "Loop Mismatch"; + case MESHCMP_POLYVERTMISMATCH: + return "Loop Vert Mismatch In Poly Test"; + case MESHCMP_POLYMISMATCH: + return "Loop Vert Mismatch"; + case MESHCMP_EDGEUNKNOWN: + return "Edge Mismatch"; + case MESHCMP_VERTCOMISMATCH: + return "Vertex Coordinate Mismatch"; + case MESHCMP_CDLAYERS_MISMATCH: + return "CustomData Layer Count Mismatch"; + default: + return "Mesh Comparison Code Unknown"; + } } /* thresh is threshold for comparing vertices, uvs, vertex colors, * weights, etc.*/ -static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, const float thresh) -{ - const float thresh_sq = thresh * thresh; - CustomDataLayer *l1, *l2; - int i, i1 = 0, i2 = 0, tot, j; - - for (i = 0; i < c1->totlayer; i++) { - if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) - { - i1++; - } - } - - for (i = 0; i < c2->totlayer; i++) { - if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) - { - i2++; - } - } - - if (i1 != i2) - return MESHCMP_CDLAYERS_MISMATCH; - - l1 = c1->layers; l2 = c2->layers; - tot = i1; - 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_MDEFORMVERT)) - { - i1++; - l1++; - } - - while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) - { - i2++; - l2++; - } - - if (l1->type == CD_MVERT) { - MVert *v1 = l1->data; - MVert *v2 = l2->data; - int vtot = m1->totvert; - - for (j = 0; j < vtot; j++, v1++, v2++) { - if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) - return MESHCMP_VERTCOMISMATCH; - /* I don't care about normals, let's just do coordinates */ - } - } - - /*we're order-agnostic for edges here*/ - if (l1->type == CD_MEDGE) { - MEdge *e1 = l1->data; - MEdge *e2 = l2->data; - int etot = m1->totedge; - EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); - - for (j = 0; j < etot; j++, e1++) { - BLI_edgehash_insert(eh, e1->v1, e1->v2, e1); - } - - for (j = 0; j < etot; j++, e2++) { - if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) - return MESHCMP_EDGEUNKNOWN; - } - BLI_edgehash_free(eh, NULL); - } - - if (l1->type == CD_MPOLY) { - MPoly *p1 = l1->data; - MPoly *p2 = l2->data; - int ptot = m1->totpoly; - - for (j = 0; j < ptot; j++, p1++, p2++) { - MLoop *lp1, *lp2; - int k; - - if (p1->totloop != p2->totloop) - return MESHCMP_POLYMISMATCH; - - lp1 = m1->mloop + p1->loopstart; - lp2 = m2->mloop + p2->loopstart; - - for (k = 0; k < p1->totloop; k++, lp1++, lp2++) { - if (lp1->v != lp2->v) - return MESHCMP_POLYVERTMISMATCH; - } - } - } - if (l1->type == CD_MLOOP) { - MLoop *lp1 = l1->data; - MLoop *lp2 = l2->data; - int ltot = m1->totloop; - - for (j = 0; j < ltot; j++, lp1++, lp2++) { - if (lp1->v != lp2->v) - return MESHCMP_LOOPMISMATCH; - } - } - if (l1->type == CD_MLOOPUV) { - MLoopUV *lp1 = l1->data; - MLoopUV *lp2 = l2->data; - int ltot = m1->totloop; - - for (j = 0; j < ltot; j++, lp1++, lp2++) { - if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) - return MESHCMP_LOOPUVMISMATCH; - } - } - - if (l1->type == CD_MLOOPCOL) { - MLoopCol *lp1 = l1->data; - MLoopCol *lp2 = l2->data; - int ltot = m1->totloop; - - for (j = 0; j < ltot; j++, lp1++, lp2++) { - if (ABS(lp1->r - lp2->r) > thresh || - ABS(lp1->g - lp2->g) > thresh || - ABS(lp1->b - lp2->b) > thresh || - ABS(lp1->a - lp2->a) > thresh) - { - return MESHCMP_LOOPCOLMISMATCH; - } - } - } - - if (l1->type == CD_MDEFORMVERT) { - MDeformVert *dv1 = l1->data; - MDeformVert *dv2 = l2->data; - int dvtot = m1->totvert; - - for (j = 0; j < dvtot; j++, dv1++, dv2++) { - int k; - MDeformWeight *dw1 = dv1->dw, *dw2 = dv2->dw; - - if (dv1->totweight != dv2->totweight) - return MESHCMP_DVERT_TOTGROUPMISMATCH; - - for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) { - if (dw1->def_nr != dw2->def_nr) - return MESHCMP_DVERT_GROUPMISMATCH; - if (fabsf(dw1->weight - dw2->weight) > thresh) - return MESHCMP_DVERT_WEIGHTMISMATCH; - } - } - } - } - - return 0; +static int customdata_compare( + CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, const float thresh) +{ + const float thresh_sq = thresh * thresh; + CustomDataLayer *l1, *l2; + int i, i1 = 0, i2 = 0, tot, j; + + for (i = 0; i < c1->totlayer; i++) { + if (ELEM(c1->layers[i].type, + CD_MVERT, + CD_MEDGE, + CD_MPOLY, + CD_MLOOPUV, + CD_MLOOPCOL, + CD_MDEFORMVERT)) { + i1++; + } + } + + for (i = 0; i < c2->totlayer; i++) { + if (ELEM(c2->layers[i].type, + CD_MVERT, + CD_MEDGE, + CD_MPOLY, + CD_MLOOPUV, + CD_MLOOPCOL, + CD_MDEFORMVERT)) { + i2++; + } + } + + if (i1 != i2) + return MESHCMP_CDLAYERS_MISMATCH; + + l1 = c1->layers; + l2 = c2->layers; + tot = i1; + 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_MDEFORMVERT)) { + i1++; + l1++; + } + + while ( + i2 < c2->totlayer && + !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { + i2++; + l2++; + } + + if (l1->type == CD_MVERT) { + MVert *v1 = l1->data; + MVert *v2 = l2->data; + int vtot = m1->totvert; + + for (j = 0; j < vtot; j++, v1++, v2++) { + if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) + return MESHCMP_VERTCOMISMATCH; + /* I don't care about normals, let's just do coordinates */ + } + } + + /*we're order-agnostic for edges here*/ + if (l1->type == CD_MEDGE) { + MEdge *e1 = l1->data; + MEdge *e2 = l2->data; + int etot = m1->totedge; + EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); + + for (j = 0; j < etot; j++, e1++) { + BLI_edgehash_insert(eh, e1->v1, e1->v2, e1); + } + + for (j = 0; j < etot; j++, e2++) { + if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) + return MESHCMP_EDGEUNKNOWN; + } + BLI_edgehash_free(eh, NULL); + } + + if (l1->type == CD_MPOLY) { + MPoly *p1 = l1->data; + MPoly *p2 = l2->data; + int ptot = m1->totpoly; + + for (j = 0; j < ptot; j++, p1++, p2++) { + MLoop *lp1, *lp2; + int k; + + if (p1->totloop != p2->totloop) + return MESHCMP_POLYMISMATCH; + + lp1 = m1->mloop + p1->loopstart; + lp2 = m2->mloop + p2->loopstart; + + for (k = 0; k < p1->totloop; k++, lp1++, lp2++) { + if (lp1->v != lp2->v) + return MESHCMP_POLYVERTMISMATCH; + } + } + } + if (l1->type == CD_MLOOP) { + MLoop *lp1 = l1->data; + MLoop *lp2 = l2->data; + int ltot = m1->totloop; + + for (j = 0; j < ltot; j++, lp1++, lp2++) { + if (lp1->v != lp2->v) + return MESHCMP_LOOPMISMATCH; + } + } + if (l1->type == CD_MLOOPUV) { + MLoopUV *lp1 = l1->data; + MLoopUV *lp2 = l2->data; + int ltot = m1->totloop; + + for (j = 0; j < ltot; j++, lp1++, lp2++) { + if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) + return MESHCMP_LOOPUVMISMATCH; + } + } + + if (l1->type == CD_MLOOPCOL) { + MLoopCol *lp1 = l1->data; + MLoopCol *lp2 = l2->data; + int ltot = m1->totloop; + + for (j = 0; j < ltot; j++, lp1++, lp2++) { + if (ABS(lp1->r - lp2->r) > thresh || ABS(lp1->g - lp2->g) > thresh || + ABS(lp1->b - lp2->b) > thresh || ABS(lp1->a - lp2->a) > thresh) { + return MESHCMP_LOOPCOLMISMATCH; + } + } + } + + if (l1->type == CD_MDEFORMVERT) { + MDeformVert *dv1 = l1->data; + MDeformVert *dv2 = l2->data; + int dvtot = m1->totvert; + + for (j = 0; j < dvtot; j++, dv1++, dv2++) { + int k; + MDeformWeight *dw1 = dv1->dw, *dw2 = dv2->dw; + + if (dv1->totweight != dv2->totweight) + return MESHCMP_DVERT_TOTGROUPMISMATCH; + + for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) { + if (dw1->def_nr != dw2->def_nr) + return MESHCMP_DVERT_GROUPMISMATCH; + if (fabsf(dw1->weight - dw2->weight) > thresh) + return MESHCMP_DVERT_WEIGHTMISMATCH; + } + } + } + } + + return 0; } /** @@ -261,154 +269,146 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 */ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) { - int c; + int c; - if (!me1 || !me2) - return "Requires two input meshes"; + if (!me1 || !me2) + return "Requires two input meshes"; - if (me1->totvert != me2->totvert) - return "Number of verts don't match"; + if (me1->totvert != me2->totvert) + return "Number of verts don't match"; - if (me1->totedge != me2->totedge) - return "Number of edges don't match"; + if (me1->totedge != me2->totedge) + return "Number of edges don't match"; - if (me1->totpoly != me2->totpoly) - return "Number of faces don't match"; + if (me1->totpoly != me2->totpoly) + return "Number of faces don't match"; - if (me1->totloop != me2->totloop) - return "Number of loops don't match"; + if (me1->totloop != me2->totloop) + return "Number of loops don't match"; - if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh))) - return cmpcode_to_str(c); + if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh))) + return cmpcode_to_str(c); - if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh))) - return cmpcode_to_str(c); + if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh))) + return cmpcode_to_str(c); - if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh))) - return cmpcode_to_str(c); + if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh))) + return cmpcode_to_str(c); - if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh))) - return cmpcode_to_str(c); + if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh))) + return cmpcode_to_str(c); - return NULL; + return NULL; } static void mesh_ensure_tessellation_customdata(Mesh *me) { - if (UNLIKELY((me->totface != 0) && (me->totpoly == 0))) { - /* Pass, otherwise this function clears 'mface' before - * versioning 'mface -> mpoly' code kicks in [#30583] - * - * Callers could also check but safer to do here - campbell */ - } - else { - 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); - const int totcol_tessface = CustomData_number_of_layers(&me->fdata, CD_MCOL); - - if (tottex_tessface != tottex_original || - totcol_tessface != totcol_original) - { - BKE_mesh_tessface_clear(me); - - 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 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_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n", - __func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original); - } - } - } + if (UNLIKELY((me->totface != 0) && (me->totpoly == 0))) { + /* Pass, otherwise this function clears 'mface' before + * versioning 'mface -> mpoly' code kicks in [#30583] + * + * Callers could also check but safer to do here - campbell */ + } + else { + 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); + const int totcol_tessface = CustomData_number_of_layers(&me->fdata, CD_MCOL); + + if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) { + BKE_mesh_tessface_clear(me); + + 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 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_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: " + "%d\n", + __func__, + tottex_tessface, + tottex_original, + totcol_tessface, + totcol_original); + } + } + } } void BKE_mesh_ensure_skin_customdata(Mesh *me) { - BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL; - MVertSkin *vs; - - if (bm) { - if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMVert *v; - BMIter iter; - - BM_data_layer_add(bm, &bm->vdata, CD_MVERT_SKIN); - - /* Mark an arbitrary vertex as root */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - vs = CustomData_bmesh_get( - &bm->vdata, v->head.data, - CD_MVERT_SKIN); - vs->flag |= MVERT_SKIN_ROOT; - break; - } - } - } - else { - if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) { - vs = CustomData_add_layer( - &me->vdata, - CD_MVERT_SKIN, - CD_DEFAULT, - NULL, - me->totvert); - - /* Mark an arbitrary vertex as root */ - if (vs) { - vs->flag |= MVERT_SKIN_ROOT; - } - } - } + BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : NULL; + MVertSkin *vs; + + if (bm) { + if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { + BMVert *v; + BMIter iter; + + BM_data_layer_add(bm, &bm->vdata, CD_MVERT_SKIN); + + /* Mark an arbitrary vertex as root */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN); + vs->flag |= MVERT_SKIN_ROOT; + break; + } + } + } + else { + if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) { + vs = CustomData_add_layer(&me->vdata, CD_MVERT_SKIN, CD_DEFAULT, NULL, me->totvert); + + /* Mark an arbitrary vertex as root */ + if (vs) { + vs->flag |= MVERT_SKIN_ROOT; + } + } + } } bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me) { - BMesh *bm = me->edit_mesh ? me->edit_mesh->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; + BMesh *bm = me->edit_mesh ? me->edit_mesh->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_mesh ? me->edit_mesh->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; + BMesh *bm = me->edit_mesh ? me->edit_mesh->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 @@ -419,101 +419,101 @@ bool BKE_mesh_clear_facemap_customdata(struct Mesh *me) * versions of the mesh. - campbell*/ static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd) { - if (do_ensure_tess_cd) { - mesh_ensure_tessellation_customdata(me); - } + if (do_ensure_tess_cd) { + mesh_ensure_tessellation_customdata(me); + } - CustomData_bmesh_update_active_layers(&me->fdata, &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) { - mesh_update_linked_customdata(me, do_ensure_tess_cd); + mesh_update_linked_customdata(me, do_ensure_tess_cd); - me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); - me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); + me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); + me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); - me->medge = CustomData_get_layer(&me->edata, CD_MEDGE); + me->medge = CustomData_get_layer(&me->edata, CD_MEDGE); - me->mface = CustomData_get_layer(&me->fdata, CD_MFACE); - me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL); - me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); + me->mface = CustomData_get_layer(&me->fdata, CD_MFACE); + me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL); + me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); - me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); - me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); + me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); + me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); - me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); - me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); + me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); + me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); } bool BKE_mesh_has_custom_loop_normals(Mesh *me) { - if (me->edit_mesh) { - return CustomData_has_layer(&me->edit_mesh->bm->ldata, CD_CUSTOMLOOPNORMAL); - } - else { - return CustomData_has_layer(&me->ldata, CD_CUSTOMLOOPNORMAL); - } + if (me->edit_mesh) { + return CustomData_has_layer(&me->edit_mesh->bm->ldata, CD_CUSTOMLOOPNORMAL); + } + else { + return CustomData_has_layer(&me->ldata, CD_CUSTOMLOOPNORMAL); + } } /** Free (or release) any data used by this mesh (does not free the mesh itself). */ void BKE_mesh_free(Mesh *me) { - BKE_animdata_free(&me->id, false); + BKE_animdata_free(&me->id, false); - BKE_mesh_runtime_clear_cache(me); + BKE_mesh_runtime_clear_cache(me); - CustomData_free(&me->vdata, me->totvert); - CustomData_free(&me->edata, me->totedge); - CustomData_free(&me->fdata, me->totface); - CustomData_free(&me->ldata, me->totloop); - CustomData_free(&me->pdata, me->totpoly); + CustomData_free(&me->vdata, me->totvert); + CustomData_free(&me->edata, me->totedge); + CustomData_free(&me->fdata, me->totface); + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); - MEM_SAFE_FREE(me->mat); - MEM_SAFE_FREE(me->bb); - MEM_SAFE_FREE(me->mselect); - MEM_SAFE_FREE(me->edit_mesh); + MEM_SAFE_FREE(me->mat); + MEM_SAFE_FREE(me->bb); + MEM_SAFE_FREE(me->mselect); + MEM_SAFE_FREE(me->edit_mesh); } static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata) { - if (free_customdata) { - CustomData_free(&mesh->fdata, mesh->totface); - } - else { - CustomData_reset(&mesh->fdata); - } + if (free_customdata) { + CustomData_free(&mesh->fdata, mesh->totface); + } + else { + CustomData_reset(&mesh->fdata); + } - mesh->mface = NULL; - mesh->mtface = NULL; - mesh->mcol = NULL; - mesh->totface = 0; + mesh->mface = NULL; + mesh->mtface = NULL; + mesh->mcol = NULL; + mesh->totface = 0; } void BKE_mesh_init(Mesh *me) { - BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(me, id)); + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(me, id)); - me->size[0] = me->size[1] = me->size[2] = 1.0; - me->smoothresh = DEG2RADF(30); - me->texflag = ME_AUTOSPACE; + me->size[0] = me->size[1] = me->size[2] = 1.0; + me->smoothresh = DEG2RADF(30); + me->texflag = ME_AUTOSPACE; - CustomData_reset(&me->vdata); - CustomData_reset(&me->edata); - CustomData_reset(&me->fdata); - CustomData_reset(&me->pdata); - CustomData_reset(&me->ldata); + CustomData_reset(&me->vdata); + CustomData_reset(&me->edata); + CustomData_reset(&me->fdata); + CustomData_reset(&me->pdata); + CustomData_reset(&me->ldata); } Mesh *BKE_mesh_add(Main *bmain, const char *name) { - Mesh *me; + Mesh *me; - me = BKE_libblock_alloc(bmain, ID_ME, name, 0); + me = BKE_libblock_alloc(bmain, ID_ME, name, 0); - BKE_mesh_init(me); + BKE_mesh_init(me); - return me; + return me; } /** @@ -526,659 +526,675 @@ 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) { - BKE_mesh_runtime_reset_on_copy(me_dst, flag); - if ((me_src->id.tag & LIB_TAG_NO_MAIN) == 0) { - /* This is a direct copy of a main mesh, so for now it has the same topology. */ - me_dst->runtime.deformed_only = true; - } - /* XXX WHAT? Why? Comment, please! And pretty sure this is not valid for regular Mesh copying? */ - me_dst->runtime.is_original = false; + BKE_mesh_runtime_reset_on_copy(me_dst, flag); + if ((me_src->id.tag & LIB_TAG_NO_MAIN) == 0) { + /* This is a direct copy of a main mesh, so for now it has the same topology. */ + me_dst->runtime.deformed_only = true; + } + /* XXX WHAT? Why? Comment, please! And pretty sure this is not valid for regular Mesh copying? */ + me_dst->runtime.is_original = false; - const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0)); /* only do tessface if we have no polys */ - CustomData_MeshMasks mask = CD_MASK_MESH; + const bool do_tessface = ((me_src->totface != 0) && + (me_src->totpoly == 0)); /* only do tessface if we have no polys */ + CustomData_MeshMasks mask = CD_MASK_MESH; - if (me_src->id.tag & LIB_TAG_NO_MAIN) { - /* For copies in depsgraph, keep data like origindex and orco. */ - CustomData_MeshMasks_update(&mask, &CD_MASK_DERIVEDMESH); - } + if (me_src->id.tag & LIB_TAG_NO_MAIN) { + /* For copies in depsgraph, keep data like origindex and orco. */ + CustomData_MeshMasks_update(&mask, &CD_MASK_DERIVEDMESH); + } - me_dst->mat = MEM_dupallocN(me_src->mat); + me_dst->mat = MEM_dupallocN(me_src->mat); - const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; - CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, alloc_type, me_dst->totvert); - CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, alloc_type, me_dst->totedge); - CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, alloc_type, me_dst->totloop); - CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, alloc_type, me_dst->totpoly); - if (do_tessface) { - CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, alloc_type, me_dst->totface); - } - else { - mesh_tessface_clear_intern(me_dst, false); - } + const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; + CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, alloc_type, me_dst->totvert); + CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, alloc_type, me_dst->totedge); + CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, alloc_type, me_dst->totloop); + CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, alloc_type, me_dst->totpoly); + if (do_tessface) { + CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, alloc_type, me_dst->totface); + } + else { + mesh_tessface_clear_intern(me_dst, false); + } - BKE_mesh_update_customdata_pointers(me_dst, do_tessface); + BKE_mesh_update_customdata_pointers(me_dst, do_tessface); - me_dst->edit_mesh = NULL; + me_dst->edit_mesh = NULL; - me_dst->mselect = MEM_dupallocN(me_dst->mselect); - me_dst->bb = MEM_dupallocN(me_dst->bb); + 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 && (flag & LIB_ID_COPY_SHAPEKEY)) { - BKE_id_copy_ex(bmain, &me_src->key->id, (ID **)&me_dst->key, flag); - } + /* TODO Do we want to add flag to prevent this? */ + if (me_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) { + BKE_id_copy_ex(bmain, &me_src->key->id, (ID **)&me_dst->key, flag); + } } /* 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 (!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); + if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) + CustomData_add_layer(&mesh->fdata, CD_MFACE, 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 *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_COPY_LOCALIZE); - BKE_libblock_init_empty(&mesh->id); + Mesh *mesh = BKE_libblock_alloc(NULL, ID_ME, BKE_idcode_to_name(ID_ME), LIB_ID_COPY_LOCALIZE); + 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); + /* 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->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); - BKE_mesh_update_customdata_pointers(mesh, false); + mesh_ensure_cdlayers_primary(mesh, true); + BKE_mesh_update_customdata_pointers(mesh, false); - return mesh; + 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, - CustomData_MeshMasks mask) +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, + CustomData_MeshMasks 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))); + /* 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); + 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->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; + 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; - me_dst->cd_flag = me_src->cd_flag; - me_dst->editflag = me_src->editflag; + me_dst->cd_flag = me_src->cd_flag; + me_dst->editflag = me_src->editflag; - CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_CALLOC, verts_len); - CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_CALLOC, edges_len); - CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_CALLOC, loops_len); - CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_CALLOC, polys_len); - if (do_tessface) { - CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, CD_CALLOC, tessface_len); - } - else { - mesh_tessface_clear_intern(me_dst, false); - } + CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_CALLOC, verts_len); + CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_CALLOC, edges_len); + CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_CALLOC, loops_len); + CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_CALLOC, polys_len); + if (do_tessface) { + CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, 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); - BKE_mesh_update_customdata_pointers(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); + BKE_mesh_update_customdata_pointers(me_dst, false); - return me_dst; + 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) +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); + 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_COPY_LOCALIZE; + int flags = LIB_ID_COPY_LOCALIZE; - if (reference) { - flags |= LIB_ID_COPY_CD_REFERENCE; - } + if (reference) { + flags |= LIB_ID_COPY_CD_REFERENCE; + } - Mesh *result; - BKE_id_copy_ex(NULL, &source->id, (ID **)&result, flags); - return result; + Mesh *result; + BKE_id_copy_ex(NULL, &source->id, (ID **)&result, flags); + return result; } Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) { - Mesh *me_copy; - BKE_id_copy(bmain, &me->id, (ID **)&me_copy); - return me_copy; + Mesh *me_copy; + BKE_id_copy(bmain, &me->id, (ID **)&me_copy); + return me_copy; } -BMesh *BKE_mesh_to_bmesh_ex( - const Mesh *me, - const struct BMeshCreateParams *create_params, - const struct BMeshFromMeshParams *convert_params) +BMesh *BKE_mesh_to_bmesh_ex(const Mesh *me, + const struct BMeshCreateParams *create_params, + const struct BMeshFromMeshParams *convert_params) { - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me); + 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); + bm = BM_mesh_create(&allocsize, create_params); + BM_mesh_bm_from_me(bm, me, convert_params); - return bm; + return bm; } -BMesh *BKE_mesh_to_bmesh( - Mesh *me, Object *ob, - const bool add_key_index, const struct BMeshCreateParams *params) +BMesh *BKE_mesh_to_bmesh(Mesh *me, + Object *ob, + const bool add_key_index, + const struct BMeshCreateParams *params) { - 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, - }); + 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, + }); } 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; + 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; } Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const CustomData_MeshMasks *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; + Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL); + BM_mesh_bm_to_me_for_eval(bm, mesh, cd_mask_extra); + return mesh; } /** * TODO(campbell): support mesh with only an edit-mesh which is lazy initialized. */ -Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap( - BMEditMesh *em, const CustomData_MeshMasks *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; +Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(BMEditMesh *em, + const CustomData_MeshMasks *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) { - BKE_id_make_local_generic(bmain, &me->id, true, lib_local); -} - -bool BKE_mesh_uv_cdlayer_rename_index( - Mesh *me, const int loop_index, const int face_index, - const char *new_name, const bool do_tessface) -{ - CustomData *ldata, *fdata; - CustomDataLayer *cdlu, *cdlf; - - if (me->edit_mesh) { - ldata = &me->edit_mesh->bm->ldata; - fdata = NULL; /* No tessellated data in BMesh! */ - } - else { - ldata = &me->ldata; - fdata = &me->fdata; - } - - cdlu = &ldata->layers[loop_index]; - cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL; - - 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(cdlu->name, new_name, sizeof(cdlu->name)); - CustomData_set_layer_unique_name(ldata, loop_index); - } - - 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 *ldata, *fdata; - if (me->edit_mesh) { - ldata = &me->edit_mesh->bm->ldata; - /* No tessellated data in BMesh! */ - fdata = NULL; - do_tessface = false; - } - else { - ldata = &me->ldata; - fdata = &me->fdata; - do_tessface = (do_tessface && fdata->totlayer); - } - - { - 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 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 (lidx == -1) { - if (fidx == -1) { - /* No layer found with this name! */ - return false; - } - else { - lidx = fidx; - } - } - - /* Go back to absolute indices! */ - lidx += lidx_start; - if (fidx != -1) - fidx += fidx_start; - - return BKE_mesh_uv_cdlayer_rename_index(me, lidx, fidx, new_name, do_tessface); - } + BKE_id_make_local_generic(bmain, &me->id, true, lib_local); +} + +bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, + const int loop_index, + const int face_index, + const char *new_name, + const bool do_tessface) +{ + CustomData *ldata, *fdata; + CustomDataLayer *cdlu, *cdlf; + + if (me->edit_mesh) { + ldata = &me->edit_mesh->bm->ldata; + fdata = NULL; /* No tessellated data in BMesh! */ + } + else { + ldata = &me->ldata; + fdata = &me->fdata; + } + + cdlu = &ldata->layers[loop_index]; + cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL; + + 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(cdlu->name, new_name, sizeof(cdlu->name)); + CustomData_set_layer_unique_name(ldata, loop_index); + } + + 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 *ldata, *fdata; + if (me->edit_mesh) { + ldata = &me->edit_mesh->bm->ldata; + /* No tessellated data in BMesh! */ + fdata = NULL; + do_tessface = false; + } + else { + ldata = &me->ldata; + fdata = &me->fdata; + do_tessface = (do_tessface && fdata->totlayer); + } + + { + 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 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 (lidx == -1) { + if (fidx == -1) { + /* No layer found with this name! */ + return false; + } + else { + lidx = fidx; + } + } + + /* Go back to absolute indices! */ + lidx += lidx_start; + if (fidx != -1) + fidx += fidx_start; + + return BKE_mesh_uv_cdlayer_rename_index(me, lidx, fidx, new_name, do_tessface); + } } void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3]) { - BoundBox *bb; - float min[3], max[3]; - float mloc[3], msize[3]; + BoundBox *bb; + float min[3], max[3]; + float mloc[3], msize[3]; - if (me->bb == NULL) me->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); - bb = me->bb; + if (me->bb == NULL) + me->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); + bb = me->bb; - if (!r_loc) r_loc = mloc; - if (!r_size) r_size = msize; + if (!r_loc) + r_loc = mloc; + if (!r_size) + r_size = msize; - INIT_MINMAX(min, max); - if (!BKE_mesh_minmax(me, min, max)) { - min[0] = min[1] = min[2] = -1.0f; - max[0] = max[1] = max[2] = 1.0f; - } + INIT_MINMAX(min, max); + if (!BKE_mesh_minmax(me, min, max)) { + min[0] = min[1] = min[2] = -1.0f; + max[0] = max[1] = max[2] = 1.0f; + } - mid_v3_v3v3(r_loc, min, max); + mid_v3_v3v3(r_loc, min, max); - r_size[0] = (max[0] - min[0]) / 2.0f; - r_size[1] = (max[1] - min[1]) / 2.0f; - r_size[2] = (max[2] - min[2]) / 2.0f; + r_size[0] = (max[0] - min[0]) / 2.0f; + r_size[1] = (max[1] - min[1]) / 2.0f; + r_size[2] = (max[2] - min[2]) / 2.0f; - BKE_boundbox_init_from_minmax(bb, min, max); + BKE_boundbox_init_from_minmax(bb, min, max); - bb->flag &= ~BOUNDBOX_DIRTY; + bb->flag &= ~BOUNDBOX_DIRTY; } void BKE_mesh_texspace_calc(Mesh *me) { - float loc[3], size[3]; - int a; + float loc[3], size[3]; + int a; - BKE_mesh_boundbox_calc(me, loc, size); + BKE_mesh_boundbox_calc(me, loc, size); - if (me->texflag & ME_AUTOSPACE) { - for (a = 0; a < 3; a++) { - if (size[a] == 0.0f) size[a] = 1.0f; - else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f; - else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f; - } + if (me->texflag & ME_AUTOSPACE) { + for (a = 0; a < 3; a++) { + if (size[a] == 0.0f) + size[a] = 1.0f; + else if (size[a] > 0.0f && size[a] < 0.00001f) + size[a] = 0.00001f; + else if (size[a] < 0.0f && size[a] > -0.00001f) + size[a] = -0.00001f; + } - copy_v3_v3(me->loc, loc); - copy_v3_v3(me->size, size); - zero_v3(me->rot); - } + copy_v3_v3(me->loc, loc); + copy_v3_v3(me->size, size); + zero_v3(me->rot); + } } BoundBox *BKE_mesh_boundbox_get(Object *ob) { - /* This is Object-level data access, DO NOT touch to Mesh's bb, would be totally thread-unsafe. */ - if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) { - Mesh *me = ob->data; - float min[3], max[3]; + /* This is Object-level data access, DO NOT touch to Mesh's bb, would be totally thread-unsafe. */ + if (ob->runtime.bb == NULL || ob->runtime.bb->flag & BOUNDBOX_DIRTY) { + Mesh *me = ob->data; + float min[3], max[3]; - INIT_MINMAX(min, max); - if (!BKE_mesh_minmax(me, min, max)) { - min[0] = min[1] = min[2] = -1.0f; - max[0] = max[1] = max[2] = 1.0f; - } + INIT_MINMAX(min, max); + if (!BKE_mesh_minmax(me, min, max)) { + min[0] = min[1] = min[2] = -1.0f; + max[0] = max[1] = max[2] = 1.0f; + } - if (ob->runtime.bb == NULL) { - ob->runtime.bb = MEM_mallocN(sizeof(*ob->runtime.bb), __func__); - } - BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); - ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY; - } + if (ob->runtime.bb == NULL) { + ob->runtime.bb = MEM_mallocN(sizeof(*ob->runtime.bb), __func__); + } + BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max); + ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY; + } - return ob->runtime.bb; + return ob->runtime.bb; } BoundBox *BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]) { - if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { - BKE_mesh_texspace_calc(me); - } + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { + BKE_mesh_texspace_calc(me); + } - if (r_loc) copy_v3_v3(r_loc, me->loc); - if (r_rot) copy_v3_v3(r_rot, me->rot); - if (r_size) copy_v3_v3(r_size, me->size); + if (r_loc) + copy_v3_v3(r_loc, me->loc); + if (r_rot) + copy_v3_v3(r_rot, me->rot); + if (r_size) + copy_v3_v3(r_size, me->size); - return me->bb; + return me->bb; } -void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_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 (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; + 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; - short *texflag; + float *texloc, *texrot, *texsize; + short *texflag; - if (BKE_object_obdata_texspace_get(ob, &texflag, &texloc, &texsize, &texrot)) { - me->texflag = *texflag; - copy_v3_v3(me->loc, texloc); - copy_v3_v3(me->size, texsize); - copy_v3_v3(me->rot, texrot); - } + if (BKE_object_obdata_texspace_get(ob, &texflag, &texloc, &texsize, &texrot)) { + me->texflag = *texflag; + copy_v3_v3(me->loc, texloc); + copy_v3_v3(me->size, texsize); + copy_v3_v3(me->rot, texrot); + } } float (*BKE_mesh_orco_verts_get(Object *ob))[3] { - Mesh *me = ob->data; - MVert *mvert = NULL; - Mesh *tme = me->texcomesh ? me->texcomesh : me; - int a, totvert; - float (*vcos)[3] = NULL; + Mesh *me = ob->data; + MVert *mvert = NULL; + Mesh *tme = me->texcomesh ? me->texcomesh : me; + int a, totvert; + float(*vcos)[3] = NULL; - /* Get appropriate vertex coordinates */ - vcos = MEM_calloc_arrayN(me->totvert, sizeof(*vcos), "orco mesh"); - mvert = tme->mvert; - totvert = min_ii(tme->totvert, me->totvert); + /* Get appropriate vertex coordinates */ + vcos = MEM_calloc_arrayN(me->totvert, sizeof(*vcos), "orco mesh"); + mvert = tme->mvert; + totvert = min_ii(tme->totvert, me->totvert); - for (a = 0; a < totvert; a++, mvert++) { - copy_v3_v3(vcos[a], mvert->co); - } + for (a = 0; a < totvert; a++, mvert++) { + copy_v3_v3(vcos[a], mvert->co); + } - return vcos; + return vcos; } void BKE_mesh_orco_verts_transform(Mesh *me, float (*orco)[3], int totvert, int invert) { - float loc[3], size[3]; - int a; + float loc[3], size[3]; + int a; - BKE_mesh_texspace_get(me->texcomesh ? me->texcomesh : me, loc, NULL, size); + BKE_mesh_texspace_get(me->texcomesh ? me->texcomesh : me, loc, NULL, size); - if (invert) { - for (a = 0; a < totvert; a++) { - float *co = orco[a]; - madd_v3_v3v3v3(co, loc, co, size); - } - } - else { - for (a = 0; a < totvert; a++) { - float *co = orco[a]; - co[0] = (co[0] - loc[0]) / size[0]; - co[1] = (co[1] - loc[1]) / size[1]; - co[2] = (co[2] - loc[2]) / size[2]; - } - } + if (invert) { + for (a = 0; a < totvert; a++) { + float *co = orco[a]; + madd_v3_v3v3v3(co, loc, co, size); + } + } + else { + for (a = 0; a < totvert; a++) { + float *co = orco[a]; + co[0] = (co[0] - loc[0]) / size[0]; + co[1] = (co[1] - loc[1]) / size[1]; + co[2] = (co[2] - loc[2]) / size[2]; + } + } } /* rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0. * this is necessary to make the if (mface->v4) check for quads work */ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) { - /* first test if the face is legal */ - if ((mface->v3 || nr == 4) && mface->v3 == mface->v4) { - mface->v4 = 0; - nr--; - } - if ((mface->v2 || mface->v4) && mface->v2 == mface->v3) { - mface->v3 = mface->v4; - mface->v4 = 0; - nr--; - } - if (mface->v1 == mface->v2) { - mface->v2 = mface->v3; - mface->v3 = mface->v4; - mface->v4 = 0; - nr--; - } - - /* check corrupt cases, bow-tie geometry, cant handle these because edge data wont exist so just return 0 */ - if (nr == 3) { - if ( - /* real edges */ - mface->v1 == mface->v2 || - mface->v2 == mface->v3 || - mface->v3 == mface->v1) - { - return 0; - } - } - else if (nr == 4) { - if ( - /* real edges */ - mface->v1 == mface->v2 || - mface->v2 == mface->v3 || - mface->v3 == mface->v4 || - mface->v4 == mface->v1 || - /* across the face */ - mface->v1 == mface->v3 || - mface->v2 == mface->v4) - { - return 0; - } - } - - /* prevent a zero at wrong index location */ - if (nr == 3) { - if (mface->v3 == 0) { - static int corner_indices[4] = {1, 2, 0, 3}; - - SWAP(unsigned int, mface->v1, mface->v2); - SWAP(unsigned int, mface->v2, mface->v3); - - if (fdata) - CustomData_swap_corners(fdata, mfindex, corner_indices); - } - } - else if (nr == 4) { - if (mface->v3 == 0 || mface->v4 == 0) { - static int corner_indices[4] = {2, 3, 0, 1}; - - SWAP(unsigned int, mface->v1, mface->v3); - SWAP(unsigned int, mface->v2, mface->v4); - - if (fdata) - CustomData_swap_corners(fdata, mfindex, corner_indices); - } - } - - return nr; + /* first test if the face is legal */ + if ((mface->v3 || nr == 4) && mface->v3 == mface->v4) { + mface->v4 = 0; + nr--; + } + if ((mface->v2 || mface->v4) && mface->v2 == mface->v3) { + mface->v3 = mface->v4; + mface->v4 = 0; + nr--; + } + if (mface->v1 == mface->v2) { + mface->v2 = mface->v3; + mface->v3 = mface->v4; + mface->v4 = 0; + nr--; + } + + /* check corrupt cases, bow-tie geometry, cant handle these because edge data wont exist so just return 0 */ + if (nr == 3) { + if ( + /* real edges */ + mface->v1 == mface->v2 || mface->v2 == mface->v3 || mface->v3 == mface->v1) { + return 0; + } + } + else if (nr == 4) { + if ( + /* real edges */ + mface->v1 == mface->v2 || mface->v2 == mface->v3 || mface->v3 == mface->v4 || + mface->v4 == mface->v1 || + /* across the face */ + mface->v1 == mface->v3 || mface->v2 == mface->v4) { + return 0; + } + } + + /* prevent a zero at wrong index location */ + if (nr == 3) { + if (mface->v3 == 0) { + static int corner_indices[4] = {1, 2, 0, 3}; + + SWAP(unsigned int, mface->v1, mface->v2); + SWAP(unsigned int, mface->v2, mface->v3); + + if (fdata) + CustomData_swap_corners(fdata, mfindex, corner_indices); + } + } + else if (nr == 4) { + if (mface->v3 == 0 || mface->v4 == 0) { + static int corner_indices[4] = {2, 3, 0, 1}; + + SWAP(unsigned int, mface->v1, mface->v3); + SWAP(unsigned int, mface->v2, mface->v4); + + if (fdata) + CustomData_swap_corners(fdata, mfindex, corner_indices); + } + } + + return nr; } Mesh *BKE_mesh_from_object(Object *ob) { - if (ob == NULL) return NULL; - if (ob->type == OB_MESH) return ob->data; - else return NULL; + if (ob == NULL) + return NULL; + if (ob->type == OB_MESH) + return ob->data; + else + return NULL; } void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me) { - Mesh *old = NULL; + Mesh *old = NULL; - multires_force_update(ob); + multires_force_update(ob); - if (ob == NULL) return; + if (ob == NULL) + return; - if (ob->type == OB_MESH) { - old = ob->data; - if (old) - id_us_min(&old->id); - ob->data = me; - id_us_plus((ID *)me); - } + if (ob->type == OB_MESH) { + old = ob->data; + if (old) + id_us_min(&old->id); + ob->data = me; + id_us_plus((ID *)me); + } - test_object_materials(bmain, ob, (ID *)me); + test_object_materials(bmain, ob, (ID *)me); - test_object_modifiers(ob); + test_object_modifiers(ob); } void BKE_mesh_material_index_remove(Mesh *me, short index) { - MPoly *mp; - MFace *mf; - int i; + MPoly *mp; + MFace *mf; + int i; - for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) { - if (mp->mat_nr && mp->mat_nr >= index) { - mp->mat_nr--; - } - } + for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) { + if (mp->mat_nr && mp->mat_nr >= index) { + mp->mat_nr--; + } + } - for (mf = me->mface, i = 0; i < me->totface; i++, mf++) { - if (mf->mat_nr && mf->mat_nr >= index) { - mf->mat_nr--; - } - } + for (mf = me->mface, i = 0; i < me->totface; i++, mf++) { + if (mf->mat_nr && mf->mat_nr >= index) { + mf->mat_nr--; + } + } } void BKE_mesh_material_index_clear(Mesh *me) { - MPoly *mp; - MFace *mf; - int i; + MPoly *mp; + MFace *mf; + int i; - for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) { - mp->mat_nr = 0; - } + for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) { + mp->mat_nr = 0; + } - for (mf = me->mface, i = 0; i < me->totface; i++, mf++) { - mf->mat_nr = 0; - } + for (mf = me->mface, i = 0; i < me->totface; i++, mf++) { + mf->mat_nr = 0; + } } void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len) { - const short remap_len_short = (short)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_mesh) { - BMEditMesh *em = me->edit_mesh; - 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); - } - } + if (n < remap_len_short) { \ + BLI_assert(n >= 0 && remap[n] < remap_len_short); \ + n = remap[n]; \ + } \ + ((void)0) + + if (me->edit_mesh) { + BMEditMesh *em = me->edit_mesh; + 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; - int i; + Mesh *me = meshOb->data; + int i; - for (i = 0; i < me->totpoly; i++) { - MPoly *mp = &me->mpoly[i]; + for (i = 0; i < me->totpoly; i++) { + MPoly *mp = &me->mpoly[i]; - if (enableSmooth) { - mp->flag |= ME_SMOOTH; - } - else { - mp->flag &= ~ME_SMOOTH; - } - } + if (enableSmooth) { + mp->flag |= ME_SMOOTH; + } + else { + mp->flag &= ~ME_SMOOTH; + } + } - for (i = 0; i < me->totface; i++) { - MFace *mf = &me->mface[i]; + for (i = 0; i < me->totface; i++) { + MFace *mf = &me->mface[i]; - if (enableSmooth) { - mf->flag |= ME_SMOOTH; - } - else { - mf->flag &= ~ME_SMOOTH; - } - } + if (enableSmooth) { + mf->flag |= ME_SMOOTH; + } + else { + mf->flag &= ~ME_SMOOTH; + } + } } /** @@ -1187,31 +1203,30 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) */ float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_verts_len))[3] { - int i, verts_len = me->totvert; - float (*cos)[3] = MEM_malloc_arrayN(verts_len, sizeof(*cos), "vertexcos1"); + int i, verts_len = me->totvert; + float(*cos)[3] = MEM_malloc_arrayN(verts_len, sizeof(*cos), "vertexcos1"); - 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); + 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; + return cos; } /** * 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++) { - if (loopstart->v == vert) - return j; - } + int j; + for (j = 0; j < poly->totloop; j++, loopstart++) { + if (loopstart->v == vert) + return j; + } - return -1; + return -1; } /** @@ -1219,23 +1234,20 @@ int poly_find_loop_from_vert( * 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( - const MPoly *poly, - const MLoop *mloop, unsigned int vert, - unsigned int r_adj[2]) +int poly_get_adj_loops_from_vert(const MPoly *poly, + const MLoop *mloop, + unsigned int vert, + unsigned int r_adj[2]) { - int corner = poly_find_loop_from_vert( - poly, - &mloop[poly->loopstart], - vert); + int corner = poly_find_loop_from_vert(poly, &mloop[poly->loopstart], vert); - if (corner != -1) { - /* 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; - } + if (corner != -1) { + /* 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; + } - return corner; + return corner; } /** @@ -1244,12 +1256,12 @@ int poly_get_adj_loops_from_vert( */ int BKE_mesh_edge_other_vert(const MEdge *e, int v) { - if (e->v1 == v) - return e->v2; - else if (e->v2 == v) - return e->v1; - else - return -1; + if (e->v1 == v) + return e->v2; + else if (e->v2 == v) + return e->v1; + else + return -1; } /** @@ -1257,224 +1269,222 @@ int BKE_mesh_edge_other_vert(const MEdge *e, int v) */ 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]; + 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); + 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; - } + 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]) { - int i = me->totvert; - MVert *mvert; - for (mvert = me->mvert; i--; mvert++) { - minmax_v3v3_v3(r_min, r_max, mvert->co); - } + int i = me->totvert; + MVert *mvert; + for (mvert = me->mvert; i--; mvert++) { + minmax_v3v3_v3(r_min, r_max, mvert->co); + } - return (me->totvert != 0); + return (me->totvert != 0); } 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); + 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); + for (i = 0; i < me->totvert; i++, mvert++) + mul_m4_v3(mat, mvert->co); - if (do_keys && me->key) { - KeyBlock *kb; - for (kb = me->key->block.first; kb; kb = kb->next) { - float *fp = kb->data; - for (i = kb->totelem; i--; fp += 3) { - mul_m4_v3(mat, fp); - } - } - } + if (do_keys && me->key) { + KeyBlock *kb; + for (kb = me->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } - /* 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]; + /* 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); - } - } + 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) { - int i = me->totvert; - MVert *mvert; - for (mvert = me->mvert; i--; mvert++) { - add_v3_v3(mvert->co, offset); - } + int i = me->totvert; + MVert *mvert; + for (mvert = me->mvert; i--; mvert++) { + add_v3_v3(mvert->co, offset); + } - if (do_keys && me->key) { - KeyBlock *kb; - for (kb = me->key->block.first; kb; kb = kb->next) { - float *fp = kb->data; - for (i = kb->totelem; i--; fp += 3) { - add_v3_v3(fp, offset); - } - } - } + if (do_keys && me->key) { + KeyBlock *kb; + for (kb = me->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + add_v3_v3(fp, offset); + } + } + } } void BKE_mesh_ensure_navmesh(Mesh *me) { - if (!CustomData_has_layer(&me->pdata, CD_RECAST)) { - int i; - int polys_len = me->totpoly; - int *recastData; - 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, polys_len, "recastData"); - } + if (!CustomData_has_layer(&me->pdata, CD_RECAST)) { + int i; + int polys_len = me->totpoly; + int *recastData; + 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, polys_len, "recastData"); + } } void BKE_mesh_tessface_calc(Mesh *mesh) { - mesh->totface = BKE_mesh_recalc_tessellation( - &mesh->fdata, &mesh->ldata, &mesh->pdata, - mesh->mvert, - mesh->totface, mesh->totloop, mesh->totpoly, - /* calc normals right after, don't copy from polys here */ - false); + mesh->totface = BKE_mesh_recalc_tessellation( + &mesh->fdata, + &mesh->ldata, + &mesh->pdata, + mesh->mvert, + mesh->totface, + mesh->totloop, + mesh->totpoly, + /* calc normals right after, don't copy from polys here */ + false); - BKE_mesh_update_customdata_pointers(mesh, true); + BKE_mesh_update_customdata_pointers(mesh, true); } void BKE_mesh_tessface_ensure(Mesh *mesh) { - if (mesh->totpoly && mesh->totface == 0) { - BKE_mesh_tessface_calc(mesh); - } + if (mesh->totpoly && mesh->totface == 0) { + BKE_mesh_tessface_calc(mesh); + } } void BKE_mesh_tessface_clear(Mesh *mesh) { - mesh_tessface_clear_intern(mesh, true); + mesh_tessface_clear_intern(mesh, true); } void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh) { - if (UNLIKELY(mesh->cd_flag)) { - return; - } - else { - MVert *mv; - MEdge *med; - int i; - - for (mv = mesh->mvert, i = 0; i < mesh->totvert; mv++, i++) { - if (mv->bweight != 0) { - mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; - break; - } - } - - for (med = mesh->medge, i = 0; i < mesh->totedge; med++, i++) { - if (med->bweight != 0) { - mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) { - break; - } - } - if (med->crease != 0) { - mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; - if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { - break; - } - } - } - - } + if (UNLIKELY(mesh->cd_flag)) { + return; + } + else { + MVert *mv; + MEdge *med; + int i; + + for (mv = mesh->mvert, i = 0; i < mesh->totvert; mv++, i++) { + if (mv->bweight != 0) { + mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; + break; + } + } + + for (med = mesh->medge, i = 0; i < mesh->totedge; med++, i++) { + if (med->bweight != 0) { + mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) { + break; + } + } + if (med->crease != 0) { + mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; + if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { + break; + } + } + } + } } - /* -------------------------------------------------------------------- */ /* MSelect functions (currently used in weight paint mode) */ void BKE_mesh_mselect_clear(Mesh *me) { - if (me->mselect) { - MEM_freeN(me->mselect); - me->mselect = NULL; - } - me->totselect = 0; + if (me->mselect) { + MEM_freeN(me->mselect); + me->mselect = NULL; + } + me->totselect = 0; } void BKE_mesh_mselect_validate(Mesh *me) { - MSelect *mselect_src, *mselect_dst; - int i_src, i_dst; - - if (me->totselect == 0) - return; - - mselect_src = me->mselect; - mselect_dst = MEM_malloc_arrayN((me->totselect), sizeof(MSelect), "Mesh selection history"); - - for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) { - int index = mselect_src[i_src].index; - switch (mselect_src[i_src].type) { - case ME_VSEL: - { - if (me->mvert[index].flag & SELECT) { - mselect_dst[i_dst] = mselect_src[i_src]; - i_dst++; - } - break; - } - case ME_ESEL: - { - if (me->medge[index].flag & SELECT) { - mselect_dst[i_dst] = mselect_src[i_src]; - i_dst++; - } - break; - } - case ME_FSEL: - { - if (me->mpoly[index].flag & SELECT) { - mselect_dst[i_dst] = mselect_src[i_src]; - i_dst++; - } - break; - } - default: - { - BLI_assert(0); - break; - } - } - } - - MEM_freeN(mselect_src); - - if (i_dst == 0) { - MEM_freeN(mselect_dst); - mselect_dst = NULL; - } - else if (i_dst != me->totselect) { - mselect_dst = MEM_reallocN(mselect_dst, sizeof(MSelect) * i_dst); - } - - me->totselect = i_dst; - me->mselect = mselect_dst; - + MSelect *mselect_src, *mselect_dst; + int i_src, i_dst; + + if (me->totselect == 0) + return; + + mselect_src = me->mselect; + mselect_dst = MEM_malloc_arrayN((me->totselect), sizeof(MSelect), "Mesh selection history"); + + for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) { + int index = mselect_src[i_src].index; + switch (mselect_src[i_src].type) { + case ME_VSEL: { + if (me->mvert[index].flag & SELECT) { + mselect_dst[i_dst] = mselect_src[i_src]; + i_dst++; + } + break; + } + case ME_ESEL: { + if (me->medge[index].flag & SELECT) { + mselect_dst[i_dst] = mselect_src[i_src]; + i_dst++; + } + break; + } + case ME_FSEL: { + if (me->mpoly[index].flag & SELECT) { + mselect_dst[i_dst] = mselect_src[i_src]; + i_dst++; + } + break; + } + default: { + BLI_assert(0); + break; + } + } + } + + MEM_freeN(mselect_src); + + if (i_dst == 0) { + MEM_freeN(mselect_dst); + mselect_dst = NULL; + } + else if (i_dst != me->totselect) { + mselect_dst = MEM_reallocN(mselect_dst, sizeof(MSelect) * i_dst); + } + + me->totselect = i_dst; + me->mselect = mselect_dst; } /** @@ -1482,19 +1492,17 @@ void BKE_mesh_mselect_validate(Mesh *me) */ int BKE_mesh_mselect_find(Mesh *me, int index, int type) { - int i; + int i; - BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); + BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); - for (i = 0; i < me->totselect; i++) { - if ((me->mselect[i].index == index) && - (me->mselect[i].type == type)) - { - return i; - } - } + for (i = 0; i < me->totselect; i++) { + if ((me->mselect[i].index == index) && (me->mselect[i].type == type)) { + return i; + } + } - return -1; + return -1; } /** @@ -1502,77 +1510,76 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type) */ int BKE_mesh_mselect_active_get(Mesh *me, int type) { - BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); + BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); - if (me->totselect) { - if (me->mselect[me->totselect - 1].type == type) { - return me->mselect[me->totselect - 1].index; - } - } - return -1; + if (me->totselect) { + if (me->mselect[me->totselect - 1].type == type) { + return me->mselect[me->totselect - 1].index; + } + } + return -1; } void BKE_mesh_mselect_active_set(Mesh *me, int index, int type) { - const int msel_index = BKE_mesh_mselect_find(me, index, type); + const int msel_index = BKE_mesh_mselect_find(me, index, type); - if (msel_index == -1) { - /* add to the end */ - me->mselect = MEM_reallocN(me->mselect, sizeof(MSelect) * (me->totselect + 1)); - me->mselect[me->totselect].index = index; - me->mselect[me->totselect].type = type; - me->totselect++; - } - else if (msel_index != me->totselect - 1) { - /* move to the end */ - SWAP(MSelect, me->mselect[msel_index], me->mselect[me->totselect - 1]); - } + if (msel_index == -1) { + /* add to the end */ + me->mselect = MEM_reallocN(me->mselect, sizeof(MSelect) * (me->totselect + 1)); + me->mselect[me->totselect].index = index; + me->mselect[me->totselect].type = type; + me->totselect++; + } + else if (msel_index != me->totselect - 1) { + /* move to the end */ + SWAP(MSelect, me->mselect[msel_index], me->mselect[me->totselect - 1]); + } - BLI_assert((me->mselect[me->totselect - 1].index == index) && - (me->mselect[me->totselect - 1].type == type)); + BLI_assert((me->mselect[me->totselect - 1].index == index) && + (me->mselect[me->totselect - 1].type == type)); } void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3]) { - r_count[0] = r_count[1] = r_count[2] = 0; - if (mesh->edit_mesh) { - BMesh *bm = mesh->edit_mesh->bm; - r_count[0] = bm->totvertsel; - r_count[1] = bm->totedgesel; - r_count[2] = bm->totfacesel; - } - /* We could support faces in paint modes. */ - + r_count[0] = r_count[1] = r_count[2] = 0; + if (mesh->edit_mesh) { + BMesh *bm = mesh->edit_mesh->bm; + r_count[0] = bm->totvertsel; + r_count[1] = bm->totedgesel; + r_count[2] = bm->totfacesel; + } + /* We could support faces in paint modes. */ } void BKE_mesh_apply_vert_coords(Mesh *mesh, float (*vertCoords)[3]) { - MVert *vert; - int i; + 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; + /* 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]); + for (i = 0; i < mesh->totvert; ++i, ++vert) + copy_v3_v3(vert->co, vertCoords[i]); - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } void BKE_mesh_apply_vert_normals(Mesh *mesh, short (*vertNormals)[3]) { - MVert *vert; - int i; + 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; + /* 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]); + for (i = 0; i < mesh->totvert; ++i, ++vert) + copy_v3_v3_short(vert->no, vertNormals[i]); - mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; } /** @@ -1583,246 +1590,268 @@ void BKE_mesh_apply_vert_normals(Mesh *mesh, short (*vertNormals)[3]) */ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr) { - float (*r_loopnors)[3]; - float (*polynors)[3]; - short (*clnors)[2] = NULL; - bool free_polynors = false; - - /* Note that we enforce computing clnors when the clnor space array is requested by caller here. - * However, we obviously only use the autosmooth angle threshold only in case autosmooth is enabled. */ - const bool use_split_normals = (r_lnors_spacearr != NULL) || ((mesh->flag & ME_AUTOSMOOTH) != 0); - const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI; - - 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_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__); - BKE_mesh_calc_normals_poly( - mesh->mvert, NULL, 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, - use_split_normals, split_angle, r_lnors_spacearr, clnors, NULL); - - if (free_polynors) { - MEM_freeN(polynors); - } - - mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; + float(*r_loopnors)[3]; + float(*polynors)[3]; + short(*clnors)[2] = NULL; + bool free_polynors = false; + + /* Note that we enforce computing clnors when the clnor space array is requested by caller here. + * However, we obviously only use the autosmooth angle threshold only in case autosmooth is enabled. */ + const bool use_split_normals = (r_lnors_spacearr != NULL) || ((mesh->flag & ME_AUTOSMOOTH) != 0); + const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI; + + 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_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__); + BKE_mesh_calc_normals_poly(mesh->mvert, + NULL, + 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, + use_split_normals, + split_angle, + r_lnors_spacearr, + clnors, + NULL); + + if (free_polynors) { + MEM_freeN(polynors); + } + + mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL; } void BKE_mesh_calc_normals_split(Mesh *mesh) { - BKE_mesh_calc_normals_split_ex(mesh, NULL); + BKE_mesh_calc_normals_split_ex(mesh, NULL); } /* Split faces helper functions. */ typedef struct SplitFaceNewVert { - struct SplitFaceNewVert *next; - int new_index; - int orig_index; - float *vnor; + struct SplitFaceNewVert *next; + int new_index; + int orig_index; + float *vnor; } SplitFaceNewVert; typedef struct SplitFaceNewEdge { - struct SplitFaceNewEdge *next; - int new_index; - int orig_index; - int v1; - int v2; + struct SplitFaceNewEdge *next; + int new_index; + int orig_index; + int v1; + int v2; } SplitFaceNewEdge; /* Detect needed new vertices, and update accordingly loops' vertex indices. * WARNING! Leaves mesh in invalid state. */ -static int split_faces_prepare_new_verts( - const Mesh *mesh, MLoopNorSpaceArray *lnors_spacearr, SplitFaceNewVert **new_verts, MemArena *memarena) -{ - /* This is now mandatory, trying to do the job in simple way without that data is doomed to fail, even when only - * dealing with smooth/flat faces one can find cases that no simple algorithm can handle properly. */ - BLI_assert(lnors_spacearr != NULL); - - 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(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 < 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 ? verts_len++ : vert_idx; - - BLI_assert(*lnor_space); - - if ((*lnor_space)->flags & MLNOR_SPACE_IS_SINGLE) { - /* Single loop in this fan... */ - BLI_assert(POINTER_AS_INT((*lnor_space)->loops) == loop_idx); - BLI_BITMAP_ENABLE(done_loops, loop_idx); - if (vert_used) { - ml->v = new_vert_idx; - } - } - else { - for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) { - const int ml_fan_idx = POINTER_AS_INT(lnode->link); - BLI_BITMAP_ENABLE(done_loops, ml_fan_idx); - if (vert_used) { - mloop[ml_fan_idx].v = new_vert_idx; - } - } - } - - if (!vert_used) { - BLI_BITMAP_ENABLE(verts_used, vert_idx); - /* We need to update that vertex's normal here, we won't go over it again. */ - /* This is important! *DO NOT* set vnor to final computed lnor, vnor should always be defined to - * 'automatic normal' value computed from its polys, not some custom normal. - * Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */ - normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor); - } - else { - /* Add new vert to list. */ - SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert)); - new_vert->orig_index = vert_idx; - new_vert->new_index = new_vert_idx; - new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */ - new_vert->next = *new_verts; - *new_verts = new_vert; - } - } - } - - MEM_freeN(done_loops); - MEM_freeN(verts_used); - - return verts_len - mesh->totvert; +static int split_faces_prepare_new_verts(const Mesh *mesh, + MLoopNorSpaceArray *lnors_spacearr, + SplitFaceNewVert **new_verts, + MemArena *memarena) +{ + /* This is now mandatory, trying to do the job in simple way without that data is doomed to fail, even when only + * dealing with smooth/flat faces one can find cases that no simple algorithm can handle properly. */ + BLI_assert(lnors_spacearr != NULL); + + 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(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 < 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 ? verts_len++ : vert_idx; + + BLI_assert(*lnor_space); + + if ((*lnor_space)->flags & MLNOR_SPACE_IS_SINGLE) { + /* Single loop in this fan... */ + BLI_assert(POINTER_AS_INT((*lnor_space)->loops) == loop_idx); + BLI_BITMAP_ENABLE(done_loops, loop_idx); + if (vert_used) { + ml->v = new_vert_idx; + } + } + else { + for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) { + const int ml_fan_idx = POINTER_AS_INT(lnode->link); + BLI_BITMAP_ENABLE(done_loops, ml_fan_idx); + if (vert_used) { + mloop[ml_fan_idx].v = new_vert_idx; + } + } + } + + if (!vert_used) { + BLI_BITMAP_ENABLE(verts_used, vert_idx); + /* We need to update that vertex's normal here, we won't go over it again. */ + /* This is important! *DO NOT* set vnor to final computed lnor, vnor should always be defined to + * 'automatic normal' value computed from its polys, not some custom normal. + * Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */ + normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor); + } + else { + /* Add new vert to list. */ + SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert)); + new_vert->orig_index = vert_idx; + new_vert->new_index = new_vert_idx; + new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */ + new_vert->next = *new_verts; + *new_verts = new_vert; + } + } + } + + MEM_freeN(done_loops); + MEM_freeN(verts_used); + + return verts_len - mesh->totvert; } /* Detect needed new edges, and update accordingly loops' edge indices. * WARNING! Leaves mesh in invalid state. */ -static int split_faces_prepare_new_edges( - const Mesh *mesh, SplitFaceNewEdge **new_edges, MemArena *memarena) -{ - const int num_polys = mesh->totpoly; - int num_edges = mesh->totedge; - MEdge *medge = mesh->medge; - MLoop *mloop = mesh->mloop; - const MPoly *mpoly = mesh->mpoly; - - BLI_bitmap *edges_used = BLI_BITMAP_NEW(num_edges, __func__); - EdgeHash *edges_hash = BLI_edgehash_new_ex(__func__, num_edges); - - const MPoly *mp = mpoly; - for (int poly_idx = 0; poly_idx < num_polys; poly_idx++, mp++) { - MLoop *ml_prev = &mloop[mp->loopstart + mp->totloop - 1]; - MLoop *ml = &mloop[mp->loopstart]; - for (int loop_idx = 0; loop_idx < mp->totloop; loop_idx++, ml++) { - void **eval; - if (!BLI_edgehash_ensure_p(edges_hash, ml_prev->v, ml->v, &eval)) { - const int edge_idx = ml_prev->e; - - /* That edge has not been encountered yet, define it. */ - if (BLI_BITMAP_TEST(edges_used, edge_idx)) { - /* Original edge has already been used, we need to define a new one. */ - const int new_edge_idx = num_edges++; - *eval = POINTER_FROM_INT(new_edge_idx); - ml_prev->e = new_edge_idx; - - SplitFaceNewEdge *new_edge = BLI_memarena_alloc(memarena, sizeof(*new_edge)); - new_edge->orig_index = edge_idx; - new_edge->new_index = new_edge_idx; - new_edge->v1 = ml_prev->v; - new_edge->v2 = ml->v; - new_edge->next = *new_edges; - *new_edges = new_edge; - } - else { - /* We can re-use original edge. */ - medge[edge_idx].v1 = ml_prev->v; - medge[edge_idx].v2 = ml->v; - *eval = POINTER_FROM_INT(edge_idx); - BLI_BITMAP_ENABLE(edges_used, edge_idx); - } - } - else { - /* Edge already known, just update loop's edge index. */ - ml_prev->e = POINTER_AS_INT(*eval); - } - - ml_prev = ml; - } - } - - MEM_freeN(edges_used); - BLI_edgehash_free(edges_hash, NULL); - - return num_edges - mesh->totedge; +static int split_faces_prepare_new_edges(const Mesh *mesh, + SplitFaceNewEdge **new_edges, + MemArena *memarena) +{ + const int num_polys = mesh->totpoly; + int num_edges = mesh->totedge; + MEdge *medge = mesh->medge; + MLoop *mloop = mesh->mloop; + const MPoly *mpoly = mesh->mpoly; + + BLI_bitmap *edges_used = BLI_BITMAP_NEW(num_edges, __func__); + EdgeHash *edges_hash = BLI_edgehash_new_ex(__func__, num_edges); + + const MPoly *mp = mpoly; + for (int poly_idx = 0; poly_idx < num_polys; poly_idx++, mp++) { + MLoop *ml_prev = &mloop[mp->loopstart + mp->totloop - 1]; + MLoop *ml = &mloop[mp->loopstart]; + for (int loop_idx = 0; loop_idx < mp->totloop; loop_idx++, ml++) { + void **eval; + if (!BLI_edgehash_ensure_p(edges_hash, ml_prev->v, ml->v, &eval)) { + const int edge_idx = ml_prev->e; + + /* That edge has not been encountered yet, define it. */ + if (BLI_BITMAP_TEST(edges_used, edge_idx)) { + /* Original edge has already been used, we need to define a new one. */ + const int new_edge_idx = num_edges++; + *eval = POINTER_FROM_INT(new_edge_idx); + ml_prev->e = new_edge_idx; + + SplitFaceNewEdge *new_edge = BLI_memarena_alloc(memarena, sizeof(*new_edge)); + new_edge->orig_index = edge_idx; + new_edge->new_index = new_edge_idx; + new_edge->v1 = ml_prev->v; + new_edge->v2 = ml->v; + new_edge->next = *new_edges; + *new_edges = new_edge; + } + else { + /* We can re-use original edge. */ + medge[edge_idx].v1 = ml_prev->v; + medge[edge_idx].v2 = ml->v; + *eval = POINTER_FROM_INT(edge_idx); + BLI_BITMAP_ENABLE(edges_used, edge_idx); + } + } + else { + /* Edge already known, just update loop's edge index. */ + ml_prev->e = POINTER_AS_INT(*eval); + } + + ml_prev = ml; + } + } + + MEM_freeN(edges_used); + BLI_edgehash_free(edges_hash, NULL); + + return num_edges - mesh->totedge; } /* Perform actual split of vertices. */ -static void split_faces_split_new_verts( - Mesh *mesh, SplitFaceNewVert *new_verts, const int num_new_verts) +static void split_faces_split_new_verts(Mesh *mesh, + SplitFaceNewVert *new_verts, + const int num_new_verts) { - const int verts_len = mesh->totvert - num_new_verts; - MVert *mvert = mesh->mvert; + 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 >= 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); - if (new_verts->vnor) { - normal_float_to_short_v3(new_mv->no, new_verts->vnor); - } - } + /* 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 >= 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); + if (new_verts->vnor) { + normal_float_to_short_v3(new_mv->no, new_verts->vnor); + } + } } /* Perform actual split of edges. */ -static void split_faces_split_new_edges( - Mesh *mesh, SplitFaceNewEdge *new_edges, const int num_new_edges) +static void split_faces_split_new_edges(Mesh *mesh, + SplitFaceNewEdge *new_edges, + const int num_new_edges) { - const int num_edges = mesh->totedge - num_new_edges; - MEdge *medge = mesh->medge; + const int num_edges = mesh->totedge - num_new_edges; + MEdge *medge = mesh->medge; - /* Remember new_edges is a single linklist, so its items are in reversed order... */ - MEdge *new_med = &medge[mesh->totedge - 1]; - for (int i = mesh->totedge - 1; i >= num_edges ; i--, new_med--, new_edges = new_edges->next) { - BLI_assert(new_edges->new_index == i); - BLI_assert(new_edges->new_index != new_edges->orig_index); - CustomData_copy_data(&mesh->edata, &mesh->edata, new_edges->orig_index, i, 1); - new_med->v1 = new_edges->v1; - new_med->v2 = new_edges->v2; - } + /* Remember new_edges is a single linklist, so its items are in reversed order... */ + MEdge *new_med = &medge[mesh->totedge - 1]; + for (int i = mesh->totedge - 1; i >= num_edges; i--, new_med--, new_edges = new_edges->next) { + BLI_assert(new_edges->new_index == i); + BLI_assert(new_edges->new_index != new_edges->orig_index); + CustomData_copy_data(&mesh->edata, &mesh->edata, new_edges->orig_index, i, 1); + new_med->v1 = new_edges->v1; + new_med->v2 = new_edges->v2; + } } /* Split faces based on the edge angle and loop normals. @@ -1833,76 +1862,75 @@ static void split_faces_split_new_edges( */ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) { - const int num_polys = mesh->totpoly; - - if (num_polys == 0) { - return; - } - BKE_mesh_tessface_clear(mesh); - - MLoopNorSpaceArray lnors_spacearr = {NULL}; - /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */ - BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr); - /* Stealing memarena from loop normals space array. */ - MemArena *memarena = lnors_spacearr.mem; - - SplitFaceNewVert *new_verts = NULL; - SplitFaceNewEdge *new_edges = NULL; - - /* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */ - const int num_new_verts = split_faces_prepare_new_verts(mesh, &lnors_spacearr, &new_verts, memarena); - - if (num_new_verts > 0) { - /* Reminder: beyond this point, there is no way out, mesh is in invalid state (due to early-reassignment of - * loops' vertex and edge indices to new, to-be-created split ones). */ - - const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena); - /* We can have to split a vertex without having to add a single new edge... */ - const bool do_edges = (num_new_edges > 0); - - /* Reallocate all vert and edge related data. */ - mesh->totvert += num_new_verts; - CustomData_realloc(&mesh->vdata, mesh->totvert); - if (do_edges) { - mesh->totedge += num_new_edges; - CustomData_realloc(&mesh->edata, mesh->totedge); - } - /* Update pointers to a newly allocated memory. */ - BKE_mesh_update_customdata_pointers(mesh, false); - - /* Perform actual split of vertices and edges. */ - split_faces_split_new_verts(mesh, new_verts, num_new_verts); - if (do_edges) { - split_faces_split_new_edges(mesh, new_edges, num_new_edges); - } - } - - /* Note: after this point mesh is expected to be valid again. */ - - /* CD_NORMAL is expected to be temporary only. */ - if (free_loop_normals) { - CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop); - } - - /* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */ - BKE_lnor_spacearr_free(&lnors_spacearr); + const int num_polys = mesh->totpoly; + + if (num_polys == 0) { + return; + } + BKE_mesh_tessface_clear(mesh); + + MLoopNorSpaceArray lnors_spacearr = {NULL}; + /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */ + BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr); + /* Stealing memarena from loop normals space array. */ + MemArena *memarena = lnors_spacearr.mem; + + SplitFaceNewVert *new_verts = NULL; + SplitFaceNewEdge *new_edges = NULL; + + /* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */ + const int num_new_verts = split_faces_prepare_new_verts( + mesh, &lnors_spacearr, &new_verts, memarena); + + if (num_new_verts > 0) { + /* Reminder: beyond this point, there is no way out, mesh is in invalid state (due to early-reassignment of + * loops' vertex and edge indices to new, to-be-created split ones). */ + + const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena); + /* We can have to split a vertex without having to add a single new edge... */ + const bool do_edges = (num_new_edges > 0); + + /* Reallocate all vert and edge related data. */ + mesh->totvert += num_new_verts; + CustomData_realloc(&mesh->vdata, mesh->totvert); + if (do_edges) { + mesh->totedge += num_new_edges; + CustomData_realloc(&mesh->edata, mesh->totedge); + } + /* Update pointers to a newly allocated memory. */ + BKE_mesh_update_customdata_pointers(mesh, false); + + /* Perform actual split of vertices and edges. */ + split_faces_split_new_verts(mesh, new_verts, num_new_verts); + if (do_edges) { + split_faces_split_new_edges(mesh, new_edges, num_new_edges); + } + } + + /* Note: after this point mesh is expected to be valid again. */ + + /* CD_NORMAL is expected to be temporary only. */ + if (free_loop_normals) { + CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop); + } + + /* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */ + BKE_lnor_spacearr_free(&lnors_spacearr); #ifdef VALIDATE_MESH - BKE_mesh_validate(mesh, true, true); + BKE_mesh_validate(mesh, true, true); #endif } /* **** Depsgraph evaluation **** */ -void BKE_mesh_eval_geometry( - Depsgraph *depsgraph, - Mesh *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); - } - /* Clear autospace flag in evaluated mesh, so that texspace does not get recomputed when bbox is - * (e.g. after modifiers, etc.) */ - mesh->texflag &= ~ME_AUTOSPACE; +void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *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); + } + /* Clear autospace flag in evaluated mesh, so that texspace does not get recomputed when bbox is + * (e.g. after modifiers, etc.) */ + mesh->texflag &= ~ME_AUTOSPACE; } |