From 1de995ae9911fdc3ce609a8c8f84e023531ea6bc Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Wed, 7 Jul 2021 12:14:12 -0700 Subject: Options to clean/simplify convex hull generated from mesh Clean: remove duplicate and interior vertices (uses Bullet algorithm) Simplify: modify the geometry for further simplification (uses VHACD algorithm) In the editor, single convex hull now uses the clean option. Added a new editor entry to create a simplified convex hull, can be useful for creating convex hull from highly tessellated triangle meshes. --- scene/resources/mesh.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'scene/resources/mesh.cpp') diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index f44c0c3ee2..2f92872ad5 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -30,6 +30,7 @@ #include "mesh.h" +#include "core/math/convex_hull.h" #include "core/templates/pair.h" #include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_3d.h" @@ -221,9 +222,17 @@ Vector Mesh::get_faces() const { */ } -Ref Mesh::create_convex_shape() const { - Vector vertices; +Ref Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { + if (p_simplify) { + Vector> decomposed = convex_decompose(1); + if (decomposed.size() == 1) { + return decomposed[0]; + } else { + ERR_PRINT("Convex shape simplification failed, falling back to simpler process."); + } + } + Vector vertices; for (int i = 0; i < get_surface_count(); i++) { Array a = surface_get_arrays(i); ERR_FAIL_COND_V(a.is_empty(), Ref()); @@ -232,6 +241,18 @@ Ref Mesh::create_convex_shape() const { } Ref shape = memnew(ConvexPolygonShape3D); + + if (p_clean) { + Geometry3D::MeshData md; + Error err = ConvexHullComputer::convex_hull(vertices, md); + if (err == OK) { + shape->set_points(md.vertices); + return shape; + } else { + ERR_PRINT("Convex shape cleaning failed, falling back to simpler process."); + } + } + shape->set_points(vertices); return shape; } @@ -543,12 +564,12 @@ void Mesh::clear_cache() const { debug_lines.clear(); } -Vector> Mesh::convex_decompose() const { +Vector> Mesh::convex_decompose(int p_max_convex_hulls) const { ERR_FAIL_COND_V(!convex_composition_function, Vector>()); const Vector faces = get_faces(); - Vector> decomposed = convex_composition_function(faces); + Vector> decomposed = convex_composition_function(faces, p_max_convex_hulls); Vector> ret; @@ -1852,7 +1873,7 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name); ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name); ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape); - ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape); + ClassDB::bind_method(D_METHOD("create_convex_shape", "clean", "simplify"), &ArrayMesh::create_convex_shape, DEFVAL(true), DEFVAL(false)); ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline); ClassDB::bind_method(D_METHOD("regen_normal_maps"), &ArrayMesh::regen_normal_maps); ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normal_maps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); -- cgit v1.2.3