2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2005 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/editderivedmesh.c
33 * the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
34 * to three loops per triangle. the derivedmesh stores a cache of tessellations
35 * for each face. this cache will smartly update as needed (though at first
36 * it'll simply be more brute force). keeping track of face/edge counts may
39 * this won't be the most efficient thing, considering that internal edges and
40 * faces of tessellations are exposed. looking up an edge by index in particular
41 * is likely to be a little slow.
45 #include "BLI_jitter.h"
46 #include "BLI_bitmap.h"
49 #include "BKE_cdderivedmesh.h"
51 #include "BKE_editmesh.h"
52 #include "BKE_editmesh_bvh.h"
54 #include "DNA_scene_types.h"
55 #include "DNA_object_types.h"
57 #include "MEM_guardedalloc.h"
60 #include "GPU_buffers.h"
61 #include "GPU_shader.h"
62 #include "GPU_basic_shader.h"
64 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]);
66 typedef struct EditDerivedBMesh {
71 /** when set, \a vertexNos, polyNos are lazy initialized */
72 const float (*vertexCos)[3];
74 /** lazy initialize (when \a vertexCos is set) */
75 float const (*vertexNos)[3];
76 float const (*polyNos)[3];
77 /** also lazy init but dont depend on \a vertexCos */
78 const float (*polyCos)[3];
81 /* -------------------------------------------------------------------- */
82 /* Lazy initialize datastructures */
84 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm);
86 static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm)
88 if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) {
90 BMesh *bm = bmdm->em->bm;
91 const float (*vertexCos)[3], (*polyNos)[3];
92 float (*vertexNos)[3];
94 /* calculate vertex normals from poly normals */
95 emDM_ensurePolyNormals(bmdm);
97 BM_mesh_elem_index_ensure(bm, BM_FACE);
99 polyNos = bmdm->polyNos;
100 vertexCos = bmdm->vertexCos;
101 vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__);
103 BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos);
105 bmdm->vertexNos = (const float (*)[3])vertexNos;
109 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm)
111 if (bmdm->vertexCos && (bmdm->polyNos == NULL)) {
112 BMesh *bm = bmdm->em->bm;
113 const float (*vertexCos)[3];
120 BM_mesh_elem_index_ensure(bm, BM_VERT);
122 polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__);
124 vertexCos = bmdm->vertexCos;
126 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
127 BM_elem_index_set(efa, i); /* set_inline */
128 BM_face_calc_normal_vcos(bm, efa, polyNos[i], vertexCos);
130 bm->elem_index_dirty &= ~BM_FACE;
132 bmdm->polyNos = (const float (*)[3])polyNos;
136 static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
138 if (bmdm->polyCos == NULL) {
139 BMesh *bm = bmdm->em->bm;
146 polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__);
148 if (bmdm->vertexCos) {
149 const float (*vertexCos)[3];
150 vertexCos = bmdm->vertexCos;
152 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
153 BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
157 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
158 BM_face_calc_center_mean(efa, polyCos[i]);
162 bmdm->polyCos = (const float (*)[3])polyCos;
166 static void emDM_calcNormals(DerivedMesh *dm)
168 /* Nothing to do: normals are already calculated and stored on the
169 * BMVerts and BMFaces */
170 dm->dirty &= ~DM_DIRTY_NORMALS;
173 static void emDM_calcLoopNormalsSpaceArray(
174 DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr);
176 static void emDM_calcLoopNormals(DerivedMesh *dm, const bool use_split_normals, const float split_angle)
178 emDM_calcLoopNormalsSpaceArray(dm, use_split_normals, split_angle, NULL);
181 /* #define DEBUG_CLNORS */
183 static void emDM_calcLoopNormalsSpaceArray(
184 DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr)
186 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
187 BMesh *bm = bmdm->em->bm;
188 const float (*vertexCos)[3], (*vertexNos)[3], (*polyNos)[3];
190 short (*clnors_data)[2];
191 int cd_loop_clnors_offset;
193 /* calculate loop normals from poly and vertex normals */
194 emDM_ensureVertNormals(bmdm);
195 emDM_ensurePolyNormals(bmdm);
196 dm->dirty &= ~DM_DIRTY_NORMALS;
198 vertexCos = bmdm->vertexCos;
199 vertexNos = bmdm->vertexNos;
200 polyNos = bmdm->polyNos;
202 loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
204 DM_add_loop_layer(dm, CD_NORMAL, CD_CALLOC, NULL);
205 loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
208 /* We can have both, give priority to dm's data, and fallback to bm's ones. */
209 clnors_data = dm->getLoopDataArray(dm, CD_CUSTOMLOOPNORMAL);
210 cd_loop_clnors_offset = clnors_data ? -1 : CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
212 BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, use_split_normals, split_angle, loopNos,
213 r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
215 if (r_lnors_spacearr) {
217 for (i = 0; i < numLoops; i++) {
218 if (r_lnors_spacearr->lspacearr[i]->ref_alpha != 0.0f) {
219 LinkNode *loops = r_lnors_spacearr->lspacearr[i]->loops;
220 printf("Loop %d uses lnor space %p:\n", i, r_lnors_spacearr->lspacearr[i]);
221 print_v3("\tfinal lnor:", loopNos[i]);
222 print_v3("\tauto lnor:", r_lnors_spacearr->lspacearr[i]->vec_lnor);
223 print_v3("\tref_vec:", r_lnors_spacearr->lspacearr[i]->vec_ref);
224 printf("\talpha: %f\n\tbeta: %f\n\tloops: %p\n", r_lnors_spacearr->lspacearr[i]->ref_alpha,
225 r_lnors_spacearr->lspacearr[i]->ref_beta, r_lnors_spacearr->lspacearr[i]->loops);
226 printf("\t\t(shared with loops");
228 printf(" %d", GET_INT_FROM_POINTER(loops->link));
234 printf("Loop %d has no lnor space\n", i);
242 /** \name Tangent Space Calculation
245 /* Necessary complexity to handle looptri's as quads for correct tangents */
246 #define USE_LOOPTRI_DETECT_QUADS
249 const float (*precomputedFaceNormals)[3];
250 const float (*precomputedLoopNormals)[3];
251 const BMLoop *(*looptris)[3];
252 int cd_loop_uv_offset; /* texture coordinates */
253 const float (*orco)[3];
254 float (*tangent)[4]; /* destination */
257 #ifdef USE_LOOPTRI_DETECT_QUADS
258 /* map from 'fake' face index to looptri,
259 * quads will point to the first looptri of the quad */
260 const int *face_as_quad_map;
261 int num_face_as_quad_map;
264 } SGLSLEditMeshToTangent;
266 #ifdef USE_LOOPTRI_DETECT_QUADS
267 /* seems weak but only used on quads */
268 static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
270 const BMLoop *l = BM_FACE_FIRST_LOOP(f);
271 while (vert_index--) {
279 #include "mikktspace.h"
281 static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
283 SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
285 #ifdef USE_LOOPTRI_DETECT_QUADS
286 return pMesh->num_face_as_quad_map;
288 return pMesh->numTessFaces;
292 static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
294 #ifdef USE_LOOPTRI_DETECT_QUADS
295 SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
296 if (pMesh->face_as_quad_map) {
297 const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
298 if (lt[0]->f->len == 4) {
304 UNUSED_VARS(pContext, face_num);
309 static void emdm_ts_GetPosition(
310 const SMikkTSpaceContext *pContext, float r_co[3],
311 const int face_num, const int vert_index)
313 //assert(vert_index >= 0 && vert_index < 4);
314 SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
318 #ifdef USE_LOOPTRI_DETECT_QUADS
319 if (pMesh->face_as_quad_map) {
320 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
321 if (lt[0]->f->len == 4) {
322 l = bm_loop_at_face_index(lt[0]->f, vert_index);
325 /* fall through to regular triangle */
328 lt = pMesh->looptris[face_num];
331 lt = pMesh->looptris[face_num];
339 copy_v3_v3(r_co, co);
342 static void emdm_ts_GetTextureCoordinate(
343 const SMikkTSpaceContext *pContext, float r_uv[2],
344 const int face_num, const int vert_index)
346 //assert(vert_index >= 0 && vert_index < 4);
347 SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
351 #ifdef USE_LOOPTRI_DETECT_QUADS
352 if (pMesh->face_as_quad_map) {
353 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
354 if (lt[0]->f->len == 4) {
355 l = bm_loop_at_face_index(lt[0]->f, vert_index);
358 /* fall through to regular triangle */
361 lt = pMesh->looptris[face_num];
364 lt = pMesh->looptris[face_num];
369 if (pMesh->cd_loop_uv_offset != -1) {
370 const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
371 copy_v2_v2(r_uv, uv);
374 const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
375 map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
379 static void emdm_ts_GetNormal(
380 const SMikkTSpaceContext *pContext, float r_no[3],
381 const int face_num, const int vert_index)
383 //assert(vert_index >= 0 && vert_index < 4);
384 SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
388 #ifdef USE_LOOPTRI_DETECT_QUADS
389 if (pMesh->face_as_quad_map) {
390 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
391 if (lt[0]->f->len == 4) {
392 l = bm_loop_at_face_index(lt[0]->f, vert_index);
395 /* fall through to regular triangle */
398 lt = pMesh->looptris[face_num];
401 lt = pMesh->looptris[face_num];
406 if (pMesh->precomputedLoopNormals) {
407 copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
409 else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
410 if (pMesh->precomputedFaceNormals) {
411 copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
414 copy_v3_v3(r_no, l->f->no);
418 copy_v3_v3(r_no, l->v->no);
422 static void emdm_ts_SetTSpace(
423 const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
424 const int face_num, const int vert_index)
426 //assert(vert_index >= 0 && vert_index < 4);
427 SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
431 #ifdef USE_LOOPTRI_DETECT_QUADS
432 if (pMesh->face_as_quad_map) {
433 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
434 if (lt[0]->f->len == 4) {
435 l = bm_loop_at_face_index(lt[0]->f, vert_index);
438 /* fall through to regular triangle */
441 lt = pMesh->looptris[face_num];
444 lt = pMesh->looptris[face_num];
451 pRes = pMesh->tangent[BM_elem_index_get(l)];
452 copy_v3_v3(pRes, fvTangent);
456 static void emDM_calc_loop_tangents_thread(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
458 struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
459 /* new computation method */
461 SMikkTSpaceContext sContext = {NULL};
462 SMikkTSpaceInterface sInterface = {NULL};
463 sContext.m_pUserData = mesh2tangent;
464 sContext.m_pInterface = &sInterface;
465 sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
466 sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
467 sInterface.m_getPosition = emdm_ts_GetPosition;
468 sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
469 sInterface.m_getNormal = emdm_ts_GetNormal;
470 sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
472 genTangSpaceDefault(&sContext);
477 * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data.
479 * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
480 * This is done because #CD_TANGENT is cache data used only for drawing.
483 static void emDM_calc_loop_tangents(
484 DerivedMesh *dm, bool calc_active_tangent,
485 const char (*tangent_names)[MAX_NAME], int tangent_names_count)
487 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
488 BMEditMesh *em = bmdm->em;
489 BMesh *bm = bmdm->em->bm;
490 if (CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV) == 0)
495 bool calc_act = false;
496 bool calc_ren = false;
497 char act_uv_name[MAX_NAME];
498 char ren_uv_name[MAX_NAME];
499 char tangent_mask = 0;
501 DM_calc_loop_tangents_step_0(
502 &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count,
503 &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
505 if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) {
506 for (int i = 0; i < tangent_names_count; i++)
507 if (tangent_names[i][0])
508 DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]);
509 if (calc_act && act_uv_name[0])
510 DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name);
511 if (calc_ren && ren_uv_name[0])
512 DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, ren_uv_name);
513 int totface = em->tottri;
514 #ifdef USE_LOOPTRI_DETECT_QUADS
515 int num_face_as_quad_map;
516 int *face_as_quad_map = NULL;
518 /* map faces to quads */
519 if (bmdm->em->tottri != bm->totface) {
520 /* over alloc, since we dont know how many ngon or quads we have */
522 /* map fake face index to looptri */
523 face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
525 for (i = 0, j = 0; j < totface; i++, j++) {
526 face_as_quad_map[i] = j;
527 /* step over all quads */
528 if (em->looptris[j][0]->f->len == 4) {
529 j++; /* skips the nest looptri */
532 num_face_as_quad_map = i;
535 num_face_as_quad_map = totface;
540 TaskScheduler *scheduler = BLI_task_scheduler_get();
542 task_pool = BLI_task_pool_create(scheduler, NULL);
544 dm->tangent_mask = 0;
545 /* Calculate tangent layers */
546 SGLSLEditMeshToTangent data_array[MAX_MTFACE];
549 CustomData_update_typemap(&dm->loopData);
550 const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT);
551 for (n = 0; n < tangent_layer_num; n++) {
552 index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n);
553 BLI_assert(n < MAX_MTFACE);
554 SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
555 mesh2tangent->numTessFaces = em->tottri;
556 #ifdef USE_LOOPTRI_DETECT_QUADS
557 mesh2tangent->face_as_quad_map = face_as_quad_map;
558 mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
560 mesh2tangent->precomputedFaceNormals = bmdm->polyNos; /* dm->getPolyDataArray(dm, CD_NORMAL) */
561 /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
562 * have to check this is valid...
564 mesh2tangent->precomputedLoopNormals = CustomData_get_layer(&dm->loopData, CD_NORMAL);
565 mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
567 /* needed for indexing loop-tangents */
568 int htype_index = BM_LOOP;
569 if (mesh2tangent->cd_loop_uv_offset == -1) {
570 mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
571 if (!mesh2tangent->orco)
573 /* needed for orco lookups */
574 htype_index |= BM_VERT;
576 if (mesh2tangent->precomputedFaceNormals) {
577 /* needed for face normal lookups */
578 htype_index |= BM_FACE;
580 BM_mesh_elem_index_ensure(bm, htype_index);
582 mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
583 mesh2tangent->tangent = dm->loopData.layers[index].data;
585 /* Fill the resulting tangent_mask */
586 int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name);
587 int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
588 BLI_assert(uv_ind != -1 && uv_start != -1);
589 BLI_assert(uv_ind - uv_start < MAX_MTFACE);
590 dm->tangent_mask |= 1 << (uv_ind - uv_start);
591 BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
594 BLI_assert(dm->tangent_mask == tangent_mask);
595 BLI_task_pool_work_and_wait(task_pool);
596 BLI_task_pool_free(task_pool);
598 #ifdef USE_LOOPTRI_DETECT_QUADS
599 if (face_as_quad_map) {
600 MEM_freeN(face_as_quad_map);
602 #undef USE_LOOPTRI_DETECT_QUADS
605 /* Update active layer index */
606 int uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
607 int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[uv_index].name);
608 CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
610 /* Update render layer index */
611 uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
612 tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[uv_index].name);
613 CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
619 static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
624 static void emDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
626 /* Nothing to do: emDM tessellation is known,
627 * allocate and fill in with emDM_getLoopTriArray */
630 static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
632 if (dm->looptris.array) {
633 BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
636 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
637 BMLoop *(*looptris)[3] = bmdm->em->looptris;
639 const int tottri = bmdm->em->tottri;
642 DM_ensure_looptri_data(dm);
643 mlooptri = dm->looptris.array;
645 BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
646 BLI_assert(tottri == dm->looptris.num);
648 BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
650 for (i = 0; i < tottri; i++) {
651 BMLoop **ltri = looptris[i];
652 MLoopTri *lt = &mlooptri[i];
656 BM_elem_index_get(ltri[0]),
657 BM_elem_index_get(ltri[1]),
658 BM_elem_index_get(ltri[2]));
659 lt->poly = BM_elem_index_get(ltri[0]->f);
662 return dm->looptris.array;
665 static void emDM_foreachMappedVert(
667 void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
671 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
672 BMesh *bm = bmdm->em->bm;
677 if (bmdm->vertexCos) {
678 const float (*vertexCos)[3] = bmdm->vertexCos;
679 const float (*vertexNos)[3];
681 if (flag & DM_FOREACH_USE_NORMAL) {
682 emDM_ensureVertNormals(bmdm);
683 vertexNos = bmdm->vertexNos;
689 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
690 const float *no = (flag & DM_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
691 func(userData, i, vertexCos[i], no, NULL);
695 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
696 const float *no = (flag & DM_FOREACH_USE_NORMAL) ? eve->no : NULL;
697 func(userData, i, eve->co, no, NULL);
701 static void emDM_foreachMappedEdge(
703 void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
706 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
707 BMesh *bm = bmdm->em->bm;
712 if (bmdm->vertexCos) {
714 BM_mesh_elem_index_ensure(bm, BM_VERT);
716 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
718 bmdm->vertexCos[BM_elem_index_get(eed->v1)],
719 bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
723 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
724 func(userData, i, eed->v1->co, eed->v2->co);
729 static void emDM_drawMappedEdges(
731 DMSetDrawOptions setDrawOptions,
734 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
735 BMesh *bm = bmdm->em->bm;
740 if (bmdm->vertexCos) {
742 BM_mesh_elem_index_ensure(bm, BM_VERT);
745 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
746 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
747 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
748 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
755 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
756 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
757 glVertex3fv(eed->v1->co);
758 glVertex3fv(eed->v2->co);
764 static void emDM_drawEdges(
766 bool UNUSED(drawLooseEdges),
767 bool UNUSED(drawAllEdges))
769 emDM_drawMappedEdges(dm, NULL, NULL);
772 static void emDM_drawMappedEdgesInterp(
774 DMSetDrawOptions setDrawOptions,
775 DMSetDrawInterpOptions setDrawInterpOptions,
778 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
779 BMesh *bm = bmdm->em->bm;
784 if (bmdm->vertexCos) {
786 BM_mesh_elem_index_ensure(bm, BM_VERT);
789 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
790 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
791 setDrawInterpOptions(userData, i, 0.0);
792 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
793 setDrawInterpOptions(userData, i, 1.0);
794 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
801 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
802 if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
803 setDrawInterpOptions(userData, i, 0.0);
804 glVertex3fv(eed->v1->co);
805 setDrawInterpOptions(userData, i, 1.0);
806 glVertex3fv(eed->v2->co);
813 static void emDM_drawUVEdges(DerivedMesh *dm)
815 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
816 BMesh *bm = bmdm->em->bm;
820 const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
822 if (UNLIKELY(cd_loop_uv_offset == -1)) {
827 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
828 BMLoop *l_iter, *l_first;
829 const float *uv, *uv_prev;
831 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
834 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
835 uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
837 uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
839 glVertex2fv(uv_prev);
841 } while ((l_iter = l_iter->next) != l_first);
846 static void emDM_foreachMappedLoop(
848 void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
852 /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
853 * return loop data from bmesh itself. */
854 const float (*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : NULL;
856 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
857 BMesh *bm = bmdm->em->bm;
861 const float (*vertexCos)[3] = bmdm->vertexCos;
864 BM_mesh_elem_index_ensure(bm, BM_VERT);
866 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
867 BMLoop *l_iter, *l_first;
869 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
871 const BMVert *eve = l_iter->v;
872 const int v_idx = BM_elem_index_get(eve);
873 const float *no = lnors ? *lnors++ : NULL;
874 func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
875 } while ((l_iter = l_iter->next) != l_first);
879 static void emDM_foreachMappedFaceCenter(
881 void (*func)(void *userData, int index, const float co[3], const float no[3]),
885 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
886 BMesh *bm = bmdm->em->bm;
887 const float (*polyNos)[3];
888 const float (*polyCos)[3];
893 emDM_ensurePolyCenters(bmdm);
894 polyCos = bmdm->polyCos; /* always set */
896 if (flag & DM_FOREACH_USE_NORMAL) {
897 emDM_ensurePolyNormals(bmdm);
898 polyNos = bmdm->polyNos; /* maybe NULL */
905 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
906 const float *no = polyNos[i];
907 func(userData, i, polyCos[i], no);
911 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
912 const float *no = (flag & DM_FOREACH_USE_NORMAL) ? efa->no : NULL;
913 func(userData, i, polyCos[i], no);
918 static void emDM_drawMappedFaces(
920 DMSetDrawOptions setDrawOptions,
921 DMSetMaterial setMaterial,
922 /* currently unused -- each original face is handled separately */
923 DMCompareDrawOptions UNUSED(compareDrawOptions),
927 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
928 BMEditMesh *em = bmdm->em;
931 struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
932 const int tottri = bmdm->em->tottri;
933 DMDrawOption draw_option;
935 const int skip_normals = !(flag & DM_DRAW_NEED_NORMALS);
936 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
937 MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
938 unsigned char(*color_vert_array)[4] = em->derivedVertColor;
939 unsigned char(*color_face_array)[4] = em->derivedFaceColor;
940 bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals;
941 bool has_fcol_preview = (color_face_array != NULL) && !skip_normals;
942 bool has_vcol_any = has_vcol_preview;
944 /* GL_ZERO is used to detect if drawing has started or not */
945 GLenum poly_prev = GL_ZERO;
946 GLenum shade_prev = GL_ZERO;
947 DMDrawOption draw_option_prev = DM_DRAW_OPTION_SKIP;
949 /* call again below is ok */
950 if (has_vcol_preview) {
951 BM_mesh_elem_index_ensure(bm, BM_VERT);
953 if (has_fcol_preview) {
954 BM_mesh_elem_index_ensure(bm, BM_FACE);
956 if (has_vcol_preview || has_fcol_preview) {
957 flag |= DM_DRAW_ALWAYS_SMOOTH;
958 /* weak, this logic should really be moved higher up */
962 if (bmdm->vertexCos) {
963 short prev_mat_nr = -1;
965 /* add direct access */
966 const float (*vertexCos)[3] = bmdm->vertexCos;
967 const float (*vertexNos)[3];
968 const float (*polyNos)[3];
975 emDM_ensureVertNormals(bmdm);
976 emDM_ensurePolyNormals(bmdm);
977 vertexNos = bmdm->vertexNos;
978 polyNos = bmdm->polyNos;
981 BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
983 for (i = 0; i < tottri; i++) {
984 BMLoop **ltri = looptris[i];
988 drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
990 draw_option = (!setDrawOptions ?
991 DM_DRAW_OPTION_NORMAL :
992 setDrawOptions(userData, BM_elem_index_get(efa)));
993 if (draw_option != DM_DRAW_OPTION_SKIP) {
994 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
996 if (draw_option_prev != draw_option) {
997 if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) {
998 if (poly_prev != GL_ZERO) glEnd();
999 poly_prev = GL_ZERO; /* force glBegin */
1001 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1003 draw_option_prev = draw_option;
1007 if (efa->mat_nr != prev_mat_nr) {
1009 if (poly_prev != GL_ZERO) glEnd();
1010 poly_prev = GL_ZERO; /* force glBegin */
1012 setMaterial(efa->mat_nr + 1, NULL);
1014 prev_mat_nr = efa->mat_nr;
1017 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
1019 if (poly_prev != GL_ZERO) glEnd();
1020 poly_prev = GL_ZERO; /* force glBegin */
1022 GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
1023 GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
1026 if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1027 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
1029 if (poly_type != poly_prev) {
1030 if (poly_prev != GL_ZERO) glEnd();
1031 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1033 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1034 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1035 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1036 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1037 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1038 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1041 const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
1042 if (shade_type != shade_prev) {
1043 if (poly_prev != GL_ZERO) glEnd();
1044 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
1045 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1047 if (poly_type != poly_prev) {
1048 if (poly_prev != GL_ZERO) glEnd();
1049 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1053 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1054 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1055 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1056 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1057 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1058 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1059 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1062 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1063 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1064 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1065 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1066 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1067 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1068 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1069 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1070 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1071 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1072 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1073 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1080 short prev_mat_nr = -1;
1082 BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE);
1084 for (i = 0; i < tottri; i++) {
1085 BMLoop **ltri = looptris[i];
1089 drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
1091 draw_option = (setDrawOptions ?
1092 setDrawOptions(userData, BM_elem_index_get(efa)) :
1093 DM_DRAW_OPTION_NORMAL);
1095 if (draw_option != DM_DRAW_OPTION_SKIP) {
1096 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
1098 if (draw_option_prev != draw_option) {
1099 if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) {
1100 if (poly_prev != GL_ZERO) glEnd();
1101 poly_prev = GL_ZERO; /* force glBegin */
1103 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1105 draw_option_prev = draw_option;
1108 if (efa->mat_nr != prev_mat_nr) {
1110 if (poly_prev != GL_ZERO) glEnd();
1111 poly_prev = GL_ZERO; /* force glBegin */
1113 setMaterial(efa->mat_nr + 1, NULL);
1115 prev_mat_nr = efa->mat_nr;
1118 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
1120 if (poly_prev != GL_ZERO) glEnd();
1121 poly_prev = GL_ZERO; /* force glBegin */
1123 GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
1124 GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
1127 if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1128 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
1131 if (poly_type != poly_prev) {
1132 if (poly_prev != GL_ZERO) glEnd();
1133 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1135 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1136 glVertex3fv(ltri[0]->v->co);
1137 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1138 glVertex3fv(ltri[1]->v->co);
1139 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1140 glVertex3fv(ltri[2]->v->co);
1143 const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
1144 if (shade_type != shade_prev) {
1145 if (poly_prev != GL_ZERO) glEnd();
1146 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
1147 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1149 if (poly_type != poly_prev) {
1150 if (poly_prev != GL_ZERO) glEnd();
1151 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1155 glNormal3fv(efa->no);
1156 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1157 glVertex3fv(ltri[0]->v->co);
1158 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1159 glVertex3fv(ltri[1]->v->co);
1160 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1161 glVertex3fv(ltri[2]->v->co);
1164 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1165 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1166 else glNormal3fv(ltri[0]->v->no);
1167 glVertex3fv(ltri[0]->v->co);
1168 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1169 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1170 else glNormal3fv(ltri[1]->v->no);
1171 glVertex3fv(ltri[1]->v->co);
1172 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1173 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1174 else glNormal3fv(ltri[2]->v->no);
1175 glVertex3fv(ltri[2]->v->co);
1182 /* if non zero we know a face was rendered */
1183 if (poly_prev != GL_ZERO) glEnd();
1186 static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
1188 luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset);
1189 luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset);
1190 luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset);
1193 static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
1195 lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset);
1196 lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset);
1197 lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset);
1200 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4])
1202 lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)];
1203 lcol[1] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[1]->v)];
1204 lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
1207 static void emDM_drawFacesTex_common(
1209 DMSetDrawOptionsTex drawParams,
1210 DMSetDrawOptionsMappedTex drawParamsMapped,
1211 DMCompareDrawOptions compareDrawOptions,
1214 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1215 BMEditMesh *em = bmdm->em;
1217 struct BMLoop *(*looptris)[3] = em->looptris;
1219 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1220 MLoopUV *luv[3], dummyluv = {{0}};
1221 MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
1222 const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
1223 const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
1224 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
1225 unsigned char(*color_vert_array)[4] = em->derivedVertColor;
1226 bool has_uv = (cd_loop_uv_offset != -1);
1227 bool has_vcol_preview = (color_vert_array != NULL);
1228 bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false);
1229 bool has_vcol_any = (has_vcol_preview || has_vcol);
1232 (void) compareDrawOptions;
1234 luv[0] = luv[1] = luv[2] = &dummyluv;
1236 // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */
1238 /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1239 BM_mesh_elem_index_ensure(bm, BM_FACE);
1241 /* call again below is ok */
1242 if (has_vcol_preview) {
1243 BM_mesh_elem_index_ensure(bm, BM_VERT);
1246 if (bmdm->vertexCos) {
1247 /* add direct access */
1248 const float (*vertexCos)[3] = bmdm->vertexCos;
1249 const float (*vertexNos)[3];
1250 const float (*polyNos)[3];
1252 emDM_ensureVertNormals(bmdm);
1253 emDM_ensurePolyNormals(bmdm);
1254 vertexNos = bmdm->vertexNos;
1255 polyNos = bmdm->polyNos;
1257 BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
1259 for (i = 0; i < em->tottri; i++) {
1260 BMLoop **ltri = looptris[i];
1261 MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
1262 /*unsigned char *cp = NULL;*/ /*UNUSED*/
1263 int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
1264 DMDrawOption draw_option;
1269 draw_option = drawParams(tp, has_vcol, efa->mat_nr);
1271 else if (drawParamsMapped)
1272 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
1274 draw_option = DM_DRAW_OPTION_NORMAL;
1276 if (draw_option != DM_DRAW_OPTION_SKIP) {
1278 if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset);
1279 if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
1280 else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1282 glBegin(GL_TRIANGLES);
1284 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1286 glTexCoord2fv(luv[0]->uv);
1287 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1288 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1290 glTexCoord2fv(luv[1]->uv);
1291 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1292 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1294 glTexCoord2fv(luv[2]->uv);
1295 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1296 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1299 glTexCoord2fv(luv[0]->uv);
1300 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1301 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1302 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1303 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1305 glTexCoord2fv(luv[1]->uv);
1306 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1307 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1308 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1309 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1311 glTexCoord2fv(luv[2]->uv);
1312 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1313 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1314 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1315 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1322 BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
1324 for (i = 0; i < em->tottri; i++) {
1325 BMLoop **ltri = looptris[i];
1326 MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
1327 /*unsigned char *cp = NULL;*/ /*UNUSED*/
1328 int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
1329 DMDrawOption draw_option;
1334 draw_option = drawParams(tp, has_vcol, efa->mat_nr);
1335 else if (drawParamsMapped)
1336 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
1338 draw_option = DM_DRAW_OPTION_NORMAL;
1340 if (draw_option != DM_DRAW_OPTION_SKIP) {
1342 if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset);
1343 if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
1344 else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1346 glBegin(GL_TRIANGLES);
1348 glNormal3fv(efa->no);
1350 glTexCoord2fv(luv[0]->uv);
1351 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1352 glVertex3fv(ltri[0]->v->co);
1354 glTexCoord2fv(luv[1]->uv);
1355 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1356 glVertex3fv(ltri[1]->v->co);
1358 glTexCoord2fv(luv[2]->uv);
1359 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1360 glVertex3fv(ltri[2]->v->co);
1363 glTexCoord2fv(luv[0]->uv);
1364 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1365 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1366 else glNormal3fv(ltri[0]->v->no);
1367 glVertex3fv(ltri[0]->v->co);
1369 glTexCoord2fv(luv[1]->uv);
1370 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1371 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1372 else glNormal3fv(ltri[1]->v->no);
1373 glVertex3fv(ltri[1]->v->co);
1375 glTexCoord2fv(luv[2]->uv);
1376 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1377 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1378 else glNormal3fv(ltri[2]->v->no);
1379 glVertex3fv(ltri[2]->v->co);
1387 static void emDM_drawFacesTex(
1389 DMSetDrawOptionsTex setDrawOptions,
1390 DMCompareDrawOptions compareDrawOptions,
1391 void *userData, DMDrawFlag UNUSED(flag))
1393 emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
1396 static void emDM_drawMappedFacesTex(
1398 DMSetDrawOptionsMappedTex setDrawOptions,
1399 DMCompareDrawOptions compareDrawOptions,
1400 void *userData, DMDrawFlag UNUSED(flag))
1402 emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1405 static void emdm_pass_attrib_update_uniforms(const DMVertexAttribs *attribs)
1408 if (attribs->totorco) {
1409 glUniform1i(attribs->orco.gl_info_index, 0);
1411 for (i = 0; i < attribs->tottface; i++) {
1412 glUniform1i(attribs->tface[i].gl_info_index, 0);
1414 for (i = 0; i < attribs->totmcol; i++) {
1415 glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
1418 for (i = 0; i < attribs->tottang; i++) {
1419 glUniform1i(attribs->tang[i].gl_info_index, 0);
1427 * const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
1429 * This is intentionally different to calling:
1430 * CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i);
1432 * ... because the material may use layer names to select different UV's
1435 static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop)
1437 BMVert *eve = loop->v;
1439 const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1441 if (attribs->totorco) {
1442 int index = BM_elem_index_get(eve);
1443 const float *orco = (attribs->orco.array) ? attribs->orco.array[index] : zero;
1445 if (attribs->orco.gl_texco)
1446 glTexCoord3fv(orco);
1448 glVertexAttrib3fv(attribs->orco.gl_index, orco);
1450 for (i = 0; i < attribs->tottface; i++) {
1453 if (attribs->tface[i].em_offset != -1) {
1454 const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
1461 if (attribs->tface[i].gl_texco)
1464 glVertexAttrib2fv(attribs->tface[i].gl_index, uv);
1466 for (i = 0; i < attribs->totmcol; i++) {
1468 if (attribs->mcol[i].em_offset != -1) {
1469 const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
1470 rgba_uchar_to_float(col, &cp->r);
1473 col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f;
1475 glVertexAttrib4fv(attribs->mcol[i].gl_index, col);
1478 for (i = 0; i < attribs->tottang; i++) {
1480 if (attribs->tang[i].em_offset != -1) {
1481 tang = attribs->tang[i].array[BM_elem_index_get(loop)];
1486 glVertexAttrib4fv(attribs->tang[i].gl_index, tang);
1490 static void emDM_drawMappedFacesGLSL(
1492 DMSetMaterial setMaterial,
1493 DMSetDrawOptions setDrawOptions,
1496 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1497 BMEditMesh *em = bmdm->em;
1499 struct BMLoop *(*looptris)[3] = em->looptris;
1500 /* add direct access */
1501 const float (*vertexCos)[3] = bmdm->vertexCos;
1502 const float (*vertexNos)[3];
1503 const float (*polyNos)[3];
1504 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1507 DMVertexAttribs attribs;
1508 GPUVertexAttribs gattribs;
1510 int i, matnr, new_matnr, fi;
1516 memset(&attribs, 0, sizeof(attribs));
1518 emDM_ensureVertNormals(bmdm);
1519 emDM_ensurePolyNormals(bmdm);
1520 vertexNos = bmdm->vertexNos;
1521 polyNos = bmdm->polyNos;
1523 BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
1525 for (i = 0; i < em->tottri; i++) {
1526 BMLoop **ltri = looptris[i];
1531 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
1535 new_matnr = efa->mat_nr + 1;
1536 if (new_matnr != matnr) {
1540 do_draw = setMaterial(matnr = new_matnr, &gattribs);
1542 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1543 emdm_pass_attrib_update_uniforms(&attribs);
1544 if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
1545 BM_mesh_elem_index_ensure(bm, BM_LOOP);
1549 glBegin(GL_TRIANGLES);
1555 drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1559 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1560 for (fi = 0; fi < 3; fi++) {
1561 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1562 glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
1566 glNormal3fv(efa->no);
1567 for (fi = 0; fi < 3; fi++) {
1568 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1569 glVertex3fv(ltri[fi]->v->co);
1575 for (fi = 0; fi < 3; fi++) {
1576 const int j = BM_elem_index_get(ltri[fi]->v);
1577 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1578 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1579 else glNormal3fv(vertexNos[j]);
1580 glVertex3fv(vertexCos[j]);
1584 for (fi = 0; fi < 3; fi++) {
1585 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1586 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1587 else glNormal3fv(ltri[fi]->v->no);
1588 glVertex3fv(ltri[fi]->v->co);
1600 static void emDM_drawFacesGLSL(
1602 int (*setMaterial)(int matnr, void *attribs))
1604 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1607 static void emDM_drawMappedFacesMat(
1609 void (*setMaterial)(void *userData, int matnr, void *attribs),
1610 bool (*setFace)(void *userData, int index), void *userData)
1612 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1613 BMEditMesh *em = bmdm->em;
1615 struct BMLoop *(*looptris)[3] = em->looptris;
1616 const float (*vertexCos)[3] = bmdm->vertexCos;
1617 const float (*vertexNos)[3];
1618 const float (*polyNos)[3];
1619 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1621 DMVertexAttribs attribs = {{{NULL}}};
1622 GPUVertexAttribs gattribs;
1623 int i, matnr, new_matnr, fi;
1627 emDM_ensureVertNormals(bmdm);
1628 emDM_ensurePolyNormals(bmdm);
1630 vertexNos = bmdm->vertexNos;
1631 polyNos = bmdm->polyNos;
1633 BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
1635 for (i = 0; i < em->tottri; i++) {
1636 BMLoop **ltri = looptris[i];
1642 if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1646 new_matnr = efa->mat_nr + 1;
1647 if (new_matnr != matnr) {
1651 setMaterial(userData, matnr = new_matnr, &gattribs);
1652 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1653 if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
1654 BM_mesh_elem_index_ensure(bm, BM_LOOP);
1657 glBegin(GL_TRIANGLES);
1661 drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1665 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1666 for (fi = 0; fi < 3; fi++) {
1667 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1668 glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
1672 glNormal3fv(efa->no);
1673 for (fi = 0; fi < 3; fi++) {
1674 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1675 glVertex3fv(ltri[fi]->v->co);
1681 for (fi = 0; fi < 3; fi++) {
1682 const int j = BM_elem_index_get(ltri[fi]->v);
1683 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1684 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1685 else glNormal3fv(vertexNos[j]);
1686 glVertex3fv(vertexCos[j]);
1690 for (fi = 0; fi < 3; fi++) {
1691 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1692 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1693 else glNormal3fv(ltri[fi]->v->no);
1694 glVertex3fv(ltri[fi]->v->co);
1705 static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
1707 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1708 BMesh *bm = bmdm->em->bm;
1714 if (bmdm->vertexCos) {
1715 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1716 minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]);
1720 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1721 minmax_v3v3_v3(r_min, r_max, eve->co);
1730 static int emDM_getNumVerts(DerivedMesh *dm)
1732 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1734 return bmdm->em->bm->totvert;
1737 static int emDM_getNumEdges(DerivedMesh *dm)
1739 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1741 return bmdm->em->bm->totedge;
1744 static int emDM_getNumTessFaces(DerivedMesh *dm)
1746 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1748 return bmdm->em->tottri;
1751 static int emDM_getNumLoops(DerivedMesh *dm)
1753 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1755 return bmdm->em->bm->totloop;
1758 static int emDM_getNumPolys(DerivedMesh *dm)
1760 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1762 return bmdm->em->bm->totface;
1765 static void bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *r_vert)
1769 copy_v3_v3(r_vert->co, ev->co);
1771 normal_float_to_short_v3(r_vert->no, ev->no);
1773 r_vert->flag = BM_vert_flag_to_mflag(ev);
1775 if ((f = CustomData_bmesh_get(&bm->vdata, ev->head.data, CD_BWEIGHT))) {
1776 r_vert->bweight = (unsigned char)((*f) * 255.0f);
1780 static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
1782 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1783 BMesh *bm = bmdm->em->bm;
1786 if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1787 BLI_assert(!"error in emDM_getVert");
1791 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1792 ev = bm->vtable[index]; /* should be BM_vert_at_index() */
1793 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1795 bmvert_to_mvert(bm, ev, r_vert);
1796 if (bmdm->vertexCos)
1797 copy_v3_v3(r_vert->co, bmdm->vertexCos[index]);
1800 static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
1802 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1803 BMesh *bm = bmdm->em->bm;
1805 if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1806 BLI_assert(!"error in emDM_getVertCo");
1810 if (bmdm->vertexCos) {
1811 copy_v3_v3(r_co, bmdm->vertexCos[index]);
1816 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1817 ev = bm->vtable[index]; /* should be BM_vert_at_index() */
1818 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1819 copy_v3_v3(r_co, ev->co);
1823 static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
1825 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1826 BMesh *bm = bmdm->em->bm;
1828 if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1829 BLI_assert(!"error in emDM_getVertNo");
1834 if (bmdm->vertexCos) {
1835 emDM_ensureVertNormals(bmdm);
1836 copy_v3_v3(r_no, bmdm->vertexNos[index]);
1841 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1842 ev = bm->vtable[index]; /* should be BM_vert_at_index() */
1843 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1844 copy_v3_v3(r_no, ev->no);
1848 static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3])
1850 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1851 BMesh *bm = bmdm->em->bm;
1853 if (UNLIKELY(index < 0 || index >= bm->totface)) {
1854 BLI_assert(!"error in emDM_getPolyNo");
1858 if (bmdm->vertexCos) {
1859 emDM_ensurePolyNormals(bmdm);
1860 copy_v3_v3(r_no, bmdm->polyNos[index]);
1865 BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
1866 efa = bm->ftable[index]; /* should be BM_vert_at_index() */
1867 // efa = BM_face_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1868 copy_v3_v3(r_no, efa->no);
1872 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
1874 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1875 BMesh *bm = bmdm->em->bm;
1879 if (UNLIKELY(index < 0 || index >= bm->totedge)) {
1880 BLI_assert(!"error in emDM_getEdge");
1884 BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
1885 e = bm->etable[index]; /* should be BM_edge_at_index() */
1886 // e = BM_edge_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1888 r_edge->flag = BM_edge_flag_to_mflag(e);
1890 r_edge->v1 = BM_elem_index_get(e->v1);
1891 r_edge->v2 = BM_elem_index_get(e->v2);
1893 if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
1894 r_edge->bweight = (unsigned char)((*f) * 255.0f);
1896 if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
1897 r_edge->crease = (unsigned char)((*f) * 255.0f);
1901 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
1903 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1907 if (UNLIKELY(index < 0 || index >= bmdm->em->tottri)) {
1908 BLI_assert(!"error in emDM_getTessFace");
1912 ltri = bmdm->em->looptris[index];
1916 r_face->mat_nr = (unsigned char) ef->mat_nr;
1917 r_face->flag = BM_face_flag_to_mflag(ef);
1919 r_face->v1 = BM_elem_index_get(ltri[0]->v);
1920 r_face->v2 = BM_elem_index_get(ltri[1]->v);
1921 r_face->v3 = BM_elem_index_get(ltri[2]->v);
1924 test_index_face(r_face, NULL, 0, 3);
1927 static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
1929 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1930 BMesh *bm = bmdm->em->bm;
1933 const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
1935 if (bmdm->vertexCos) {
1938 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1939 copy_v3_v3(r_vert->co, bmdm->vertexCos[i]);
1940 normal_float_to_short_v3(r_vert->no, eve->no);
1941 r_vert->flag = BM_vert_flag_to_mflag(eve);
1943 r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1949 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1950 copy_v3_v3(r_vert->co, eve->co);
1951 normal_float_to_short_v3(r_vert->no, eve->no);
1952 r_vert->flag = BM_vert_flag_to_mflag(eve);
1954 r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1961 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
1963 BMesh *bm = ((EditDerivedBMesh *)dm)->em->bm;
1967 const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
1968 const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
1970 BM_mesh_elem_index_ensure(bm, BM_VERT);
1972 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1973 r_edge->v1 = BM_elem_index_get(eed->v1);
1974 r_edge->v2 = BM_elem_index_get(eed->v2);
1976 r_edge->flag = BM_edge_flag_to_mflag(eed);
1978 r_edge->crease = (cd_edge_crease_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset) : 0;
1979 r_edge->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
1985 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
1987 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1988 BMesh *bm = bmdm->em->bm;
1989 struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
1993 BM_mesh_elem_index_ensure(bm, BM_VERT);
1995 for (i = 0; i < bmdm->em->tottri; i++, r_face++) {
1996 BMLoop **ltri = looptris[i];
1999 r_face->mat_nr = (unsigned char) ef->mat_nr;
2001 r_face->flag = BM_face_flag_to_mflag(ef);
2004 r_face->v1 = BM_elem_index_get(ltri[0]->v);
2005 r_face->v2 = BM_elem_index_get(ltri[1]->v);
2006 r_face->v3 = BM_elem_index_get(ltri[2]->v);
2009 test_index_face(r_face, NULL, 0, 3);
2013 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
2015 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2016 BMesh *bm = bmdm->em->bm;
2020 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
2022 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2023 BMLoop *l_iter, *l_first;
2024 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
2026 r_loop->v = BM_elem_index_get(l_iter->v);
2027 r_loop->e = BM_elem_index_get(l_iter->e);
2029 } while ((l_iter = l_iter->next) != l_first);
2033 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
2035 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2036 BMesh *bm = bmdm->em->bm;
2042 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2043 r_poly->flag = BM_face_flag_to_mflag(efa);
2044 r_poly->loopstart = i;
2045 r_poly->totloop = efa->len;
2046 r_poly->mat_nr = efa->mat_nr;
2053 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
2055 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2056 BMesh *bm = bmdm->em->bm;
2059 datalayer = DM_get_tessface_data_layer(dm, type);
2063 /* layers are store per face for editmesh, we convert to a temporary
2064 * data layer array in the derivedmesh when these are requested */
2065 if (type == CD_MTFACE || type == CD_MCOL) {
2066 const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
2070 index = CustomData_get_layer_index(&bm->pdata, type_from);
2073 /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
2074 BMLoop *(*looptris)[3] = bmdm->em->looptris;
2075 const int size = CustomData_sizeof(type);
2078 DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
2079 index = CustomData_get_layer_index(&dm->faceData, type);
2080 dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
2082 data = datalayer = DM_get_tessface_data_layer(dm, type);
2084 if (type == CD_MTFACE) {
2085 const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
2086 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
2088 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
2089 BMFace *efa = looptris[i][0]->f;
2091 // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
2092 bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
2094 ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata));
2095 for (j = 0; j < 3; j++) {
2096 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
2097 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
2098 copy_v2_v2(((MTFace *)data)->uv[j], ((const MLoopUV *)bmdata)->uv);
2103 const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
2104 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
2105 for (j = 0; j < 3; j++) {
2106 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
2107 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
2108 MESH_MLOOPCOL_TO_MCOL(((const MLoopCol *)bmdata), (((MCol *)data) + j));
2115 /* Special handling for CD_TESSLOOPNORMAL, we generate it on demand as well. */
2116 if (type == CD_TESSLOOPNORMAL) {
2117 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
2120 BMLoop *(*looptris)[3] = bmdm->em->looptris;
2121 short (*tlnors)[4][3], (*tlnor)[4][3];
2124 DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
2125 index = CustomData_get_layer_index(&dm->faceData, type);
2126 dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
2128 tlnor = tlnors = DM_get_tessface_data_layer(dm, type);
2130 BM_mesh_elem_index_ensure(bm, BM_LOOP);
2132 for (i = 0; i < bmdm->em->tottri; i++, tlnor++, looptris++) {
2133 for (j = 0; j < 3; j++) {
2134 normal_float_to_short_v3((*tlnor)[j], lnors[BM_elem_index_get((*looptris)[j])]);
2143 static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
2145 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2146 BMesh *bm = bmdm->em->bm;
2151 if (bmdm->vertexCos) {
2152 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2153 copy_v3_v3(r_cos[i], bmdm->vertexCos[i]);
2157 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2158 copy_v3_v3(r_cos[i], eve->co);
2163 static void emDM_release(DerivedMesh *dm)
2165 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2167 if (DM_release(dm)) {
2168 if (bmdm->vertexCos) {
2169 MEM_freeN((void *)bmdm->vertexCos);
2170 if (bmdm->vertexNos) {
2171 MEM_freeN((void *)bmdm->vertexNos);
2173 if (bmdm->polyNos) {
2174 MEM_freeN((void *)bmdm->polyNos);
2178 if (bmdm->polyCos) {
2179 MEM_freeN((void *)bmdm->polyCos);
2186 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
2188 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2190 return &bmdm->em->bm->vdata;
2193 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
2195 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2197 return &bmdm->em->bm->edata;
2200 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
2202 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2204 return &bmdm->dm.faceData;
2207 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
2209 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2211 return &bmdm->em->bm->ldata;
2214 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
2216 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2218 return &bmdm->em->bm->pdata;
2222 DerivedMesh *getEditDerivedBMesh(
2225 float (*vertexCos)[3])
2227 EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
2229 const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
2230 const int cd_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
2234 DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, bm->totvert,
2235 bm->totedge, em->tottri, bm->totloop, bm->totface);
2237 /* could also get from the objects mesh directly */
2238 bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
2240 bmdm->dm.getVertCos = emDM_getVertCos;
2241 bmdm->dm.getMinMax = emDM_getMinMax;
2243 bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
2244 bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
2245 bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
2246 bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
2247 bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
2249 bmdm->dm.getNumVerts = emDM_getNumVerts;
2250 bmdm->dm.getNumEdges = emDM_getNumEdges;
2251 bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
2252 bmdm->dm.getNumLoops = emDM_getNumLoops;
2253 bmdm->dm.getNumPolys = emDM_getNumPolys;
2255 bmdm->dm.getLoopTriArray = emDM_getLoopTriArray;
2257 bmdm->dm.getVert = emDM_getVert;
2258 bmdm->dm.getVertCo = emDM_getVertCo;
2259 bmdm->dm.getVertNo = emDM_getVertNo;
2260 bmdm->dm.getPolyNo = emDM_getPolyNo;
2261 bmdm->dm.getEdge = emDM_getEdge;
2262 bmdm->dm.getTessFace = emDM_getTessFace;
2263 bmdm->dm.copyVertArray = emDM_copyVertArray;
2264 bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
2265 bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
2266 bmdm->dm.copyLoopArray = emDM_copyLoopArray;
2267 bmdm->dm.copyPolyArray = emDM_copyPolyArray;
2269 bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
2271 bmdm->dm.calcNormals = emDM_calcNormals;
2272 bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
2273 bmdm->dm.calcLoopNormalsSpaceArray = emDM_calcLoopNormalsSpaceArray;
2274 bmdm->dm.calcLoopTangents = emDM_calc_loop_tangents;
2275 bmdm->dm.recalcTessellation = emDM_recalcTessellation;
2276 bmdm->dm.recalcLoopTri = emDM_recalcLoopTri;
2278 bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
2279 bmdm->dm.foreachMappedLoop = emDM_foreachMappedLoop;
2280 bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
2281 bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
2283 bmdm->dm.drawEdges = emDM_drawEdges;
2284 bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
2285 bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
2286 bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
2287 bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
2288 bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
2289 bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
2290 bmdm->dm.drawFacesTex = emDM_drawFacesTex;
2291 bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
2292 bmdm->dm.drawUVEdges = emDM_drawUVEdges;
2294 bmdm->dm.release = emDM_release;
2296 bmdm->vertexCos = (const float (*)[3])vertexCos;
2297 bmdm->dm.deformedOnly = (vertexCos != NULL);
2299 if (cd_dvert_offset != -1) {
2304 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
2306 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2307 DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
2308 BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
2312 if (cd_skin_offset != -1) {
2317 DM_add_vert_layer(&bmdm->dm, CD_MVERT_SKIN, CD_CALLOC, NULL);
2319 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2320 DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN,
2321 BM_ELEM_CD_GET_VOID_P(eve, cd_skin_offset));
2325 return (DerivedMesh *)bmdm;
2330 /* -------------------------------------------------------------------- */
2331 /* StatVis Functions */
2333 static void axis_from_enum_v3(float v[3], const char axis)
2336 if (axis < 3) v[axis] = 1.0f;
2337 else v[axis - 3] = -1.0f;
2340 static void statvis_calc_overhang(
2342 const float (*polyNos)[3],
2343 /* values for calculating */
2344 const float min, const float max, const char axis,
2346 unsigned char (*r_face_colors)[4])
2353 const float minmax_irange = 1.0f / (max - min);
2357 unsigned char col_fallback[4] = {64, 64, 64, 255}; /* gray */
2358 unsigned char col_fallback_max[4] = {0, 0, 0, 255}; /* max color */
2360 BLI_assert(min <= max);
2362 axis_from_enum_v3(dir, axis);
2364 if (LIKELY(em->ob)) {
2365 mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
2372 weight_to_rgb(fcol, 1.0f);
2373 rgb_float_to_uchar(col_fallback_max, fcol);
2376 /* now convert into global space */
2377 BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2378 float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
2381 if ((is_max = (fac <= max)) && (fac >= min)) {
2383 fac = (fac - min) * minmax_irange;
2385 CLAMP(fac, 0.0f, 1.0f);
2386 weight_to_rgb(fcol, fac);
2387 rgb_float_to_uchar(r_face_colors[index], fcol);
2390 const unsigned char *fallback = is_max ? col_fallback_max : col_fallback;
2391 copy_v4_v4_uchar(r_face_colors[index], fallback);
2396 /* so we can use jitter values for face interpolation */
2397 static void uv_from_jitter_v2(float uv[2])
2401 if (uv[0] + uv[1] > 1.0f) {
2402 uv[0] = 1.0f - uv[0];
2403 uv[1] = 1.0f - uv[1];
2406 CLAMP(uv[0], 0.0f, 1.0f);
2407 CLAMP(uv[1], 0.0f, 1.0f);
2410 static void statvis_calc_thickness(
2412 const float (*vertexCos)[3],
2413 /* values for calculating */
2414 const float min, const float max, const int samples,
2416 unsigned char (*r_face_colors)[4])
2418 const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
2419 float *face_dists = (float *)r_face_colors; /* cheating */
2420 const bool use_jit = samples < 32;
2421 float jit_ofs[32][2];
2423 const int tottri = em->tottri;
2424 const float minmax_irange = 1.0f / (max - min);
2427 struct BMLoop *(*looptris)[3] = em->looptris;
2430 const unsigned char col_fallback[4] = {64, 64, 64, 255};
2432 struct BMBVHTree *bmtree;
2434 BLI_assert(min <= max);
2436 copy_vn_fl(face_dists, em->bm->totface, max);
2440 BLI_assert(samples < 32);
2441 BLI_jitter_init(jit_ofs, samples);
2443 for (j = 0; j < samples; j++) {
2444 uv_from_jitter_v2(jit_ofs[j]);
2448 BM_mesh_elem_index_ensure(bm, BM_FACE);
2450 BM_mesh_elem_index_ensure(bm, BM_VERT);
2453 bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
2455 for (i = 0; i < tottri; i++) {
2457 BMLoop **ltri = looptris[i];
2458 const int index = BM_elem_index_get(ltri[0]->f);
2459 const float *cos[3];
2464 cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
2465 cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
2466 cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
2469 cos[0] = ltri[0]->v->co;
2470 cos[1] = ltri[1]->v->co;
2471 cos[2] = ltri[2]->v->co;
2474 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
2476 #define FACE_RAY_TEST_ANGLE \
2477 f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \
2478 &dist, NULL, NULL); \
2479 if (f_hit && dist < face_dists[index]) { \
2480 float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
2481 angle_fac = 1.0f - angle_fac; \
2482 angle_fac = angle_fac * angle_fac * angle_fac; \
2483 angle_fac = 1.0f - angle_fac; \
2484 dist /= angle_fac; \
2485 if (dist < face_dists[index]) { \
2486 face_dists[index] = dist; \
2492 for (j = 0; j < samples; j++) {
2493 float dist = face_dists[index];
2494 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
2495 madd_v3_v3fl(ray_co, ray_no, eps_offset);
2497 FACE_RAY_TEST_ANGLE;
2501 float dist = face_dists[index];
2502 mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
2503 madd_v3_v3fl(ray_co, ray_no, eps_offset);
2505 FACE_RAY_TEST_ANGLE;
2509 BKE_bmbvh_free(bmtree);
2511 /* convert floats into color! */
2512 for (i = 0; i < bm->totface; i++) {
2513 float fac = face_dists[i];
2515 /* important not '<=' */
2518 fac = (fac - min) * minmax_irange;
2520 CLAMP(fac, 0.0f, 1.0f);
2521 weight_to_rgb(fcol, fac);
2522 rgb_float_to_uchar(r_face_colors[i], fcol);
2525 copy_v4_v4_uchar(r_face_colors[i], col_fallback);
2530 static void statvis_calc_intersect(
2532 const float (*vertexCos)[3],
2534 unsigned char (*r_face_colors)[4])
2540 // const char col_fallback[4] = {64, 64, 64, 255};
2542 unsigned char col[3];
2544 struct BMBVHTree *bmtree;
2545 BVHTreeOverlap *overlap;
2546 unsigned int overlap_len;
2548 memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
2550 BM_mesh_elem_index_ensure(bm, BM_FACE);
2552 BM_mesh_elem_index_ensure(bm, BM_VERT);
2555 bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
2557 overlap = BKE_bmbvh_overlap(bmtree, bmtree, &overlap_len);
2559 /* same for all faces */
2560 weight_to_rgb(fcol, 1.0f);
2561 rgb_float_to_uchar(col, fcol);
2564 for (i = 0; i < overlap_len; i++) {
2565 BMFace *f_hit_pair[2] = {
2566 em->looptris[overlap[i].indexA][0]->f,
2567 em->looptris[overlap[i].indexB][0]->f,
2571 for (j = 0; j < 2; j++) {
2572 BMFace *f_hit = f_hit_pair[j];
2575 index = BM_elem_index_get(f_hit);
2577 copy_v3_v3_uchar(r_face_colors[index], col);
2583 BKE_bmbvh_free(bmtree);
2586 static void statvis_calc_distort(
2588 const float (*vertexCos)[3], const float (*polyNos)[3],
2589 /* values for calculating */
2590 const float min, const float max,
2592 unsigned char (*r_face_colors)[4])
2599 const float minmax_irange = 1.0f / (max - min);
2602 const unsigned char col_fallback[4] = {64, 64, 64, 255};
2604 /* now convert into global space */
2605 BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2612 BMLoop *l_iter, *l_first;
2614 f_no = polyNos[index];
2621 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2625 normal_tri_v3(no_corner,
2626 vertexCos[BM_elem_index_get(l_iter->prev->v)],
2627 vertexCos[BM_elem_index_get(l_iter->v)],
2628 vertexCos[BM_elem_index_get(l_iter->next->v)]);
2631 BM_loop_calc_face_normal(l_iter, no_corner);
2633 /* simple way to detect (what is most likely) concave */
2634 if (dot_v3v3(f_no, no_corner) < 0.0f) {
2635 negate_v3(no_corner);
2637 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
2638 } while ((l_iter = l_iter->next) != l_first);
2645 fac = (fac - min) * minmax_irange;
2646 CLAMP(fac, 0.0f, 1.0f);
2647 weight_to_rgb(fcol, fac);
2648 rgb_float_to_uchar(r_face_colors[index], fcol);
2651 copy_v4_v4_uchar(r_face_colors[index], col_fallback);
2656 static void statvis_calc_sharp(
2658 const float (*vertexCos)[3],
2659 /* values for calculating */
2660 const float min, const float max,
2662 unsigned char (*r_vert_colors)[4])
2664 float *vert_angles = (float *)r_vert_colors; /* cheating */
2669 const float minmax_irange = 1.0f / (max - min);
2673 const unsigned char col_fallback[4] = {64, 64, 64, 255};
2675 (void)vertexCos; /* TODO */
2677 copy_vn_fl(vert_angles, em->bm->totvert, -M_PI);
2679 /* first assign float values to verts */
2680 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2681 float angle = BM_edge_calc_face_angle_signed(e);
2682 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
2683 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
2684 *col1 = max_ff(*col1, angle);
2685 *col2 = max_ff(*col2, angle);
2688 /* convert floats into color! */
2689 for (i = 0; i < bm->totvert; i++) {
2690 float fac = vert_angles[i];
2692 /* important not '<=' */
2695 fac = (fac - min) * minmax_irange;
2696 CLAMP(fac, 0.0f, 1.0f);
2697 weight_to_rgb(fcol, fac);
2698 rgb_float_to_uchar(r_vert_colors[i], fcol);
2701 copy_v4_v4_uchar(r_vert_colors[i], col_fallback);
2706 void BKE_editmesh_statvis_calc(
2707 BMEditMesh *em, DerivedMesh *dm,
2708 const MeshStatVis *statvis)
2710 EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2711 BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
2713 switch (statvis->type) {
2714 case SCE_STATVIS_OVERHANG:
2716 BKE_editmesh_color_ensure(em, BM_FACE);
2717 statvis_calc_overhang(
2718 em, bmdm ? bmdm->polyNos : NULL,
2719 statvis->overhang_min / (float)M_PI,
2720 statvis->overhang_max / (float)M_PI,
2721 statvis->overhang_axis,
2722 em->derivedFaceColor);
2725 case SCE_STATVIS_THICKNESS:
2727 const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
2728 BKE_editmesh_color_ensure(em, BM_FACE);
2729 statvis_calc_thickness(
2730 em, bmdm ? bmdm->vertexCos : NULL,
2731 statvis->thickness_min * scale,
2732 statvis->thickness_max * scale,
2733 statvis->thickness_samples,
2734 em->derivedFaceColor);
2737 case SCE_STATVIS_INTERSECT:
2739 BKE_editmesh_color_ensure(em, BM_FACE);
2740 statvis_calc_intersect(
2741 em, bmdm ? bmdm->vertexCos : NULL,
2742 em->derivedFaceColor);
2745 case SCE_STATVIS_DISTORT:
2747 BKE_editmesh_color_ensure(em, BM_FACE);
2750 emDM_ensurePolyNormals(bmdm);
2752 statvis_calc_distort(
2753 em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL,
2754 statvis->distort_min,
2755 statvis->distort_max,
2756 em->derivedFaceColor);
2759 case SCE_STATVIS_SHARP:
2761 BKE_editmesh_color_ensure(em, BM_VERT);
2763 em, bmdm ? bmdm->vertexCos : NULL,
2766 /* in this case they are vertex colors */
2767 em->derivedVertColor);
2775 /* -------------------------------------------------------------------- */
2776 /* Editmesh Vert Coords */
2778 struct CageUserData {
2780 float (*cos_cage)[3];
2781 BLI_bitmap *visit_bitmap;
2784 static void cage_mapped_verts_callback(
2785 void *userData, int index, const float co[3],
2786 const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2788 struct CageUserData *data = userData;
2790 if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
2791 BLI_BITMAP_ENABLE(data->visit_bitmap, index);
2792 copy_v3_v3(data->cos_cage[index], co);
2796 float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
2798 DerivedMesh *cage, *final;
2799 BLI_bitmap *visit_bitmap;
2800 struct CageUserData data;
2801 float (*cos_cage)[3];
2803 cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final);
2804 cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
2806 /* when initializing cage verts, we only want the first cage coordinate for each vertex,
2807 * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
2808 visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2810 data.totvert = em->bm->totvert;
2811 data.cos_cage = cos_cage;
2812 data.visit_bitmap = visit_bitmap;
2814 cage->foreachMappedVert(cage, cage_mapped_verts_callback, &data, DM_FOREACH_NOP);
2816 MEM_freeN(visit_bitmap);
2819 *r_numVerts = em->bm->totvert;