38# include <openvdb/openvdb.h>
39# include <openvdb/tools/MeshToVolume.h>
40# include <openvdb/tools/VolumeToMesh.h>
55static Mesh *remesh_quadriflow(
const Mesh *input_mesh,
59 bool preserve_boundary,
61 void (*update_cb)(
void *,
float progress,
int *cancel),
66 const Span<float3> input_positions = input_mesh->vert_positions();
67 const Span<int> input_corner_verts = input_mesh->corner_verts();
68 const Span<int3> corner_tris = input_mesh->corner_tris();
80 qrd.
faces = vert_tris.as_span().cast<
int>().
data();
115 mesh->vert_positions_for_write().copy_from(
119 const int loopstart =
i * 4;
120 corner_verts[loopstart] = qrd.
out_faces[loopstart];
121 corner_verts[loopstart + 1] = qrd.
out_faces[loopstart + 1];
122 corner_verts[loopstart + 2] = qrd.
out_faces[loopstart + 2];
123 corner_verts[loopstart + 3] = qrd.
out_faces[loopstart + 3];
139 bool preserve_boundary,
141 void (*update_cb)(
void *,
float progress,
int *cancel),
142 void *update_cb_data)
144#ifdef WITH_QUADRIFLOW
145 if (target_faces <= 0) {
148 return remesh_quadriflow(
mesh,
170static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(
177 std::vector<openvdb::Vec3s> points(
mesh->verts_num);
178 std::vector<openvdb::Vec3I> triangles(corner_tris.
size());
181 const float3 &co = positions[
i];
182 points[
i] = openvdb::Vec3s(co.
x, co.
y, co.
z);
186 const int3 &tri = corner_tris[
i];
187 triangles[
i] = openvdb::Vec3I(
188 corner_verts[tri[0]], corner_verts[tri[1]], corner_verts[tri[2]]);
191 openvdb::FloatGrid::Ptr grid = openvdb::tools::meshToLevelSet<openvdb::FloatGrid>(
197static Mesh *remesh_voxel_volume_to_mesh(
const openvdb::FloatGrid::Ptr level_set_grid,
198 const float isovalue,
199 const float adaptivity,
200 const bool relax_disoriented_triangles)
204 std::vector<openvdb::Vec3s> vertices;
205 std::vector<openvdb::Vec4I> quads;
206 std::vector<openvdb::Vec3I> tris;
207 openvdb::tools::volumeToMesh<openvdb::FloatGrid>(
208 *level_set_grid, vertices, tris, quads, isovalue, adaptivity, relax_disoriented_triangles);
211 vertices.size(), 0, quads.size() + tris.size(), quads.size() * 4 + tris.size() * 3);
216 const int triangle_loop_start = quads.size() * 4;
220 3, triangle_loop_start, face_offsets.
drop_front(quads.size()));
224 vert_positions[
i] =
float3(vertices[
i].
x(), vertices[
i].
y(), vertices[
i].
z());
228 const int loopstart =
i * 4;
229 mesh_corner_verts[loopstart] = quads[
i][0];
230 mesh_corner_verts[loopstart + 1] = quads[
i][3];
231 mesh_corner_verts[loopstart + 2] = quads[
i][2];
232 mesh_corner_verts[loopstart + 3] = quads[
i][1];
236 const int loopstart = triangle_loop_start +
i * 3;
237 mesh_corner_verts[loopstart] = tris[
i][2];
238 mesh_corner_verts[loopstart + 1] = tris[
i][1];
239 mesh_corner_verts[loopstart + 2] = tris[
i][0];
249 const float voxel_size,
250 const float adaptivity,
251 const float isovalue,
258 transform = openvdb::math::Transform::createLinearTransform(voxel_size);
260 catch (
const openvdb::ArithmeticError & ) {
265 object, modifier_data,
"Voxel size of %f too small to be solved", voxel_size);
268 openvdb::FloatGrid::Ptr level_set = remesh_voxel_level_set_create(
mesh,
transform);
269 Mesh *
result = remesh_voxel_volume_to_mesh(level_set, isovalue, adaptivity,
false);
273 UNUSED_VARS(
mesh, voxel_size, adaptivity, isovalue,
object, modifier_data);
279 const float voxel_size,
280 const float adaptivity,
281 const float isovalue,
287 transform = openvdb::math::Transform::createLinearTransform(voxel_size);
289 catch (
const openvdb::ArithmeticError & ) {
296 openvdb::FloatGrid::Ptr level_set = remesh_voxel_level_set_create(
mesh,
transform);
297 Mesh *
result = remesh_voxel_volume_to_mesh(level_set, isovalue, adaptivity,
false);
313 edge_centers[
i] =
math::midpoint(positions[edges[
i][0]], positions[edges[
i][1]]);
322 for (
const int i :
faces.index_range()) {
346 find_nearest_tris(positions.slice(range), bvhtree, tris.slice(range));
358 for (const int dst_vert : range) {
359 const float3 &dst_position = dst_positions[dst_vert];
360 const int3 &src_tri = src_corner_tris[nearest_vert_tris[dst_vert]];
362 std::array<float, 3> distances;
363 for (const int i : IndexRange(3)) {
364 const int src_vert = corner_verts[src_tri[i]];
365 distances[i] = math::distance_squared(positions[src_vert], dst_position);
368 const int min = std::min_element(distances.begin(), distances.end()) - distances.begin();
369 nearest_verts[dst_vert] = corner_verts[src_tri[min]];
387 threading::isolate_task([&] {
388 TLS &tls = all_tls.local();
389 Vector<float3> &face_centers = tls.face_centers;
390 face_centers.reinitialize(range.size());
391 calc_face_centers(dst_positions, dst_faces.slice(range), dst_corner_verts, face_centers);
393 Vector<int> &tri_indices = tls.tri_indices;
394 tri_indices.reinitialize(range.size());
395 find_nearest_tris(face_centers, bvhtree, tri_indices);
397 array_utils::gather(src_tri_faces, tri_indices.as_span(), nearest_faces.slice(range));
412 Vector<float, 64> distances;
413 for (const int dst_corner : range) {
414 const int dst_vert = dst_corner_verts[dst_corner];
415 const float3 &dst_position = dst_positions[dst_vert];
417 const int src_tri = nearest_vert_tris[dst_vert];
418 const IndexRange src_face = src_faces[src_tri_faces[src_tri]];
419 const Span<int> src_face_verts = src_corner_verts.slice(src_face);
422 distances.reinitialize(src_face_verts.size());
423 for (const int i : src_face_verts.index_range()) {
424 const int src_vert = src_face_verts[i];
425 distances[i] = math::distance_squared(src_positions[src_vert], dst_position);
428 const int min = std::min_element(distances.begin(), distances.end()) - distances.begin();
429 nearest_corners[dst_corner] = src_face[min];
452 threading::isolate_task([&] {
453 TLS &tls = all_tls.local();
454 Vector<float3> &edge_centers = tls.edge_centers;
455 edge_centers.reinitialize(range.size());
456 calc_edge_centers(dst_positions, dst_edges.slice(range), edge_centers);
458 Vector<int> &tri_indices = tls.tri_indices;
459 tri_indices.reinitialize(range.size());
460 find_nearest_tris_parallel(edge_centers, bvhtree, tri_indices);
462 Vector<int> &face_indices = tls.face_indices;
463 face_indices.reinitialize(range.size());
464 array_utils::gather(src_tri_faces, tri_indices.as_span(), face_indices.as_mutable_span());
469 Vector<float, 64> distances;
470 for (const int i : range.index_range()) {
471 const int dst_edge = range[i];
472 const float3 &dst_position = edge_centers[i];
474 const int src_face = face_indices[i];
475 const Span<int> src_face_edges = src_corner_edges.slice(src_faces[src_face]);
477 distances.reinitialize(src_face_edges.size());
478 for (const int i : src_face_edges.index_range()) {
479 const int2 src_edge = src_edges[src_face_edges[i]];
480 const float3 src_center = math::midpoint(src_positions[src_edge[0]],
481 src_positions[src_edge[1]]);
482 distances[i] = math::distance_squared(src_center, dst_position);
485 const int min = std::min_element(distances.begin(), distances.end()) - distances.begin();
486 nearest_edges[dst_edge] = src_face_edges[min];
517 if (
ELEM(iter.
name,
"position",
".edge_verts",
".corner_vert",
".corner_edge")) {
544 const Span<float3> src_positions = src.vert_positions();
546 const Span<int> src_corner_verts = src.corner_verts();
547 const Span<int3> src_corner_tris = src.corner_tris();
562 const Span<float3> dst_positions = dst.vert_positions();
564 const Span<int> dst_corner_verts = dst.corner_verts();
575 src_positions, src_corner_verts, src_corner_tris, dst_positions, vert_nearest_tris, map);
584 const Span<int> src_tri_faces = src.corner_tri_faces();
600 const Span<int> src_corner_edges = src.corner_edges();
601 const Span<int> src_tri_faces = src.corner_tri_faces();
617 const Span<int> src_tri_faces = src.corner_tri_faces();
619 find_nearest_faces(src_tri_faces, dst_positions, dst_faces, dst_corner_verts, bvhtree, map);
686 bool dissolve =
true;
708 for (
int i = 0;
i < 4;
i++) {
727 "recalc_face_normals faces=%hf",
void BKE_id_attributes_default_color_set(struct ID *id, std::optional< blender::StringRef > name)
void BKE_id_attributes_active_color_set(struct ID *id, std::optional< blender::StringRef > name)
Mesh * BKE_mesh_from_bmesh_nomain(BMesh *bm, const BMeshToMeshParams *params, const Mesh *me_settings)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_unreachable()
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
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])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BM_face_kill(BMesh *bm, BMFace *f)
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.
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
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)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype)
BMesh const char void * data
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.
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const BMeshCreateParams *params)
BMesh Make Mesh.
#define BMALLOC_TEMPLATE_FROM_ME(...)
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *mesh, const 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)
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)
int BM_edge_face_count(const BMEdge *e)
int BM_vert_edge_count(const BMVert *v)
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
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
static unsigned long seed
const CPPType & type() const
constexpr bool is_empty() const
constexpr MutableSpan drop_front(const int64_t n) const
constexpr IndexRange index_range() const
constexpr MutableSpan take_front(const int64_t n) const
Span< NewT > constexpr cast() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
IndexRange index_range() const
void MEM_freeN(void *vmemh)
Mesh * BKE_mesh_remesh_voxel(const Mesh *mesh, const float voxel_size, const float adaptivity, const float isovalue, const Object *object, ModifierData *modifier_data)
Mesh * BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
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 gather(GSpan src, Span< int > map, GMutableSpan dst)
void vert_tris_from_corner_tris(Span< int > corner_verts, Span< int3 > corner_tris, MutableSpan< int3 > vert_tris)
float3 face_center_calc(Span< float3 > vert_positions, Span< int > face_verts)
static void find_nearest_tris_parallel(const Span< float3 > positions, BVHTreeFromMesh &bvhtree, MutableSpan< int > tris)
static void find_nearest_faces(const Span< int > src_tri_faces, const Span< float3 > dst_positions, const OffsetIndices< int > dst_faces, const Span< int > dst_corner_verts, BVHTreeFromMesh &bvhtree, MutableSpan< int > nearest_faces)
static void calc_edge_centers(const Span< float3 > positions, const Span< int2 > edges, MutableSpan< float3 > edge_centers)
void mesh_remesh_reproject_attributes(const Mesh &src, Mesh &dst)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
static void find_nearest_verts(const Span< float3 > positions, const Span< int > corner_verts, const Span< int3 > src_corner_tris, const Span< float3 > dst_positions, const Span< int > nearest_vert_tris, MutableSpan< int > nearest_verts)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
static void find_nearest_edges(const Span< float3 > src_positions, const Span< int2 > src_edges, const OffsetIndices< int > src_faces, const Span< int > src_corner_edges, const Span< int > src_tri_faces, const Span< float3 > dst_positions, const Span< int2 > dst_edges, BVHTreeFromMesh &bvhtree, MutableSpan< int > nearest_edges)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
static void find_nearest_corners(const Span< float3 > src_positions, const OffsetIndices< int > src_faces, const Span< int > src_corner_verts, const Span< int > src_tri_faces, const Span< float3 > dst_positions, const Span< int > dst_corner_verts, const Span< int > nearest_vert_tris, MutableSpan< int > nearest_corners)
static void calc_face_centers(const Span< float3 > positions, const OffsetIndices< int > faces, const Span< int > corner_verts, MutableSpan< float3 > face_centers)
static void find_nearest_tris(const Span< float3 > positions, BVHTreeFromMesh &bvhtree, MutableSpan< int > tris)
T midpoint(const T &a, const T &b)
void fill_constant_group_size(int size, int start_offset, MutableSpan< int > offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
char * default_color_attribute
ListBase vertex_group_names
char * active_color_attribute
BVHTree_NearestPointCallback nearest_callback