diff --git a/doc/classes/MeshConvexDecompositionSettings.xml b/doc/classes/MeshConvexDecompositionSettings.xml
new file mode 100644
index 00000000000..a2784c4485a
--- /dev/null
+++ b/doc/classes/MeshConvexDecompositionSettings.xml
@@ -0,0 +1,60 @@
+
+
+
+ Parameters to be used with a [Mesh] convex decomposition operation.
+
+
+ Parameters to be used with a [Mesh] convex decomposition operation.
+
+
+
+
+
+ If enabled uses approximation for computing convex hulls.
+
+
+ Controls the precision of the convex-hull generation process during the clipping plane selection stage. Ranges from [code]1[/code] to [code]16[/code].
+
+
+ Maximum concavity. Ranges from [code]0.0[/code] to [code]1.0[/code].
+
+
+ The maximum number of convex hulls to produce from the merge operation.
+
+
+ Controls the maximum number of triangles per convex-hull. Ranges from [code]4[/code] to [code]1024[/code].
+
+
+ Controls the adaptive sampling of the generated convex-hulls. Ranges from [code]0.0[/code] to [code]0.01[/code].
+
+
+ Mode for the approximate convex decomposition.
+
+
+ If enabled normalizes the mesh before applying the convex decomposition.
+
+
+ Controls the granularity of the search for the "best" clipping plane. Ranges from [code]1[/code] to [code]16[/code].
+
+
+ If enabled projects output convex hull vertices onto original source mesh to increase floating point accuracy of the results.
+
+
+ Maximum number of voxels generated during the voxelization stage.
+
+
+ Controls the bias toward clipping along revolution axes. Ranges from [code]0.0[/code] to [code]1.0[/code].
+
+
+ Controls the bias toward clipping along symmetry planes. Ranges from [code]0.0[/code] to [code]1.0[/code].
+
+
+
+
+ Constant for voxel-based approximate convex decomposition.
+
+
+ Constant for tetrahedron-based approximate convex decomposition.
+
+
+
diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml
index 187f2510c5b..fb6702263eb 100644
--- a/doc/classes/MeshInstance3D.xml
+++ b/doc/classes/MeshInstance3D.xml
@@ -31,8 +31,9 @@
+
- This helper creates a [StaticBody3D] child node with multiple [ConvexPolygonShape3D] collision shapes calculated from the mesh geometry via convex decomposition. It's mainly used for testing.
+ This helper creates a [StaticBody3D] child node with multiple [ConvexPolygonShape3D] collision shapes calculated from the mesh geometry via convex decomposition. The convex decomposition operation can be controlled with parameters from the optional [param settings].
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 038a16f566c..c052f925081 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1604,22 +1604,23 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/shape_type", PROPERTY_HINT_ENUM, "Decompose Convex,Simple Convex,Trimesh,Box,Sphere,Cylinder,Capsule", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
// Decomposition
- Mesh::ConvexDecompositionSettings decomposition_default;
+ Ref decomposition_default = Ref();
+ decomposition_default.instantiate();
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/advanced", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/precision", PROPERTY_HINT_RANGE, "1,10,1"), 5));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/max_concavity", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_concavity));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/symmetry_planes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.symmetry_planes_clipping_bias));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/revolution_axes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.revolution_axes_clipping_bias));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/min_volume_per_convex_hull", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.min_volume_per_convex_hull));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/resolution", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.resolution));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_num_vertices_per_convex_hull", PROPERTY_HINT_RANGE, "5,512,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_num_vertices_per_convex_hull));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/plane_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.plane_downsampling));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/convexhull_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_downsampling));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/normalize_mesh", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.normalize_mesh));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), static_cast(decomposition_default.mode)));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/convexhull_approximation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_approximation));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_convex_hulls", PROPERTY_HINT_RANGE, "1,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_convex_hulls));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/project_hull_vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.project_hull_vertices));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/max_concavity", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_max_concavity()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/symmetry_planes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_symmetry_planes_clipping_bias()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/revolution_axes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_revolution_axes_clipping_bias()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/min_volume_per_convex_hull", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_min_volume_per_convex_hull()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/resolution", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_resolution()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_num_vertices_per_convex_hull", PROPERTY_HINT_RANGE, "5,512,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_max_num_vertices_per_convex_hull()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/plane_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_plane_downsampling()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/convexhull_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_convex_hull_downsampling()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/normalize_mesh", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_normalize_mesh()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), static_cast(decomposition_default->get_mode())));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/convexhull_approximation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_convex_hull_approximation()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_convex_hulls", PROPERTY_HINT_RANGE, "1,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_max_convex_hulls()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/project_hull_vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default->get_project_hull_vertices()));
// Primitives: Box, Sphere, Cylinder, Capsule.
r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3(2.0, 2.0, 2.0)));
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 520ccd10708..a66fd034f82 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -323,7 +323,8 @@ Vector[> ResourceImporterScene::get_collision_shapes(const Ref decomposition_settings = Ref();
+ decomposition_settings.instantiate();
bool advanced = false;
if (p_options.has(SNAME("decomposition/advanced"))) {
advanced = p_options[SNAME("decomposition/advanced")];
@@ -331,55 +332,55 @@ Vector][> ResourceImporterScene::get_collision_shapes(const Refset_max_concavity(p_options[SNAME("decomposition/max_concavity")]);
}
if (p_options.has(SNAME("decomposition/symmetry_planes_clipping_bias"))) {
- decomposition_settings.symmetry_planes_clipping_bias = p_options[SNAME("decomposition/symmetry_planes_clipping_bias")];
+ decomposition_settings->set_symmetry_planes_clipping_bias(p_options[SNAME("decomposition/symmetry_planes_clipping_bias")]);
}
if (p_options.has(SNAME("decomposition/revolution_axes_clipping_bias"))) {
- decomposition_settings.revolution_axes_clipping_bias = p_options[SNAME("decomposition/revolution_axes_clipping_bias")];
+ decomposition_settings->set_revolution_axes_clipping_bias(p_options[SNAME("decomposition/revolution_axes_clipping_bias")]);
}
if (p_options.has(SNAME("decomposition/min_volume_per_convex_hull"))) {
- decomposition_settings.min_volume_per_convex_hull = p_options[SNAME("decomposition/min_volume_per_convex_hull")];
+ decomposition_settings->set_min_volume_per_convex_hull(p_options[SNAME("decomposition/min_volume_per_convex_hull")]);
}
if (p_options.has(SNAME("decomposition/resolution"))) {
- decomposition_settings.resolution = p_options[SNAME("decomposition/resolution")];
+ decomposition_settings->set_resolution(p_options[SNAME("decomposition/resolution")]);
}
if (p_options.has(SNAME("decomposition/max_num_vertices_per_convex_hull"))) {
- decomposition_settings.max_num_vertices_per_convex_hull = p_options[SNAME("decomposition/max_num_vertices_per_convex_hull")];
+ decomposition_settings->set_max_num_vertices_per_convex_hull(p_options[SNAME("decomposition/max_num_vertices_per_convex_hull")]);
}
if (p_options.has(SNAME("decomposition/plane_downsampling"))) {
- decomposition_settings.plane_downsampling = p_options[SNAME("decomposition/plane_downsampling")];
+ decomposition_settings->set_plane_downsampling(p_options[SNAME("decomposition/plane_downsampling")]);
}
if (p_options.has(SNAME("decomposition/convexhull_downsampling"))) {
- decomposition_settings.convexhull_downsampling = p_options[SNAME("decomposition/convexhull_downsampling")];
+ decomposition_settings->set_convex_hull_downsampling(p_options[SNAME("decomposition/convexhull_downsampling")]);
}
if (p_options.has(SNAME("decomposition/normalize_mesh"))) {
- decomposition_settings.normalize_mesh = p_options[SNAME("decomposition/normalize_mesh")];
+ decomposition_settings->set_normalize_mesh(p_options[SNAME("decomposition/normalize_mesh")]);
}
if (p_options.has(SNAME("decomposition/mode"))) {
- decomposition_settings.mode = (Mesh::ConvexDecompositionSettings::Mode)p_options[SNAME("decomposition/mode")].operator int();
+ decomposition_settings->set_mode((MeshConvexDecompositionSettings::Mode)p_options[SNAME("decomposition/mode")].operator int());
}
if (p_options.has(SNAME("decomposition/convexhull_approximation"))) {
- decomposition_settings.convexhull_approximation = p_options[SNAME("decomposition/convexhull_approximation")];
+ decomposition_settings->set_convex_hull_approximation(p_options[SNAME("decomposition/convexhull_approximation")]);
}
if (p_options.has(SNAME("decomposition/max_convex_hulls"))) {
- decomposition_settings.max_convex_hulls = MAX(1, (int)p_options[SNAME("decomposition/max_convex_hulls")]);
+ decomposition_settings->set_max_convex_hulls(MAX(1, (int)p_options[SNAME("decomposition/max_convex_hulls")]));
}
if (p_options.has(SNAME("decomposition/project_hull_vertices"))) {
- decomposition_settings.project_hull_vertices = p_options[SNAME("decomposition/project_hull_vertices")];
+ decomposition_settings->set_project_hull_vertices(p_options[SNAME("decomposition/project_hull_vertices")]);
}
} else {
int precision_level = 5;
@@ -389,13 +390,13 @@ Vector][> ResourceImporterScene::get_collision_shapes(const Refset_max_concavity(Math::lerp(real_t(1.0), real_t(0.001), precision));
+ decomposition_settings->set_min_volume_per_convex_hull(Math::lerp(real_t(0.01), real_t(0.0001), precision));
+ decomposition_settings->set_resolution(Math::lerp(10'000, 100'000, precision));
+ decomposition_settings->set_max_num_vertices_per_convex_hull(Math::lerp(32, 64, precision));
+ decomposition_settings->set_plane_downsampling(Math::lerp(3, 16, precision));
+ decomposition_settings->set_convex_hull_downsampling(Math::lerp(3, 16, precision));
+ decomposition_settings->set_max_convex_hulls(Math::lerp(1, 32, precision));
}
return p_mesh->convex_decompose(decomposition_settings);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index e8976667dd5..2ebb4d29c5e 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -214,7 +214,11 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
return;
}
- Mesh::ConvexDecompositionSettings settings;
+ Ref settings = Ref();
+ settings.instantiate();
+ settings->set_max_convex_hulls(32);
+ settings->set_max_concavity(0.001);
+
Vector][> shapes = mesh->convex_decompose(settings);
if (!shapes.size()) {
diff --git a/modules/vhacd/register_types.cpp b/modules/vhacd/register_types.cpp
index 6310becf1b6..088f03ebe85 100644
--- a/modules/vhacd/register_types.cpp
+++ b/modules/vhacd/register_types.cpp
@@ -32,22 +32,22 @@
#include "scene/resources/mesh.h"
#include "thirdparty/vhacd/public/VHACD.h"
-static Vector> convex_decompose(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const Mesh::ConvexDecompositionSettings &p_settings, Vector> *r_convex_indices) {
+static Vector> convex_decompose(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const Ref &p_settings, Vector> *r_convex_indices) {
VHACD::IVHACD::Parameters params;
- params.m_concavity = p_settings.max_concavity;
- params.m_alpha = p_settings.symmetry_planes_clipping_bias;
- params.m_beta = p_settings.revolution_axes_clipping_bias;
- params.m_minVolumePerCH = p_settings.min_volume_per_convex_hull;
- params.m_resolution = p_settings.resolution;
- params.m_maxNumVerticesPerCH = p_settings.max_num_vertices_per_convex_hull;
- params.m_planeDownsampling = p_settings.plane_downsampling;
- params.m_convexhullDownsampling = p_settings.convexhull_downsampling;
- params.m_pca = p_settings.normalize_mesh;
- params.m_mode = p_settings.mode;
- params.m_convexhullApproximation = p_settings.convexhull_approximation;
+ params.m_concavity = p_settings->get_max_concavity();
+ params.m_alpha = p_settings->get_symmetry_planes_clipping_bias();
+ params.m_beta = p_settings->get_revolution_axes_clipping_bias();
+ params.m_minVolumePerCH = p_settings->get_min_volume_per_convex_hull();
+ params.m_resolution = p_settings->get_resolution();
+ params.m_maxNumVerticesPerCH = p_settings->get_max_num_vertices_per_convex_hull();
+ params.m_planeDownsampling = p_settings->get_plane_downsampling();
+ params.m_convexhullDownsampling = p_settings->get_convex_hull_downsampling();
+ params.m_pca = p_settings->get_normalize_mesh();
+ params.m_mode = p_settings->get_mode();
+ params.m_convexhullApproximation = p_settings->get_convex_hull_approximation();
params.m_oclAcceleration = true;
- params.m_maxConvexHulls = p_settings.max_convex_hulls;
- params.m_projectHullVertices = p_settings.project_hull_vertices;
+ params.m_maxConvexHulls = p_settings->get_max_convex_hulls();
+ params.m_projectHullVertices = p_settings->get_project_hull_vertices();
VHACD::IVHACD *decomposer = VHACD::CreateVHACD();
decomposer->Compute(p_vertices, p_vertex_count, p_triangles, p_triangle_count, params);
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 86301ee53f7..0f7db64f5c4 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -284,12 +284,18 @@ void MeshInstance3D::create_convex_collision(bool p_clean, bool p_simplify) {
}
}
-Node *MeshInstance3D::create_multiple_convex_collisions_node() {
+Node *MeshInstance3D::create_multiple_convex_collisions_node(const Ref &p_settings) {
if (mesh.is_null()) {
return nullptr;
}
- Mesh::ConvexDecompositionSettings settings;
+ Ref settings;
+ if (p_settings.is_valid()) {
+ settings = p_settings;
+ } else {
+ settings.instantiate();
+ }
+
Vector][> shapes = mesh->convex_decompose(settings);
if (!shapes.size()) {
return nullptr;
@@ -304,8 +310,8 @@ Node *MeshInstance3D::create_multiple_convex_collisions_node() {
return static_body;
}
-void MeshInstance3D::create_multiple_convex_collisions() {
- StaticBody3D *static_body = Object::cast_to(create_multiple_convex_collisions_node());
+void MeshInstance3D::create_multiple_convex_collisions(const Ref &p_settings) {
+ StaticBody3D *static_body = Object::cast_to(create_multiple_convex_collisions_node(p_settings));
ERR_FAIL_COND(!static_body);
static_body->set_name(String(get_name()) + "_col");
@@ -504,7 +510,7 @@ void MeshInstance3D::_bind_methods() {
ClassDB::set_method_flags("MeshInstance3D", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("create_convex_collision", "clean", "simplify"), &MeshInstance3D::create_convex_collision, DEFVAL(true), DEFVAL(false));
ClassDB::set_method_flags("MeshInstance3D", "create_convex_collision", METHOD_FLAGS_DEFAULT);
- ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance3D::create_multiple_convex_collisions);
+ ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions", "settings"), &MeshInstance3D::create_multiple_convex_collisions, DEFVAL(Ref()));
ClassDB::set_method_flags("MeshInstance3D", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &MeshInstance3D::get_blend_shape_count);
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 4a6d7dd95dd..0a7ffa0beed 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -88,8 +88,8 @@ public:
Node *create_convex_collision_node(bool p_clean = true, bool p_simplify = false);
void create_convex_collision(bool p_clean = true, bool p_simplify = false);
- Node *create_multiple_convex_collisions_node();
- void create_multiple_convex_collisions();
+ Node *create_multiple_convex_collisions_node(const Ref &p_settings = Ref());
+ void create_multiple_convex_collisions(const Ref &p_settings = Ref());
MeshInstance3D *create_debug_tangents_node();
void create_debug_tangents();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b13b8a41af9..feff4a6dc9b 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -781,6 +781,7 @@ void register_scene_types() {
ParticleProcessMaterial::init_shaders();
GDREGISTER_VIRTUAL_CLASS(Mesh);
+ GDREGISTER_CLASS(MeshConvexDecompositionSettings);
GDREGISTER_CLASS(ArrayMesh);
GDREGISTER_CLASS(PlaceholderMesh);
GDREGISTER_CLASS(ImmediateMesh);
diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp
index 0fc72ca90f6..09738757fd4 100644
--- a/scene/resources/importer_mesh.cpp
+++ b/scene/resources/importer_mesh.cpp
@@ -938,7 +938,7 @@ Vector ImporterMesh::get_faces() const {
return faces;
}
-Vector][> ImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const {
+Vector][> ImporterMesh::convex_decompose(const Ref &p_settings) const {
ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector][>());
const Vector faces = get_faces();
@@ -987,8 +987,9 @@ Vector][> ImporterMesh::convex_decompose(const Mesh::ConvexDecomposit
Ref ImporterMesh::create_convex_shape(bool p_clean, bool p_simplify) const {
if (p_simplify) {
- Mesh::ConvexDecompositionSettings settings;
- settings.max_convex_hulls = 1;
+ Ref settings;
+ settings.instantiate();
+ settings->set_max_convex_hulls(1);
Vector][> decomposed = convex_decompose(settings);
if (decomposed.size() == 1) {
return decomposed[0];
diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h
index 33d08643428..69becc46a34 100644
--- a/scene/resources/importer_mesh.h
+++ b/scene/resources/importer_mesh.h
@@ -118,7 +118,7 @@ public:
Ref get_shadow_mesh() const;
Vector get_faces() const;
- Vector][> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const;
+ Vector][> convex_decompose(const Ref &p_settings) const;
Ref create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
Ref create_trimesh_shape() const;
Ref create_navigation_mesh();
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index a7b53244e24..8a91e9f6e02 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -37,6 +37,168 @@
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
+void MeshConvexDecompositionSettings::set_max_concavity(real_t p_max_concavity) {
+ max_concavity = CLAMP(p_max_concavity, 0.001, 1.0);
+}
+
+real_t MeshConvexDecompositionSettings::get_max_concavity() const {
+ return max_concavity;
+};
+
+void MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias(real_t p_symmetry_planes_clipping_bias) {
+ symmetry_planes_clipping_bias = CLAMP(p_symmetry_planes_clipping_bias, 0.0, 1.0);
+};
+
+real_t MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias() const {
+ return symmetry_planes_clipping_bias;
+};
+
+void MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias(real_t p_revolution_axes_clipping_bias) {
+ revolution_axes_clipping_bias = CLAMP(p_revolution_axes_clipping_bias, 0.0, 1.0);
+};
+
+real_t MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias() const {
+ return revolution_axes_clipping_bias;
+};
+
+void MeshConvexDecompositionSettings::set_min_volume_per_convex_hull(real_t p_min_volume_per_convex_hull) {
+ min_volume_per_convex_hull = CLAMP(p_min_volume_per_convex_hull, 0.0001, 0.01);
+}
+
+real_t MeshConvexDecompositionSettings::get_min_volume_per_convex_hull() const {
+ return min_volume_per_convex_hull;
+}
+
+void MeshConvexDecompositionSettings::set_resolution(uint32_t p_resolution) {
+ resolution = p_resolution < 10'000 ? 10'000 : (p_resolution > 100'000 ? 100'000 : p_resolution);
+}
+
+uint32_t MeshConvexDecompositionSettings::get_resolution() const {
+ return resolution;
+}
+
+void MeshConvexDecompositionSettings::set_max_num_vertices_per_convex_hull(uint32_t p_max_num_vertices_per_convex_hull) {
+ max_num_vertices_per_convex_hull = p_max_num_vertices_per_convex_hull < 4 ? 4 : (p_max_num_vertices_per_convex_hull > 1024 ? 1024 : p_max_num_vertices_per_convex_hull);
+}
+
+uint32_t MeshConvexDecompositionSettings::get_max_num_vertices_per_convex_hull() const {
+ return max_num_vertices_per_convex_hull;
+}
+
+void MeshConvexDecompositionSettings::set_plane_downsampling(uint32_t p_plane_downsampling) {
+ plane_downsampling = p_plane_downsampling < 1 ? 1 : (p_plane_downsampling > 16 ? 16 : p_plane_downsampling);
+}
+
+uint32_t MeshConvexDecompositionSettings::get_plane_downsampling() const {
+ return plane_downsampling;
+}
+
+void MeshConvexDecompositionSettings::set_convex_hull_downsampling(uint32_t p_convex_hull_downsampling) {
+ convex_hull_downsampling = p_convex_hull_downsampling < 1 ? 1 : (p_convex_hull_downsampling > 16 ? 16 : p_convex_hull_downsampling);
+}
+
+uint32_t MeshConvexDecompositionSettings::get_convex_hull_downsampling() const {
+ return convex_hull_downsampling;
+}
+
+void MeshConvexDecompositionSettings::set_normalize_mesh(bool p_normalize_mesh) {
+ normalize_mesh = p_normalize_mesh;
+}
+
+bool MeshConvexDecompositionSettings::get_normalize_mesh() const {
+ return normalize_mesh;
+}
+
+void MeshConvexDecompositionSettings::set_mode(Mode p_mode) {
+ mode = p_mode;
+}
+
+MeshConvexDecompositionSettings::Mode MeshConvexDecompositionSettings::get_mode() const {
+ return mode;
+}
+
+void MeshConvexDecompositionSettings::set_convex_hull_approximation(bool p_convex_hull_approximation) {
+ convex_hull_approximation = p_convex_hull_approximation;
+}
+
+bool MeshConvexDecompositionSettings::get_convex_hull_approximation() const {
+ return convex_hull_approximation;
+}
+
+void MeshConvexDecompositionSettings::set_max_convex_hulls(uint32_t p_max_convex_hulls) {
+ max_convex_hulls = p_max_convex_hulls < 1 ? 1 : (p_max_convex_hulls > 32 ? 32 : p_max_convex_hulls);
+}
+
+uint32_t MeshConvexDecompositionSettings::get_max_convex_hulls() const {
+ return max_convex_hulls;
+}
+
+void MeshConvexDecompositionSettings::set_project_hull_vertices(bool p_project_hull_vertices) {
+ project_hull_vertices = p_project_hull_vertices;
+}
+
+bool MeshConvexDecompositionSettings::get_project_hull_vertices() const {
+ return project_hull_vertices;
+}
+
+void MeshConvexDecompositionSettings::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_max_concavity", "max_concavity"), &MeshConvexDecompositionSettings::set_max_concavity);
+ ClassDB::bind_method(D_METHOD("get_max_concavity"), &MeshConvexDecompositionSettings::get_max_concavity);
+
+ ClassDB::bind_method(D_METHOD("set_symmetry_planes_clipping_bias", "symmetry_planes_clipping_bias"), &MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias);
+ ClassDB::bind_method(D_METHOD("get_symmetry_planes_clipping_bias"), &MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias);
+
+ ClassDB::bind_method(D_METHOD("set_revolution_axes_clipping_bias", "revolution_axes_clipping_bias"), &MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias);
+ ClassDB::bind_method(D_METHOD("get_revolution_axes_clipping_bias"), &MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias);
+
+ ClassDB::bind_method(D_METHOD("set_min_volume_per_convex_hull", "min_volume_per_convex_hull"), &MeshConvexDecompositionSettings::set_min_volume_per_convex_hull);
+ ClassDB::bind_method(D_METHOD("get_min_volume_per_convex_hull"), &MeshConvexDecompositionSettings::get_min_volume_per_convex_hull);
+
+ ClassDB::bind_method(D_METHOD("set_resolution", "min_volume_per_convex_hull"), &MeshConvexDecompositionSettings::set_resolution);
+ ClassDB::bind_method(D_METHOD("get_resolution"), &MeshConvexDecompositionSettings::get_resolution);
+
+ ClassDB::bind_method(D_METHOD("set_max_num_vertices_per_convex_hull", "max_num_vertices_per_convex_hull"), &MeshConvexDecompositionSettings::set_max_num_vertices_per_convex_hull);
+ ClassDB::bind_method(D_METHOD("get_max_num_vertices_per_convex_hull"), &MeshConvexDecompositionSettings::get_max_num_vertices_per_convex_hull);
+
+ ClassDB::bind_method(D_METHOD("set_plane_downsampling", "plane_downsampling"), &MeshConvexDecompositionSettings::set_plane_downsampling);
+ ClassDB::bind_method(D_METHOD("get_plane_downsampling"), &MeshConvexDecompositionSettings::get_plane_downsampling);
+
+ ClassDB::bind_method(D_METHOD("set_convex_hull_downsampling", "convex_hull_downsampling"), &MeshConvexDecompositionSettings::set_convex_hull_downsampling);
+ ClassDB::bind_method(D_METHOD("get_convex_hull_downsampling"), &MeshConvexDecompositionSettings::get_convex_hull_downsampling);
+
+ ClassDB::bind_method(D_METHOD("set_normalize_mesh", "normalize_mesh"), &MeshConvexDecompositionSettings::set_normalize_mesh);
+ ClassDB::bind_method(D_METHOD("get_normalize_mesh"), &MeshConvexDecompositionSettings::get_normalize_mesh);
+
+ ClassDB::bind_method(D_METHOD("set_mode", "mode"), &MeshConvexDecompositionSettings::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"), &MeshConvexDecompositionSettings::get_mode);
+
+ ClassDB::bind_method(D_METHOD("set_convex_hull_approximation", "convex_hull_approximation"), &MeshConvexDecompositionSettings::set_convex_hull_approximation);
+ ClassDB::bind_method(D_METHOD("get_convex_hull_approximation"), &MeshConvexDecompositionSettings::get_convex_hull_approximation);
+
+ ClassDB::bind_method(D_METHOD("set_max_convex_hulls", "max_convex_hulls"), &MeshConvexDecompositionSettings::set_max_convex_hulls);
+ ClassDB::bind_method(D_METHOD("get_max_convex_hulls"), &MeshConvexDecompositionSettings::get_max_convex_hulls);
+
+ ClassDB::bind_method(D_METHOD("set_project_hull_vertices", "project_hull_vertices"), &MeshConvexDecompositionSettings::set_project_hull_vertices);
+ ClassDB::bind_method(D_METHOD("get_project_hull_vertices"), &MeshConvexDecompositionSettings::get_project_hull_vertices);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_concavity", PROPERTY_HINT_RANGE, "0.001,1.0,0.001"), "set_max_concavity", "get_max_concavity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "symmetry_planes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_symmetry_planes_clipping_bias", "get_symmetry_planes_clipping_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "revolution_axes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_revolution_axes_clipping_bias", "get_revolution_axes_clipping_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_volume_per_convex_hull", PROPERTY_HINT_RANGE, "0.0001,0.01,0.0001"), "set_min_volume_per_convex_hull", "get_min_volume_per_convex_hull");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution"), "set_resolution", "get_resolution");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_num_vertices_per_convex_hull"), "set_max_num_vertices_per_convex_hull", "get_max_num_vertices_per_convex_hull");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "plane_downsampling", PROPERTY_HINT_RANGE, "1,16,1"), "set_plane_downsampling", "get_plane_downsampling");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "convex_hull_downsampling", PROPERTY_HINT_RANGE, "1,16,1"), "set_convex_hull_downsampling", "get_convex_hull_downsampling");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalize_mesh"), "set_normalize_mesh", "get_normalize_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "convex_hull_approximation"), "set_convex_hull_approximation", "get_convex_hull_approximation");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_convex_hulls"), "set_max_convex_hulls", "get_max_convex_hulls");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "project_hull_vertices"), "set_project_hull_vertices", "get_project_hull_vertices");
+
+ BIND_ENUM_CONSTANT(CONVEX_DECOMPOSITION_MODE_VOXEL);
+ BIND_ENUM_CONSTANT(CONVEX_DECOMPOSITION_MODE_TETRAHEDRON);
+}
+
Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr;
int Mesh::get_surface_count() const {
@@ -355,8 +517,10 @@ Vector Mesh::get_surface_faces(int p_surface) const {
Ref Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
if (p_simplify) {
- ConvexDecompositionSettings settings;
- settings.max_convex_hulls = 1;
+ Ref settings = Ref();
+ settings.instantiate();
+ settings->set_max_convex_hulls(1);
+ settings->set_max_concavity(1.0);
Vector][> decomposed = convex_decompose(settings);
if (decomposed.size() == 1) {
return decomposed[0];
@@ -725,7 +889,7 @@ void Mesh::clear_cache() const {
debug_lines.clear();
}
-Vector][> Mesh::convex_decompose(const ConvexDecompositionSettings &p_settings) const {
+Vector][> Mesh::convex_decompose(const Ref &p_settings) const {
ERR_FAIL_COND_V(!convex_decomposition_function, Vector][>());
Ref tm = generate_triangle_mesh();
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 1b870d996ae..4d9b9b40871 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -39,6 +39,7 @@
class ConcavePolygonShape3D;
class ConvexPolygonShape3D;
+class MeshConvexDecompositionSettings;
class Shape3D;
class Mesh : public Resource {
@@ -178,42 +179,11 @@ public:
Size2i get_lightmap_size_hint() const;
void clear_cache() const;
- struct ConvexDecompositionSettings {
- enum Mode : int {
- CONVEX_DECOMPOSITION_MODE_VOXEL = 0,
- CONVEX_DECOMPOSITION_MODE_TETRAHEDRON
- };
-
- /// Maximum concavity. [Range: 0.0 -> 1.0]
- real_t max_concavity = 1.0;
- /// Controls the bias toward clipping along symmetry planes. [Range: 0.0 -> 1.0]
- real_t symmetry_planes_clipping_bias = 0.05;
- /// Controls the bias toward clipping along revolution axes. [Range: 0.0 -> 1.0]
- real_t revolution_axes_clipping_bias = 0.05;
- real_t min_volume_per_convex_hull = 0.0001;
- /// Maximum number of voxels generated during the voxelization stage.
- uint32_t resolution = 10'000;
- uint32_t max_num_vertices_per_convex_hull = 32;
- /// Controls the granularity of the search for the "best" clipping plane.
- /// [Range: 1 -> 16]
- uint32_t plane_downsampling = 4;
- /// Controls the precision of the convex-hull generation process during the
- /// clipping plane selection stage.
- /// [Range: 1 -> 16]
- uint32_t convexhull_downsampling = 4;
- /// enable/disable normalizing the mesh before applying the convex decomposition.
- bool normalize_mesh = false;
- Mode mode = CONVEX_DECOMPOSITION_MODE_VOXEL;
- bool convexhull_approximation = true;
- /// This is the maximum number of convex hulls to produce from the merge operation.
- uint32_t max_convex_hulls = 1;
- bool project_hull_vertices = true;
- };
- typedef Vector> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const ConvexDecompositionSettings &p_settings, Vector> *r_convex_indices);
+ typedef Vector> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const Ref &p_settings, Vector> *r_convex_indices);
static ConvexDecompositionFunc convex_decomposition_function;
- Vector][> convex_decompose(const ConvexDecompositionSettings &p_settings) const;
+ Vector][> convex_decompose(const Ref &p_settings) const;
Ref create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
Ref create_trimesh_shape() const;
@@ -225,6 +195,89 @@ public:
Mesh();
};
+class MeshConvexDecompositionSettings : public RefCounted {
+ GDCLASS(MeshConvexDecompositionSettings, RefCounted);
+
+public:
+ enum Mode : int {
+ CONVEX_DECOMPOSITION_MODE_VOXEL = 0,
+ CONVEX_DECOMPOSITION_MODE_TETRAHEDRON = 1
+ };
+
+private:
+ Mode mode = CONVEX_DECOMPOSITION_MODE_VOXEL;
+
+ /// Maximum concavity. [Range: 0.0 -> 1.0]
+ real_t max_concavity = 1.0;
+ /// Controls the bias toward clipping along symmetry planes. [Range: 0.0 -> 1.0]
+ real_t symmetry_planes_clipping_bias = 0.05;
+ /// Controls the bias toward clipping along revolution axes. [Range: 0.0 -> 1.0]
+ real_t revolution_axes_clipping_bias = 0.05;
+ real_t min_volume_per_convex_hull = 0.0001;
+ /// Maximum number of voxels generated during the voxelization stage.
+ uint32_t resolution = 10'000;
+ uint32_t max_num_vertices_per_convex_hull = 32;
+ /// Controls the granularity of the search for the "best" clipping plane.
+ /// [Range: 1 -> 16]
+ uint32_t plane_downsampling = 4;
+ /// Controls the precision of the convex-hull generation process during the
+ /// clipping plane selection stage.
+ /// [Range: 1 -> 16]
+ uint32_t convex_hull_downsampling = 4;
+ /// enable/disable normalizing the mesh before applying the convex decomposition.
+ bool normalize_mesh = false;
+
+ bool convex_hull_approximation = true;
+ /// This is the maximum number of convex hulls to produce from the merge operation.
+ uint32_t max_convex_hulls = 1;
+ bool project_hull_vertices = true;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_max_concavity(real_t p_max_concavity);
+ real_t get_max_concavity() const;
+
+ void set_symmetry_planes_clipping_bias(real_t p_symmetry_planes_clipping_bias);
+ real_t get_symmetry_planes_clipping_bias() const;
+
+ void set_revolution_axes_clipping_bias(real_t p_revolution_axes_clipping_bias);
+ real_t get_revolution_axes_clipping_bias() const;
+
+ void set_min_volume_per_convex_hull(real_t p_min_volume_per_convex_hull);
+ real_t get_min_volume_per_convex_hull() const;
+
+ void set_resolution(uint32_t p_resolution);
+ uint32_t get_resolution() const;
+
+ void set_max_num_vertices_per_convex_hull(uint32_t p_max_num_vertices_per_convex_hull);
+ uint32_t get_max_num_vertices_per_convex_hull() const;
+
+ void set_plane_downsampling(uint32_t p_plane_downsampling);
+ uint32_t get_plane_downsampling() const;
+
+ void set_convex_hull_downsampling(uint32_t p_convex_hull_downsampling);
+ uint32_t get_convex_hull_downsampling() const;
+
+ void set_normalize_mesh(bool p_normalize_mesh);
+ bool get_normalize_mesh() const;
+
+ void set_mode(Mode p_mode);
+ Mode get_mode() const;
+
+ void set_convex_hull_approximation(bool p_convex_hull_approximation);
+ bool get_convex_hull_approximation() const;
+
+ void set_max_convex_hulls(uint32_t p_max_convex_hulls);
+ uint32_t get_max_convex_hulls() const;
+
+ void set_project_hull_vertices(bool p_project_hull_vertices);
+ bool get_project_hull_vertices() const;
+};
+
+VARIANT_ENUM_CAST(MeshConvexDecompositionSettings::Mode);
+
class ArrayMesh : public Mesh {
GDCLASS(ArrayMesh, Mesh);
RES_BASE_EXTENSION("mesh");
]