Browse Source

Add Mesh ConvexDecompositionSettings wrapper

Adds wrapper MeshConvexDecompositionSettings to control parameters for Mesh ConvexDecomposition operations.
smix8 2 years ago
parent
commit
1549aeaef8

+ 60 - 0
doc/classes/MeshConvexDecompositionSettings.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MeshConvexDecompositionSettings" inherits="RefCounted" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+	<brief_description>
+		Parameters to be used with a [Mesh] convex decomposition operation.
+	</brief_description>
+	<description>
+		Parameters to be used with a [Mesh] convex decomposition operation.
+	</description>
+	<tutorials>
+	</tutorials>
+	<members>
+		<member name="convex_hull_approximation" type="bool" setter="set_convex_hull_approximation" getter="get_convex_hull_approximation" default="true">
+			If enabled uses approximation for computing convex hulls.
+		</member>
+		<member name="convex_hull_downsampling" type="int" setter="set_convex_hull_downsampling" getter="get_convex_hull_downsampling" default="4">
+			Controls the precision of the convex-hull generation process during the clipping plane selection stage. Ranges from [code]1[/code] to [code]16[/code].
+		</member>
+		<member name="max_concavity" type="float" setter="set_max_concavity" getter="get_max_concavity" default="1.0">
+			Maximum concavity. Ranges from [code]0.0[/code] to [code]1.0[/code].
+		</member>
+		<member name="max_convex_hulls" type="int" setter="set_max_convex_hulls" getter="get_max_convex_hulls" default="1">
+			The maximum number of convex hulls to produce from the merge operation.
+		</member>
+		<member name="max_num_vertices_per_convex_hull" type="int" setter="set_max_num_vertices_per_convex_hull" getter="get_max_num_vertices_per_convex_hull" default="32">
+			Controls the maximum number of triangles per convex-hull. Ranges from [code]4[/code] to [code]1024[/code].
+		</member>
+		<member name="min_volume_per_convex_hull" type="float" setter="set_min_volume_per_convex_hull" getter="get_min_volume_per_convex_hull" default="0.0001">
+			Controls the adaptive sampling of the generated convex-hulls. Ranges from [code]0.0[/code] to [code]0.01[/code].
+		</member>
+		<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="MeshConvexDecompositionSettings.Mode" default="0">
+			Mode for the approximate convex decomposition.
+		</member>
+		<member name="normalize_mesh" type="bool" setter="set_normalize_mesh" getter="get_normalize_mesh" default="false">
+			If enabled normalizes the mesh before applying the convex decomposition.
+		</member>
+		<member name="plane_downsampling" type="int" setter="set_plane_downsampling" getter="get_plane_downsampling" default="4">
+			Controls the granularity of the search for the "best" clipping plane. Ranges from [code]1[/code] to [code]16[/code].
+		</member>
+		<member name="project_hull_vertices" type="bool" setter="set_project_hull_vertices" getter="get_project_hull_vertices" default="true">
+			If enabled projects output convex hull vertices onto original source mesh to increase floating point accuracy of the results.
+		</member>
+		<member name="resolution" type="int" setter="set_resolution" getter="get_resolution" default="10000">
+			Maximum number of voxels generated during the voxelization stage.
+		</member>
+		<member name="revolution_axes_clipping_bias" type="float" setter="set_revolution_axes_clipping_bias" getter="get_revolution_axes_clipping_bias" default="0.05">
+			Controls the bias toward clipping along revolution axes. Ranges from [code]0.0[/code] to [code]1.0[/code].
+		</member>
+		<member name="symmetry_planes_clipping_bias" type="float" setter="set_symmetry_planes_clipping_bias" getter="get_symmetry_planes_clipping_bias" default="0.05">
+			Controls the bias toward clipping along symmetry planes. Ranges from [code]0.0[/code] to [code]1.0[/code].
+		</member>
+	</members>
+	<constants>
+		<constant name="CONVEX_DECOMPOSITION_MODE_VOXEL" value="0" enum="Mode">
+			Constant for voxel-based approximate convex decomposition.
+		</constant>
+		<constant name="CONVEX_DECOMPOSITION_MODE_TETRAHEDRON" value="1" enum="Mode">
+			Constant for tetrahedron-based approximate convex decomposition.
+		</constant>
+	</constants>
+</class>

+ 2 - 1
doc/classes/MeshInstance3D.xml

@@ -31,8 +31,9 @@
 		</method>
 		<method name="create_multiple_convex_collisions">
 			<return type="void" />
+			<param index="0" name="settings" type="MeshConvexDecompositionSettings" default="null" />
 			<description>
-				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].
 			</description>
 		</method>
 		<method name="create_trimesh_collision">

+ 15 - 14
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<MeshConvexDecompositionSettings> decomposition_default = Ref<MeshConvexDecompositionSettings>();
+			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<int>(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<int>(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)));

+ 22 - 21
editor/import/resource_importer_scene.h

@@ -323,7 +323,8 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Impor
 	}
 
 	if (generate_shape_type == SHAPE_TYPE_DECOMPOSE_CONVEX) {
-		Mesh::ConvexDecompositionSettings decomposition_settings;
+		Ref<MeshConvexDecompositionSettings> decomposition_settings = Ref<MeshConvexDecompositionSettings>();
+		decomposition_settings.instantiate();
 		bool advanced = false;
 		if (p_options.has(SNAME("decomposition/advanced"))) {
 			advanced = p_options[SNAME("decomposition/advanced")];
@@ -331,55 +332,55 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Impor
 
 		if (advanced) {
 			if (p_options.has(SNAME("decomposition/max_concavity"))) {
-				decomposition_settings.max_concavity = p_options[SNAME("decomposition/max_concavity")];
+				decomposition_settings->set_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<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Impor
 
 			const real_t precision = real_t(precision_level - 1) / 9.0;
 
-			decomposition_settings.max_concavity = Math::lerp(real_t(1.0), real_t(0.001), precision);
-			decomposition_settings.min_volume_per_convex_hull = Math::lerp(real_t(0.01), real_t(0.0001), precision);
-			decomposition_settings.resolution = Math::lerp(10'000, 100'000, precision);
-			decomposition_settings.max_num_vertices_per_convex_hull = Math::lerp(32, 64, precision);
-			decomposition_settings.plane_downsampling = Math::lerp(3, 16, precision);
-			decomposition_settings.convexhull_downsampling = Math::lerp(3, 16, precision);
-			decomposition_settings.max_convex_hulls = Math::lerp(1, 32, precision);
+			decomposition_settings->set_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);

+ 5 - 1
editor/plugins/mesh_instance_3d_editor_plugin.cpp

@@ -214,7 +214,11 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
 				return;
 			}
 
-			Mesh::ConvexDecompositionSettings settings;
+			Ref<MeshConvexDecompositionSettings> settings = Ref<MeshConvexDecompositionSettings>();
+			settings.instantiate();
+			settings->set_max_convex_hulls(32);
+			settings->set_max_concavity(0.001);
+
 			Vector<Ref<Shape3D>> shapes = mesh->convex_decompose(settings);
 
 			if (!shapes.size()) {

+ 14 - 14
modules/vhacd/register_types.cpp

@@ -32,22 +32,22 @@
 #include "scene/resources/mesh.h"
 #include "thirdparty/vhacd/public/VHACD.h"
 
-static Vector<Vector<Vector3>> 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<Vector<uint32_t>> *r_convex_indices) {
+static Vector<Vector<Vector3>> convex_decompose(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const Ref<MeshConvexDecompositionSettings> &p_settings, Vector<Vector<uint32_t>> *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);

+ 11 - 5
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<MeshConvexDecompositionSettings> &p_settings) {
 	if (mesh.is_null()) {
 		return nullptr;
 	}
 
-	Mesh::ConvexDecompositionSettings settings;
+	Ref<MeshConvexDecompositionSettings> settings;
+	if (p_settings.is_valid()) {
+		settings = p_settings;
+	} else {
+		settings.instantiate();
+	}
+
 	Vector<Ref<Shape3D>> 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<StaticBody3D>(create_multiple_convex_collisions_node());
+void MeshInstance3D::create_multiple_convex_collisions(const Ref<MeshConvexDecompositionSettings> &p_settings) {
+	StaticBody3D *static_body = Object::cast_to<StaticBody3D>(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<MeshConvexDecompositionSettings>()));
 	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);

+ 2 - 2
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<MeshConvexDecompositionSettings> &p_settings = Ref<MeshConvexDecompositionSettings>());
+	void create_multiple_convex_collisions(const Ref<MeshConvexDecompositionSettings> &p_settings = Ref<MeshConvexDecompositionSettings>());
 
 	MeshInstance3D *create_debug_tangents_node();
 	void create_debug_tangents();

+ 1 - 0
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);

+ 4 - 3
scene/resources/importer_mesh.cpp

@@ -938,7 +938,7 @@ Vector<Face3> ImporterMesh::get_faces() const {
 	return faces;
 }
 
-Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const {
+Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Ref<MeshConvexDecompositionSettings> &p_settings) const {
 	ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>());
 
 	const Vector<Face3> faces = get_faces();
@@ -987,8 +987,9 @@ Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Mesh::ConvexDecomposit
 
 Ref<ConvexPolygonShape3D> ImporterMesh::create_convex_shape(bool p_clean, bool p_simplify) const {
 	if (p_simplify) {
-		Mesh::ConvexDecompositionSettings settings;
-		settings.max_convex_hulls = 1;
+		Ref<MeshConvexDecompositionSettings> settings;
+		settings.instantiate();
+		settings->set_max_convex_hulls(1);
 		Vector<Ref<Shape3D>> decomposed = convex_decompose(settings);
 		if (decomposed.size() == 1) {
 			return decomposed[0];

+ 1 - 1
scene/resources/importer_mesh.h

@@ -118,7 +118,7 @@ public:
 	Ref<ImporterMesh> get_shadow_mesh() const;
 
 	Vector<Face3> get_faces() const;
-	Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const;
+	Vector<Ref<Shape3D>> convex_decompose(const Ref<MeshConvexDecompositionSettings> &p_settings) const;
 	Ref<ConvexPolygonShape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
 	Ref<ConcavePolygonShape3D> create_trimesh_shape() const;
 	Ref<NavigationMesh> create_navigation_mesh();

+ 167 - 3
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<Face3> Mesh::get_surface_faces(int p_surface) const {
 
 Ref<ConvexPolygonShape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
 	if (p_simplify) {
-		ConvexDecompositionSettings settings;
-		settings.max_convex_hulls = 1;
+		Ref<MeshConvexDecompositionSettings> settings = Ref<MeshConvexDecompositionSettings>();
+		settings.instantiate();
+		settings->set_max_convex_hulls(1);
+		settings->set_max_concavity(1.0);
 		Vector<Ref<Shape3D>> decomposed = convex_decompose(settings);
 		if (decomposed.size() == 1) {
 			return decomposed[0];
@@ -725,7 +889,7 @@ void Mesh::clear_cache() const {
 	debug_lines.clear();
 }
 
-Vector<Ref<Shape3D>> Mesh::convex_decompose(const ConvexDecompositionSettings &p_settings) const {
+Vector<Ref<Shape3D>> Mesh::convex_decompose(const Ref<MeshConvexDecompositionSettings> &p_settings) const {
 	ERR_FAIL_COND_V(!convex_decomposition_function, Vector<Ref<Shape3D>>());
 
 	Ref<TriangleMesh> tm = generate_triangle_mesh();

+ 86 - 33
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<Vector<Vector3>> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const ConvexDecompositionSettings &p_settings, Vector<Vector<uint32_t>> *r_convex_indices);
+	typedef Vector<Vector<Vector3>> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const Ref<MeshConvexDecompositionSettings> &p_settings, Vector<Vector<uint32_t>> *r_convex_indices);
 
 	static ConvexDecompositionFunc convex_decomposition_function;
 
-	Vector<Ref<Shape3D>> convex_decompose(const ConvexDecompositionSettings &p_settings) const;
+	Vector<Ref<Shape3D>> convex_decompose(const Ref<MeshConvexDecompositionSettings> &p_settings) const;
 	Ref<ConvexPolygonShape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
 	Ref<ConcavePolygonShape3D> 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");