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_convert.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_convert.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_convert.c | 2569 |
1 files changed, 1316 insertions, 1253 deletions
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 5be4b8524b1..6f96267ff55 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -59,7 +59,8 @@ // #undef VALIDATE_MESH #ifdef VALIDATE_MESH -# define ASSERT_IS_VALID_MESH(mesh) (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true))) +# define ASSERT_IS_VALID_MESH(mesh) \ + (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true))) #else # define ASSERT_IS_VALID_MESH(mesh) #endif @@ -68,163 +69,168 @@ static CLG_LogRef LOG = {"bke.mesh_convert"}; void BKE_mesh_from_metaball(ListBase *lb, Mesh *me) { - DispList *dl; - MVert *mvert; - MLoop *mloop, *allloop; - MPoly *mpoly; - const float *nors, *verts; - int a, *index; - - dl = lb->first; - if (dl == NULL) return; - - if (dl->type == DL_INDEX4) { - mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, dl->nr); - allloop = mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, dl->parts * 4); - mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, dl->parts); - me->mvert = mvert; - me->mloop = mloop; - me->mpoly = mpoly; - me->totvert = dl->nr; - me->totpoly = dl->parts; - - a = dl->nr; - nors = dl->nors; - verts = dl->verts; - while (a--) { - copy_v3_v3(mvert->co, verts); - normal_float_to_short_v3(mvert->no, nors); - mvert++; - nors += 3; - verts += 3; - } - - a = dl->parts; - index = dl->index; - while (a--) { - int count = index[2] != index[3] ? 4 : 3; - - mloop[0].v = index[0]; - mloop[1].v = index[1]; - mloop[2].v = index[2]; - if (count == 4) - mloop[3].v = index[3]; - - mpoly->totloop = count; - mpoly->loopstart = (int)(mloop - allloop); - mpoly->flag = ME_SMOOTH; - - - mpoly++; - mloop += count; - me->totloop += count; - index += 4; - } - - BKE_mesh_update_customdata_pointers(me, true); - - BKE_mesh_calc_normals(me); - - BKE_mesh_calc_edges(me, true, false); - } + DispList *dl; + MVert *mvert; + MLoop *mloop, *allloop; + MPoly *mpoly; + const float *nors, *verts; + int a, *index; + + dl = lb->first; + if (dl == NULL) + return; + + if (dl->type == DL_INDEX4) { + mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, dl->nr); + allloop = mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, dl->parts * 4); + mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, dl->parts); + me->mvert = mvert; + me->mloop = mloop; + me->mpoly = mpoly; + me->totvert = dl->nr; + me->totpoly = dl->parts; + + a = dl->nr; + nors = dl->nors; + verts = dl->verts; + while (a--) { + copy_v3_v3(mvert->co, verts); + normal_float_to_short_v3(mvert->no, nors); + mvert++; + nors += 3; + verts += 3; + } + + a = dl->parts; + index = dl->index; + while (a--) { + int count = index[2] != index[3] ? 4 : 3; + + mloop[0].v = index[0]; + mloop[1].v = index[1]; + mloop[2].v = index[2]; + if (count == 4) + mloop[3].v = index[3]; + + mpoly->totloop = count; + mpoly->loopstart = (int)(mloop - allloop); + mpoly->flag = ME_SMOOTH; + + mpoly++; + mloop += count; + me->totloop += count; + index += 4; + } + + BKE_mesh_update_customdata_pointers(me, true); + + BKE_mesh_calc_normals(me); + + BKE_mesh_calc_edges(me, true, false); + } } /** * Specialized function to use when we _know_ existing edges don't overlap with poly edges. */ static void make_edges_mdata_extend( - MEdge **r_alledge, int *r_totedge, - const MPoly *mpoly, MLoop *mloop, - const int totpoly) + MEdge **r_alledge, int *r_totedge, const MPoly *mpoly, MLoop *mloop, const int totpoly) { - int totedge = *r_totedge; - int totedge_new; - EdgeHash *eh; - unsigned int eh_reserve; - const MPoly *mp; - int i; + int totedge = *r_totedge; + int totedge_new; + EdgeHash *eh; + unsigned int eh_reserve; + const MPoly *mp; + int i; - eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly)); - eh = BLI_edgehash_new_ex(__func__, eh_reserve); + eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly)); + eh = BLI_edgehash_new_ex(__func__, eh_reserve); - for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { - BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart); - } + for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { + BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart); + } - totedge_new = BLI_edgehash_len(eh); + totedge_new = BLI_edgehash_len(eh); #ifdef DEBUG - /* ensure that there's no overlap! */ - if (totedge_new) { - MEdge *medge = *r_alledge; - for (i = 0; i < totedge; i++, medge++) { - BLI_assert(BLI_edgehash_haskey(eh, medge->v1, medge->v2) == false); - } - } + /* ensure that there's no overlap! */ + if (totedge_new) { + MEdge *medge = *r_alledge; + for (i = 0; i < totedge; i++, medge++) { + BLI_assert(BLI_edgehash_haskey(eh, medge->v1, medge->v2) == false); + } + } #endif - if (totedge_new) { - EdgeHashIterator *ehi; - MEdge *medge; - unsigned int e_index = totedge; - - *r_alledge = medge = (*r_alledge ? MEM_reallocN(*r_alledge, sizeof(MEdge) * (totedge + totedge_new)) : - MEM_calloc_arrayN(totedge_new, sizeof(MEdge), __func__)); - medge += totedge; - - totedge += totedge_new; - - /* --- */ - for (ehi = BLI_edgehashIterator_new(eh); - BLI_edgehashIterator_isDone(ehi) == false; - BLI_edgehashIterator_step(ehi), ++medge, e_index++) - { - BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2); - BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index)); - - medge->crease = medge->bweight = 0; - medge->flag = ME_EDGEDRAW | ME_EDGERENDER; - } - BLI_edgehashIterator_free(ehi); - - *r_totedge = totedge; - - - for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { - MLoop *l = &mloop[mp->loopstart]; - MLoop *l_prev = (l + (mp->totloop - 1)); - int j; - for (j = 0; j < mp->totloop; j++, l++) { - /* lookup hashed edge index */ - l_prev->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, l_prev->v, l->v)); - l_prev = l; - } - } - } - - BLI_edgehash_free(eh, NULL); + if (totedge_new) { + EdgeHashIterator *ehi; + MEdge *medge; + unsigned int e_index = totedge; + + *r_alledge = medge = (*r_alledge ? + MEM_reallocN(*r_alledge, sizeof(MEdge) * (totedge + totedge_new)) : + MEM_calloc_arrayN(totedge_new, sizeof(MEdge), __func__)); + medge += totedge; + + totedge += totedge_new; + + /* --- */ + for (ehi = BLI_edgehashIterator_new(eh); BLI_edgehashIterator_isDone(ehi) == false; + BLI_edgehashIterator_step(ehi), ++medge, e_index++) { + BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2); + BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index)); + + medge->crease = medge->bweight = 0; + medge->flag = ME_EDGEDRAW | ME_EDGERENDER; + } + BLI_edgehashIterator_free(ehi); + + *r_totedge = totedge; + + for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { + MLoop *l = &mloop[mp->loopstart]; + MLoop *l_prev = (l + (mp->totloop - 1)); + int j; + for (j = 0; j < mp->totloop; j++, l++) { + /* lookup hashed edge index */ + l_prev->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, l_prev->v, l->v)); + l_prev = l; + } + } + } + + BLI_edgehash_free(eh, NULL); } - /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* return non-zero on error */ -int BKE_mesh_nurbs_to_mdata( - Object *ob, MVert **r_allvert, int *r_totvert, - MEdge **r_alledge, int *r_totedge, MLoop **r_allloop, MPoly **r_allpoly, - int *r_totloop, int *r_totpoly) +int BKE_mesh_nurbs_to_mdata(Object *ob, + MVert **r_allvert, + int *r_totvert, + MEdge **r_alledge, + int *r_totedge, + MLoop **r_allloop, + MPoly **r_allpoly, + int *r_totloop, + int *r_totpoly) { - ListBase disp = {NULL, NULL}; - - if (ob->runtime.curve_cache) { - disp = ob->runtime.curve_cache->disp; - } - - return BKE_mesh_nurbs_displist_to_mdata( - ob, &disp, - r_allvert, r_totvert, - r_alledge, r_totedge, - r_allloop, r_allpoly, NULL, - r_totloop, r_totpoly); + ListBase disp = {NULL, NULL}; + + if (ob->runtime.curve_cache) { + disp = ob->runtime.curve_cache->disp; + } + + return BKE_mesh_nurbs_displist_to_mdata(ob, + &disp, + r_allvert, + r_totvert, + r_alledge, + r_totedge, + r_allloop, + r_allpoly, + NULL, + r_totloop, + r_totpoly); } /* BMESH: this doesn't calculate all edges from polygons, @@ -232,609 +238,646 @@ int BKE_mesh_nurbs_to_mdata( /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* use specified dispbase */ -int BKE_mesh_nurbs_displist_to_mdata( - Object *ob, const ListBase *dispbase, - MVert **r_allvert, int *r_totvert, - MEdge **r_alledge, int *r_totedge, - MLoop **r_allloop, MPoly **r_allpoly, - MLoopUV **r_alluv, - int *r_totloop, int *r_totpoly) +int BKE_mesh_nurbs_displist_to_mdata(Object *ob, + const ListBase *dispbase, + MVert **r_allvert, + int *r_totvert, + MEdge **r_alledge, + int *r_totedge, + MLoop **r_allloop, + MPoly **r_allpoly, + MLoopUV **r_alluv, + int *r_totloop, + int *r_totpoly) { - Curve *cu = ob->data; - DispList *dl; - MVert *mvert; - MPoly *mpoly; - MLoop *mloop; - MLoopUV *mloopuv = NULL; - MEdge *medge; - const float *data; - int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totpoly = 0; - int p1, p2, p3, p4, *index; - const bool conv_polys = ((CU_DO_2DFILL(cu) == false) || /* 2d polys are filled with DL_INDEX3 displists */ - (ob->type == OB_SURF)); /* surf polys are never filled */ - - /* count */ - dl = dispbase->first; - while (dl) { - if (dl->type == DL_SEGM) { - totvert += dl->parts * dl->nr; - totedge += dl->parts * (dl->nr - 1); - } - else if (dl->type == DL_POLY) { - if (conv_polys) { - totvert += dl->parts * dl->nr; - totedge += dl->parts * dl->nr; - } - } - else if (dl->type == DL_SURF) { - int tot; - totvert += dl->parts * dl->nr; - tot = (dl->parts - 1 + ((dl->flag & DL_CYCL_V) == 2)) * (dl->nr - 1 + (dl->flag & DL_CYCL_U)); - totpoly += tot; - totloop += tot * 4; - } - else if (dl->type == DL_INDEX3) { - int tot; - totvert += dl->nr; - tot = dl->parts; - totpoly += tot; - totloop += tot * 3; - } - dl = dl->next; - } - - if (totvert == 0) { - /* error("can't convert"); */ - /* Make Sure you check ob->data is a curve */ - return -1; - } - - *r_allvert = mvert = MEM_calloc_arrayN(totvert, sizeof(MVert), "nurbs_init mvert"); - *r_alledge = medge = MEM_calloc_arrayN(totedge, sizeof(MEdge), "nurbs_init medge"); - *r_allloop = mloop = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoop), "nurbs_init mloop"); // totloop - *r_allpoly = mpoly = MEM_calloc_arrayN(totpoly, sizeof(MPoly), "nurbs_init mloop"); - - if (r_alluv) - *r_alluv = mloopuv = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoopUV), "nurbs_init mloopuv"); - - /* verts and faces */ - vertcount = 0; - - dl = dispbase->first; - while (dl) { - const bool is_smooth = (dl->rt & CU_SMOOTH) != 0; - - if (dl->type == DL_SEGM) { - startvert = vertcount; - a = dl->parts * dl->nr; - data = dl->verts; - while (a--) { - copy_v3_v3(mvert->co, data); - data += 3; - vertcount++; - mvert++; - } - - for (a = 0; a < dl->parts; a++) { - ofs = a * dl->nr; - for (b = 1; b < dl->nr; b++) { - medge->v1 = startvert + ofs + b - 1; - medge->v2 = startvert + ofs + b; - medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW; - - medge++; - } - } - - } - else if (dl->type == DL_POLY) { - if (conv_polys) { - startvert = vertcount; - a = dl->parts * dl->nr; - data = dl->verts; - while (a--) { - copy_v3_v3(mvert->co, data); - data += 3; - vertcount++; - mvert++; - } - - for (a = 0; a < dl->parts; a++) { - ofs = a * dl->nr; - for (b = 0; b < dl->nr; b++) { - medge->v1 = startvert + ofs + b; - if (b == dl->nr - 1) medge->v2 = startvert + ofs; - else medge->v2 = startvert + ofs + b + 1; - medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW; - medge++; - } - } - } - } - else if (dl->type == DL_INDEX3) { - startvert = vertcount; - a = dl->nr; - data = dl->verts; - while (a--) { - copy_v3_v3(mvert->co, data); - data += 3; - vertcount++; - mvert++; - } - - a = dl->parts; - index = dl->index; - while (a--) { - mloop[0].v = startvert + index[0]; - mloop[1].v = startvert + index[2]; - mloop[2].v = startvert + index[1]; - mpoly->loopstart = (int)(mloop - (*r_allloop)); - mpoly->totloop = 3; - mpoly->mat_nr = dl->col; - - if (mloopuv) { - int i; - - for (i = 0; i < 3; i++, mloopuv++) { - mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1); - mloopuv->uv[1] = 0.0f; - } - } - - if (is_smooth) mpoly->flag |= ME_SMOOTH; - mpoly++; - mloop += 3; - index += 3; - } - } - else if (dl->type == DL_SURF) { - startvert = vertcount; - a = dl->parts * dl->nr; - data = dl->verts; - while (a--) { - copy_v3_v3(mvert->co, data); - data += 3; - vertcount++; - mvert++; - } - - for (a = 0; a < dl->parts; a++) { - - if ( (dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) break; - - if (dl->flag & DL_CYCL_U) { /* p2 -> p1 -> */ - p1 = startvert + dl->nr * a; /* p4 -> p3 -> */ - p2 = p1 + dl->nr - 1; /* -----> next row */ - p3 = p1 + dl->nr; - p4 = p2 + dl->nr; - b = 0; - } - else { - p2 = startvert + dl->nr * a; - p1 = p2 + 1; - p4 = p2 + dl->nr; - p3 = p1 + dl->nr; - b = 1; - } - if ( (dl->flag & DL_CYCL_V) && a == dl->parts - 1) { - p3 -= dl->parts * dl->nr; - p4 -= dl->parts * dl->nr; - } - - for (; b < dl->nr; b++) { - mloop[0].v = p1; - mloop[1].v = p3; - mloop[2].v = p4; - mloop[3].v = p2; - mpoly->loopstart = (int)(mloop - (*r_allloop)); - mpoly->totloop = 4; - mpoly->mat_nr = dl->col; - - if (mloopuv) { - int orco_sizeu = dl->nr - 1; - int orco_sizev = dl->parts - 1; - int i; - - /* exception as handled in convertblender.c too */ - if (dl->flag & DL_CYCL_U) { - orco_sizeu++; - if (dl->flag & DL_CYCL_V) - orco_sizev++; - } - else if (dl->flag & DL_CYCL_V) { - orco_sizev++; - } - - for (i = 0; i < 4; i++, mloopuv++) { - /* find uv based on vertex index into grid array */ - int v = mloop[i].v - startvert; - - mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev; - mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu; - - /* cyclic correction */ - if ((i == 1 || i == 2) && mloopuv->uv[0] == 0.0f) - mloopuv->uv[0] = 1.0f; - if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f) - mloopuv->uv[1] = 1.0f; - } - } - - if (is_smooth) mpoly->flag |= ME_SMOOTH; - mpoly++; - mloop += 4; - - p4 = p3; - p3++; - p2 = p1; - p1++; - } - } - } - - dl = dl->next; - } - - if (totpoly) { - make_edges_mdata_extend( - r_alledge, &totedge, - *r_allpoly, *r_allloop, totpoly); - } - - *r_totpoly = totpoly; - *r_totloop = totloop; - *r_totedge = totedge; - *r_totvert = totvert; - - return 0; + Curve *cu = ob->data; + DispList *dl; + MVert *mvert; + MPoly *mpoly; + MLoop *mloop; + MLoopUV *mloopuv = NULL; + MEdge *medge; + const float *data; + int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totpoly = 0; + int p1, p2, p3, p4, *index; + const bool conv_polys = ((CU_DO_2DFILL(cu) == + false) || /* 2d polys are filled with DL_INDEX3 displists */ + (ob->type == OB_SURF)); /* surf polys are never filled */ + + /* count */ + dl = dispbase->first; + while (dl) { + if (dl->type == DL_SEGM) { + totvert += dl->parts * dl->nr; + totedge += dl->parts * (dl->nr - 1); + } + else if (dl->type == DL_POLY) { + if (conv_polys) { + totvert += dl->parts * dl->nr; + totedge += dl->parts * dl->nr; + } + } + else if (dl->type == DL_SURF) { + int tot; + totvert += dl->parts * dl->nr; + tot = (dl->parts - 1 + ((dl->flag & DL_CYCL_V) == 2)) * + (dl->nr - 1 + (dl->flag & DL_CYCL_U)); + totpoly += tot; + totloop += tot * 4; + } + else if (dl->type == DL_INDEX3) { + int tot; + totvert += dl->nr; + tot = dl->parts; + totpoly += tot; + totloop += tot * 3; + } + dl = dl->next; + } + + if (totvert == 0) { + /* error("can't convert"); */ + /* Make Sure you check ob->data is a curve */ + return -1; + } + + *r_allvert = mvert = MEM_calloc_arrayN(totvert, sizeof(MVert), "nurbs_init mvert"); + *r_alledge = medge = MEM_calloc_arrayN(totedge, sizeof(MEdge), "nurbs_init medge"); + *r_allloop = mloop = MEM_calloc_arrayN( + totpoly, 4 * sizeof(MLoop), "nurbs_init mloop"); // totloop + *r_allpoly = mpoly = MEM_calloc_arrayN(totpoly, sizeof(MPoly), "nurbs_init mloop"); + + if (r_alluv) + *r_alluv = mloopuv = MEM_calloc_arrayN(totpoly, 4 * sizeof(MLoopUV), "nurbs_init mloopuv"); + + /* verts and faces */ + vertcount = 0; + + dl = dispbase->first; + while (dl) { + const bool is_smooth = (dl->rt & CU_SMOOTH) != 0; + + if (dl->type == DL_SEGM) { + startvert = vertcount; + a = dl->parts * dl->nr; + data = dl->verts; + while (a--) { + copy_v3_v3(mvert->co, data); + data += 3; + vertcount++; + mvert++; + } + + for (a = 0; a < dl->parts; a++) { + ofs = a * dl->nr; + for (b = 1; b < dl->nr; b++) { + medge->v1 = startvert + ofs + b - 1; + medge->v2 = startvert + ofs + b; + medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW; + + medge++; + } + } + } + else if (dl->type == DL_POLY) { + if (conv_polys) { + startvert = vertcount; + a = dl->parts * dl->nr; + data = dl->verts; + while (a--) { + copy_v3_v3(mvert->co, data); + data += 3; + vertcount++; + mvert++; + } + + for (a = 0; a < dl->parts; a++) { + ofs = a * dl->nr; + for (b = 0; b < dl->nr; b++) { + medge->v1 = startvert + ofs + b; + if (b == dl->nr - 1) + medge->v2 = startvert + ofs; + else + medge->v2 = startvert + ofs + b + 1; + medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW; + medge++; + } + } + } + } + else if (dl->type == DL_INDEX3) { + startvert = vertcount; + a = dl->nr; + data = dl->verts; + while (a--) { + copy_v3_v3(mvert->co, data); + data += 3; + vertcount++; + mvert++; + } + + a = dl->parts; + index = dl->index; + while (a--) { + mloop[0].v = startvert + index[0]; + mloop[1].v = startvert + index[2]; + mloop[2].v = startvert + index[1]; + mpoly->loopstart = (int)(mloop - (*r_allloop)); + mpoly->totloop = 3; + mpoly->mat_nr = dl->col; + + if (mloopuv) { + int i; + + for (i = 0; i < 3; i++, mloopuv++) { + mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1); + mloopuv->uv[1] = 0.0f; + } + } + + if (is_smooth) + mpoly->flag |= ME_SMOOTH; + mpoly++; + mloop += 3; + index += 3; + } + } + else if (dl->type == DL_SURF) { + startvert = vertcount; + a = dl->parts * dl->nr; + data = dl->verts; + while (a--) { + copy_v3_v3(mvert->co, data); + data += 3; + vertcount++; + mvert++; + } + + for (a = 0; a < dl->parts; a++) { + + if ((dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) + break; + + if (dl->flag & DL_CYCL_U) { /* p2 -> p1 -> */ + p1 = startvert + dl->nr * a; /* p4 -> p3 -> */ + p2 = p1 + dl->nr - 1; /* -----> next row */ + p3 = p1 + dl->nr; + p4 = p2 + dl->nr; + b = 0; + } + else { + p2 = startvert + dl->nr * a; + p1 = p2 + 1; + p4 = p2 + dl->nr; + p3 = p1 + dl->nr; + b = 1; + } + if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) { + p3 -= dl->parts * dl->nr; + p4 -= dl->parts * dl->nr; + } + + for (; b < dl->nr; b++) { + mloop[0].v = p1; + mloop[1].v = p3; + mloop[2].v = p4; + mloop[3].v = p2; + mpoly->loopstart = (int)(mloop - (*r_allloop)); + mpoly->totloop = 4; + mpoly->mat_nr = dl->col; + + if (mloopuv) { + int orco_sizeu = dl->nr - 1; + int orco_sizev = dl->parts - 1; + int i; + + /* exception as handled in convertblender.c too */ + if (dl->flag & DL_CYCL_U) { + orco_sizeu++; + if (dl->flag & DL_CYCL_V) + orco_sizev++; + } + else if (dl->flag & DL_CYCL_V) { + orco_sizev++; + } + + for (i = 0; i < 4; i++, mloopuv++) { + /* find uv based on vertex index into grid array */ + int v = mloop[i].v - startvert; + + mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev; + mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu; + + /* cyclic correction */ + if ((i == 1 || i == 2) && mloopuv->uv[0] == 0.0f) + mloopuv->uv[0] = 1.0f; + if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f) + mloopuv->uv[1] = 1.0f; + } + } + + if (is_smooth) + mpoly->flag |= ME_SMOOTH; + mpoly++; + mloop += 4; + + p4 = p3; + p3++; + p2 = p1; + p1++; + } + } + } + + dl = dl->next; + } + + if (totpoly) { + make_edges_mdata_extend(r_alledge, &totedge, *r_allpoly, *r_allloop, totpoly); + } + + *r_totpoly = totpoly; + *r_totloop = totloop; + *r_totedge = totedge; + *r_totvert = totvert; + + return 0; } Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase) { - Curve *cu = ob->data; - Mesh *mesh; - MVert *allvert; - MEdge *alledge; - MLoop *allloop; - MPoly *allpoly; - MLoopUV *alluv = NULL; - int totvert, totedge, totloop, totpoly; - bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; - - if (BKE_mesh_nurbs_displist_to_mdata( - ob, dispbase, &allvert, &totvert, &alledge, - &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL, - &totloop, &totpoly) != 0) - { - /* Error initializing mdata. This often happens when curve is empty */ - return BKE_mesh_new_nomain(0, 0, 0, 0, 0); - } - - mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly); - mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; - - memcpy(mesh->mvert, allvert, totvert * sizeof(MVert)); - memcpy(mesh->medge, alledge, totedge * sizeof(MEdge)); - memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop)); - memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly)); - - if (alluv) { - const char *uvname = "Orco"; - CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname); - } - - MEM_freeN(allvert); - MEM_freeN(alledge); - MEM_freeN(allloop); - MEM_freeN(allpoly); - - return mesh; + Curve *cu = ob->data; + Mesh *mesh; + MVert *allvert; + MEdge *alledge; + MLoop *allloop; + MPoly *allpoly; + MLoopUV *alluv = NULL; + int totvert, totedge, totloop, totpoly; + bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; + + if (BKE_mesh_nurbs_displist_to_mdata(ob, + dispbase, + &allvert, + &totvert, + &alledge, + &totedge, + &allloop, + &allpoly, + (use_orco_uv) ? &alluv : NULL, + &totloop, + &totpoly) != 0) { + /* Error initializing mdata. This often happens when curve is empty */ + return BKE_mesh_new_nomain(0, 0, 0, 0, 0); + } + + mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly); + mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + + memcpy(mesh->mvert, allvert, totvert * sizeof(MVert)); + memcpy(mesh->medge, alledge, totedge * sizeof(MEdge)); + memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop)); + memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly)); + + if (alluv) { + const char *uvname = "Orco"; + CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname); + } + + MEM_freeN(allvert); + MEM_freeN(alledge); + MEM_freeN(allloop); + MEM_freeN(allpoly); + + return mesh; } Mesh *BKE_mesh_new_nomain_from_curve(Object *ob) { - ListBase disp = {NULL, NULL}; + ListBase disp = {NULL, NULL}; - if (ob->runtime.curve_cache) { - disp = ob->runtime.curve_cache->disp; - } + if (ob->runtime.curve_cache) { + disp = ob->runtime.curve_cache->disp; + } - return BKE_mesh_new_nomain_from_curve_displist(ob, &disp); + return BKE_mesh_new_nomain_from_curve_displist(ob, &disp); } /* this may fail replacing ob->data, be sure to check ob->type */ -void BKE_mesh_from_nurbs_displist( - Main *bmain, Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name, bool temporary) +void BKE_mesh_from_nurbs_displist(Main *bmain, + Object *ob, + ListBase *dispbase, + const bool use_orco_uv, + const char *obdata_name, + bool temporary) { - Object *ob1; - Mesh *me_eval = ob->runtime.mesh_eval; - Mesh *me; - Curve *cu; - MVert *allvert = NULL; - MEdge *alledge = NULL; - MLoop *allloop = NULL; - MLoopUV *alluv = NULL; - MPoly *allpoly = NULL; - int totvert, totedge, totloop, totpoly; - - cu = ob->data; - - if (me_eval == NULL) { - if (BKE_mesh_nurbs_displist_to_mdata( - ob, dispbase, &allvert, &totvert, - &alledge, &totedge, &allloop, - &allpoly, (use_orco_uv) ? &alluv : NULL, - &totloop, &totpoly) != 0) - { - /* Error initializing */ - return; - } - - /* make mesh */ - me = BKE_mesh_add(bmain, obdata_name); - me->totvert = totvert; - me->totedge = totedge; - me->totloop = totloop; - me->totpoly = totpoly; - - me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); - me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); - me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop); - me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly); - - if (alluv) { - const char *uvname = "Orco"; - me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname); - } - - BKE_mesh_calc_normals(me); - } - else { - me = BKE_mesh_add(bmain, obdata_name); - ob->runtime.mesh_eval = NULL; - BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true); - } - - me->totcol = cu->totcol; - me->mat = cu->mat; - - /* Copy evaluated texture space from curve to mesh. - * - * Note that we disable auto texture space feature since that will cause - * texture space to evaluate differently for curve and mesh, since curve - * uses CV to calculate bounding box, and mesh uses what is coming from - * tessellated curve. - */ - me->texflag = cu->texflag & ~CU_AUTOSPACE; - copy_v3_v3(me->loc, cu->loc); - copy_v3_v3(me->size, cu->size); - copy_v3_v3(me->rot, cu->rot); - BKE_mesh_texspace_calc(me); - - cu->mat = NULL; - cu->totcol = 0; - - /* Do not decrement ob->data usercount here, it's done at end of func with BKE_id_free_us() call. */ - ob->data = me; - ob->type = OB_MESH; - - /* other users */ - ob1 = bmain->objects.first; - while (ob1) { - if (ob1->data == cu) { - ob1->type = OB_MESH; - - id_us_min((ID *)ob1->data); - ob1->data = ob->data; - id_us_plus((ID *)ob1->data); - } - ob1 = ob1->id.next; - } - - if (temporary) { - /* For temporary objects in BKE_mesh_new_from_object don't remap - * the entire scene with associated depsgraph updates, which are - * problematic for renderers exporting data. */ - BKE_id_free(NULL, cu); - } - else { - BKE_id_free_us(bmain, cu); - } + Object *ob1; + Mesh *me_eval = ob->runtime.mesh_eval; + Mesh *me; + Curve *cu; + MVert *allvert = NULL; + MEdge *alledge = NULL; + MLoop *allloop = NULL; + MLoopUV *alluv = NULL; + MPoly *allpoly = NULL; + int totvert, totedge, totloop, totpoly; + + cu = ob->data; + + if (me_eval == NULL) { + if (BKE_mesh_nurbs_displist_to_mdata(ob, + dispbase, + &allvert, + &totvert, + &alledge, + &totedge, + &allloop, + &allpoly, + (use_orco_uv) ? &alluv : NULL, + &totloop, + &totpoly) != 0) { + /* Error initializing */ + return; + } + + /* make mesh */ + me = BKE_mesh_add(bmain, obdata_name); + me->totvert = totvert; + me->totedge = totedge; + me->totloop = totloop; + me->totpoly = totpoly; + + me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); + me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); + me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop); + me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly); + + if (alluv) { + const char *uvname = "Orco"; + me->mloopuv = CustomData_add_layer_named( + &me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname); + } + + BKE_mesh_calc_normals(me); + } + else { + me = BKE_mesh_add(bmain, obdata_name); + ob->runtime.mesh_eval = NULL; + BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true); + } + + me->totcol = cu->totcol; + me->mat = cu->mat; + + /* Copy evaluated texture space from curve to mesh. + * + * Note that we disable auto texture space feature since that will cause + * texture space to evaluate differently for curve and mesh, since curve + * uses CV to calculate bounding box, and mesh uses what is coming from + * tessellated curve. + */ + me->texflag = cu->texflag & ~CU_AUTOSPACE; + copy_v3_v3(me->loc, cu->loc); + copy_v3_v3(me->size, cu->size); + copy_v3_v3(me->rot, cu->rot); + BKE_mesh_texspace_calc(me); + + cu->mat = NULL; + cu->totcol = 0; + + /* Do not decrement ob->data usercount here, it's done at end of func with BKE_id_free_us() call. */ + ob->data = me; + ob->type = OB_MESH; + + /* other users */ + ob1 = bmain->objects.first; + while (ob1) { + if (ob1->data == cu) { + ob1->type = OB_MESH; + + id_us_min((ID *)ob1->data); + ob1->data = ob->data; + id_us_plus((ID *)ob1->data); + } + ob1 = ob1->id.next; + } + + if (temporary) { + /* For temporary objects in BKE_mesh_new_from_object don't remap + * the entire scene with associated depsgraph updates, which are + * problematic for renderers exporting data. */ + BKE_id_free(NULL, cu); + } + else { + BKE_id_free_us(bmain, cu); + } } void BKE_mesh_from_nurbs(Main *bmain, Object *ob) { - Curve *cu = (Curve *) ob->data; - bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; - ListBase disp = {NULL, NULL}; + Curve *cu = (Curve *)ob->data; + bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; + ListBase disp = {NULL, NULL}; - if (ob->runtime.curve_cache) { - disp = ob->runtime.curve_cache->disp; - } + if (ob->runtime.curve_cache) { + disp = ob->runtime.curve_cache->disp; + } - BKE_mesh_from_nurbs_displist(bmain, ob, &disp, use_orco_uv, cu->id.name, false); + BKE_mesh_from_nurbs_displist(bmain, ob, &disp, use_orco_uv, cu->id.name, false); } typedef struct EdgeLink { - struct EdgeLink *next, *prev; - void *edge; + struct EdgeLink *next, *prev; + void *edge; } EdgeLink; typedef struct VertLink { - Link *next, *prev; - unsigned int index; + Link *next, *prev; + unsigned int index; } VertLink; static void prependPolyLineVert(ListBase *lb, unsigned int index) { - VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink"); - vl->index = index; - BLI_addhead(lb, vl); + VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink"); + vl->index = index; + BLI_addhead(lb, vl); } static void appendPolyLineVert(ListBase *lb, unsigned int index) { - VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink"); - vl->index = index; - BLI_addtail(lb, vl); + VertLink *vl = MEM_callocN(sizeof(VertLink), "VertLink"); + vl->index = index; + BLI_addtail(lb, vl); } void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int edge_users_test) { - MVert *mvert = me->mvert; - MEdge *med, *medge = me->medge; - MPoly *mp, *mpoly = me->mpoly; - MLoop *mloop = me->mloop; - - int medge_len = me->totedge; - int mpoly_len = me->totpoly; - int totedges = 0; - int i; - - /* only to detect edge polylines */ - int *edge_users; - - ListBase edges = {NULL, NULL}; - - /* get boundary edges */ - edge_users = MEM_calloc_arrayN(medge_len, sizeof(int), __func__); - for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) { - MLoop *ml = &mloop[mp->loopstart]; - int j; - for (j = 0; j < mp->totloop; j++, ml++) { - edge_users[ml->e]++; - } - } - - /* create edges from all faces (so as to find edges not in any faces) */ - med = medge; - for (i = 0; i < medge_len; i++, med++) { - if (edge_users[i] == edge_users_test) { - EdgeLink *edl = MEM_callocN(sizeof(EdgeLink), "EdgeLink"); - edl->edge = med; - - BLI_addtail(&edges, edl); totedges++; - } - } - MEM_freeN(edge_users); - - if (edges.first) { - while (edges.first) { - /* each iteration find a polyline and add this as a nurbs poly spline */ - - ListBase polyline = {NULL, NULL}; /* store a list of VertLink's */ - bool closed = false; - int totpoly = 0; - MEdge *med_current = ((EdgeLink *)edges.last)->edge; - unsigned int startVert = med_current->v1; - unsigned int endVert = med_current->v2; - bool ok = true; - - appendPolyLineVert(&polyline, startVert); totpoly++; - appendPolyLineVert(&polyline, endVert); totpoly++; - BLI_freelinkN(&edges, edges.last); totedges--; - - while (ok) { /* while connected edges are found... */ - EdgeLink *edl = edges.last; - ok = false; - while (edl) { - EdgeLink *edl_prev = edl->prev; - - med = edl->edge; - - if (med->v1 == endVert) { - endVert = med->v2; - appendPolyLineVert(&polyline, med->v2); totpoly++; - BLI_freelinkN(&edges, edl); totedges--; - ok = true; - } - else if (med->v2 == endVert) { - endVert = med->v1; - appendPolyLineVert(&polyline, endVert); totpoly++; - BLI_freelinkN(&edges, edl); totedges--; - ok = true; - } - else if (med->v1 == startVert) { - startVert = med->v2; - prependPolyLineVert(&polyline, startVert); totpoly++; - BLI_freelinkN(&edges, edl); totedges--; - ok = true; - } - else if (med->v2 == startVert) { - startVert = med->v1; - prependPolyLineVert(&polyline, startVert); totpoly++; - BLI_freelinkN(&edges, edl); totedges--; - ok = true; - } - - edl = edl_prev; - } - } - - /* Now we have a polyline, make into a curve */ - if (startVert == endVert) { - BLI_freelinkN(&polyline, polyline.last); - totpoly--; - closed = true; - } - - /* --- nurbs --- */ - { - Nurb *nu; - BPoint *bp; - VertLink *vl; - - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "MeshNurb"); - - nu->pntsu = totpoly; - nu->pntsv = 1; - nu->orderu = 4; - nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0); /* endpoint */ - nu->resolu = 12; - - nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints"); - - /* add points */ - vl = polyline.first; - for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) { - copy_v3_v3(bp->vec, mvert[vl->index].co); - bp->f1 = SELECT; - bp->radius = bp->weight = 1.0; - } - BLI_freelistN(&polyline); - - /* add nurb to curve */ - BLI_addtail(nurblist, nu); - } - /* --- done with nurbs --- */ - } - } + MVert *mvert = me->mvert; + MEdge *med, *medge = me->medge; + MPoly *mp, *mpoly = me->mpoly; + MLoop *mloop = me->mloop; + + int medge_len = me->totedge; + int mpoly_len = me->totpoly; + int totedges = 0; + int i; + + /* only to detect edge polylines */ + int *edge_users; + + ListBase edges = {NULL, NULL}; + + /* get boundary edges */ + edge_users = MEM_calloc_arrayN(medge_len, sizeof(int), __func__); + for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) { + MLoop *ml = &mloop[mp->loopstart]; + int j; + for (j = 0; j < mp->totloop; j++, ml++) { + edge_users[ml->e]++; + } + } + + /* create edges from all faces (so as to find edges not in any faces) */ + med = medge; + for (i = 0; i < medge_len; i++, med++) { + if (edge_users[i] == edge_users_test) { + EdgeLink *edl = MEM_callocN(sizeof(EdgeLink), "EdgeLink"); + edl->edge = med; + + BLI_addtail(&edges, edl); + totedges++; + } + } + MEM_freeN(edge_users); + + if (edges.first) { + while (edges.first) { + /* each iteration find a polyline and add this as a nurbs poly spline */ + + ListBase polyline = {NULL, NULL}; /* store a list of VertLink's */ + bool closed = false; + int totpoly = 0; + MEdge *med_current = ((EdgeLink *)edges.last)->edge; + unsigned int startVert = med_current->v1; + unsigned int endVert = med_current->v2; + bool ok = true; + + appendPolyLineVert(&polyline, startVert); + totpoly++; + appendPolyLineVert(&polyline, endVert); + totpoly++; + BLI_freelinkN(&edges, edges.last); + totedges--; + + while (ok) { /* while connected edges are found... */ + EdgeLink *edl = edges.last; + ok = false; + while (edl) { + EdgeLink *edl_prev = edl->prev; + + med = edl->edge; + + if (med->v1 == endVert) { + endVert = med->v2; + appendPolyLineVert(&polyline, med->v2); + totpoly++; + BLI_freelinkN(&edges, edl); + totedges--; + ok = true; + } + else if (med->v2 == endVert) { + endVert = med->v1; + appendPolyLineVert(&polyline, endVert); + totpoly++; + BLI_freelinkN(&edges, edl); + totedges--; + ok = true; + } + else if (med->v1 == startVert) { + startVert = med->v2; + prependPolyLineVert(&polyline, startVert); + totpoly++; + BLI_freelinkN(&edges, edl); + totedges--; + ok = true; + } + else if (med->v2 == startVert) { + startVert = med->v1; + prependPolyLineVert(&polyline, startVert); + totpoly++; + BLI_freelinkN(&edges, edl); + totedges--; + ok = true; + } + + edl = edl_prev; + } + } + + /* Now we have a polyline, make into a curve */ + if (startVert == endVert) { + BLI_freelinkN(&polyline, polyline.last); + totpoly--; + closed = true; + } + + /* --- nurbs --- */ + { + Nurb *nu; + BPoint *bp; + VertLink *vl; + + /* create new 'nurb' within the curve */ + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "MeshNurb"); + + nu->pntsu = totpoly; + nu->pntsv = 1; + nu->orderu = 4; + nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0); /* endpoint */ + nu->resolu = 12; + + nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints"); + + /* add points */ + vl = polyline.first; + for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) { + copy_v3_v3(bp->vec, mvert[vl->index].co); + bp->f1 = SELECT; + bp->radius = bp->weight = 1.0; + } + BLI_freelistN(&polyline); + + /* add nurb to curve */ + BLI_addtail(nurblist, nu); + } + /* --- done with nurbs --- */ + } + } } void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob) { - /* make new mesh data from the original copy */ - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH); - ListBase nurblist = {NULL, NULL}; + /* make new mesh data from the original copy */ + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH); + ListBase nurblist = {NULL, NULL}; - BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 0); - BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 1); + BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 0); + BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 1); - if (nurblist.first) { - Curve *cu = BKE_curve_add(bmain, ob->id.name + 2, OB_CURVE); - cu->flag |= CU_3D; + if (nurblist.first) { + Curve *cu = BKE_curve_add(bmain, ob->id.name + 2, OB_CURVE); + cu->flag |= CU_3D; - cu->nurb = nurblist; + cu->nurb = nurblist; - id_us_min(&((Mesh *)ob->data)->id); - ob->data = cu; - ob->type = OB_CURVE; + id_us_min(&((Mesh *)ob->data)->id); + ob->data = cu; + ob->type = OB_CURVE; - BKE_object_free_derived_caches(ob); - } + BKE_object_free_derived_caches(ob); + } } /* settings: 1 - preview, 2 - render @@ -856,600 +899,620 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), * The result mesh will point to an evaluated datablocks. For example, * materials will be an evaluated IDs from the dependency graph. */ -Mesh *BKE_mesh_new_from_object( - Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob, - const bool apply_modifiers, const bool calc_undeformed) +Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph, + Main *bmain, + Scene *sce, + Object *ob, + const bool apply_modifiers, + const bool calc_undeformed) { - Mesh *tmpmesh; - Curve *tmpcu = NULL, *copycu; - int i; - const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - bool effective_apply_modifiers = apply_modifiers; - bool do_mat_id_data_us = true; - - Object *object_input = ob; - Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input); - Object object_for_eval; - - if (object_eval == object_input) { - /* Evaluated mesh contains all modifiers applied already. - * The other types of object has them applied, but are stored in other - * data structures than a mesh. So need to apply modifiers again on a - * temporary copy before converting result to mesh. */ - if (object_input->type == OB_MESH) { - effective_apply_modifiers = false; - } - else { - effective_apply_modifiers = true; - } - object_for_eval = *object_eval; - } - else { - if (apply_modifiers) { - object_for_eval = *object_eval; - if (object_for_eval.runtime.mesh_orig != NULL) { - object_for_eval.data = object_for_eval.runtime.mesh_orig; - } - } - else { - object_for_eval = *object_input; - } - } - - const bool cage = !effective_apply_modifiers; - - /* perform the mesh extraction based on type */ - switch (object_for_eval.type) { - case OB_FONT: - case OB_CURVE: - case OB_SURF: - { - ListBase dispbase = {NULL, NULL}; - Mesh *me_eval_final = NULL; - int uv_from_orco; - - /* copies object and modifiers (but not the data) */ - Object *tmpobj; - BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE); - tmpcu = (Curve *)tmpobj->data; - - /* Copy cached display list, it might be needed by the stack evaluation. - * Ideally stack should be able to use render-time display list, but doing - * so is quite tricky and not safe so close to the release. - * - * TODO(sergey): Look into more proper solution. - */ - if (object_for_eval.runtime.curve_cache != NULL) { - if (tmpobj->runtime.curve_cache == NULL) { - tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types"); - } - BKE_displist_copy(&tmpobj->runtime.curve_cache->disp, &object_for_eval.runtime.curve_cache->disp); - } - - /* if getting the original caged mesh, delete object modifiers */ - if (cage) - BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT); - - /* copies the data, but *not* the shapekeys. */ - BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)©cu, LIB_ID_COPY_LOCALIZE); - tmpobj->data = copycu; - - /* make sure texture space is calculated for a copy of curve, - * it will be used for the final result. - */ - BKE_curve_texspace_calc(copycu); - - /* temporarily set edit so we get updates from edit mode, but - * also because for text datablocks copying it while in edit - * mode gives invalid data structures */ - copycu->editfont = tmpcu->editfont; - copycu->editnurb = tmpcu->editnurb; - - /* get updated display list, and convert to a mesh */ - BKE_displist_make_curveTypes_forRender( - depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, render, - NULL); - - copycu->editfont = NULL; - copycu->editnurb = NULL; - - tmpobj->runtime.mesh_eval = me_eval_final; - - /* convert object type to mesh */ - uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0; - BKE_mesh_from_nurbs_displist(bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true); - /* Function above also frees copycu (aka tmpobj->data), make this obvious here. */ - copycu = NULL; - - tmpmesh = tmpobj->data; - id_us_min(&tmpmesh->id); /* Gets one user from its creation in BKE_mesh_from_nurbs_displist(). */ - - BKE_displist_free(&dispbase); - - /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked. - * if it didn't the curve did not have any segments or otherwise - * would have generated an empty mesh */ - if (tmpobj->type != OB_MESH) { - BKE_id_free(NULL, tmpobj); - return NULL; - } - - BKE_id_free(NULL, tmpobj); - - /* XXX The curve to mesh conversion is convoluted... But essentially, BKE_mesh_from_nurbs_displist() - * already transfers the ownership of materials from the temp copy of the Curve ID to the new - * Mesh ID, so we do not want to increase materials' usercount later. */ - do_mat_id_data_us = false; - - break; - } - - case OB_MBALL: - { - /* metaballs don't have modifiers, so just convert to mesh */ - Object *basis_ob = BKE_mball_basis_find(sce, object_input); - /* todo, re-generatre for render-res */ - /* metaball_polygonize(scene, ob) */ - - if (basis_ob != object_input) { - /* Only do basis metaball. */ - return NULL; - } - - tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2); - /* BKE_mesh_add gives us a user count we don't need */ - id_us_min(&tmpmesh->id); - - if (render) { - ListBase disp = {NULL, NULL}; - BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp); - BKE_mesh_from_metaball(&disp, tmpmesh); - BKE_displist_free(&disp); - } - else { - ListBase disp = {NULL, NULL}; - if (object_for_eval.runtime.curve_cache) { - disp = object_for_eval.runtime.curve_cache->disp; - } - BKE_mesh_from_metaball(&disp, tmpmesh); - } - - BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval); - - break; - - } - case OB_MESH: - /* copies object and modifiers (but not the data) */ - if (cage) { - /* copies the data (but *not* the shapekeys). */ - Mesh *mesh = object_for_eval.data; - BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0); - /* XXX BKE_mesh_copy() already handles materials usercount. */ - do_mat_id_data_us = false; - } - /* if not getting the original caged mesh, get final derived mesh */ - else { - /* Make a dummy mesh, saves copying */ - Mesh *me_eval; - CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter, - * for example, needs CD_MASK_MDEFORMVERT */ - - if (calc_undeformed) { - mask.vmask |= CD_MASK_ORCO; - } - - if (render) { - me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask); - } - else { - me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask); - } - - tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2); - BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true); - - /* Copy autosmooth settings from original mesh. */ - Mesh *me = (Mesh *)object_for_eval.data; - tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH); - tmpmesh->smoothresh = me->smoothresh; - } - - /* BKE_mesh_add/copy gives us a user count we don't need */ - id_us_min(&tmpmesh->id); - - break; - default: - /* "Object does not have geometry data") */ - return NULL; - } - - /* Copy materials to new mesh */ - switch (object_for_eval.type) { - case OB_SURF: - case OB_FONT: - case OB_CURVE: - tmpmesh->totcol = tmpcu->totcol; - - /* free old material list (if it exists) and adjust user counts */ - if (tmpcu->mat) { - for (i = tmpcu->totcol; i-- > 0; ) { - /* are we an object material or data based? */ - tmpmesh->mat[i] = give_current_material(object_input, i + 1); - - if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { - id_us_plus(&tmpmesh->mat[i]->id); - } - } - } - break; - - case OB_MBALL: - { - MetaBall *tmpmb = (MetaBall *)object_for_eval.data; - tmpmesh->mat = MEM_dupallocN(tmpmb->mat); - tmpmesh->totcol = tmpmb->totcol; - - /* free old material list (if it exists) and adjust user counts */ - if (tmpmb->mat) { - for (i = tmpmb->totcol; i-- > 0; ) { - /* are we an object material or data based? */ - tmpmesh->mat[i] = give_current_material(object_input, i + 1); - - if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { - id_us_plus(&tmpmesh->mat[i]->id); - } - } - } - break; - } - - case OB_MESH: - if (!cage) { - Mesh *origmesh = object_for_eval.data; - tmpmesh->flag = origmesh->flag; - tmpmesh->mat = MEM_dupallocN(origmesh->mat); - tmpmesh->totcol = origmesh->totcol; - tmpmesh->smoothresh = origmesh->smoothresh; - if (origmesh->mat) { - for (i = origmesh->totcol; i-- > 0; ) { - /* are we an object material or data based? */ - tmpmesh->mat[i] = give_current_material(object_input, i + 1); - - if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && tmpmesh->mat[i]) { - id_us_plus(&tmpmesh->mat[i]->id); - } - } - } - } - break; - } /* end copy materials */ - - return tmpmesh; + Mesh *tmpmesh; + Curve *tmpcu = NULL, *copycu; + int i; + const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + bool effective_apply_modifiers = apply_modifiers; + bool do_mat_id_data_us = true; + + Object *object_input = ob; + Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input); + Object object_for_eval; + + if (object_eval == object_input) { + /* Evaluated mesh contains all modifiers applied already. + * The other types of object has them applied, but are stored in other + * data structures than a mesh. So need to apply modifiers again on a + * temporary copy before converting result to mesh. */ + if (object_input->type == OB_MESH) { + effective_apply_modifiers = false; + } + else { + effective_apply_modifiers = true; + } + object_for_eval = *object_eval; + } + else { + if (apply_modifiers) { + object_for_eval = *object_eval; + if (object_for_eval.runtime.mesh_orig != NULL) { + object_for_eval.data = object_for_eval.runtime.mesh_orig; + } + } + else { + object_for_eval = *object_input; + } + } + + const bool cage = !effective_apply_modifiers; + + /* perform the mesh extraction based on type */ + switch (object_for_eval.type) { + case OB_FONT: + case OB_CURVE: + case OB_SURF: { + ListBase dispbase = {NULL, NULL}; + Mesh *me_eval_final = NULL; + int uv_from_orco; + + /* copies object and modifiers (but not the data) */ + Object *tmpobj; + BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE); + tmpcu = (Curve *)tmpobj->data; + + /* Copy cached display list, it might be needed by the stack evaluation. + * Ideally stack should be able to use render-time display list, but doing + * so is quite tricky and not safe so close to the release. + * + * TODO(sergey): Look into more proper solution. + */ + if (object_for_eval.runtime.curve_cache != NULL) { + if (tmpobj->runtime.curve_cache == NULL) { + tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), + "CurveCache for curve types"); + } + BKE_displist_copy(&tmpobj->runtime.curve_cache->disp, + &object_for_eval.runtime.curve_cache->disp); + } + + /* if getting the original caged mesh, delete object modifiers */ + if (cage) + BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT); + + /* copies the data, but *not* the shapekeys. */ + BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)©cu, LIB_ID_COPY_LOCALIZE); + tmpobj->data = copycu; + + /* make sure texture space is calculated for a copy of curve, + * it will be used for the final result. + */ + BKE_curve_texspace_calc(copycu); + + /* temporarily set edit so we get updates from edit mode, but + * also because for text datablocks copying it while in edit + * mode gives invalid data structures */ + copycu->editfont = tmpcu->editfont; + copycu->editnurb = tmpcu->editnurb; + + /* get updated display list, and convert to a mesh */ + BKE_displist_make_curveTypes_forRender( + depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, render, NULL); + + copycu->editfont = NULL; + copycu->editnurb = NULL; + + tmpobj->runtime.mesh_eval = me_eval_final; + + /* convert object type to mesh */ + uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0; + BKE_mesh_from_nurbs_displist( + bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true); + /* Function above also frees copycu (aka tmpobj->data), make this obvious here. */ + copycu = NULL; + + tmpmesh = tmpobj->data; + id_us_min( + &tmpmesh->id); /* Gets one user from its creation in BKE_mesh_from_nurbs_displist(). */ + + BKE_displist_free(&dispbase); + + /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked. + * if it didn't the curve did not have any segments or otherwise + * would have generated an empty mesh */ + if (tmpobj->type != OB_MESH) { + BKE_id_free(NULL, tmpobj); + return NULL; + } + + BKE_id_free(NULL, tmpobj); + + /* XXX The curve to mesh conversion is convoluted... But essentially, BKE_mesh_from_nurbs_displist() + * already transfers the ownership of materials from the temp copy of the Curve ID to the new + * Mesh ID, so we do not want to increase materials' usercount later. */ + do_mat_id_data_us = false; + + break; + } + + case OB_MBALL: { + /* metaballs don't have modifiers, so just convert to mesh */ + Object *basis_ob = BKE_mball_basis_find(sce, object_input); + /* todo, re-generatre for render-res */ + /* metaball_polygonize(scene, ob) */ + + if (basis_ob != object_input) { + /* Only do basis metaball. */ + return NULL; + } + + tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2); + /* BKE_mesh_add gives us a user count we don't need */ + id_us_min(&tmpmesh->id); + + if (render) { + ListBase disp = {NULL, NULL}; + BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp); + BKE_mesh_from_metaball(&disp, tmpmesh); + BKE_displist_free(&disp); + } + else { + ListBase disp = {NULL, NULL}; + if (object_for_eval.runtime.curve_cache) { + disp = object_for_eval.runtime.curve_cache->disp; + } + BKE_mesh_from_metaball(&disp, tmpmesh); + } + + BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval); + + break; + } + case OB_MESH: + /* copies object and modifiers (but not the data) */ + if (cage) { + /* copies the data (but *not* the shapekeys). */ + Mesh *mesh = object_for_eval.data; + BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0); + /* XXX BKE_mesh_copy() already handles materials usercount. */ + do_mat_id_data_us = false; + } + /* if not getting the original caged mesh, get final derived mesh */ + else { + /* Make a dummy mesh, saves copying */ + Mesh *me_eval; + CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter, + * for example, needs CD_MASK_MDEFORMVERT */ + + if (calc_undeformed) { + mask.vmask |= CD_MASK_ORCO; + } + + if (render) { + me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask); + } + else { + me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask); + } + + tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2); + BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true); + + /* Copy autosmooth settings from original mesh. */ + Mesh *me = (Mesh *)object_for_eval.data; + tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH); + tmpmesh->smoothresh = me->smoothresh; + } + + /* BKE_mesh_add/copy gives us a user count we don't need */ + id_us_min(&tmpmesh->id); + + break; + default: + /* "Object does not have geometry data") */ + return NULL; + } + + /* Copy materials to new mesh */ + switch (object_for_eval.type) { + case OB_SURF: + case OB_FONT: + case OB_CURVE: + tmpmesh->totcol = tmpcu->totcol; + + /* free old material list (if it exists) and adjust user counts */ + if (tmpcu->mat) { + for (i = tmpcu->totcol; i-- > 0;) { + /* are we an object material or data based? */ + tmpmesh->mat[i] = give_current_material(object_input, i + 1); + + if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && + tmpmesh->mat[i]) { + id_us_plus(&tmpmesh->mat[i]->id); + } + } + } + break; + + case OB_MBALL: { + MetaBall *tmpmb = (MetaBall *)object_for_eval.data; + tmpmesh->mat = MEM_dupallocN(tmpmb->mat); + tmpmesh->totcol = tmpmb->totcol; + + /* free old material list (if it exists) and adjust user counts */ + if (tmpmb->mat) { + for (i = tmpmb->totcol; i-- > 0;) { + /* are we an object material or data based? */ + tmpmesh->mat[i] = give_current_material(object_input, i + 1); + + if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && + tmpmesh->mat[i]) { + id_us_plus(&tmpmesh->mat[i]->id); + } + } + } + break; + } + + case OB_MESH: + if (!cage) { + Mesh *origmesh = object_for_eval.data; + tmpmesh->flag = origmesh->flag; + tmpmesh->mat = MEM_dupallocN(origmesh->mat); + tmpmesh->totcol = origmesh->totcol; + tmpmesh->smoothresh = origmesh->smoothresh; + if (origmesh->mat) { + for (i = origmesh->totcol; i-- > 0;) { + /* are we an object material or data based? */ + tmpmesh->mat[i] = give_current_material(object_input, i + 1); + + if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) && + tmpmesh->mat[i]) { + id_us_plus(&tmpmesh->mat[i]->id); + } + } + } + } + break; + } /* end copy materials */ + + return tmpmesh; } - static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src) { - KeyBlock *kb; - Key *key = mesh_src->key; - int i; - - if (!mesh_src->key) - return; - - /* ensure we can use mesh vertex count for derived mesh custom data */ - if (mesh_src->totvert != mesh_dest->totvert) { - CLOG_ERROR(&LOG, "vertex size mismatch (mesh/dm) '%s' (%d != %d)", - mesh_src->id.name + 2, mesh_src->totvert, mesh_dest->totvert); - return; - } - - for (i = 0, kb = key->block.first; kb; kb = kb->next, i++) { - int ci; - float *array; - - if (mesh_src->totvert != kb->totelem) { - CLOG_ERROR(&LOG, "vertex size mismatch (Mesh '%s':%d != KeyBlock '%s':%d)", - mesh_src->id.name + 2, mesh_src->totvert, kb->name, kb->totelem); - array = MEM_calloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__); - } - else { - array = MEM_malloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__); - memcpy(array, kb->data, (size_t)mesh_src->totvert * 3 * sizeof(float)); - } - - CustomData_add_layer_named(&mesh_dest->vdata, CD_SHAPEKEY, CD_ASSIGN, array, mesh_dest->totvert, kb->name); - ci = CustomData_get_layer_index_n(&mesh_dest->vdata, CD_SHAPEKEY, i); - - mesh_dest->vdata.layers[ci].uid = kb->uid; - } + KeyBlock *kb; + Key *key = mesh_src->key; + int i; + + if (!mesh_src->key) + return; + + /* ensure we can use mesh vertex count for derived mesh custom data */ + if (mesh_src->totvert != mesh_dest->totvert) { + CLOG_ERROR(&LOG, + "vertex size mismatch (mesh/dm) '%s' (%d != %d)", + mesh_src->id.name + 2, + mesh_src->totvert, + mesh_dest->totvert); + return; + } + + for (i = 0, kb = key->block.first; kb; kb = kb->next, i++) { + int ci; + float *array; + + if (mesh_src->totvert != kb->totelem) { + CLOG_ERROR(&LOG, + "vertex size mismatch (Mesh '%s':%d != KeyBlock '%s':%d)", + mesh_src->id.name + 2, + mesh_src->totvert, + kb->name, + kb->totelem); + array = MEM_calloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__); + } + else { + array = MEM_malloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__); + memcpy(array, kb->data, (size_t)mesh_src->totvert * 3 * sizeof(float)); + } + + CustomData_add_layer_named( + &mesh_dest->vdata, CD_SHAPEKEY, CD_ASSIGN, array, mesh_dest->totvert, kb->name); + ci = CustomData_get_layer_index_n(&mesh_dest->vdata, CD_SHAPEKEY, i); + + mesh_dest->vdata.layers[ci].uid = kb->uid; + } } - -Mesh *BKE_mesh_create_derived_for_modifier( - struct Depsgraph *depsgraph, Scene *scene, Object *ob, - ModifierData *md, int build_shapekey_layers) +Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, + Scene *scene, + Object *ob, + ModifierData *md, + int build_shapekey_layers) { - Mesh *me = ob->runtime.mesh_orig ? ob->runtime.mesh_orig : ob->data; - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - Mesh *result; - KeyBlock *kb; - ModifierEvalContext mectx = {depsgraph, ob, 0}; + Mesh *me = ob->runtime.mesh_orig ? ob->runtime.mesh_orig : ob->data; + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + Mesh *result; + KeyBlock *kb; + ModifierEvalContext mectx = {depsgraph, ob, 0}; - if (!(md->mode & eModifierMode_Realtime)) { - return NULL; - } + if (!(md->mode & eModifierMode_Realtime)) { + return NULL; + } - if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { - return NULL; - } + if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { + return NULL; + } - if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) { - BKE_keyblock_convert_to_mesh(kb, me); - } + if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) { + BKE_keyblock_convert_to_mesh(kb, me); + } - if (mti->type == eModifierTypeType_OnlyDeform) { - int numVerts; - float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts); + if (mti->type == eModifierTypeType_OnlyDeform) { + int numVerts; + float(*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts); - mti->deformVerts(md, &mectx, NULL, deformedVerts, numVerts); - BKE_id_copy_ex(NULL, &me->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); - BKE_mesh_apply_vert_coords(result, deformedVerts); + mti->deformVerts(md, &mectx, NULL, deformedVerts, numVerts); + BKE_id_copy_ex(NULL, &me->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); + BKE_mesh_apply_vert_coords(result, deformedVerts); - if (build_shapekey_layers) - add_shapekey_layers(result, me); + if (build_shapekey_layers) + add_shapekey_layers(result, me); - MEM_freeN(deformedVerts); - } - else { - Mesh *mesh_temp; - BKE_id_copy_ex(NULL, &me->id, (ID **)&mesh_temp, LIB_ID_COPY_LOCALIZE); + MEM_freeN(deformedVerts); + } + else { + Mesh *mesh_temp; + BKE_id_copy_ex(NULL, &me->id, (ID **)&mesh_temp, LIB_ID_COPY_LOCALIZE); - if (build_shapekey_layers) - add_shapekey_layers(mesh_temp, me); + if (build_shapekey_layers) + add_shapekey_layers(mesh_temp, me); - result = mti->applyModifier(md, &mectx, mesh_temp); - ASSERT_IS_VALID_MESH(result); + result = mti->applyModifier(md, &mectx, mesh_temp); + ASSERT_IS_VALID_MESH(result); - if (mesh_temp != result) { - BKE_id_free(NULL, mesh_temp); - } - } + if (mesh_temp != result) { + BKE_id_free(NULL, mesh_temp); + } + } - return result; + return result; } /* This is a Mesh-based copy of the same function in DerivedMesh.c */ static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid) { - KeyBlock *kb; - int i, j, tot; - - if (!mesh_dst->key) - return; - - tot = CustomData_number_of_layers(&mesh_src->vdata, CD_SHAPEKEY); - for (i = 0; i < tot; i++) { - CustomDataLayer *layer = &mesh_src->vdata.layers[CustomData_get_layer_index_n(&mesh_src->vdata, CD_SHAPEKEY, i)]; - float (*cos)[3], (*kbcos)[3]; - - for (kb = mesh_dst->key->block.first; kb; kb = kb->next) { - if (kb->uid == layer->uid) - break; - } - - if (!kb) { - kb = BKE_keyblock_add(mesh_dst->key, layer->name); - kb->uid = layer->uid; - } - - if (kb->data) - MEM_freeN(kb->data); - - cos = CustomData_get_layer_n(&mesh_src->vdata, CD_SHAPEKEY, i); - kb->totelem = mesh_src->totvert; - - kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), __func__); - if (kb->uid == actshape_uid) { - MVert *mvert = mesh_src->mvert; - - for (j = 0; j < mesh_src->totvert; j++, kbcos++, mvert++) { - copy_v3_v3(*kbcos, mvert->co); - } - } - else { - for (j = 0; j < kb->totelem; j++, cos++, kbcos++) { - copy_v3_v3(*kbcos, *cos); - } - } - } - - for (kb = mesh_dst->key->block.first; kb; kb = kb->next) { - if (kb->totelem != mesh_src->totvert) { - if (kb->data) - MEM_freeN(kb->data); - - kb->totelem = mesh_src->totvert; - kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), __func__); - CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name); - } - } + KeyBlock *kb; + int i, j, tot; + + if (!mesh_dst->key) + return; + + tot = CustomData_number_of_layers(&mesh_src->vdata, CD_SHAPEKEY); + for (i = 0; i < tot; i++) { + CustomDataLayer *layer = + &mesh_src->vdata.layers[CustomData_get_layer_index_n(&mesh_src->vdata, CD_SHAPEKEY, i)]; + float(*cos)[3], (*kbcos)[3]; + + for (kb = mesh_dst->key->block.first; kb; kb = kb->next) { + if (kb->uid == layer->uid) + break; + } + + if (!kb) { + kb = BKE_keyblock_add(mesh_dst->key, layer->name); + kb->uid = layer->uid; + } + + if (kb->data) + MEM_freeN(kb->data); + + cos = CustomData_get_layer_n(&mesh_src->vdata, CD_SHAPEKEY, i); + kb->totelem = mesh_src->totvert; + + kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), __func__); + if (kb->uid == actshape_uid) { + MVert *mvert = mesh_src->mvert; + + for (j = 0; j < mesh_src->totvert; j++, kbcos++, mvert++) { + copy_v3_v3(*kbcos, mvert->co); + } + } + else { + for (j = 0; j < kb->totelem; j++, cos++, kbcos++) { + copy_v3_v3(*kbcos, *cos); + } + } + } + + for (kb = mesh_dst->key->block.first; kb; kb = kb->next) { + if (kb->totelem != mesh_src->totvert) { + if (kb->data) + MEM_freeN(kb->data); + + kb->totelem = mesh_src->totvert; + kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), __func__); + CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name); + } + } } - /* This is a Mesh-based copy of DM_to_mesh() */ -void BKE_mesh_nomain_to_mesh( - Mesh *mesh_src, Mesh *mesh_dst, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership) +void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, + Mesh *mesh_dst, + Object *ob, + const CustomData_MeshMasks *mask, + bool take_ownership) { - /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */ - /* TODO(Sybren): the above claim came from DM_to_mesh(); check whether it is still true with Mesh */ - Mesh tmp = *mesh_dst; - int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; - int did_shapekeys = 0; - eCDAllocType alloctype = CD_DUPLICATE; - - if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) { - bool has_any_referenced_layers = - CustomData_has_referenced(&mesh_src->vdata) || - CustomData_has_referenced(&mesh_src->edata) || - CustomData_has_referenced(&mesh_src->ldata) || - CustomData_has_referenced(&mesh_src->fdata) || - CustomData_has_referenced(&mesh_src->pdata); - if (!has_any_referenced_layers) { - alloctype = CD_ASSIGN; - } - } - CustomData_reset(&tmp.vdata); - CustomData_reset(&tmp.edata); - CustomData_reset(&tmp.fdata); - CustomData_reset(&tmp.ldata); - CustomData_reset(&tmp.pdata); - - BKE_mesh_ensure_normals(mesh_src); - - totvert = tmp.totvert = mesh_src->totvert; - totedge = tmp.totedge = mesh_src->totedge; - totloop = tmp.totloop = mesh_src->totloop; - totpoly = tmp.totpoly = mesh_src->totpoly; - tmp.totface = 0; - - CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert); - CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge); - CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop); - CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly); - tmp.cd_flag = mesh_src->cd_flag; - tmp.runtime.deformed_only = mesh_src->runtime.deformed_only; - - if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) { - KeyBlock *kb; - int uid; - - if (ob) { - kb = BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1); - if (kb) { - uid = kb->uid; - } - else { - CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1); - - uid = INT_MAX; - } - } - else { - /* if no object, set to INT_MAX so we don't mess up any shapekey layers */ - uid = INT_MAX; - } - - shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid); - did_shapekeys = 1; - } - - /* copy texture space */ - if (ob) { - BKE_mesh_texspace_copy_from_object(&tmp, ob); - } - - /* not all DerivedMeshes store their verts/edges/faces in CustomData, so - * we set them here in case they are missing */ - /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and always directly pass mesh_src->mxxx, - * instead of using a ternary operator. */ - if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) { - CustomData_add_layer( - &tmp.vdata, CD_MVERT, CD_ASSIGN, - (alloctype == CD_ASSIGN) ? mesh_src->mvert : MEM_dupallocN(mesh_src->mvert), - totvert); - } - if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) { - CustomData_add_layer( - &tmp.edata, CD_MEDGE, CD_ASSIGN, - (alloctype == CD_ASSIGN) ? mesh_src->medge : MEM_dupallocN(mesh_src->medge), - totedge); - } - if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { - /* TODO(Sybren): assignment to tmp.mxxx is probably not necessary due to the - * BKE_mesh_update_customdata_pointers() call below. */ - tmp.mloop = (alloctype == CD_ASSIGN) ? mesh_src->mloop : MEM_dupallocN(mesh_src->mloop); - tmp.mpoly = (alloctype == CD_ASSIGN) ? mesh_src->mpoly : MEM_dupallocN(mesh_src->mpoly); - - CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop); - CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly); - } - - /* object had got displacement layer, should copy this layer to save sculpted data */ - /* NOTE: maybe some other layers should be copied? nazgul */ - if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) { - if (totloop == mesh_dst->totloop) { - MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS); - CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop); - } - } - - /* yes, must be before _and_ after tessellate */ - BKE_mesh_update_customdata_pointers(&tmp, false); - - /* since 2.65 caller must do! */ - // BKE_mesh_tessface_calc(&tmp); - - CustomData_free(&mesh_dst->vdata, mesh_dst->totvert); - CustomData_free(&mesh_dst->edata, mesh_dst->totedge); - CustomData_free(&mesh_dst->fdata, mesh_dst->totface); - CustomData_free(&mesh_dst->ldata, mesh_dst->totloop); - CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly); - - /* ok, this should now use new CD shapekey data, - * which should be fed through the modifier - * stack */ - if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) { - CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name); - if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) { - id_us_min(&tmp.key->id); - } - tmp.key = NULL; - } - - /* Clear selection history */ - MEM_SAFE_FREE(tmp.mselect); - tmp.totselect = 0; - BLI_assert(ELEM(tmp.bb, NULL, mesh_dst->bb)); - if (mesh_dst->bb) { - MEM_freeN(mesh_dst->bb); - tmp.bb = NULL; - } - - /* skip the listbase */ - MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev); - - if (take_ownership) { - if (alloctype == CD_ASSIGN) { - CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask); - CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask); - CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask); - CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask); - } - BKE_id_free(NULL, mesh_src); - } + /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */ + /* TODO(Sybren): the above claim came from DM_to_mesh(); check whether it is still true with Mesh */ + Mesh tmp = *mesh_dst; + int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; + int did_shapekeys = 0; + eCDAllocType alloctype = CD_DUPLICATE; + + if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) { + bool has_any_referenced_layers = CustomData_has_referenced(&mesh_src->vdata) || + CustomData_has_referenced(&mesh_src->edata) || + CustomData_has_referenced(&mesh_src->ldata) || + CustomData_has_referenced(&mesh_src->fdata) || + CustomData_has_referenced(&mesh_src->pdata); + if (!has_any_referenced_layers) { + alloctype = CD_ASSIGN; + } + } + CustomData_reset(&tmp.vdata); + CustomData_reset(&tmp.edata); + CustomData_reset(&tmp.fdata); + CustomData_reset(&tmp.ldata); + CustomData_reset(&tmp.pdata); + + BKE_mesh_ensure_normals(mesh_src); + + totvert = tmp.totvert = mesh_src->totvert; + totedge = tmp.totedge = mesh_src->totedge; + totloop = tmp.totloop = mesh_src->totloop; + totpoly = tmp.totpoly = mesh_src->totpoly; + tmp.totface = 0; + + CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert); + CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge); + CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop); + CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly); + tmp.cd_flag = mesh_src->cd_flag; + tmp.runtime.deformed_only = mesh_src->runtime.deformed_only; + + if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) { + KeyBlock *kb; + int uid; + + if (ob) { + kb = BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1); + if (kb) { + uid = kb->uid; + } + else { + CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1); + + uid = INT_MAX; + } + } + else { + /* if no object, set to INT_MAX so we don't mess up any shapekey layers */ + uid = INT_MAX; + } + + shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid); + did_shapekeys = 1; + } + + /* copy texture space */ + if (ob) { + BKE_mesh_texspace_copy_from_object(&tmp, ob); + } + + /* not all DerivedMeshes store their verts/edges/faces in CustomData, so + * we set them here in case they are missing */ + /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and always directly pass mesh_src->mxxx, + * instead of using a ternary operator. */ + if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) { + CustomData_add_layer(&tmp.vdata, + CD_MVERT, + CD_ASSIGN, + (alloctype == CD_ASSIGN) ? mesh_src->mvert : + MEM_dupallocN(mesh_src->mvert), + totvert); + } + if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) { + CustomData_add_layer(&tmp.edata, + CD_MEDGE, + CD_ASSIGN, + (alloctype == CD_ASSIGN) ? mesh_src->medge : + MEM_dupallocN(mesh_src->medge), + totedge); + } + if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { + /* TODO(Sybren): assignment to tmp.mxxx is probably not necessary due to the + * BKE_mesh_update_customdata_pointers() call below. */ + tmp.mloop = (alloctype == CD_ASSIGN) ? mesh_src->mloop : MEM_dupallocN(mesh_src->mloop); + tmp.mpoly = (alloctype == CD_ASSIGN) ? mesh_src->mpoly : MEM_dupallocN(mesh_src->mpoly); + + CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop); + CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly); + } + + /* object had got displacement layer, should copy this layer to save sculpted data */ + /* NOTE: maybe some other layers should be copied? nazgul */ + if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) { + if (totloop == mesh_dst->totloop) { + MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS); + CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop); + } + } + + /* yes, must be before _and_ after tessellate */ + BKE_mesh_update_customdata_pointers(&tmp, false); + + /* since 2.65 caller must do! */ + // BKE_mesh_tessface_calc(&tmp); + + CustomData_free(&mesh_dst->vdata, mesh_dst->totvert); + CustomData_free(&mesh_dst->edata, mesh_dst->totedge); + CustomData_free(&mesh_dst->fdata, mesh_dst->totface); + CustomData_free(&mesh_dst->ldata, mesh_dst->totloop); + CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly); + + /* ok, this should now use new CD shapekey data, + * which should be fed through the modifier + * stack */ + if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) { + CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name); + if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) { + id_us_min(&tmp.key->id); + } + tmp.key = NULL; + } + + /* Clear selection history */ + MEM_SAFE_FREE(tmp.mselect); + tmp.totselect = 0; + BLI_assert(ELEM(tmp.bb, NULL, mesh_dst->bb)); + if (mesh_dst->bb) { + MEM_freeN(mesh_dst->bb); + tmp.bb = NULL; + } + + /* skip the listbase */ + MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev); + + if (take_ownership) { + if (alloctype == CD_ASSIGN) { + CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask); + CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask); + CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask); + CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask); + } + BKE_id_free(NULL, mesh_src); + } } /* This is a Mesh-based copy of DM_to_meshkey() */ void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb) { - int a, totvert = mesh_src->totvert; - float *fp; - MVert *mvert; + int a, totvert = mesh_src->totvert; + float *fp; + MVert *mvert; - if (totvert == 0 || mesh_dst->totvert == 0 || mesh_dst->totvert != totvert) { - return; - } + if (totvert == 0 || mesh_dst->totvert == 0 || mesh_dst->totvert != totvert) { + return; + } - if (kb->data) MEM_freeN(kb->data); - kb->data = MEM_malloc_arrayN(mesh_dst->key->elemsize, mesh_dst->totvert, "kb->data"); - kb->totelem = totvert; + if (kb->data) + MEM_freeN(kb->data); + kb->data = MEM_malloc_arrayN(mesh_dst->key->elemsize, mesh_dst->totvert, "kb->data"); + kb->totelem = totvert; - fp = kb->data; - mvert = mesh_src->mvert; + fp = kb->data; + mvert = mesh_src->mvert; - for (a = 0; a < kb->totelem; a++, fp += 3, mvert++) { - copy_v3_v3(fp, mvert->co); - } + for (a = 0; a < kb->totelem; a++, fp += 3, mvert++) { + copy_v3_v3(fp, mvert->co); + } } |