diff options
Diffstat (limited to 'source/blender/blenkernel/intern/editderivedmesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/editderivedmesh.c | 1448 |
1 files changed, 78 insertions, 1370 deletions
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index db9ce6c9b7d..27d1ad01f2d 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -49,35 +49,24 @@ #include "BLI_task.h" #include "BKE_cdderivedmesh.h" +#include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" +#include "BKE_editmesh_tangent.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" +#include "DNA_mesh_types.h" #include "MEM_guardedalloc.h" -#include "GPU_glew.h" -#include "GPU_buffers.h" -#include "GPU_shader.h" -#include "GPU_basic_shader.h" - -static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]); - typedef struct EditDerivedBMesh { DerivedMesh dm; BMEditMesh *em; - /** when set, \a vertexNos, polyNos are lazy initialized */ - const float (*vertexCos)[3]; - - /** lazy initialize (when \a vertexCos is set) */ - float const (*vertexNos)[3]; - float const (*polyNos)[3]; - /** also lazy init but dont depend on \a vertexCos */ - const float (*polyCos)[3]; + EditMeshData emd; } EditDerivedBMesh; /* -------------------------------------------------------------------- */ @@ -87,7 +76,7 @@ static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm); static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm) { - if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) { + if (bmdm->emd.vertexCos && (bmdm->emd.vertexNos == NULL)) { BMesh *bm = bmdm->em->bm; const float (*vertexCos)[3], (*polyNos)[3]; @@ -98,19 +87,19 @@ static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm) BM_mesh_elem_index_ensure(bm, BM_FACE); - polyNos = bmdm->polyNos; - vertexCos = bmdm->vertexCos; + polyNos = bmdm->emd.polyNos; + vertexCos = bmdm->emd.vertexCos; vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__); BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos); - bmdm->vertexNos = (const float (*)[3])vertexNos; + bmdm->emd.vertexNos = (const float (*)[3])vertexNos; } } static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm) { - if (bmdm->vertexCos && (bmdm->polyNos == NULL)) { + if (bmdm->emd.vertexCos && (bmdm->emd.polyNos == NULL)) { BMesh *bm = bmdm->em->bm; const float (*vertexCos)[3]; float (*polyNos)[3]; @@ -123,7 +112,7 @@ static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm) polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__); - vertexCos = bmdm->vertexCos; + vertexCos = bmdm->emd.vertexCos; BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { BM_elem_index_set(efa, i); /* set_inline */ @@ -131,13 +120,13 @@ static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm) } bm->elem_index_dirty &= ~BM_FACE; - bmdm->polyNos = (const float (*)[3])polyNos; + bmdm->emd.polyNos = (const float (*)[3])polyNos; } } static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) { - if (bmdm->polyCos == NULL) { + if (bmdm->emd.polyCos == NULL) { BMesh *bm = bmdm->em->bm; float (*polyCos)[3]; @@ -147,9 +136,9 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__); - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { const float (*vertexCos)[3]; - vertexCos = bmdm->vertexCos; + vertexCos = bmdm->emd.vertexCos; BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -163,7 +152,7 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) } } - bmdm->polyCos = (const float (*)[3])polyCos; + bmdm->emd.polyCos = (const float (*)[3])polyCos; } } @@ -199,9 +188,9 @@ static void emDM_calcLoopNormalsSpaceArray( emDM_ensurePolyNormals(bmdm); dm->dirty &= ~DM_DIRTY_NORMALS; - vertexCos = bmdm->vertexCos; - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; + vertexCos = bmdm->emd.vertexCos; + vertexNos = bmdm->emd.vertexNos; + polyNos = bmdm->emd.polyNos; loopNos = dm->getLoopDataArray(dm, CD_NORMAL); if (!loopNos) { @@ -214,7 +203,7 @@ static void emDM_calcLoopNormalsSpaceArray( cd_loop_clnors_offset = clnors_data ? -1 : CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, use_split_normals, split_angle, loopNos, - r_lnors_spacearr, clnors_data, cd_loop_clnors_offset); + r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, false); #ifdef DEBUG_CLNORS if (r_lnors_spacearr) { int i; @@ -242,392 +231,29 @@ static void emDM_calcLoopNormalsSpaceArray( #endif } - -/** \name Tangent Space Calculation - * \{ */ - -/* Necessary complexity to handle looptri's as quads for correct tangents */ -#define USE_LOOPTRI_DETECT_QUADS - -typedef struct { - const float (*precomputedFaceNormals)[3]; - const float (*precomputedLoopNormals)[3]; - const BMLoop *(*looptris)[3]; - int cd_loop_uv_offset; /* texture coordinates */ - const float (*orco)[3]; - float (*tangent)[4]; /* destination */ - int numTessFaces; - -#ifdef USE_LOOPTRI_DETECT_QUADS - /* map from 'fake' face index to looptri, - * quads will point to the first looptri of the quad */ - const int *face_as_quad_map; - int num_face_as_quad_map; -#endif - -} SGLSLEditMeshToTangent; - -#ifdef USE_LOOPTRI_DETECT_QUADS -/* seems weak but only used on quads */ -static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index) -{ - const BMLoop *l = BM_FACE_FIRST_LOOP(f); - while (vert_index--) { - l = l->next; - } - return l; -} -#endif - -/* interface */ -#include "mikktspace.h" - -static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) -{ - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - -#ifdef USE_LOOPTRI_DETECT_QUADS - return pMesh->num_face_as_quad_map; -#else - return pMesh->numTessFaces; -#endif -} - -static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) -{ -#ifdef USE_LOOPTRI_DETECT_QUADS - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - if (pMesh->face_as_quad_map) { - const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - return 4; - } - } - return 3; -#else - UNUSED_VARS(pContext, face_num); - return 3; -#endif -} - -static void emdm_ts_GetPosition( - const SMikkTSpaceContext *pContext, float r_co[3], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - - const float *co; - -finally: - co = l->v->co; - copy_v3_v3(r_co, co); -} - -static void emdm_ts_GetTextureCoordinate( - const SMikkTSpaceContext *pContext, float r_uv[2], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - -finally: - if (pMesh->cd_loop_uv_offset != -1) { - const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset); - copy_v2_v2(r_uv, uv); - } - else { - const float *orco = pMesh->orco[BM_elem_index_get(l->v)]; - map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); - } -} - -static void emdm_ts_GetNormal( - const SMikkTSpaceContext *pContext, float r_no[3], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - -finally: - if (pMesh->precomputedLoopNormals) { - copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]); - } - else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */ - if (pMesh->precomputedFaceNormals) { - copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]); - } - else { - copy_v3_v3(r_no, l->f->no); - } - } - else { - copy_v3_v3(r_no, l->v->no); - } -} - -static void emdm_ts_SetTSpace( - const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - - float *pRes; - -finally: - pRes = pMesh->tangent[BM_elem_index_get(l)]; - copy_v3_v3(pRes, fvTangent); - pRes[3] = fSign; -} - -static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) -{ - struct SGLSLEditMeshToTangent *mesh2tangent = taskdata; - /* new computation method */ - { - SMikkTSpaceContext sContext = {NULL}; - SMikkTSpaceInterface sInterface = {NULL}; - sContext.m_pUserData = mesh2tangent; - sContext.m_pInterface = &sInterface; - sInterface.m_getNumFaces = emdm_ts_GetNumFaces; - sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace; - sInterface.m_getPosition = emdm_ts_GetPosition; - sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate; - sInterface.m_getNormal = emdm_ts_GetNormal; - sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace; - /* 0 if failed */ - genTangSpaceDefault(&sContext); - } -} - -/** - * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data. - * - * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`. - * This is done because #CD_TANGENT is cache data used only for drawing. - */ - static void emDM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], int tangent_names_count) + const char (*tangent_names)[MAX_NAME], int tangent_names_len) { EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; BMEditMesh *em = bmdm->em; - BMesh *bm = bmdm->em->bm; - - int act_uv_n = -1; - int ren_uv_n = -1; - bool calc_act = false; - bool calc_ren = false; - char act_uv_name[MAX_NAME]; - char ren_uv_name[MAX_NAME]; - short tangent_mask = 0; - - DM_calc_loop_tangents_step_0( - &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count, - &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); - - if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) { - for (int i = 0; i < tangent_names_count; i++) - if (tangent_names[i][0]) - DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]); - if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1) - CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, ""); - if (calc_act && act_uv_name[0]) - DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name); - if (calc_ren && ren_uv_name[0]) - DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, ren_uv_name); - int totface = em->tottri; -#ifdef USE_LOOPTRI_DETECT_QUADS - int num_face_as_quad_map; - int *face_as_quad_map = NULL; - - /* map faces to quads */ - if (bmdm->em->tottri != bm->totface) { - /* over alloc, since we dont know how many ngon or quads we have */ - - /* map fake face index to looptri */ - face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__); - int i, j; - for (i = 0, j = 0; j < totface; i++, j++) { - face_as_quad_map[i] = j; - /* step over all quads */ - if (em->looptris[j][0]->f->len == 4) { - j++; /* skips the nest looptri */ - } - } - num_face_as_quad_map = i; - } - else { - num_face_as_quad_map = totface; - } -#endif - /* Calculation */ - { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL); - - dm->tangent_mask = 0; - /* Calculate tangent layers */ - SGLSLEditMeshToTangent data_array[MAX_MTFACE]; - int index = 0; - int n = 0; - CustomData_update_typemap(&dm->loopData); - const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT); - for (n = 0; n < tangent_layer_num; n++) { - index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n); - BLI_assert(n < MAX_MTFACE); - SGLSLEditMeshToTangent *mesh2tangent = &data_array[n]; - mesh2tangent->numTessFaces = em->tottri; -#ifdef USE_LOOPTRI_DETECT_QUADS - mesh2tangent->face_as_quad_map = face_as_quad_map; - mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; -#endif - mesh2tangent->precomputedFaceNormals = bmdm->polyNos; /* dm->getPolyDataArray(dm, CD_NORMAL) */ - /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled), - * have to check this is valid... - */ - mesh2tangent->precomputedLoopNormals = CustomData_get_layer(&dm->loopData, CD_NORMAL); - mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n); - - /* needed for indexing loop-tangents */ - int htype_index = BM_LOOP; - if (mesh2tangent->cd_loop_uv_offset == -1) { - mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO); - if (!mesh2tangent->orco) - continue; - /* needed for orco lookups */ - htype_index |= BM_VERT; - dm->tangent_mask |= DM_TANGENT_MASK_ORCO; - } - else { - /* Fill the resulting tangent_mask */ - int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name); - int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV); - BLI_assert(uv_ind != -1 && uv_start != -1); - BLI_assert(uv_ind - uv_start < MAX_MTFACE); - dm->tangent_mask |= 1 << (uv_ind - uv_start); - } - - if (mesh2tangent->precomputedFaceNormals) { - /* needed for face normal lookups */ - htype_index |= BM_FACE; - } - BM_mesh_elem_index_ensure(bm, htype_index); - - mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris; - mesh2tangent->tangent = dm->loopData.layers[index].data; - BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); - } - - BLI_assert(dm->tangent_mask == tangent_mask); - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - } -#ifdef USE_LOOPTRI_DETECT_QUADS - if (face_as_quad_map) { - MEM_freeN(face_as_quad_map); - } -#undef USE_LOOPTRI_DETECT_QUADS -#endif + if (CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV) == 0) { + return; } - /* Update active layer index */ - int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n); - if (act_uv_index >= 0) { - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name); - CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); - } /* else tangent has been built from orco */ - - /* Update render layer index */ - int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n); - if (ren_uv_index >= 0) { - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name); - CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); - } /* else tangent has been built from orco */ + const float (*poly_normals)[3] = bmdm->emd.polyNos; + const float (*loop_normals)[3] = CustomData_get_layer(&dm->loopData, CD_NORMAL); + const float (*vert_orco)[3] = dm->getVertDataArray(dm, CD_ORCO); /* can be NULL */ + BKE_editmesh_loop_tangent_calc( + em, calc_active_tangent, + tangent_names, tangent_names_len, + poly_normals, loop_normals, + vert_orco, + &dm->loopData, dm->numLoopData, + &dm->tangent_mask); } -/** \} */ - static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm)) { @@ -680,13 +306,13 @@ static void emDM_foreachMappedVert( BMIter iter; int i; - if (bmdm->vertexCos) { - const float (*vertexCos)[3] = bmdm->vertexCos; + if (bmdm->emd.vertexCos) { + const float (*vertexCos)[3] = bmdm->emd.vertexCos; const float (*vertexNos)[3]; if (flag & DM_FOREACH_USE_NORMAL) { emDM_ensureVertNormals(bmdm); - vertexNos = bmdm->vertexNos; + vertexNos = bmdm->emd.vertexNos; } else { vertexNos = NULL; @@ -715,14 +341,14 @@ static void emDM_foreachMappedEdge( BMIter iter; int i; - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { BM_mesh_elem_index_ensure(bm, BM_VERT); BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { func(userData, i, - bmdm->vertexCos[BM_elem_index_get(eed->v1)], - bmdm->vertexCos[BM_elem_index_get(eed->v2)]); + bmdm->emd.vertexCos[BM_elem_index_get(eed->v1)], + bmdm->emd.vertexCos[BM_elem_index_get(eed->v2)]); } } else { @@ -732,123 +358,6 @@ static void emDM_foreachMappedEdge( } } -static void emDM_drawMappedEdges( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMesh *bm = bmdm->em->bm; - BMEdge *eed; - BMIter iter; - int i; - - if (bmdm->vertexCos) { - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]); - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]); - } - } - glEnd(); - } - else { - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} -static void emDM_drawEdges( - DerivedMesh *dm, - bool UNUSED(drawLooseEdges), - bool UNUSED(drawAllEdges)) -{ - emDM_drawMappedEdges(dm, NULL, NULL); -} - -static void emDM_drawMappedEdgesInterp( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetDrawInterpOptions setDrawInterpOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMesh *bm = bmdm->em->bm; - BMEdge *eed; - BMIter iter; - int i; - - if (bmdm->vertexCos) { - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]); - } - } - glEnd(); - } - else { - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(eed->v1->co); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} - -static void emDM_drawUVEdges(DerivedMesh *dm) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMesh *bm = bmdm->em->bm; - BMFace *efa; - BMIter iter; - - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - - if (UNLIKELY(cd_loop_uv_offset == -1)) { - return; - } - - glBegin(GL_LINES); - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - const float *uv, *uv_prev; - - if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) - continue; - - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv; - do { - uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv; - glVertex2fv(uv); - glVertex2fv(uv_prev); - uv_prev = uv; - } while ((l_iter = l_iter->next) != l_first); - } - glEnd(); -} - static void emDM_foreachMappedLoop( DerivedMesh *dm, void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]), @@ -864,7 +373,7 @@ static void emDM_foreachMappedLoop( BMFace *efa; BMIter iter; - const float (*vertexCos)[3] = bmdm->vertexCos; + const float (*vertexCos)[3] = bmdm->emd.vertexCos; int f_idx; BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -897,11 +406,11 @@ static void emDM_foreachMappedFaceCenter( int i; emDM_ensurePolyCenters(bmdm); - polyCos = bmdm->polyCos; /* always set */ + polyCos = bmdm->emd.polyCos; /* always set */ if (flag & DM_FOREACH_USE_NORMAL) { emDM_ensurePolyNormals(bmdm); - polyNos = bmdm->polyNos; /* maybe NULL */ + polyNos = bmdm->emd.polyNos; /* maybe NULL */ } else { polyNos = NULL; @@ -921,783 +430,6 @@ static void emDM_foreachMappedFaceCenter( } } -static void emDM_drawMappedFaces( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetMaterial setMaterial, - /* currently unused -- each original face is handled separately */ - DMCompareDrawOptions UNUSED(compareDrawOptions), - void *userData, - DMDrawFlag flag) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - BMFace *efa; - struct BMLoop *(*looptris)[3] = bmdm->em->looptris; - const int tottri = bmdm->em->tottri; - DMDrawOption draw_option; - int i; - const int skip_normals = !(flag & DM_DRAW_NEED_NORMALS); - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */; - unsigned char(*color_vert_array)[4] = em->derivedVertColor; - unsigned char(*color_face_array)[4] = em->derivedFaceColor; - bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals; - bool has_fcol_preview = (color_face_array != NULL) && !skip_normals; - bool has_vcol_any = has_vcol_preview; - - /* GL_ZERO is used to detect if drawing has started or not */ - GLenum poly_prev = GL_ZERO; - GLenum shade_prev = GL_ZERO; - DMDrawOption draw_option_prev = DM_DRAW_OPTION_SKIP; - - /* call again below is ok */ - if (has_vcol_preview) { - BM_mesh_elem_index_ensure(bm, BM_VERT); - } - if (has_fcol_preview) { - BM_mesh_elem_index_ensure(bm, BM_FACE); - } - if (has_vcol_preview || has_fcol_preview) { - flag |= DM_DRAW_ALWAYS_SMOOTH; - /* weak, this logic should really be moved higher up */ - setMaterial = NULL; - } - - if (bmdm->vertexCos) { - short prev_mat_nr = -1; - - /* add direct access */ - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - - if (skip_normals) { - vertexNos = NULL; - polyNos = NULL; - } - else { - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - } - - BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE); - - for (i = 0; i < tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH)); - - draw_option = (!setDrawOptions ? - DM_DRAW_OPTION_NORMAL : - setDrawOptions(userData, BM_elem_index_get(efa))); - if (draw_option != DM_DRAW_OPTION_SKIP) { - const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ - - if (draw_option_prev != draw_option) { - if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - draw_option_prev = draw_option; - } - - - if (efa->mat_nr != prev_mat_nr) { - if (setMaterial) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - setMaterial(efa->mat_nr + 1, NULL); - } - prev_mat_nr = efa->mat_nr; - } - - if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ - - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - } - - if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)])); - if (skip_normals) { - if (poly_type != poly_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - else { - const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT; - if (shade_type != shade_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */ - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - if (poly_type != poly_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - - if (!drawSmooth) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - else { - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - } - } - } - } - else { - short prev_mat_nr = -1; - - BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE); - - for (i = 0; i < tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH)); - - draw_option = (setDrawOptions ? - setDrawOptions(userData, BM_elem_index_get(efa)) : - DM_DRAW_OPTION_NORMAL); - - if (draw_option != DM_DRAW_OPTION_SKIP) { - const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ - - if (draw_option_prev != draw_option) { - if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - draw_option_prev = draw_option; - } - - if (efa->mat_nr != prev_mat_nr) { - if (setMaterial) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - setMaterial(efa->mat_nr + 1, NULL); - } - prev_mat_nr = efa->mat_nr; - } - - if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ - - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - } - - if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)])); - - if (skip_normals) { - if (poly_type != poly_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(ltri[2]->v->co); - } - else { - const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT; - if (shade_type != shade_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */ - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - if (poly_type != poly_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - - if (!drawSmooth) { - glNormal3fv(efa->no); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(ltri[2]->v->co); - } - else { - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); - else glNormal3fv(ltri[0]->v->no); - glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); - else glNormal3fv(ltri[1]->v->no); - glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); - else glNormal3fv(ltri[2]->v->no); - glVertex3fv(ltri[2]->v->co); - } - } - } - } - } - - /* if non zero we know a face was rendered */ - if (poly_prev != GL_ZERO) glEnd(); - - if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - - if (shade_prev == GL_FLAT) { - glShadeModel(GL_SMOOTH); - } -} - -static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset) -{ - luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset); - luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset); - luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset); -} - -static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset) -{ - lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset); - lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset); - lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset); -} - -static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]) -{ - lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)]; - lcol[1] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[1]->v)]; - lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)]; -} - -static void emDM_drawFacesTex_common( - DerivedMesh *dm, - DMSetDrawOptionsTex drawParams, - DMSetDrawOptionsMappedTex drawParamsMapped, - DMCompareDrawOptions compareDrawOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - struct BMLoop *(*looptris)[3] = em->looptris; - BMFace *efa; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - MLoopUV *luv[3], dummyluv = {{0}}; - MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); - unsigned char(*color_vert_array)[4] = em->derivedVertColor; - bool has_uv = (cd_loop_uv_offset != -1); - bool has_vcol_preview = (color_vert_array != NULL); - bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false); - bool has_vcol_any = (has_vcol_preview || has_vcol); - int i; - - (void) compareDrawOptions; - - luv[0] = luv[1] = luv[2] = &dummyluv; - - // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */ - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - BM_mesh_elem_index_ensure(bm, BM_FACE); - - /* call again below is ok */ - if (has_vcol_preview) { - BM_mesh_elem_index_ensure(bm, BM_VERT); - } - - if (bmdm->vertexCos) { - /* add direct access */ - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - - BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL; - /*unsigned char *cp = NULL;*/ /*UNUSED*/ - int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH); - DMDrawOption draw_option; - - efa = ltri[0]->f; - - if (drawParams) { - draw_option = drawParams(tp, has_vcol, efa->mat_nr); - } - else if (drawParamsMapped) - draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr); - else - draw_option = DM_DRAW_OPTION_NORMAL; - - if (draw_option != DM_DRAW_OPTION_SKIP) { - - if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset); - if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset); - else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - - glBegin(GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - else { - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - glEnd(); - } - } - } - else { - BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL; - /*unsigned char *cp = NULL;*/ /*UNUSED*/ - int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH); - DMDrawOption draw_option; - - efa = ltri[0]->f; - - if (drawParams) - draw_option = drawParams(tp, has_vcol, efa->mat_nr); - else if (drawParamsMapped) - draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr); - else - draw_option = DM_DRAW_OPTION_NORMAL; - - if (draw_option != DM_DRAW_OPTION_SKIP) { - - if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset); - if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset); - else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - - glBegin(GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(efa->no); - - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(ltri[0]->v->co); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(ltri[1]->v->co); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(ltri[2]->v->co); - } - else { - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); - else glNormal3fv(ltri[0]->v->no); - glVertex3fv(ltri[0]->v->co); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); - else glNormal3fv(ltri[1]->v->no); - glVertex3fv(ltri[1]->v->co); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); - else glNormal3fv(ltri[2]->v->no); - glVertex3fv(ltri[2]->v->co); - } - glEnd(); - } - } - } -} - -static void emDM_drawFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag UNUSED(flag)) -{ - emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); -} - -static void emDM_drawMappedFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsMappedTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag UNUSED(flag)) -{ - emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); -} - -/** - * \note - * - * For UV's: - * const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); - * - * This is intentionally different to calling: - * CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i); - * - * ... because the material may use layer names to select different UV's - * see: [#34378] - */ -static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop) -{ - BMVert *eve = loop->v; - int i; - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - if (attribs->totorco) { - int index = BM_elem_index_get(eve); - const float *orco = (attribs->orco.array) ? attribs->orco.array[index] : zero; - - if (attribs->orco.gl_texco) - glTexCoord3fv(orco); - else - glVertexAttrib3fv(attribs->orco.gl_index, orco); - } - for (i = 0; i < attribs->tottface; i++) { - const float *uv; - - if (attribs->tface[i].em_offset != -1) { - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); - uv = luv->uv; - } - else { - uv = zero; - } - - if (attribs->tface[i].gl_texco) - glTexCoord2fv(uv); - else - glVertexAttrib2fv(attribs->tface[i].gl_index, uv); - } - for (i = 0; i < attribs->totmcol; i++) { - float col[4]; - if (attribs->mcol[i].em_offset != -1) { - const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset); - rgba_uchar_to_float(col, &cp->r); - } - else { - col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f; - } - glVertexAttrib4fv(attribs->mcol[i].gl_index, col); - } - - for (i = 0; i < attribs->tottang; i++) { - const float *tang; - if (attribs->tang[i].em_offset != -1) { - tang = attribs->tang[i].array[BM_elem_index_get(loop)]; - } - else { - tang = zero; - } - glVertexAttrib4fv(attribs->tang[i].gl_index, tang); - } -} - -static void emDM_drawMappedFacesGLSL( - DerivedMesh *dm, - DMSetMaterial setMaterial, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - struct BMLoop *(*looptris)[3] = em->looptris; - /* add direct access */ - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - - BMFace *efa; - DMVertexAttribs attribs; - GPUVertexAttribs gattribs; - - int i, matnr, new_matnr, fi; - bool do_draw; - - do_draw = false; - matnr = -1; - - memset(&attribs, 0, sizeof(attribs)); - - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - - BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0)); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - - if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP)) - continue; - - /* material */ - new_matnr = efa->mat_nr + 1; - if (new_matnr != matnr) { - if (matnr != -1) - glEnd(); - - do_draw = setMaterial(matnr = new_matnr, &gattribs); - if (do_draw) { - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - DM_draw_attrib_vertex_uniforms(&attribs); - if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) { - BM_mesh_elem_index_ensure(bm, BM_LOOP); - } - } - - glBegin(GL_TRIANGLES); - } - - if (do_draw) { - - /* draw face */ - drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH); - - if (!drawSmooth) { - if (vertexCos) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]); - } - } - else { - glNormal3fv(efa->no); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(ltri[fi]->v->co); - } - } - } - else { - if (vertexCos) { - for (fi = 0; fi < 3; fi++) { - const int j = BM_elem_index_get(ltri[fi]->v); - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(vertexNos[j]); - glVertex3fv(vertexCos[j]); - } - } - else { - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(ltri[fi]->v->no); - glVertex3fv(ltri[fi]->v->co); - } - } - } - } - } - - if (matnr != -1) { - glEnd(); - } -} - -static void emDM_drawFacesGLSL( - DerivedMesh *dm, - int (*setMaterial)(int matnr, void *attribs)) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - -static void emDM_drawMappedFacesMat( - DerivedMesh *dm, - void (*setMaterial)(void *userData, int matnr, void *attribs), - bool (*setFace)(void *userData, int index), void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - struct BMLoop *(*looptris)[3] = em->looptris; - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - BMFace *efa; - DMVertexAttribs attribs = {{{NULL}}}; - GPUVertexAttribs gattribs; - int i, matnr, new_matnr, fi; - - matnr = -1; - - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - - BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0)); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - - /* face hiding */ - if (setFace && !setFace(userData, BM_elem_index_get(efa))) - continue; - - /* material */ - new_matnr = efa->mat_nr + 1; - if (new_matnr != matnr) { - if (matnr != -1) - glEnd(); - - setMaterial(userData, matnr = new_matnr, &gattribs); - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) { - BM_mesh_elem_index_ensure(bm, BM_LOOP); - } - - glBegin(GL_TRIANGLES); - } - - /* draw face */ - drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH); - - if (!drawSmooth) { - if (vertexCos) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]); - } - } - else { - glNormal3fv(efa->no); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(ltri[fi]->v->co); - } - } - } - else { - if (vertexCos) { - for (fi = 0; fi < 3; fi++) { - const int j = BM_elem_index_get(ltri[fi]->v); - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(vertexNos[j]); - glVertex3fv(vertexCos[j]); - } - } - else { - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(ltri[fi]->v->no); - glVertex3fv(ltri[fi]->v->co); - } - } - } - } - - if (matnr != -1) { - glEnd(); - } -} - static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) { EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; @@ -1707,9 +439,9 @@ static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) int i; if (bm->totvert) { - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]); + minmax_v3v3_v3(r_min, r_max, bmdm->emd.vertexCos[i]); } } else { @@ -1789,8 +521,8 @@ static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert) // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */ bmvert_to_mvert(bm, ev, r_vert); - if (bmdm->vertexCos) - copy_v3_v3(r_vert->co, bmdm->vertexCos[index]); + if (bmdm->emd.vertexCos) + copy_v3_v3(r_vert->co, bmdm->emd.vertexCos[index]); } static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3]) @@ -1803,8 +535,8 @@ static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3]) return; } - if (bmdm->vertexCos) { - copy_v3_v3(r_co, bmdm->vertexCos[index]); + if (bmdm->emd.vertexCos) { + copy_v3_v3(r_co, bmdm->emd.vertexCos[index]); } else { BMVert *ev; @@ -1827,9 +559,9 @@ static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3]) } - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { emDM_ensureVertNormals(bmdm); - copy_v3_v3(r_no, bmdm->vertexNos[index]); + copy_v3_v3(r_no, bmdm->emd.vertexNos[index]); } else { BMVert *ev; @@ -1851,9 +583,9 @@ static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3]) return; } - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { emDM_ensurePolyNormals(bmdm); - copy_v3_v3(r_no, bmdm->polyNos[index]); + copy_v3_v3(r_no, bmdm->emd.polyNos[index]); } else { BMFace *efa; @@ -1928,11 +660,11 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert) BMIter iter; const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { int i; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(r_vert->co, bmdm->vertexCos[i]); + copy_v3_v3(r_vert->co, bmdm->emd.vertexCos[i]); normal_float_to_short_v3(r_vert->no, eve->no); r_vert->flag = BM_vert_flag_to_mflag(eve); @@ -2061,14 +793,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type) if (type == CD_MTFACE || type == CD_MCOL) { const char *bmdata; char *data; - bool has_type_source = false; - if (type == CD_MTFACE) { - has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY); - } - else { - has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL); - } + bool has_type_source = CustomData_has_layer(&bm->ldata, (type == CD_MTFACE) ? CD_MLOOPUV : CD_MLOOPCOL); if (has_type_source) { /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */ @@ -2084,15 +810,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type) if (type == CD_MTFACE) { const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); for (i = 0; i < bmdm->em->tottri; i++, data += size) { - BMFace *efa = looptris[i][0]->f; - - // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); - bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata)); for (j = 0; j < 3; j++) { // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV); bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset); @@ -2149,9 +868,9 @@ static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3]) BMIter iter; int i; - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(r_cos[i], bmdm->vertexCos[i]); + copy_v3_v3(r_cos[i], bmdm->emd.vertexCos[i]); } } else { @@ -2166,18 +885,18 @@ static void emDM_release(DerivedMesh *dm) EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; if (DM_release(dm)) { - if (bmdm->vertexCos) { - MEM_freeN((void *)bmdm->vertexCos); - if (bmdm->vertexNos) { - MEM_freeN((void *)bmdm->vertexNos); + if (bmdm->emd.vertexCos) { + MEM_freeN((void *)bmdm->emd.vertexCos); + if (bmdm->emd.vertexNos) { + MEM_freeN((void *)bmdm->emd.vertexNos); } - if (bmdm->polyNos) { - MEM_freeN((void *)bmdm->polyNos); + if (bmdm->emd.polyNos) { + MEM_freeN((void *)bmdm->emd.polyNos); } } - if (bmdm->polyCos) { - MEM_freeN((void *)bmdm->polyCos); + if (bmdm->emd.polyCos) { + MEM_freeN((void *)bmdm->emd.polyCos); } MEM_freeN(bmdm); @@ -2280,20 +999,9 @@ DerivedMesh *getEditDerivedBMesh( bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter; - bmdm->dm.drawEdges = emDM_drawEdges; - bmdm->dm.drawMappedEdges = emDM_drawMappedEdges; - bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; - bmdm->dm.drawMappedFaces = emDM_drawMappedFaces; - bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; - bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; - bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat; - bmdm->dm.drawFacesTex = emDM_drawFacesTex; - bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; - bmdm->dm.drawUVEdges = emDM_drawUVEdges; - bmdm->dm.release = emDM_release; - bmdm->vertexCos = (const float (*)[3])vertexCos; + bmdm->emd.vertexCos = (const float (*)[3])vertexCos; bmdm->dm.deformedOnly = (vertexCos != NULL); const int cd_dvert_offset = (data_mask & CD_MASK_MDEFORMVERT) ? @@ -2375,7 +1083,7 @@ static void statvis_calc_overhang( /* fallback max */ { float fcol[3]; - weight_to_rgb(fcol, 1.0f); + BKE_defvert_weight_to_rgb(fcol, 1.0f); rgb_float_to_uchar(col_fallback_max, fcol); } @@ -2389,7 +1097,7 @@ static void statvis_calc_overhang( fac = (fac - min) * minmax_irange; fac = 1.0f - fac; CLAMP(fac, 0.0f, 1.0f); - weight_to_rgb(fcol, fac); + BKE_defvert_weight_to_rgb(fcol, fac); rgb_float_to_uchar(r_face_colors[index], fcol); } else { @@ -2524,7 +1232,7 @@ static void statvis_calc_thickness( fac = (fac - min) * minmax_irange; fac = 1.0f - fac; CLAMP(fac, 0.0f, 1.0f); - weight_to_rgb(fcol, fac); + BKE_defvert_weight_to_rgb(fcol, fac); rgb_float_to_uchar(r_face_colors[i], fcol); } else { @@ -2563,7 +1271,7 @@ static void statvis_calc_intersect( overlap = BKE_bmbvh_overlap(bmtree, bmtree, &overlap_len); /* same for all faces */ - weight_to_rgb(fcol, 1.0f); + BKE_defvert_weight_to_rgb(fcol, 1.0f); rgb_float_to_uchar(col, fcol); if (overlap) { @@ -2650,7 +1358,7 @@ static void statvis_calc_distort( float fcol[3]; fac = (fac - min) * minmax_irange; CLAMP(fac, 0.0f, 1.0f); - weight_to_rgb(fcol, fac); + BKE_defvert_weight_to_rgb(fcol, fac); rgb_float_to_uchar(r_face_colors[index], fcol); } else { @@ -2700,7 +1408,7 @@ static void statvis_calc_sharp( float fcol[3]; fac = (fac - min) * minmax_irange; CLAMP(fac, 0.0f, 1.0f); - weight_to_rgb(fcol, fac); + BKE_defvert_weight_to_rgb(fcol, fac); rgb_float_to_uchar(r_vert_colors[i], fcol); } else { @@ -2721,7 +1429,7 @@ void BKE_editmesh_statvis_calc( { BKE_editmesh_color_ensure(em, BM_FACE); statvis_calc_overhang( - em, bmdm ? bmdm->polyNos : NULL, + em, bmdm ? bmdm->emd.polyNos : NULL, statvis->overhang_min / (float)M_PI, statvis->overhang_max / (float)M_PI, statvis->overhang_axis, @@ -2733,7 +1441,7 @@ void BKE_editmesh_statvis_calc( const float scale = 1.0f / mat4_to_scale(em->ob->obmat); BKE_editmesh_color_ensure(em, BM_FACE); statvis_calc_thickness( - em, bmdm ? bmdm->vertexCos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, statvis->thickness_min * scale, statvis->thickness_max * scale, statvis->thickness_samples, @@ -2744,7 +1452,7 @@ void BKE_editmesh_statvis_calc( { BKE_editmesh_color_ensure(em, BM_FACE); statvis_calc_intersect( - em, bmdm ? bmdm->vertexCos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, em->derivedFaceColor); break; } @@ -2756,7 +1464,7 @@ void BKE_editmesh_statvis_calc( emDM_ensurePolyNormals(bmdm); statvis_calc_distort( - em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, bmdm ? bmdm->emd.polyNos : NULL, statvis->distort_min, statvis->distort_max, em->derivedFaceColor); @@ -2766,7 +1474,7 @@ void BKE_editmesh_statvis_calc( { BKE_editmesh_color_ensure(em, BM_VERT); statvis_calc_sharp( - em, bmdm ? bmdm->vertexCos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, statvis->sharp_min, statvis->sharp_max, /* in this case they are vertex colors */ @@ -2799,14 +1507,14 @@ static void cage_mapped_verts_callback( } } -float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3] +float (*BKE_editmesh_vertexCos_get(struct Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, int *r_numVerts))[3] { DerivedMesh *cage, *final; BLI_bitmap *visit_bitmap; struct CageUserData data; float (*cos_cage)[3]; - cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final); + cage = editbmesh_get_derived_cage_and_final(depsgraph, scene, em->ob, em, CD_MASK_BAREMESH, &final); cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage"); /* when initializing cage verts, we only want the first cage coordinate for each vertex, |