Blender V5.0
extract_mesh_vbo_mesh_analysis.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_jitter_2d.h"
14#include "BLI_map.hh"
15#include "BLI_math_geom.h"
16#include "BLI_math_matrix.h"
17#include "BLI_math_rotation.h"
18#include "BLI_ordered_edge.hh"
19
20#include "BKE_bvhutils.hh"
21#include "BKE_editmesh.hh"
22#include "BKE_editmesh_bvh.hh"
23#include "BKE_editmesh_cache.hh"
24
25#include "extract_mesh.hh"
26
27namespace blender::draw {
28
29static void axis_from_enum_v3(float v[3], const char axis)
30{
31 zero_v3(v);
32 if (axis < 3) {
33 v[axis] = 1.0f;
34 }
35 else {
36 v[axis - 3] = -1.0f;
37 }
38}
39
40BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
41{
42 if (fac < min) {
43 fac = 1.0f;
44 }
45 else if (fac > max) {
46 fac = -1.0f;
47 }
48 else {
49 fac = (fac - min) * minmax_irange;
50 fac = 1.0f - fac;
51 CLAMP(fac, 0.0f, 1.0f);
52 }
53 return fac;
54}
55
57 const float4x4 &object_to_world,
58 MutableSpan<float> r_overhang)
59{
60 const MeshStatVis *statvis = &mr.toolsettings->statvis;
61 const float min = statvis->overhang_min / float(M_PI);
62 const float max = statvis->overhang_max / float(M_PI);
63 const char axis = statvis->overhang_axis;
64 float dir[3];
65 const float minmax_irange = 1.0f / (max - min);
66
67 BLI_assert(min <= max);
68
69 axis_from_enum_v3(dir, axis);
70
71 /* now convert into global space */
72 mul_transposed_mat3_m4_v3(object_to_world.ptr(), dir);
73 normalize_v3(dir);
74
76 BMEditMesh *em = mr.edit_bmesh;
77 BMIter iter;
78 BMesh *bm = em->bm;
79 BMFace *f;
80 int l_index = 0;
81 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
82 float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / float(M_PI);
83 fac = overhang_remap(fac, min, max, minmax_irange);
84 for (int i = 0; i < f->len; i++, l_index++) {
85 r_overhang[l_index] = fac;
86 }
87 }
88 }
89 else {
90 for (const int face_i : mr.faces.index_range()) {
91 float fac = angle_normalized_v3v3(mr.face_normals[face_i], dir) / float(M_PI);
92 fac = overhang_remap(fac, min, max, minmax_irange);
93 for (const int loop_i : mr.faces[face_i]) {
94 r_overhang[loop_i] = fac;
95 }
96 }
97 }
98}
99
103static void uv_from_jitter_v2(float uv[2])
104{
105 uv[0] += 0.5f;
106 uv[1] += 0.5f;
107 if (uv[0] + uv[1] > 1.0f) {
108 uv[0] = 1.0f - uv[0];
109 uv[1] = 1.0f - uv[1];
110 }
111
112 clamp_v2(uv, 0.0f, 1.0f);
113}
114
115BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
116{
117 /* important not '<=' */
118 if (fac < max) {
119 fac = (fac - min) * minmax_irange;
120 fac = 1.0f - fac;
121 CLAMP(fac, 0.0f, 1.0f);
122 }
123 else {
124 fac = -1.0f;
125 }
126 return fac;
127}
128
130 const float4x4 &object_to_world,
131 MutableSpan<float> r_thickness)
132{
133 const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
134 /* cheating to avoid another allocation */
135 float *face_dists = r_thickness.data() + (mr.corners_num - mr.faces_num);
136 const float scale = 1.0f / mat4_to_scale(object_to_world.ptr());
137 const MeshStatVis *statvis = &mr.toolsettings->statvis;
138 const float min = statvis->thickness_min * scale;
139 const float max = statvis->thickness_max * scale;
140 const float minmax_irange = 1.0f / (max - min);
141 const int samples = statvis->thickness_samples;
142 float jit_ofs[32][2];
143 BLI_assert(samples <= 32);
144 BLI_assert(min <= max);
145
146 copy_vn_fl(face_dists, mr.faces_num, max);
147
148 BLI_jitter_init(jit_ofs, samples);
149 for (int j = 0; j < samples; j++) {
150 uv_from_jitter_v2(jit_ofs[j]);
151 }
152
154 BMEditMesh *em = mr.edit_bmesh;
155 BMesh *bm = em->bm;
157
158 BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false);
159 const Span<std::array<BMLoop *, 3>> looptris = em->looptris;
160 for (int i = 0; i < mr.corner_tris_num; i++) {
161 const BMLoop *const *ltri = looptris[i].data();
162 const int index = BM_elem_index_get(ltri[0]->f);
163 const float *cos[3] = {
164 bm_vert_co_get(mr, ltri[0]->v),
165 bm_vert_co_get(mr, ltri[1]->v),
166 bm_vert_co_get(mr, ltri[2]->v),
167 };
168 float ray_co[3];
169 float ray_no[3];
170
171 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
172
173 for (int j = 0; j < samples; j++) {
174 float dist = face_dists[index];
175 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
176 madd_v3_v3fl(ray_co, ray_no, eps_offset);
177
178 BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, nullptr, nullptr);
179 if (f_hit && dist < face_dists[index]) {
180 float angle_fac = fabsf(
181 dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit)));
182 angle_fac = 1.0f - angle_fac;
183 angle_fac = angle_fac * angle_fac * angle_fac;
184 angle_fac = 1.0f - angle_fac;
185 dist /= angle_fac;
186 face_dists[index] = std::min(dist, face_dists[index]);
187 }
188 }
189 }
190 BKE_bmbvh_free(bmtree);
191
192 BMIter iter;
193 BMFace *f;
194 int l_index = 0;
195 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
196 float fac = face_dists[BM_elem_index_get(f)];
197 fac = thickness_remap(fac, min, max, minmax_irange);
198 for (int i = 0; i < f->len; i++, l_index++) {
199 r_thickness[l_index] = fac;
200 }
201 }
202 }
203 else {
204 bke::BVHTreeFromMesh treeData = mr.mesh->bvh_corner_tris();
205 const BVHTree *tree = treeData.tree;
206 if (tree == nullptr) {
207 return;
208 }
209
210 const Span<int3> corner_tris = mr.mesh->corner_tris();
211 const Span<int> tri_faces = mr.mesh->corner_tri_faces();
212 for (const int i : corner_tris.index_range()) {
213 const int index = tri_faces[i];
214 const float *cos[3] = {mr.vert_positions[mr.corner_verts[corner_tris[i][0]]],
215 mr.vert_positions[mr.corner_verts[corner_tris[i][1]]],
216 mr.vert_positions[mr.corner_verts[corner_tris[i][2]]]};
217 float ray_co[3];
218 float ray_no[3];
219
220 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
221
222 for (int j = 0; j < samples; j++) {
223 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
224 madd_v3_v3fl(ray_co, ray_no, eps_offset);
225
226 BVHTreeRayHit hit;
227 hit.index = -1;
228 hit.dist = face_dists[index];
230 tree, ray_co, ray_no, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) &&
231 hit.dist < face_dists[index])
232 {
233 float angle_fac = fabsf(dot_v3v3(mr.face_normals[index], hit.no));
234 angle_fac = 1.0f - angle_fac;
235 angle_fac = angle_fac * angle_fac * angle_fac;
236 angle_fac = 1.0f - angle_fac;
237 hit.dist /= angle_fac;
238 face_dists[index] = std::min(hit.dist, face_dists[index]);
239 }
240 }
241 }
242
243 for (const int face_i : mr.faces.index_range()) {
244 float fac = face_dists[face_i];
245 fac = thickness_remap(fac, min, max, minmax_irange);
246 for (const int loop_i : mr.faces[face_i]) {
247 r_thickness[loop_i] = fac;
248 }
249 }
250 }
251}
252
260
261static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int /*thread*/)
262{
263 BVHTree_OverlapData *data = static_cast<BVHTree_OverlapData *>(userdata);
264
265 if (UNLIKELY(data->tri_faces[index_a] == data->tri_faces[index_b])) {
266 return false;
267 }
268
269 const int3 tri_a = data->corner_tris[index_a];
270 const int3 tri_b = data->corner_tris[index_b];
271
272 const float *tri_a_co[3] = {data->positions[data->corner_verts[tri_a[0]]],
273 data->positions[data->corner_verts[tri_a[1]]],
274 data->positions[data->corner_verts[tri_a[2]]]};
275 const float *tri_b_co[3] = {data->positions[data->corner_verts[tri_b[0]]],
276 data->positions[data->corner_verts[tri_b[1]]],
277 data->positions[data->corner_verts[tri_b[2]]]};
278 float ix_pair[2][3];
279 int verts_shared = 0;
280
281 verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
282 ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
283
284 /* if 2 points are shared, bail out */
285 if (verts_shared >= 2) {
286 return false;
287 }
288
289 return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) &&
290 /* if we share a vertex, check the intersection isn't a 'point' */
291 ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
292}
293
295{
296 for (int l_index = 0; l_index < mr.corners_num; l_index++) {
297 r_intersect[l_index] = -1.0f;
298 }
299
301 BMEditMesh *em = mr.edit_bmesh;
302 uint overlap_len;
303 BMesh *bm = em->bm;
304
306
307 BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false);
308 BVHTreeOverlap *overlap = BKE_bmbvh_overlap_self(bmtree, &overlap_len);
309
310 if (overlap) {
311 for (int i = 0; i < overlap_len; i++) {
312 BMFace *f_hit_pair[2] = {
313 em->looptris[overlap[i].indexA][0]->f,
314 em->looptris[overlap[i].indexB][0]->f,
315 };
316 for (int j = 0; j < 2; j++) {
317 BMFace *f_hit = f_hit_pair[j];
318 BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit);
319 int l_index = BM_elem_index_get(l_first);
320 for (int k = 0; k < f_hit->len; k++, l_index++) {
321 r_intersect[l_index] = 1.0f;
322 }
323 }
324 }
325 MEM_freeN(overlap);
326 }
327
328 BKE_bmbvh_free(bmtree);
329 }
330 else {
331 uint overlap_len;
332 bke::BVHTreeFromMesh treeData = mr.mesh->bvh_corner_tris();
333 const BVHTree *tree = treeData.tree;
334 if (tree == nullptr) {
335 return;
336 }
337
339 data.positions = mr.vert_positions;
340 data.corner_verts = mr.corner_verts;
341 data.corner_tris = mr.mesh->corner_tris();
342 data.tri_faces = mr.mesh->corner_tri_faces();
344
346 if (overlap) {
347 for (int i = 0; i < overlap_len; i++) {
348
349 for (const IndexRange f_hit : {mr.faces[data.tri_faces[overlap[i].indexA]],
350 mr.faces[data.tri_faces[overlap[i].indexB]]})
351 {
352 int l_index = f_hit.start();
353 for (int k = 0; k < f_hit.size(); k++, l_index++) {
354 r_intersect[l_index] = 1.0f;
355 }
356 }
357 }
358 MEM_freeN(overlap);
359 }
360 }
361}
362
363BLI_INLINE float distort_remap(float fac, float min, float /*max*/, float minmax_irange)
364{
365 if (fac >= min) {
366 fac = (fac - min) * minmax_irange;
367 CLAMP(fac, 0.0f, 1.0f);
368 }
369 else {
370 /* fallback */
371 fac = -1.0f;
372 }
373 return fac;
374}
375
377{
378 const MeshStatVis *statvis = &mr.toolsettings->statvis;
379 const float min = statvis->distort_min;
380 const float max = statvis->distort_max;
381 const float minmax_irange = 1.0f / (max - min);
382
384 BMEditMesh *em = mr.edit_bmesh;
385 BMIter iter;
386 BMesh *bm = em->bm;
387 BMFace *f;
388
389 int l_index = 0;
390 int f_index = 0;
391 BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) {
392 float fac = -1.0f;
393
394 if (f->len > 3) {
395 BMLoop *l_iter, *l_first;
396
397 fac = 0.0f;
398 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
399 do {
400 const float *no_face;
401 float no_corner[3];
402 if (!mr.bm_vert_coords.is_empty()) {
403 no_face = mr.bm_face_normals[f_index];
405 l_iter,
406 no_face,
407 reinterpret_cast<const float (*)[3]>(mr.bm_vert_coords.data()),
408 no_corner);
409 }
410 else {
411 no_face = f->no;
412 BM_loop_calc_face_normal_safe(l_iter, no_corner);
413 }
414
415 /* simple way to detect (what is most likely) concave */
416 if (dot_v3v3(no_face, no_corner) < 0.0f) {
417 negate_v3(no_corner);
418 }
419 fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner));
420
421 } while ((l_iter = l_iter->next) != l_first);
422 fac *= 2.0f;
423 }
424
425 fac = distort_remap(fac, min, max, minmax_irange);
426 for (int i = 0; i < f->len; i++, l_index++) {
427 r_distort[l_index] = fac;
428 }
429 }
430 }
431 else {
432 for (const int face_index : mr.faces.index_range()) {
433 const IndexRange face = mr.faces[face_index];
434 float fac = -1.0f;
435
436 if (face.size() > 3) {
437 const float *f_no = mr.face_normals[face_index];
438 fac = 0.0f;
439
440 for (const int corner : face.drop_front(1)) {
441 const int corner_prev = bke::mesh::face_corner_prev(face, corner);
442 const int corner_next = bke::mesh::face_corner_next(face, corner);
443 float no_corner[3];
444 normal_tri_v3(no_corner,
445 mr.vert_positions[mr.corner_verts[corner_prev]],
446 mr.vert_positions[mr.corner_verts[corner]],
447 mr.vert_positions[mr.corner_verts[corner_next]]);
448 /* simple way to detect (what is most likely) concave */
449 if (dot_v3v3(f_no, no_corner) < 0.0f) {
450 negate_v3(no_corner);
451 }
452 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
453 }
454 fac *= 2.0f;
455 }
456
457 fac = distort_remap(fac, min, max, minmax_irange);
458 for (const int corner : face) {
459 r_distort[corner] = fac;
460 }
461 }
462 }
463}
464
465BLI_INLINE float sharp_remap(float fac, float min, float /*max*/, float minmax_irange)
466{
467 /* important not '>=' */
468 if (fac > min) {
469 fac = (fac - min) * minmax_irange;
470 CLAMP(fac, 0.0f, 1.0f);
471 }
472 else {
473 /* fallback */
474 fac = -1.0f;
475 }
476 return fac;
477}
478
480{
481 const MeshStatVis *statvis = &mr.toolsettings->statvis;
482 const float min = statvis->sharp_min;
483 const float max = statvis->sharp_max;
484 const float minmax_irange = 1.0f / (max - min);
485
486 /* Can we avoid this extra allocation? */
487 float *vert_angles = MEM_malloc_arrayN<float>(mr.verts_num, __func__);
488 copy_vn_fl(vert_angles, mr.verts_num, -M_PI);
489
491 BMEditMesh *em = mr.edit_bmesh;
492 BMIter iter;
493 BMesh *bm = em->bm;
494 BMFace *efa;
495 BMEdge *e;
496 /* first assign float values to verts */
497 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
499 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
500 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
501 *col1 = max_ff(*col1, angle);
502 *col2 = max_ff(*col2, angle);
503 }
504 /* Copy vert value to loops. */
505 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
506 BMLoop *l_iter, *l_first;
507 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
508 do {
509 int l_index = BM_elem_index_get(l_iter);
510 int v_index = BM_elem_index_get(l_iter->v);
511 r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange);
512 } while ((l_iter = l_iter->next) != l_first);
513 }
514 }
515 else {
516 /* first assign float values to verts */
517
519 eh.reserve(mr.edges_num);
520
521 for (int face_index = 0; face_index < mr.faces_num; face_index++) {
522 const IndexRange face = mr.faces[face_index];
523 for (const int corner : face) {
524 const int vert_curr = mr.corner_verts[corner];
525 const int vert_next = mr.corner_verts[bke::mesh::face_corner_next(face, corner)];
526 float angle;
527 eh.add_or_modify(
528 {vert_curr, vert_next},
529 [&](int *value) { *value = face_index; },
530 [&](int *value) {
531 const int other_face_index = *value;
532 if (other_face_index == -1) {
533 /* non-manifold edge */
534 angle = DEG2RADF(90.0f);
535 return;
536 }
537 const float *f1_no = mr.face_normals[face_index];
538 const float *f2_no = mr.face_normals[other_face_index];
539 angle = angle_normalized_v3v3(f1_no, f2_no);
540 angle = is_edge_convex_v3(mr.vert_positions[vert_curr],
541 mr.vert_positions[vert_next],
542 f1_no,
543 f2_no) ?
544 angle :
545 -angle;
546 /* Tag as manifold. */
547 *value = -1;
548 });
549 float *col1 = &vert_angles[vert_curr];
550 float *col2 = &vert_angles[vert_next];
551 *col1 = max_ff(*col1, angle);
552 *col2 = max_ff(*col2, angle);
553 }
554 }
555 /* Remaining non manifold edges. */
556 for (const OrderedEdge &edge : eh.keys()) {
557 const float angle = DEG2RADF(90.0f);
558 float *col1 = &vert_angles[edge.v_low];
559 float *col2 = &vert_angles[edge.v_high];
560 *col1 = max_ff(*col1, angle);
561 *col2 = max_ff(*col2, angle);
562 }
563
564 for (int l_index = 0; l_index < mr.corners_num; l_index++) {
565 const int vert = mr.corner_verts[l_index];
566 r_sharp[l_index] = sharp_remap(vert_angles[vert], min, max, minmax_irange);
567 }
568 }
569
570 MEM_freeN(vert_angles);
571}
572
574{
575 static const GPUVertFormat format = GPU_vertformat_from_attribute("weight",
576 gpu::VertAttrType::SFLOAT_32);
577
580 MutableSpan<float> vbo_data = vbo->data<float>();
581
582 switch (mr.toolsettings->statvis.type) {
584 statvis_calc_overhang(mr, object_to_world, vbo_data);
585 break;
587 statvis_calc_thickness(mr, object_to_world, vbo_data);
588 break;
590 statvis_calc_intersect(mr, vbo_data);
591 break;
593 statvis_calc_distort(mr, vbo_data);
594 break;
596 statvis_calc_sharp(mr, vbo_data);
597 break;
598 }
599 return vbo;
600}
601
602} // namespace blender::draw
BMBVHTree * BKE_bmbvh_new_from_editmesh(struct BMEditMesh *em, int flag, const blender::float3 *cos_cage, bool cos_cage_free)
struct BMFace * BKE_bmbvh_ray_cast(const BMBVHTree *tree, const float co[3], const float dir[3], float radius, float *r_dist, float r_hitout[3], float r_cagehit[3])
struct BVHTreeOverlap * BKE_bmbvh_overlap_self(const BMBVHTree *bmtree, unsigned int *r_overlap_tot)
void BKE_bmbvh_free(BMBVHTree *tree)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_INLINE
void BLI_jitter_init(float(*jitarr)[2], int num)
Definition jitter_2d.cc:127
BVHTreeOverlap * BLI_bvhtree_overlap_self(const BVHTree *tree, unsigned int *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
MINLINE float max_ff(float a, float b)
#define DEG2RADF(_deg)
#define M_PI
bool isect_tri_tri_v3(const float t_a0[3], const float t_a1[3], const float t_a2[3], const float t_b0[3], const float t_b1[3], const float t_b2[3], float r_i1[3], float r_i2[3])
bool is_edge_convex_v3(const float v1[3], const float v2[3], const float f1_no[3], const float f2_no[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:41
float mat4_to_scale(const float mat[4][4])
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void copy_vn_fl(float *array_tar, int size, float val)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v3(float r[3])
MINLINE void clamp_v2(float vec[2], float min, float max)
MINLINE void zero_v3(float r[3])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3v3_uv(float p[3], const float v1[3], const float v2[3], const float v3[3], const float uv[2])
MINLINE float normalize_v3(float n[3])
unsigned int uint
#define CLAMP(a, b, c)
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
@ SCE_STATVIS_DISTORT
@ SCE_STATVIS_SHARP
@ SCE_STATVIS_INTERSECT
@ SCE_STATVIS_THICKNESS
@ SCE_STATVIS_OVERHANG
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
GPUVertFormat GPU_vertformat_from_attribute(blender::StringRef name, blender::gpu::VertAttrType type)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
#define BM_FACE_FIRST_LOOP(p)
#define BM_elem_index_get(ele)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_FACES_OF_MESH
BMesh const char void * data
BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
#define BM_FACE
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l, const float normal_fallback[3], float const (*vertexCos)[3], float r_normal[3])
float BM_edge_calc_face_angle_signed(const BMEdge *e)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t size() const
constexpr IndexRange drop_front(int64_t n) const
KeyIterator keys() const &
Definition BLI_map.hh:875
void reserve(int64_t n)
Definition BLI_map.hh:1028
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:481
constexpr T * data() const
Definition BLI_span.hh:539
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
nullptr float
KDTree_3d * tree
Extraction of Mesh data into VBO to feed to GPU.
format
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
int face_corner_prev(const IndexRange face, const int corner)
Definition BKE_mesh.hh:306
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:315
static void statvis_calc_distort(const MeshRenderData &mr, MutableSpan< float > r_distort)
BLI_INLINE float distort_remap(float fac, float min, float, float minmax_irange)
static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int)
static void axis_from_enum_v3(float v[3], const char axis)
static void statvis_calc_thickness(const MeshRenderData &mr, const float4x4 &object_to_world, MutableSpan< float > r_thickness)
BLI_INLINE float sharp_remap(float fac, float min, float, float minmax_irange)
static void statvis_calc_overhang(const MeshRenderData &mr, const float4x4 &object_to_world, MutableSpan< float > r_overhang)
BLI_INLINE const float * bm_face_no_get(const MeshRenderData &mr, const BMFace *efa)
static void uv_from_jitter_v2(float uv[2])
static void statvis_calc_sharp(const MeshRenderData &mr, MutableSpan< float > r_sharp)
static void statvis_calc_intersect(const MeshRenderData &mr, MutableSpan< float > r_intersect)
BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
BLI_INLINE const float * bm_vert_co_get(const MeshRenderData &mr, const BMVert *eve)
gpu::VertBufPtr extract_mesh_analysis(const MeshRenderData &mr, const float4x4 &object_to_world)
BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
std::unique_ptr< gpu::VertBuf, gpu::VertBufDeleter > VertBufPtr
T cos(const AngleRadianBase< T > &a)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 3 > int3
#define fabsf
blender::Array< std::array< BMLoop *, 3 > > looptris
float no[3]
struct BMVert * v
struct BMLoop * next
struct MeshStatVis statvis
const c_style_mat & ptr() const
BVHTree_RayCastCallback raycast_callback
const ToolSettings * toolsettings
OffsetIndices< int > faces
i
Definition text_draw.cc:230