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