diff options
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_tessellate.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_tessellate.c | 364 |
1 files changed, 0 insertions, 364 deletions
diff --git a/source/blender/blenkernel/intern/mesh_tessellate.c b/source/blender/blenkernel/intern/mesh_tessellate.c index 71d5722cb0e..173fb98912b 100644 --- a/source/blender/blenkernel/intern/mesh_tessellate.c +++ b/source/blender/blenkernel/intern/mesh_tessellate.c @@ -32,370 +32,6 @@ #define MESH_FACE_TESSELLATE_THREADED_LIMIT 4096 /* -------------------------------------------------------------------- */ -/** \name MFace Tessellation - * - * #MFace is a legacy data-structure that should be avoided, use #MLoopTri instead. - * \{ */ - -/** - * Convert all CD layers from loop/poly to tessface data. - * - * \param loopindices: is an array of an int[4] per tessface, - * mapping tessface's verts to loops indices. - * - * \note when mface is not NULL, mface[face_index].v4 - * is used to test quads, else, loopindices[face_index][3] is used. - */ -static void mesh_loops_to_tessdata(CustomData *fdata, - CustomData *ldata, - MFace *mface, - const int *polyindices, - uint (*loopindices)[4], - const int num_faces) -{ - /* NOTE(mont29): performances are sub-optimal when we get a NULL #MFace, - * we could be ~25% quicker with dedicated code. - * The issue is, unless having two different functions with nearly the same code, - * there's not much ways to solve this. Better IMHO to live with it for now (sigh). */ - const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV); - const int numCol = CustomData_number_of_layers(ldata, CD_PROP_BYTE_COLOR); - const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL); - const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP); - const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL); - const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT); - int findex, i, j; - const int *pidx; - uint(*lidx)[4]; - - for (i = 0; i < numUV; i++) { - MTFace *texface = CustomData_get_layer_n(fdata, CD_MTFACE, i); - const MLoopUV *mloopuv = CustomData_get_layer_n(ldata, CD_MLOOPUV, i); - - for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces; - pidx++, lidx++, findex++, texface++) { - for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) { - copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv); - } - } - } - - for (i = 0; i < numCol; i++) { - MCol(*mcol)[4] = CustomData_get_layer_n(fdata, CD_MCOL, i); - const MLoopCol *mloopcol = CustomData_get_layer_n(ldata, CD_PROP_BYTE_COLOR, i); - - for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) { - for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) { - MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]); - } - } - } - - if (hasPCol) { - MCol(*mcol)[4] = CustomData_get_layer(fdata, CD_PREVIEW_MCOL); - const MLoopCol *mloopcol = CustomData_get_layer(ldata, CD_PREVIEW_MLOOPCOL); - - for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) { - for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) { - MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]); - } - } - } - - if (hasOrigSpace) { - OrigSpaceFace *of = CustomData_get_layer(fdata, CD_ORIGSPACE); - const OrigSpaceLoop *lof = CustomData_get_layer(ldata, CD_ORIGSPACE_MLOOP); - - for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) { - for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) { - copy_v2_v2(of->uv[j], lof[(*lidx)[j]].uv); - } - } - } - - if (hasLoopNormal) { - short(*fnors)[4][3] = CustomData_get_layer(fdata, CD_TESSLOOPNORMAL); - const float(*lnors)[3] = CustomData_get_layer(ldata, CD_NORMAL); - - for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, fnors++) { - for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) { - normal_float_to_short_v3((*fnors)[j], lnors[(*lidx)[j]]); - } - } - } - - if (hasLoopTangent) { - /* Need to do for all UV maps at some point. */ - float(*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT); - const float(*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT); - - for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces; - pidx++, lidx++, findex++) { - int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; - for (j = nverts; j--;) { - copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]); - } - } - } -} - -static int mesh_tessface_calc(CustomData *fdata, - CustomData *ldata, - CustomData *pdata, - MVert *mvert, - int totface, - int totloop, - int totpoly) -{ -#define USE_TESSFACE_SPEEDUP -#define USE_TESSFACE_QUADS - -/* We abuse #MFace.edcode to tag quad faces. See below for details. */ -#define TESSFACE_IS_QUAD 1 - - const int looptri_num = poly_to_tri_count(totpoly, totloop); - - const MPoly *mp, *mpoly; - const MLoop *ml, *mloop; - MFace *mface, *mf; - MemArena *arena = NULL; - int *mface_to_poly_map; - uint(*lindices)[4]; - int poly_index, mface_index; - uint j; - - mpoly = CustomData_get_layer(pdata, CD_MPOLY); - mloop = CustomData_get_layer(ldata, CD_MLOOP); - - /* Allocate the length of `totfaces`, avoid many small reallocation's, - * if all faces are triangles it will be correct, `quads == 2x` allocations. */ - /* Take care since memory is _not_ zeroed so be sure to initialize each field. */ - mface_to_poly_map = MEM_malloc_arrayN((size_t)looptri_num, sizeof(*mface_to_poly_map), __func__); - mface = MEM_malloc_arrayN((size_t)looptri_num, sizeof(*mface), __func__); - lindices = MEM_malloc_arrayN((size_t)looptri_num, sizeof(*lindices), __func__); - - mface_index = 0; - mp = mpoly; - for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) { - const uint mp_loopstart = (uint)mp->loopstart; - const uint mp_totloop = (uint)mp->totloop; - uint l1, l2, l3, l4; - uint *lidx; - if (mp_totloop < 3) { - /* Do nothing. */ - } - -#ifdef USE_TESSFACE_SPEEDUP - -# define ML_TO_MF(i1, i2, i3) \ - mface_to_poly_map[mface_index] = poly_index; \ - mf = &mface[mface_index]; \ - lidx = lindices[mface_index]; \ - /* Set loop indices, transformed to vert indices later. */ \ - l1 = mp_loopstart + i1; \ - l2 = mp_loopstart + i2; \ - l3 = mp_loopstart + i3; \ - mf->v1 = mloop[l1].v; \ - mf->v2 = mloop[l2].v; \ - mf->v3 = mloop[l3].v; \ - mf->v4 = 0; \ - lidx[0] = l1; \ - lidx[1] = l2; \ - lidx[2] = l3; \ - lidx[3] = 0; \ - mf->mat_nr = mp->mat_nr; \ - mf->flag = mp->flag; \ - mf->edcode = 0; \ - (void)0 - -/* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */ -# define ML_TO_MF_QUAD() \ - mface_to_poly_map[mface_index] = poly_index; \ - mf = &mface[mface_index]; \ - lidx = lindices[mface_index]; \ - /* Set loop indices, transformed to vert indices later. */ \ - l1 = mp_loopstart + 0; /* EXCEPTION */ \ - l2 = mp_loopstart + 1; /* EXCEPTION */ \ - l3 = mp_loopstart + 2; /* EXCEPTION */ \ - l4 = mp_loopstart + 3; /* EXCEPTION */ \ - mf->v1 = mloop[l1].v; \ - mf->v2 = mloop[l2].v; \ - mf->v3 = mloop[l3].v; \ - mf->v4 = mloop[l4].v; \ - lidx[0] = l1; \ - lidx[1] = l2; \ - lidx[2] = l3; \ - lidx[3] = l4; \ - mf->mat_nr = mp->mat_nr; \ - mf->flag = mp->flag; \ - mf->edcode = TESSFACE_IS_QUAD; \ - (void)0 - - else if (mp_totloop == 3) { - ML_TO_MF(0, 1, 2); - mface_index++; - } - else if (mp_totloop == 4) { -# ifdef USE_TESSFACE_QUADS - ML_TO_MF_QUAD(); - mface_index++; -# else - ML_TO_MF(0, 1, 2); - mface_index++; - ML_TO_MF(0, 2, 3); - mface_index++; -# endif - } -#endif /* USE_TESSFACE_SPEEDUP */ - else { - const float *co_curr, *co_prev; - - float normal[3]; - - float axis_mat[3][3]; - float(*projverts)[2]; - uint(*tris)[3]; - - const uint totfilltri = mp_totloop - 2; - - if (UNLIKELY(arena == NULL)) { - arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } - - tris = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri); - projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp_totloop); - - zero_v3(normal); - - /* Calculate the normal, flipped: to get a positive 2D cross product. */ - ml = mloop + mp_loopstart; - co_prev = mvert[ml[mp_totloop - 1].v].co; - for (j = 0; j < mp_totloop; j++, ml++) { - co_curr = mvert[ml->v].co; - add_newell_cross_v3_v3v3(normal, co_prev, co_curr); - co_prev = co_curr; - } - if (UNLIKELY(normalize_v3(normal) == 0.0f)) { - normal[2] = 1.0f; - } - - /* Project verts to 2D. */ - axis_dominant_v3_to_m3_negate(axis_mat, normal); - - ml = mloop + mp_loopstart; - for (j = 0; j < mp_totloop; j++, ml++) { - mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co); - } - - BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, arena); - - /* Apply fill. */ - for (j = 0; j < totfilltri; j++) { - uint *tri = tris[j]; - lidx = lindices[mface_index]; - - mface_to_poly_map[mface_index] = poly_index; - mf = &mface[mface_index]; - - /* Set loop indices, transformed to vert indices later. */ - l1 = mp_loopstart + tri[0]; - l2 = mp_loopstart + tri[1]; - l3 = mp_loopstart + tri[2]; - - mf->v1 = mloop[l1].v; - mf->v2 = mloop[l2].v; - mf->v3 = mloop[l3].v; - mf->v4 = 0; - - lidx[0] = l1; - lidx[1] = l2; - lidx[2] = l3; - lidx[3] = 0; - - mf->mat_nr = mp->mat_nr; - mf->flag = mp->flag; - mf->edcode = 0; - - mface_index++; - } - - BLI_memarena_clear(arena); - } - } - - if (arena) { - BLI_memarena_free(arena); - arena = NULL; - } - - CustomData_free(fdata, totface); - totface = mface_index; - - BLI_assert(totface <= looptri_num); - - /* Not essential but without this we store over-allocated memory in the #CustomData layers. */ - if (LIKELY(looptri_num != totface)) { - mface = MEM_reallocN(mface, sizeof(*mface) * (size_t)totface); - mface_to_poly_map = MEM_reallocN(mface_to_poly_map, - sizeof(*mface_to_poly_map) * (size_t)totface); - } - - CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface); - - /* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons - * they are directly tessellated from. */ - CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface); - CustomData_from_bmeshpoly(fdata, ldata, totface); - - /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx: - * Polygons take care of their loops ordering, hence not of their vertices ordering. - * Currently, our tfaces' fourth vertex index might be 0 even for a quad. - * However, we know our fourth loop index is never 0 for quads - * (because they are sorted for polygons, and our quads are still mere copies of their polygons). - * So we pass NULL as MFace pointer, and #mesh_loops_to_tessdata - * will use the fourth loop index as quad test. */ - mesh_loops_to_tessdata(fdata, ldata, NULL, mface_to_poly_map, lindices, totface); - - /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx: - * ...However, most TFace code uses 'MFace->v4 == 0' test to check whether it is a tri or quad. - * BKE_mesh_mface_index_validate() will check this and rotate the tessellated face if needed. - */ -#ifdef USE_TESSFACE_QUADS - mf = mface; - for (mface_index = 0; mface_index < totface; mface_index++, mf++) { - if (mf->edcode == TESSFACE_IS_QUAD) { - BKE_mesh_mface_index_validate(mf, fdata, mface_index, 4); - mf->edcode = 0; - } - } -#endif - - MEM_freeN(lindices); - - return totface; - -#undef USE_TESSFACE_SPEEDUP -#undef USE_TESSFACE_QUADS - -#undef ML_TO_MF -#undef ML_TO_MF_QUAD -} - -void BKE_mesh_tessface_calc(Mesh *mesh) -{ - mesh->totface = mesh_tessface_calc(&mesh->fdata, - &mesh->ldata, - &mesh->pdata, - mesh->mvert, - mesh->totface, - mesh->totloop, - mesh->totpoly); - - BKE_mesh_update_customdata_pointers(mesh, true); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Loop Tessellation * * Fill in #MLoopTri data-structure. |