Blender  V3.3
extract_mesh_vbo_mesh_analysis.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_edgehash.h"
11 #include "BLI_jitter_2d.h"
12 
13 #include "BKE_bvhutils.h"
14 #include "BKE_editmesh_bvh.h"
15 #include "BKE_editmesh_cache.h"
16 
17 #include "extract_mesh.hh"
18 
19 namespace blender::draw {
20 
21 /* ---------------------------------------------------------------------- */
26  MeshBatchCache *UNUSED(cache),
27  void *buf,
28  void *UNUSED(tls_data))
29 {
30  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
31  static GPUVertFormat format = {0};
32  if (format.attr_len == 0) {
34  }
35 
38 }
39 
40 static void axis_from_enum_v3(float v[3], const char axis)
41 {
42  zero_v3(v);
43  if (axis < 3) {
44  v[axis] = 1.0f;
45  }
46  else {
47  v[axis - 3] = -1.0f;
48  }
49 }
50 
51 BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
52 {
53  if (fac < min) {
54  fac = 1.0f;
55  }
56  else if (fac > max) {
57  fac = -1.0f;
58  }
59  else {
60  fac = (fac - min) * minmax_irange;
61  fac = 1.0f - fac;
62  CLAMP(fac, 0.0f, 1.0f);
63  }
64  return fac;
65 }
66 
67 static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
68 {
69  const MeshStatVis *statvis = &mr->toolsettings->statvis;
70  const float min = statvis->overhang_min / (float)M_PI;
71  const float max = statvis->overhang_max / (float)M_PI;
72  const char axis = statvis->overhang_axis;
73  BMEditMesh *em = mr->edit_bmesh;
74  BMIter iter;
75  BMesh *bm = em->bm;
76  BMFace *f;
77  float dir[3];
78  const float minmax_irange = 1.0f / (max - min);
79 
80  BLI_assert(min <= max);
81 
82  axis_from_enum_v3(dir, axis);
83 
84  /* now convert into global space */
86  normalize_v3(dir);
87 
88  if (mr->extract_type == MR_EXTRACT_BMESH) {
89  int l_index = 0;
90  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
91  float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
92  fac = overhang_remap(fac, min, max, minmax_irange);
93  for (int i = 0; i < f->len; i++, l_index++) {
94  r_overhang[l_index] = fac;
95  }
96  }
97  }
98  else {
99  const MPoly *mp = mr->mpoly;
100  for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
101  float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI;
102  fac = overhang_remap(fac, min, max, minmax_irange);
103  for (int i = 0; i < mp->totloop; i++, l_index++) {
104  r_overhang[l_index] = fac;
105  }
106  }
107  }
108 }
109 
113 static void uv_from_jitter_v2(float uv[2])
114 {
115  uv[0] += 0.5f;
116  uv[1] += 0.5f;
117  if (uv[0] + uv[1] > 1.0f) {
118  uv[0] = 1.0f - uv[0];
119  uv[1] = 1.0f - uv[1];
120  }
121 
122  clamp_v2(uv, 0.0f, 1.0f);
123 }
124 
125 BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
126 {
127  /* important not '<=' */
128  if (fac < max) {
129  fac = (fac - min) * minmax_irange;
130  fac = 1.0f - fac;
131  CLAMP(fac, 0.0f, 1.0f);
132  }
133  else {
134  fac = -1.0f;
135  }
136  return fac;
137 }
138 
139 static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
140 {
141  const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
142  /* cheating to avoid another allocation */
143  float *face_dists = r_thickness + (mr->loop_len - mr->poly_len);
144  BMEditMesh *em = mr->edit_bmesh;
145  const float scale = 1.0f / mat4_to_scale(mr->obmat);
146  const MeshStatVis *statvis = &mr->toolsettings->statvis;
147  const float min = statvis->thickness_min * scale;
148  const float max = statvis->thickness_max * scale;
149  const float minmax_irange = 1.0f / (max - min);
150  const int samples = statvis->thickness_samples;
151  float jit_ofs[32][2];
152  BLI_assert(samples <= 32);
153  BLI_assert(min <= max);
154 
155  copy_vn_fl(face_dists, mr->poly_len, max);
156 
157  BLI_jitter_init(jit_ofs, samples);
158  for (int j = 0; j < samples; j++) {
159  uv_from_jitter_v2(jit_ofs[j]);
160  }
161 
162  if (mr->extract_type == MR_EXTRACT_BMESH) {
163  BMesh *bm = em->bm;
165 
166  struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false);
167  struct BMLoop *(*looptris)[3] = em->looptris;
168  for (int i = 0; i < mr->tri_len; i++) {
169  BMLoop **ltri = looptris[i];
170  const int index = BM_elem_index_get(ltri[0]->f);
171  const float *cos[3] = {
172  bm_vert_co_get(mr, ltri[0]->v),
173  bm_vert_co_get(mr, ltri[1]->v),
174  bm_vert_co_get(mr, ltri[2]->v),
175  };
176  float ray_co[3];
177  float ray_no[3];
178 
179  normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
180 
181  for (int j = 0; j < samples; j++) {
182  float dist = face_dists[index];
183  interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
184  madd_v3_v3fl(ray_co, ray_no, eps_offset);
185 
186  BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, nullptr, nullptr);
187  if (f_hit && dist < face_dists[index]) {
188  float angle_fac = fabsf(
189  dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit)));
190  angle_fac = 1.0f - angle_fac;
191  angle_fac = angle_fac * angle_fac * angle_fac;
192  angle_fac = 1.0f - angle_fac;
193  dist /= angle_fac;
194  if (dist < face_dists[index]) {
195  face_dists[index] = dist;
196  }
197  }
198  }
199  }
200  BKE_bmbvh_free(bmtree);
201 
202  BMIter iter;
203  BMFace *f;
204  int l_index = 0;
205  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
206  float fac = face_dists[BM_elem_index_get(f)];
207  fac = thickness_remap(fac, min, max, minmax_irange);
208  for (int i = 0; i < f->len; i++, l_index++) {
209  r_thickness[l_index] = fac;
210  }
211  }
212  }
213  else {
214  BVHTreeFromMesh treeData = {nullptr};
215 
217  const MLoopTri *mlooptri = mr->mlooptri;
218  for (int i = 0; i < mr->tri_len; i++, mlooptri++) {
219  const int index = mlooptri->poly;
220  const float *cos[3] = {mr->mvert[mr->mloop[mlooptri->tri[0]].v].co,
221  mr->mvert[mr->mloop[mlooptri->tri[1]].v].co,
222  mr->mvert[mr->mloop[mlooptri->tri[2]].v].co};
223  float ray_co[3];
224  float ray_no[3];
225 
226  normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
227 
228  for (int j = 0; j < samples; j++) {
229  interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
230  madd_v3_v3fl(ray_co, ray_no, eps_offset);
231 
232  BVHTreeRayHit hit;
233  hit.index = -1;
234  hit.dist = face_dists[index];
236  tree, ray_co, ray_no, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) &&
237  hit.dist < face_dists[index]) {
238  float angle_fac = fabsf(dot_v3v3(mr->poly_normals[index], hit.no));
239  angle_fac = 1.0f - angle_fac;
240  angle_fac = angle_fac * angle_fac * angle_fac;
241  angle_fac = 1.0f - angle_fac;
242  hit.dist /= angle_fac;
243  if (hit.dist < face_dists[index]) {
244  face_dists[index] = hit.dist;
245  }
246  }
247  }
248  }
249 
250  const MPoly *mp = mr->mpoly;
251  for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
252  float fac = face_dists[mp_index];
253  fac = thickness_remap(fac, min, max, minmax_irange);
254  for (int i = 0; i < mp->totloop; i++, l_index++) {
255  r_thickness[l_index] = fac;
256  }
257  }
258  }
259 }
260 
262  const Mesh *me;
264  float epsilon;
265 };
266 
267 static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
268 {
269  struct BVHTree_OverlapData *data = static_cast<struct BVHTree_OverlapData *>(userdata);
270  const Mesh *me = data->me;
271 
272  const MLoopTri *tri_a = &data->mlooptri[index_a];
273  const MLoopTri *tri_b = &data->mlooptri[index_b];
274 
275  if (UNLIKELY(tri_a->poly == tri_b->poly)) {
276  return false;
277  }
278 
279  const float *tri_a_co[3] = {me->mvert[me->mloop[tri_a->tri[0]].v].co,
280  me->mvert[me->mloop[tri_a->tri[1]].v].co,
281  me->mvert[me->mloop[tri_a->tri[2]].v].co};
282  const float *tri_b_co[3] = {me->mvert[me->mloop[tri_b->tri[0]].v].co,
283  me->mvert[me->mloop[tri_b->tri[1]].v].co,
284  me->mvert[me->mloop[tri_b->tri[2]].v].co};
285  float ix_pair[2][3];
286  int verts_shared = 0;
287 
288  verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
289  ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
290 
291  /* if 2 points are shared, bail out */
292  if (verts_shared >= 2) {
293  return false;
294  }
295 
296  return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) &&
297  /* if we share a vertex, check the intersection isn't a 'point' */
298  ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
299 }
300 
301 static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
302 {
303  BMEditMesh *em = mr->edit_bmesh;
304 
305  for (int l_index = 0; l_index < mr->loop_len; l_index++) {
306  r_intersect[l_index] = -1.0f;
307  }
308 
309  if (mr->extract_type == MR_EXTRACT_BMESH) {
310  uint overlap_len;
311  BMesh *bm = em->bm;
312 
314 
315  struct BMBVHTree *bmtree = BKE_bmbvh_new_from_editmesh(em, 0, nullptr, false);
316  BVHTreeOverlap *overlap = BKE_bmbvh_overlap_self(bmtree, &overlap_len);
317 
318  if (overlap) {
319  for (int i = 0; i < overlap_len; i++) {
320  BMFace *f_hit_pair[2] = {
321  em->looptris[overlap[i].indexA][0]->f,
322  em->looptris[overlap[i].indexB][0]->f,
323  };
324  for (int j = 0; j < 2; j++) {
325  BMFace *f_hit = f_hit_pair[j];
326  BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit);
327  int l_index = BM_elem_index_get(l_first);
328  for (int k = 0; k < f_hit->len; k++, l_index++) {
329  r_intersect[l_index] = 1.0f;
330  }
331  }
332  }
333  MEM_freeN(overlap);
334  }
335 
336  BKE_bmbvh_free(bmtree);
337  }
338  else {
339  uint overlap_len;
340  BVHTreeFromMesh treeData = {nullptr};
341 
343 
344  struct BVHTree_OverlapData data = {nullptr};
345  data.me = mr->me;
346  data.mlooptri = mr->mlooptri;
347  data.epsilon = BLI_bvhtree_get_epsilon(tree);
348 
349  BVHTreeOverlap *overlap = BLI_bvhtree_overlap(tree, tree, &overlap_len, bvh_overlap_cb, &data);
350  if (overlap) {
351  for (int i = 0; i < overlap_len; i++) {
352  const MPoly *f_hit_pair[2] = {
353  &mr->mpoly[mr->mlooptri[overlap[i].indexA].poly],
354  &mr->mpoly[mr->mlooptri[overlap[i].indexB].poly],
355  };
356  for (int j = 0; j < 2; j++) {
357  const MPoly *f_hit = f_hit_pair[j];
358  int l_index = f_hit->loopstart;
359  for (int k = 0; k < f_hit->totloop; k++, l_index++) {
360  r_intersect[l_index] = 1.0f;
361  }
362  }
363  }
364  MEM_freeN(overlap);
365  }
366  }
367 }
368 
369 BLI_INLINE float distort_remap(float fac, float min, float UNUSED(max), float minmax_irange)
370 {
371  if (fac >= min) {
372  fac = (fac - min) * minmax_irange;
373  CLAMP(fac, 0.0f, 1.0f);
374  }
375  else {
376  /* fallback */
377  fac = -1.0f;
378  }
379  return fac;
380 }
381 
382 static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
383 {
384  BMEditMesh *em = mr->edit_bmesh;
385  const MeshStatVis *statvis = &mr->toolsettings->statvis;
386  const float min = statvis->distort_min;
387  const float max = statvis->distort_max;
388  const float minmax_irange = 1.0f / (max - min);
389 
390  if (mr->extract_type == MR_EXTRACT_BMESH) {
391  BMIter iter;
392  BMesh *bm = em->bm;
393  BMFace *f;
394 
395  if (mr->bm_vert_coords != nullptr) {
397 
398  /* Most likely this is already valid, ensure just in case.
399  * Needed for #BM_loop_calc_face_normal_safe_vcos. */
401  }
402 
403  int l_index = 0;
404  int f_index = 0;
405  BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) {
406  float fac = -1.0f;
407 
408  if (f->len > 3) {
409  BMLoop *l_iter, *l_first;
410 
411  fac = 0.0f;
412  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
413  do {
414  const float *no_face;
415  float no_corner[3];
416  if (mr->bm_vert_coords != nullptr) {
417  no_face = mr->bm_poly_normals[f_index];
418  BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
419  }
420  else {
421  no_face = f->no;
422  BM_loop_calc_face_normal_safe(l_iter, no_corner);
423  }
424 
425  /* simple way to detect (what is most likely) concave */
426  if (dot_v3v3(no_face, no_corner) < 0.0f) {
427  negate_v3(no_corner);
428  }
429  fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner));
430 
431  } while ((l_iter = l_iter->next) != l_first);
432  fac *= 2.0f;
433  }
434 
435  fac = distort_remap(fac, min, max, minmax_irange);
436  for (int i = 0; i < f->len; i++, l_index++) {
437  r_distort[l_index] = fac;
438  }
439  }
440  }
441  else {
442  const MPoly *mp = mr->mpoly;
443  for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
444  float fac = -1.0f;
445 
446  if (mp->totloop > 3) {
447  const float *f_no = mr->poly_normals[mp_index];
448  fac = 0.0f;
449 
450  for (int i = 1; i <= mp->totloop; i++) {
451  const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop];
452  const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
453  const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
454  float no_corner[3];
455  normal_tri_v3(no_corner,
456  mr->mvert[l_prev->v].co,
457  mr->mvert[l_curr->v].co,
458  mr->mvert[l_next->v].co);
459  /* simple way to detect (what is most likely) concave */
460  if (dot_v3v3(f_no, no_corner) < 0.0f) {
461  negate_v3(no_corner);
462  }
463  fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
464  }
465  fac *= 2.0f;
466  }
467 
468  fac = distort_remap(fac, min, max, minmax_irange);
469  for (int i = 0; i < mp->totloop; i++, l_index++) {
470  r_distort[l_index] = fac;
471  }
472  }
473  }
474 }
475 
476 BLI_INLINE float sharp_remap(float fac, float min, float UNUSED(max), float minmax_irange)
477 {
478  /* important not '>=' */
479  if (fac > min) {
480  fac = (fac - min) * minmax_irange;
481  CLAMP(fac, 0.0f, 1.0f);
482  }
483  else {
484  /* fallback */
485  fac = -1.0f;
486  }
487  return fac;
488 }
489 
490 static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
491 {
492  BMEditMesh *em = mr->edit_bmesh;
493  const MeshStatVis *statvis = &mr->toolsettings->statvis;
494  const float min = statvis->sharp_min;
495  const float max = statvis->sharp_max;
496  const float minmax_irange = 1.0f / (max - min);
497 
498  /* Can we avoid this extra allocation? */
499  float *vert_angles = (float *)MEM_mallocN(sizeof(float) * mr->vert_len, __func__);
500  copy_vn_fl(vert_angles, mr->vert_len, -M_PI);
501 
502  if (mr->extract_type == MR_EXTRACT_BMESH) {
503  BMIter iter;
504  BMesh *bm = em->bm;
505  BMFace *efa;
506  BMEdge *e;
507  /* first assign float values to verts */
508  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
510  float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
511  float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
512  *col1 = max_ff(*col1, angle);
513  *col2 = max_ff(*col2, angle);
514  }
515  /* Copy vert value to loops. */
516  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
517  BMLoop *l_iter, *l_first;
518  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
519  do {
520  int l_index = BM_elem_index_get(l_iter);
521  int v_index = BM_elem_index_get(l_iter->v);
522  r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange);
523  } while ((l_iter = l_iter->next) != l_first);
524  }
525  }
526  else {
527  /* first assign float values to verts */
528  const MPoly *mp = mr->mpoly;
529 
530  EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len);
531 
532  for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
533  for (int i = 0; i < mp->totloop; i++) {
534  const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop];
535  const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop];
536  const MVert *v_curr = &mr->mvert[l_curr->v];
537  const MVert *v_next = &mr->mvert[l_next->v];
538  float angle;
539  void **pval;
540  bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
541  if (!value_is_init) {
542  *pval = (void *)mr->poly_normals[mp_index];
543  /* non-manifold edge, yet... */
544  continue;
545  }
546  if (*pval != nullptr) {
547  const float *f1_no = mr->poly_normals[mp_index];
548  const float *f2_no = static_cast<const float *>(*pval);
549  angle = angle_normalized_v3v3(f1_no, f2_no);
550  angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle;
551  /* Tag as manifold. */
552  *pval = nullptr;
553  }
554  else {
555  /* non-manifold edge */
556  angle = DEG2RADF(90.0f);
557  }
558  float *col1 = &vert_angles[l_curr->v];
559  float *col2 = &vert_angles[l_next->v];
560  *col1 = max_ff(*col1, angle);
561  *col2 = max_ff(*col2, angle);
562  }
563  }
564  /* Remaining non manifold edges. */
567  if (BLI_edgehashIterator_getValue(ehi) != nullptr) {
568  uint v1, v2;
569  const float angle = DEG2RADF(90.0f);
571  float *col1 = &vert_angles[v1];
572  float *col2 = &vert_angles[v2];
573  *col1 = max_ff(*col1, angle);
574  *col2 = max_ff(*col2, angle);
575  }
576  }
578  BLI_edgehash_free(eh, nullptr);
579 
580  const MLoop *ml = mr->mloop;
581  for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) {
582  r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange);
583  }
584  }
585 
586  MEM_freeN(vert_angles);
587 }
588 
590  MeshBatchCache *UNUSED(cache),
591  void *buf,
592  void *UNUSED(data))
593 {
594  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
595  BLI_assert(mr->edit_bmesh);
596 
597  float *l_weight = (float *)GPU_vertbuf_get_data(vbo);
598 
599  switch (mr->toolsettings->statvis.type) {
601  statvis_calc_overhang(mr, l_weight);
602  break;
604  statvis_calc_thickness(mr, l_weight);
605  break;
607  statvis_calc_intersect(mr, l_weight);
608  break;
609  case SCE_STATVIS_DISTORT:
610  statvis_calc_distort(mr, l_weight);
611  break;
612  case SCE_STATVIS_SHARP:
613  statvis_calc_sharp(mr, l_weight);
614  break;
615  }
616 }
617 
619 {
620  MeshExtract extractor = {nullptr};
621  extractor.init = extract_mesh_analysis_init;
623  /* This is not needed for all visualization types.
624  * Maybe split into different extract. */
626  extractor.data_size = 0;
627  extractor.use_threading = false;
628  extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.mesh_analysis);
629  return extractor;
630 }
631 
634 } // namespace blender::draw
635 
typedef float(TangentPoint)[2]
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:73
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition: bvhutils.cc:1213
struct BMFace * BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], float radius, float *r_dist, float r_hitout[3], float r_cagehit[3])
Definition: editmesh_bvh.c:290
void BKE_bmbvh_free(BMBVHTree *tree)
Definition: editmesh_bvh.c:170
struct BVHTreeOverlap * BKE_bmbvh_overlap_self(const BMBVHTree *bmtree, unsigned int *r_overlap_tot)
Definition: editmesh_bvh.c:575
BMBVHTree * BKE_bmbvh_new_from_editmesh(struct BMEditMesh *em, int flag, const float(*cos_cage)[3], bool cos_cage_free)
Definition: editmesh_bvh.c:31
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, struct EditMeshData *emd)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value)
Definition: edgehash.c:230
BLI_INLINE void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *r_v0, unsigned int *r_v1)
Definition: BLI_edgehash.h:161
EdgeHashIterator * BLI_edgehashIterator_new(EdgeHash *eh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:394
bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:307
BLI_INLINE void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:153
void BLI_edgehashIterator_free(EdgeHashIterator *ehi)
Definition: edgehash.c:408
BLI_INLINE void * BLI_edgehashIterator_getValue(EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:169
BLI_INLINE bool BLI_edgehashIterator_isDone(const EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:157
EdgeHash * BLI_edgehash_new_ex(const char *info, unsigned int nentries_reserve)
Definition: edgehash.c:212
void BLI_jitter_init(float(*jitarr)[2], int num)
Definition: jitter_2d.c:126
BVHTreeOverlap * BLI_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1363
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
Definition: BLI_kdopbvh.c:1044
int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1942
MINLINE float max_ff(float a, float b)
#define M_PI
Definition: BLI_math_base.h:20
bool is_edge_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:5734
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])
Definition: math_geom.c:2367
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:946
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2185
#define DEG2RADF(_deg)
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
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)
Definition: math_vector.c:1259
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
Definition: math_vector.c:445
void interp_v3_v3v3v3_uv(float p[3], const float v1[3], const float v2[3], const float v3[3], const float uv[2])
Definition: math_vector.c:202
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
#define SCE_STATVIS_INTERSECT
#define SCE_STATVIS_THICKNESS
#define SCE_STATVIS_SHARP
#define SCE_STATVIS_DISTORT
#define SCE_STATVIS_OVERHANG
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#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)
Definition: bmesh_mesh.cc:446
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
Definition: bmesh_query.c:1256
float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l, const float normal_fallback[3], float const (*vertexCos)[3], float r_normal[3])
Definition: bmesh_query.c:1261
float BM_edge_calc_face_angle_signed(const BMEdge *e)
Definition: bmesh_query.c:1379
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Definition: thread.h:34
@ MR_DATA_POLY_NOR
@ MR_DATA_LOOPTRI
void * tree
Extraction of Mesh data into VBO to feed to GPU.
BLI_INLINE const float * bm_face_no_get(const MeshRenderData *mr, const BMFace *efa)
BLI_INLINE const float * bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve)
@ MR_EXTRACT_BMESH
Definition: extract_mesh.hh:31
const MeshExtract extract_mesh_analysis
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define fabsf(x)
Definition: metal/compat.h:219
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
static void axis_from_enum_v3(float v[3], const char axis)
static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
BLI_INLINE float distort_remap(float fac, float min, float UNUSED(max), float minmax_irange)
static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr, MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(data))
static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
static void uv_from_jitter_v2(float uv[2])
BLI_INLINE float sharp_remap(float fac, float min, float UNUSED(max), float minmax_irange)
constexpr MeshExtract create_extractor_mesh_analysis()
BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
static void extract_mesh_analysis_init(const MeshRenderData *mr, MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data))
BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
#define min(a, b)
Definition: sort.c:35
struct BMLoop *(* looptris)[3]
Definition: BKE_editmesh.h:48
struct BMesh * bm
Definition: BKE_editmesh.h:40
int len
Definition: bmesh_class.h:267
float no[3]
Definition: bmesh_class.h:271
struct BMVert * v
Definition: bmesh_class.h:153
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
BVHTree_RayCastCallback raycast_callback
Definition: BKE_bvhutils.h:54
float no[3]
Definition: BLI_kdopbvh.h:70
unsigned int poly
unsigned int tri[3]
unsigned int v
float co[3]
GPUVertBuf * mesh_analysis
size_t mesh_buffer_offset
eMRDataType data_type
ExtractFinishFn * finish
size_t data_size
bool use_threading
ExtractInitFn * init
eMRExtractType extract_type
Definition: extract_mesh.hh:37
const float(* poly_normals)[3]
Definition: extract_mesh.hh:85
const MLoop * mloop
Definition: extract_mesh.hh:76
const float(* bm_poly_normals)[3]
Definition: extract_mesh.hh:63
EditMeshData * edit_data
Definition: extract_mesh.hh:57
const MVert * mvert
Definition: extract_mesh.hh:74
const float(* bm_vert_coords)[3]
Definition: extract_mesh.hh:61
const ToolSettings * toolsettings
Definition: extract_mesh.hh:53
const MPoly * mpoly
Definition: extract_mesh.hh:77
MLoopTri * mlooptri
Definition: extract_mesh.hh:83
BMEditMesh * edit_bmesh
Definition: extract_mesh.hh:55
float obmat[4][4]
Definition: extract_mesh.hh:51
struct MVert * mvert
struct MLoop * mloop
struct MeshStatVis statvis
float max