Blender  V3.3
mesh_remesh_voxel.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. All rights reserved. */
3 
8 #include <cctype>
9 #include <cfloat>
10 #include <cmath>
11 #include <cstdlib>
12 #include <cstring>
13 #include <ctime>
14 
15 #include "MEM_guardedalloc.h"
16 
17 #include "BLI_array.hh"
18 #include "BLI_index_range.hh"
19 #include "BLI_math_vec_types.hh"
20 #include "BLI_math_vector.h"
21 #include "BLI_span.hh"
22 
23 #include "DNA_mesh_types.h"
24 #include "DNA_meshdata_types.h"
25 
26 #include "BKE_attribute.h"
27 #include "BKE_bvhutils.h"
28 #include "BKE_customdata.h"
29 #include "BKE_editmesh.h"
30 #include "BKE_lib_id.h"
31 #include "BKE_mesh.h"
32 #include "BKE_mesh_mapping.h"
33 #include "BKE_mesh_remesh_voxel.h" /* own include */
34 #include "BKE_mesh_runtime.h"
35 
36 #include "bmesh_tools.h"
37 
38 #ifdef WITH_OPENVDB
39 # include <openvdb/openvdb.h>
40 # include <openvdb/tools/MeshToVolume.h>
41 # include <openvdb/tools/VolumeToMesh.h>
42 #endif
43 
44 #ifdef WITH_QUADRIFLOW
45 # include "quadriflow_capi.hpp"
46 #endif
47 
48 using blender::Array;
49 using blender::float3;
52 using blender::Span;
53 
54 #ifdef WITH_QUADRIFLOW
55 static Mesh *remesh_quadriflow(const Mesh *input_mesh,
56  int target_faces,
57  int seed,
58  bool preserve_sharp,
59  bool preserve_boundary,
60  bool adaptive_scale,
61  void (*update_cb)(void *, float progress, int *cancel),
62  void *update_cb_data)
63 {
64  /* Ensure that the triangulated mesh data is up to data */
65  const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
66 
67  /* Gather the required data for export to the internal quadriflow mesh format. */
68  MVertTri *verttri = (MVertTri *)MEM_callocN(
69  sizeof(*verttri) * BKE_mesh_runtime_looptri_len(input_mesh), "remesh_looptri");
71  verttri, input_mesh->mloop, looptri, BKE_mesh_runtime_looptri_len(input_mesh));
72 
73  const int totfaces = BKE_mesh_runtime_looptri_len(input_mesh);
74  const int totverts = input_mesh->totvert;
75  Array<float3> verts(totverts);
76  Array<int> faces(totfaces * 3);
77 
78  for (const int i : IndexRange(totverts)) {
79  verts[i] = input_mesh->mvert[i].co;
80  }
81 
82  for (const int i : IndexRange(totfaces)) {
83  MVertTri &vt = verttri[i];
84  faces[i * 3] = vt.tri[0];
85  faces[i * 3 + 1] = vt.tri[1];
86  faces[i * 3 + 2] = vt.tri[2];
87  }
88 
89  /* Fill out the required input data */
91 
92  qrd.totfaces = totfaces;
93  qrd.totverts = totverts;
94  qrd.verts = (float *)verts.data();
95  qrd.faces = faces.data();
96  qrd.target_faces = target_faces;
97 
98  qrd.preserve_sharp = preserve_sharp;
99  qrd.preserve_boundary = preserve_boundary;
100  qrd.adaptive_scale = adaptive_scale;
101  qrd.minimum_cost_flow = false;
102  qrd.aggresive_sat = false;
103  qrd.rng_seed = seed;
104 
105  qrd.out_faces = nullptr;
106 
107  /* Run the remesher */
108  QFLOW_quadriflow_remesh(&qrd, update_cb, update_cb_data);
109 
110  MEM_freeN(verttri);
111 
112  if (qrd.out_faces == nullptr) {
113  /* The remeshing was canceled */
114  return nullptr;
115  }
116 
117  if (qrd.out_totfaces == 0) {
118  /* Meshing failed */
119  MEM_freeN(qrd.out_faces);
120  MEM_freeN(qrd.out_verts);
121  return nullptr;
122  }
123 
124  /* Construct the new output mesh */
126 
127  for (const int i : IndexRange(qrd.out_totverts)) {
128  copy_v3_v3(mesh->mvert[i].co, &qrd.out_verts[i * 3]);
129  }
130 
131  for (const int i : IndexRange(qrd.out_totfaces)) {
132  MPoly &poly = mesh->mpoly[i];
133  const int loopstart = i * 4;
134  poly.loopstart = loopstart;
135  poly.totloop = 4;
136  mesh->mloop[loopstart].v = qrd.out_faces[loopstart];
137  mesh->mloop[loopstart + 1].v = qrd.out_faces[loopstart + 1];
138  mesh->mloop[loopstart + 2].v = qrd.out_faces[loopstart + 2];
139  mesh->mloop[loopstart + 3].v = qrd.out_faces[loopstart + 3];
140  }
141 
142  BKE_mesh_calc_edges(mesh, false, false);
143 
144  MEM_freeN(qrd.out_faces);
145  MEM_freeN(qrd.out_verts);
146 
147  return mesh;
148 }
149 #endif
150 
152  int target_faces,
153  int seed,
154  bool preserve_sharp,
155  bool preserve_boundary,
156  bool adaptive_scale,
157  void (*update_cb)(void *, float progress, int *cancel),
158  void *update_cb_data)
159 {
160 #ifdef WITH_QUADRIFLOW
161  if (target_faces <= 0) {
162  target_faces = -1;
163  }
164  return remesh_quadriflow(mesh,
165  target_faces,
166  seed,
167  preserve_sharp,
168  preserve_boundary,
169  adaptive_scale,
170  update_cb,
171  update_cb_data);
172 #else
174  target_faces,
175  seed,
176  preserve_sharp,
177  preserve_boundary,
178  adaptive_scale,
179  update_cb,
180  update_cb_data);
181  return nullptr;
182 #endif
183 }
184 
185 #ifdef WITH_OPENVDB
186 static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(const Mesh *mesh,
187  const float voxel_size)
188 {
189  Span<MLoop> mloop{mesh->mloop, mesh->totloop};
192 
193  std::vector<openvdb::Vec3s> points(mesh->totvert);
194  std::vector<openvdb::Vec3I> triangles(looptris.size());
195 
196  for (const int i : IndexRange(mesh->totvert)) {
197  const float3 co = mesh->mvert[i].co;
198  points[i] = openvdb::Vec3s(co.x, co.y, co.z);
199  }
200 
201  for (const int i : IndexRange(looptris.size())) {
202  const MLoopTri &loop_tri = looptris[i];
203  triangles[i] = openvdb::Vec3I(
204  mloop[loop_tri.tri[0]].v, mloop[loop_tri.tri[1]].v, mloop[loop_tri.tri[2]].v);
205  }
206 
207  openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
208  voxel_size);
209  openvdb::FloatGrid::Ptr grid = openvdb::tools::meshToLevelSet<openvdb::FloatGrid>(
210  *transform, points, triangles, 1.0f);
211 
212  return grid;
213 }
214 
215 static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set_grid,
216  const float isovalue,
217  const float adaptivity,
218  const bool relax_disoriented_triangles)
219 {
220  std::vector<openvdb::Vec3s> vertices;
221  std::vector<openvdb::Vec4I> quads;
222  std::vector<openvdb::Vec3I> tris;
223  openvdb::tools::volumeToMesh<openvdb::FloatGrid>(
224  *level_set_grid, vertices, tris, quads, isovalue, adaptivity, relax_disoriented_triangles);
225 
227  vertices.size(), 0, 0, quads.size() * 4 + tris.size() * 3, quads.size() + tris.size());
231 
232  for (const int i : mverts.index_range()) {
233  copy_v3_v3(mverts[i].co, float3(vertices[i].x(), vertices[i].y(), vertices[i].z()));
234  }
235 
236  for (const int i : IndexRange(quads.size())) {
237  MPoly &poly = mpolys[i];
238  const int loopstart = i * 4;
239  poly.loopstart = loopstart;
240  poly.totloop = 4;
241  mloops[loopstart].v = quads[i][0];
242  mloops[loopstart + 1].v = quads[i][3];
243  mloops[loopstart + 2].v = quads[i][2];
244  mloops[loopstart + 3].v = quads[i][1];
245  }
246 
247  const int triangle_loop_start = quads.size() * 4;
248  for (const int i : IndexRange(tris.size())) {
249  MPoly &poly = mpolys[quads.size() + i];
250  const int loopstart = triangle_loop_start + i * 3;
251  poly.loopstart = loopstart;
252  poly.totloop = 3;
253  mloops[loopstart].v = tris[i][2];
254  mloops[loopstart + 1].v = tris[i][1];
255  mloops[loopstart + 2].v = tris[i][0];
256  }
257 
258  BKE_mesh_calc_edges(mesh, false, false);
259 
260  return mesh;
261 }
262 #endif
263 
265  const float voxel_size,
266  const float adaptivity,
267  const float isovalue)
268 {
269 #ifdef WITH_OPENVDB
270  openvdb::FloatGrid::Ptr level_set = remesh_voxel_level_set_create(mesh, voxel_size);
271  return remesh_voxel_volume_to_mesh(level_set, isovalue, adaptivity, false);
272 #else
273  UNUSED_VARS(mesh, voxel_size, adaptivity, isovalue);
274  return nullptr;
275 #endif
276 }
277 
279 {
280  BVHTreeFromMesh bvhtree = {nullptr};
281  BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
282  MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
283 
284  float *target_mask;
285  if (CustomData_has_layer(&target->vdata, CD_PAINT_MASK)) {
286  target_mask = (float *)CustomData_get_layer(&target->vdata, CD_PAINT_MASK);
287  }
288  else {
289  target_mask = (float *)CustomData_add_layer(
290  &target->vdata, CD_PAINT_MASK, CD_CALLOC, nullptr, target->totvert);
291  }
292 
293  const float *source_mask;
294  if (CustomData_has_layer(&source->vdata, CD_PAINT_MASK)) {
295  source_mask = (float *)CustomData_get_layer(&source->vdata, CD_PAINT_MASK);
296  }
297  else {
298  source_mask = (float *)CustomData_add_layer(
299  &source->vdata, CD_PAINT_MASK, CD_CALLOC, nullptr, source->totvert);
300  }
301 
302  for (int i = 0; i < target->totvert; i++) {
303  float from_co[3];
304  BVHTreeNearest nearest;
305  nearest.index = -1;
306  nearest.dist_sq = FLT_MAX;
307  copy_v3_v3(from_co, target_verts[i].co);
308  BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
309  if (nearest.index != -1) {
310  target_mask[i] = source_mask[nearest.index];
311  }
312  }
313  free_bvhtree_from_mesh(&bvhtree);
314 }
315 
317 {
318  BVHTreeFromMesh bvhtree = {nullptr};
319 
320  const MPoly *target_polys = (const MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
321  const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
322  const MLoop *target_loops = (const MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP);
323 
324  int *target_face_sets;
326  target_face_sets = (int *)CustomData_get_layer(&target->pdata, CD_SCULPT_FACE_SETS);
327  }
328  else {
329  target_face_sets = (int *)CustomData_add_layer(
330  &target->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, nullptr, target->totpoly);
331  }
332 
333  const int *source_face_sets;
335  source_face_sets = (const int *)CustomData_get_layer(&source->pdata, CD_SCULPT_FACE_SETS);
336  }
337  else {
338  source_face_sets = (const int *)CustomData_add_layer(
339  &source->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, nullptr, source->totpoly);
340  }
341 
342  const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source);
343  BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
344 
345  for (int i = 0; i < target->totpoly; i++) {
346  float from_co[3];
347  BVHTreeNearest nearest;
348  nearest.index = -1;
349  nearest.dist_sq = FLT_MAX;
350  const MPoly *mpoly = &target_polys[i];
351  BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
352  BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
353  if (nearest.index != -1) {
354  target_face_sets[i] = source_face_sets[looptri[nearest.index].poly];
355  }
356  else {
357  target_face_sets[i] = 1;
358  }
359  }
360  free_bvhtree_from_mesh(&bvhtree);
361 }
362 
363 void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
364 {
365  BVHTreeFromMesh bvhtree = {nullptr};
366  BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
367 
368  int i = 0;
369  const CustomDataLayer *layer;
370 
371  MeshElemMap *source_lmap = nullptr;
372  int *source_lmap_mem = nullptr;
373  MeshElemMap *target_lmap = nullptr;
374  int *target_lmap_mem = nullptr;
375 
376  while ((layer = BKE_id_attribute_from_index(
377  const_cast<ID *>(&source->id), i++, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL))) {
378  eAttrDomain domain = BKE_id_attribute_domain(&source->id, layer);
379 
380  CustomData *target_cdata = domain == ATTR_DOMAIN_POINT ? &target->vdata : &target->ldata;
381  const CustomData *source_cdata = domain == ATTR_DOMAIN_POINT ? &source->vdata : &source->ldata;
382 
383  /* Check attribute exists in target. */
384  int layer_i = CustomData_get_named_layer_index(target_cdata, layer->type, layer->name);
385  if (layer_i == -1) {
386  int elem_num = domain == ATTR_DOMAIN_POINT ? target->totvert : target->totloop;
387 
389  target_cdata, layer->type, CD_CALLOC, nullptr, elem_num, layer->name);
390  layer_i = CustomData_get_named_layer_index(target_cdata, layer->type, layer->name);
391  }
392 
393  size_t data_size = CustomData_sizeof(layer->type);
394  void *target_data = target_cdata->layers[layer_i].data;
395  void *source_data = layer->data;
396  MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
397 
398  if (domain == ATTR_DOMAIN_POINT) {
399  for (int i = 0; i < target->totvert; i++) {
400  BVHTreeNearest nearest;
401  nearest.index = -1;
402  nearest.dist_sq = FLT_MAX;
404  bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
405 
406  if (nearest.index != -1) {
407  memcpy(POINTER_OFFSET(target_data, (size_t)i * data_size),
408  POINTER_OFFSET(source_data, (size_t)nearest.index * data_size),
409  data_size);
410  }
411  }
412  }
413  else {
414  /* Lazily init vertex -> loop maps. */
415  if (!source_lmap) {
416  const MPoly *source_polys = (MPoly *)CustomData_get_layer(&source->pdata, CD_MPOLY);
417  const MLoop *source_loops = (MLoop *)CustomData_get_layer(&source->ldata, CD_MLOOP);
418  const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
419  const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP);
420 
421  BKE_mesh_vert_loop_map_create(&source_lmap,
422  &source_lmap_mem,
423  source_polys,
424  source_loops,
425  source->totvert,
426  source->totpoly,
427  source->totloop);
428 
429  BKE_mesh_vert_loop_map_create(&target_lmap,
430  &target_lmap_mem,
431  target_polys,
432  target_loops,
433  target->totvert,
434  target->totpoly,
435  target->totloop);
436  }
437 
438  for (int i = 0; i < target->totvert; i++) {
439  BVHTreeNearest nearest;
440  nearest.index = -1;
441  nearest.dist_sq = FLT_MAX;
443  bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
444 
445  if (nearest.index == -1) {
446  continue;
447  }
448 
449  MeshElemMap *source_loops = source_lmap + nearest.index;
450  MeshElemMap *target_loops = target_lmap + i;
451 
452  if (target_loops->count == 0 || source_loops->count == 0) {
453  continue;
454  }
455 
456  /*
457  * Average color data for loops around the source vertex into
458  * the first target loop around the target vertex
459  */
460 
461  CustomData_interp(source_cdata,
462  target_cdata,
463  source_loops->indices,
464  nullptr,
465  nullptr,
466  source_loops->count,
467  target_loops->indices[0]);
468 
469  void *elem = POINTER_OFFSET(target_data, (size_t)target_loops->indices[0] * data_size);
470 
471  /* Copy to rest of target loops. */
472  for (int j = 1; j < target_loops->count; j++) {
473  memcpy(POINTER_OFFSET(target_data, (size_t)target_loops->indices[j] * data_size),
474  elem,
475  data_size);
476  }
477  }
478  }
479  }
480 
481  MEM_SAFE_FREE(source_lmap);
482  MEM_SAFE_FREE(source_lmap_mem);
483  MEM_SAFE_FREE(target_lmap);
484  MEM_SAFE_FREE(target_lmap_mem);
485  free_bvhtree_from_mesh(&bvhtree);
486 
487  /* Transfer active/render color attributes */
488 
489  CustomDataLayer *active_layer = BKE_id_attributes_active_color_get(&source->id);
490  CustomDataLayer *render_layer = BKE_id_attributes_render_color_get(&source->id);
491 
492  if (active_layer) {
494  &target->id, BKE_id_attributes_color_find(&target->id, active_layer->name));
495  }
496 
497  if (render_layer) {
499  &target->id, BKE_id_attributes_color_find(&target->id, render_layer->name));
500  }
501 }
502 
504 {
505  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
506 
507  BMeshCreateParams bmesh_create_params{};
508  bmesh_create_params.use_toolflags = true;
509  BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
510 
511  BMeshFromMeshParams bmesh_from_mesh_params{};
512  bmesh_from_mesh_params.calc_face_normal = true;
513  bmesh_from_mesh_params.calc_vert_normal = true;
514  BM_mesh_bm_from_me(bm, mesh, &bmesh_from_mesh_params);
515 
516  BMVert *v;
517  BMEdge *ed, *ed_next;
518  BMFace *f, *f_next;
519  BMIter iter_a, iter_b;
520 
521  /* Merge 3 edge poles vertices that exist in the same face */
523  BM_ITER_MESH_MUTABLE (f, f_next, &iter_a, bm, BM_FACES_OF_MESH) {
524  BMVert *v1, *v2;
525  v1 = nullptr;
526  v2 = nullptr;
527  BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) {
528  if (BM_vert_edge_count(v) == 3) {
529  if (v1) {
530  v2 = v;
531  }
532  else {
533  v1 = v;
534  }
535  }
536  }
537  if (v1 && v2 && (v1 != v2) && !BM_edge_exists(v1, v2)) {
538  BM_face_kill(bm, f);
539  BMEdge *e = BM_edge_create(bm, v1, v2, nullptr, BM_CREATE_NOP);
541  }
542  }
543 
544  BM_ITER_MESH_MUTABLE (ed, ed_next, &iter_a, bm, BM_EDGES_OF_MESH) {
545  if (BM_elem_flag_test(ed, BM_ELEM_TAG)) {
546  float co[3];
547  mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
548  BMVert *vc = BM_edge_collapse(bm, ed, ed->v1, true, true);
549  copy_v3_v3(vc->co, co);
550  }
551  }
552 
553  /* Delete faces with a 3 edge pole in all their vertices */
555  BM_ITER_MESH (f, &iter_a, bm, BM_FACES_OF_MESH) {
556  bool dissolve = true;
557  BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) {
558  if (BM_vert_edge_count(v) != 3) {
559  dissolve = false;
560  }
561  }
562  if (dissolve) {
563  BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) {
565  }
566  }
567  }
569 
570  BM_ITER_MESH (ed, &iter_a, bm, BM_EDGES_OF_MESH) {
571  if (BM_edge_face_count(ed) != 2) {
572  BM_elem_flag_set(ed, BM_ELEM_TAG, true);
573  }
574  }
575  BM_mesh_edgenet(bm, false, true);
576 
577  /* Smooth the result */
578  for (int i = 0; i < 4; i++) {
579  BM_ITER_MESH (v, &iter_a, bm, BM_VERTS_OF_MESH) {
580  float co[3];
581  zero_v3(co);
582  BM_ITER_ELEM (ed, &iter_b, v, BM_EDGES_OF_VERT) {
583  BMVert *vert = BM_edge_other_vert(ed, v);
584  add_v3_v3(co, vert->co);
585  }
586  mul_v3_fl(co, 1.0f / (float)BM_vert_edge_count(v));
587  mid_v3_v3v3(v->co, v->co, co);
588  }
589  }
590 
592 
597  "recalc_face_normals faces=%hf",
598  BM_ELEM_TAG);
600 
601  BMeshToMeshParams bmesh_to_mesh_params{};
602  bmesh_to_mesh_params.calc_object_remap = false;
603  Mesh *result = BKE_mesh_from_bmesh_nomain(bm, &bmesh_to_mesh_params, mesh);
604 
605  BM_mesh_free(bm);
606  return result;
607 }
Generic geometry attributes built on CustomData.
void BKE_id_attributes_active_color_set(struct ID *id, struct CustomDataLayer *active_layer)
Definition: attribute.cc:715
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
void BKE_id_attributes_render_color_set(struct ID *id, struct CustomDataLayer *active_layer)
Definition: attribute.cc:727
struct CustomDataLayer * BKE_id_attributes_active_color_get(const struct ID *id)
struct CustomDataLayer * BKE_id_attributes_render_color_get(const struct ID *id)
CustomDataLayer * BKE_id_attribute_from_index(struct ID *id, int lookup_index, eAttrDomainMask domain_mask, eCustomDataMask layer_mask)
Definition: attribute.cc:551
eAttrDomain BKE_id_attribute_domain(const struct ID *id, const struct CustomDataLayer *layer)
#define ATTR_DOMAIN_MASK_COLOR
Definition: BKE_attribute.h:48
struct CustomDataLayer * BKE_id_attributes_color_find(const struct ID *id, const char *name)
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.cc:1410
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:73
@ BVHTREE_FROM_VERTS
Definition: BKE_bvhutils.h:70
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition: bvhutils.cc:1213
CustomData interface, see also DNA_customdata_types.h.
@ CD_CALLOC
bool CustomData_has_layer(const struct CustomData *data, int type)
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.cc:2792
void CustomData_interp(const struct CustomData *source, struct CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_sizeof(int type)
Definition: customdata.cc:4268
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void BKE_mesh_calc_poly_center(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_cent[3])
struct Mesh * BKE_mesh_from_bmesh_nomain(struct BMesh *bm, const struct BMeshToMeshParams *params, const struct Mesh *me_settings)
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.cc:991
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, bool select_new_edges)
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *mpoly, const struct MLoop *mloop, int totvert, int totpoly, int totloop)
void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri, const struct MLoop *mloop, const struct MLoopTri *looptri, int looptri_num)
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1616
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define UNUSED_VARS(...)
#define POINTER_OFFSET(v, ofs)
#define CD_MASK_COLOR_ALL
@ CD_PAINT_MASK
@ CD_SCULPT_FACE_SETS
@ CD_MVERT
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_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 y
_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
float float3[3]
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:828
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
Definition: bmesh_core.c:123
@ BM_CREATE_NOP
Definition: bmesh_core.h:12
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
Definition: bmesh_delete.c:258
void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag)
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:16
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_FACE
@ BM_FACES_OF_MESH
@ BM_EDGES_OF_VERT
#define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
Definition: bmesh_mesh.cc:125
#define BMALLOC_TEMPLATE_FROM_ME(...)
Definition: bmesh_mesh.h:197
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
void BM_mesh_normals_update(BMesh *bm)
BMVert * BM_edge_collapse(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces)
Definition: bmesh_mods.c:442
@ DEL_VERTS
@ BMO_FLAG_RESPECT_HIDE
bool BMO_op_callf(BMesh *bm, int flag, const char *fmt,...)
#define BMO_FLAG_DEFAULTS
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
int BM_edge_face_count(const BMEdge *e)
Definition: bmesh_query.c:629
int BM_vert_edge_count(const BMVert *v)
Definition: bmesh_query.c:607
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
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 btVector3 transform(const btVector3 &point) const
static unsigned long seed
Definition: btSoftBody.h:39
static float verts[][3]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static char faces[256]
Mesh * BKE_mesh_remesh_voxel(const Mesh *mesh, const float voxel_size, const float adaptivity, const float isovalue)
void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
Mesh * BKE_mesh_remesh_quadriflow(const Mesh *mesh, int target_faces, int seed, bool preserve_sharp, bool preserve_boundary, bool adaptive_scale, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
struct Mesh * BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
std::unique_ptr< T > Ptr
Definition: BLI_any.hh:58
vec_base< float, 3 > float3
void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
static void update_cb(PBVHNode *node, void *rebuild)
Definition: sculpt_undo.c:133
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
float co[3]
Definition: bmesh_class.h:87
struct BVHTree * tree
Definition: BKE_bvhutils.h:50
BVHTree_NearestPointCallback nearest_callback
Definition: BKE_bvhutils.h:53
CustomDataLayer * layers
Definition: DNA_ID.h:368
unsigned int poly
unsigned int tri[3]
unsigned int v
unsigned int tri[3]
float co[3]
CustomData vdata
struct MVert * mvert
int totvert
struct MLoop * mloop
CustomData pdata
int totpoly
int totloop
struct MPoly * mpoly
CustomData ldata
float z
float y
float x