Merge pull request #50328 from nekomatata/convex-hull-simplification-3.x
[3.x] Options to clean/simplify convex hull generated from mesh
This commit is contained in:
commit
9d2cbe2c02
|
@ -2249,14 +2249,22 @@ real_t ConvexHullComputer::compute(const Vector3 *p_coords, int32_t p_count, rea
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) {
|
Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) {
|
||||||
|
return convex_hull(p_points.ptr(), p_points.size(), r_mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error ConvexHullComputer::convex_hull(const PoolVector<Vector3> &p_points, Geometry::MeshData &r_mesh) {
|
||||||
|
return convex_hull(p_points.read().ptr(), p_points.size(), r_mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error ConvexHullComputer::convex_hull(const Vector3 *p_points, int32_t p_point_count, Geometry::MeshData &r_mesh) {
|
||||||
r_mesh = Geometry::MeshData(); // clear
|
r_mesh = Geometry::MeshData(); // clear
|
||||||
|
|
||||||
if (p_points.size() == 0) {
|
if (p_point_count == 0) {
|
||||||
return FAILED; // matches QuickHull
|
return FAILED; // matches QuickHull
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvexHullComputer ch;
|
ConvexHullComputer ch;
|
||||||
ch.compute(p_points.ptr(), p_points.size(), -1.0, -1.0);
|
ch.compute(p_points, p_point_count, -1.0, -1.0);
|
||||||
|
|
||||||
r_mesh.vertices = ch.vertices;
|
r_mesh.vertices = ch.vertices;
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,8 @@ public:
|
||||||
real_t compute(const Vector3 *p_coords, int32_t p_count, real_t p_shrink, real_t p_shrink_clamp);
|
real_t compute(const Vector3 *p_coords, int32_t p_count, real_t p_shrink, real_t p_shrink_clamp);
|
||||||
|
|
||||||
static Error convex_hull(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh);
|
static Error convex_hull(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh);
|
||||||
|
static Error convex_hull(const PoolVector<Vector3> &p_points, Geometry::MeshData &r_mesh);
|
||||||
|
static Error convex_hull(const Vector3 *p_points, int32_t p_point_count, Geometry::MeshData &r_mesh);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONVEX_HULL_H
|
#endif // CONVEX_HULL_H
|
||||||
|
|
|
@ -16,8 +16,14 @@
|
||||||
<method name="create_convex_shape" qualifiers="const">
|
<method name="create_convex_shape" qualifiers="const">
|
||||||
<return type="Shape">
|
<return type="Shape">
|
||||||
</return>
|
</return>
|
||||||
|
<argument index="0" name="clean" type="bool" default="true">
|
||||||
|
</argument>
|
||||||
|
<argument index="1" name="simplify" type="bool" default="false">
|
||||||
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Calculate a [ConvexPolygonShape] from the mesh.
|
Calculate a [ConvexPolygonShape] from the mesh.
|
||||||
|
If [code]clean[/code] is [code]true[/code] (default), duplicate and interior vertices are removed automatically. You can set it to [code]false[/code] to make the process faster if not needed.
|
||||||
|
If [code]simplify[/code] is [code]true[/code], the geometry can be further simplified to reduce the amount of vertices. Disabled by default.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="create_outline" qualifiers="const">
|
<method name="create_outline" qualifiers="const">
|
||||||
|
|
|
@ -16,8 +16,14 @@
|
||||||
<method name="create_convex_collision">
|
<method name="create_convex_collision">
|
||||||
<return type="void">
|
<return type="void">
|
||||||
</return>
|
</return>
|
||||||
|
<argument index="0" name="clean" type="bool" default="true">
|
||||||
|
</argument>
|
||||||
|
<argument index="1" name="simplify" type="bool" default="false">
|
||||||
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
This helper creates a [StaticBody] child node with a [ConvexPolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing.
|
This helper creates a [StaticBody] child node with a [ConvexPolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing.
|
||||||
|
If [code]clean[/code] is [code]true[/code] (default), duplicate and interior vertices are removed automatically. You can set it to [code]false[/code] to make the process faster if not needed.
|
||||||
|
If [code]simplify[/code] is [code]true[/code], the geometry can be further simplified to reduce the amount of vertices. Disabled by default.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="create_debug_tangents">
|
<method name="create_debug_tangents">
|
||||||
|
|
|
@ -153,14 +153,18 @@ void MeshInstanceEditor::_menu_option(int p_option) {
|
||||||
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
|
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
|
||||||
ur->commit_action();
|
ur->commit_action();
|
||||||
} break;
|
} break;
|
||||||
case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: {
|
|
||||||
|
case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE:
|
||||||
|
case MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE: {
|
||||||
if (node == get_tree()->get_edited_scene_root()) {
|
if (node == get_tree()->get_edited_scene_root()) {
|
||||||
err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root."));
|
err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root."));
|
||||||
err_dialog->popup_centered_minsize();
|
err_dialog->popup_centered_minsize();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Shape> shape = mesh->create_convex_shape();
|
bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
|
||||||
|
|
||||||
|
Ref<Shape> shape = mesh->create_convex_shape(true, simplify);
|
||||||
|
|
||||||
if (shape.is_null()) {
|
if (shape.is_null()) {
|
||||||
err_dialog->set_text(TTR("Couldn't create a single convex collision shape."));
|
err_dialog->set_text(TTR("Couldn't create a single convex collision shape."));
|
||||||
|
@ -169,7 +173,11 @@ void MeshInstanceEditor::_menu_option(int p_option) {
|
||||||
}
|
}
|
||||||
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
||||||
|
|
||||||
ur->create_action(TTR("Create Single Convex Shape"));
|
if (simplify) {
|
||||||
|
ur->create_action(TTR("Create Simplified Convex Shape"));
|
||||||
|
} else {
|
||||||
|
ur->create_action(TTR("Create Single Convex Shape"));
|
||||||
|
}
|
||||||
|
|
||||||
CollisionShape *cshape = memnew(CollisionShape);
|
CollisionShape *cshape = memnew(CollisionShape);
|
||||||
cshape->set_shape(shape);
|
cshape->set_shape(shape);
|
||||||
|
@ -186,6 +194,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
|
||||||
ur->commit_action();
|
ur->commit_action();
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: {
|
case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: {
|
||||||
if (node == get_tree()->get_edited_scene_root()) {
|
if (node == get_tree()->get_edited_scene_root()) {
|
||||||
err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root."));
|
err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root."));
|
||||||
|
@ -447,8 +456,10 @@ MeshInstanceEditor::MeshInstanceEditor() {
|
||||||
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
|
||||||
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
|
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
|
||||||
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
|
||||||
|
options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
|
||||||
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
|
||||||
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
|
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
|
||||||
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options."));
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
|
||||||
options->get_popup()->add_separator();
|
options->get_popup()->add_separator();
|
||||||
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
|
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
|
||||||
options->get_popup()->add_separator();
|
options->get_popup()->add_separator();
|
||||||
|
|
|
@ -44,6 +44,7 @@ class MeshInstanceEditor : public Control {
|
||||||
MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
|
MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
|
||||||
MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
|
MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
|
||||||
MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE,
|
MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE,
|
||||||
|
MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE,
|
||||||
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
|
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
|
||||||
MENU_OPTION_CREATE_NAVMESH,
|
MENU_OPTION_CREATE_NAVMESH,
|
||||||
MENU_OPTION_CREATE_OUTLINE_MESH,
|
MENU_OPTION_CREATE_OUTLINE_MESH,
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "scene/resources/mesh.h"
|
#include "scene/resources/mesh.h"
|
||||||
#include "thirdparty/vhacd/public/VHACD.h"
|
#include "thirdparty/vhacd/public/VHACD.h"
|
||||||
|
|
||||||
static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces) {
|
static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, int p_max_convex_hulls = -1) {
|
||||||
Vector<float> vertices;
|
Vector<float> vertices;
|
||||||
vertices.resize(p_faces.size() * 9);
|
vertices.resize(p_faces.size() * 9);
|
||||||
Vector<uint32_t> indices;
|
Vector<uint32_t> indices;
|
||||||
|
@ -47,8 +47,12 @@ static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VHACD::IVHACD *decomposer = VHACD::CreateVHACD();
|
|
||||||
VHACD::IVHACD::Parameters params;
|
VHACD::IVHACD::Parameters params;
|
||||||
|
if (p_max_convex_hulls > 0) {
|
||||||
|
params.m_maxConvexHulls = p_max_convex_hulls;
|
||||||
|
}
|
||||||
|
|
||||||
|
VHACD::IVHACD *decomposer = VHACD::CreateVHACD();
|
||||||
decomposer->Compute(vertices.ptr(), vertices.size() / 3, indices.ptr(), indices.size() / 3, params);
|
decomposer->Compute(vertices.ptr(), vertices.size() / 3, indices.ptr(), indices.size() / 3, params);
|
||||||
|
|
||||||
int hull_count = decomposer->GetNConvexHulls();
|
int hull_count = decomposer->GetNConvexHulls();
|
||||||
|
|
|
@ -611,12 +611,12 @@ void MeshInstance::create_multiple_convex_collisions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *MeshInstance::create_convex_collision_node() {
|
Node *MeshInstance::create_convex_collision_node(bool p_clean, bool p_simplify) {
|
||||||
if (mesh.is_null()) {
|
if (mesh.is_null()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Shape> shape = mesh->create_convex_shape();
|
Ref<Shape> shape = mesh->create_convex_shape(p_clean, p_simplify);
|
||||||
if (shape.is_null()) {
|
if (shape.is_null()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -628,8 +628,8 @@ Node *MeshInstance::create_convex_collision_node() {
|
||||||
return static_body;
|
return static_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshInstance::create_convex_collision() {
|
void MeshInstance::create_convex_collision(bool p_clean, bool p_simplify) {
|
||||||
StaticBody *static_body = Object::cast_to<StaticBody>(create_convex_collision_node());
|
StaticBody *static_body = Object::cast_to<StaticBody>(create_convex_collision_node(p_clean, p_simplify));
|
||||||
ERR_FAIL_COND(!static_body);
|
ERR_FAIL_COND(!static_body);
|
||||||
static_body->set_name(String(get_name()) + "_col");
|
static_body->set_name(String(get_name()) + "_col");
|
||||||
|
|
||||||
|
@ -841,7 +841,7 @@ void MeshInstance::_bind_methods() {
|
||||||
ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
|
ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
|
||||||
ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance::create_multiple_convex_collisions);
|
ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance::create_multiple_convex_collisions);
|
||||||
ClassDB::set_method_flags("MeshInstance", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT);
|
ClassDB::set_method_flags("MeshInstance", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT);
|
||||||
ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance::create_convex_collision);
|
ClassDB::bind_method(D_METHOD("create_convex_collision", "clean", "simplify"), &MeshInstance::create_convex_collision, DEFVAL(true), DEFVAL(false));
|
||||||
ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);
|
ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);
|
||||||
ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed);
|
ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed);
|
||||||
ClassDB::bind_method(D_METHOD("_update_skinning"), &MeshInstance::_update_skinning);
|
ClassDB::bind_method(D_METHOD("_update_skinning"), &MeshInstance::_update_skinning);
|
||||||
|
|
|
@ -128,8 +128,8 @@ public:
|
||||||
Node *create_multiple_convex_collisions_node();
|
Node *create_multiple_convex_collisions_node();
|
||||||
void create_multiple_convex_collisions();
|
void create_multiple_convex_collisions();
|
||||||
|
|
||||||
Node *create_convex_collision_node();
|
Node *create_convex_collision_node(bool p_clean = true, bool p_simplify = false);
|
||||||
void create_convex_collision();
|
void create_convex_collision(bool p_clean = true, bool p_simplify = false);
|
||||||
|
|
||||||
void create_debug_tangents();
|
void create_debug_tangents();
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "core/crypto/crypto_core.h"
|
#include "core/crypto/crypto_core.h"
|
||||||
#include "core/local_vector.h"
|
#include "core/local_vector.h"
|
||||||
|
#include "core/math/convex_hull.h"
|
||||||
#include "core/pair.h"
|
#include "core/pair.h"
|
||||||
#include "scene/resources/concave_polygon_shape.h"
|
#include "scene/resources/concave_polygon_shape.h"
|
||||||
#include "scene/resources/convex_polygon_shape.h"
|
#include "scene/resources/convex_polygon_shape.h"
|
||||||
|
@ -229,9 +230,17 @@ PoolVector<Face3> Mesh::get_faces() const {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Shape> Mesh::create_convex_shape() const {
|
Ref<Shape> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
|
||||||
PoolVector<Vector3> vertices;
|
if (p_simplify) {
|
||||||
|
Vector<Ref<Shape>> decomposed = convex_decompose(1);
|
||||||
|
if (decomposed.size() == 1) {
|
||||||
|
return decomposed[0];
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Convex shape simplification failed, falling back to simpler process.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolVector<Vector3> vertices;
|
||||||
for (int i = 0; i < get_surface_count(); i++) {
|
for (int i = 0; i < get_surface_count(); i++) {
|
||||||
Array a = surface_get_arrays(i);
|
Array a = surface_get_arrays(i);
|
||||||
ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape>());
|
ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape>());
|
||||||
|
@ -240,6 +249,24 @@ Ref<Shape> Mesh::create_convex_shape() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ConvexPolygonShape> shape = memnew(ConvexPolygonShape);
|
Ref<ConvexPolygonShape> shape = memnew(ConvexPolygonShape);
|
||||||
|
|
||||||
|
if (p_clean) {
|
||||||
|
Geometry::MeshData md;
|
||||||
|
Error err = ConvexHullComputer::convex_hull(vertices, md);
|
||||||
|
if (err == OK) {
|
||||||
|
int vertex_count = md.vertices.size();
|
||||||
|
vertices.resize(vertex_count);
|
||||||
|
{
|
||||||
|
PoolVector<Vector3>::Write w = vertices.write();
|
||||||
|
for (int idx = 0; idx < vertex_count; ++idx) {
|
||||||
|
w[idx] = md.vertices[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Convex shape cleaning failed, falling back to simpler process.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shape->set_points(vertices);
|
shape->set_points(vertices);
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
@ -539,7 +566,7 @@ void Mesh::clear_cache() const {
|
||||||
debug_lines.clear();
|
debug_lines.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Ref<Shape>> Mesh::convex_decompose() const {
|
Vector<Ref<Shape>> Mesh::convex_decompose(int p_max_convex_hulls) const {
|
||||||
ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape>>());
|
ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape>>());
|
||||||
|
|
||||||
PoolVector<Face3> faces = get_faces();
|
PoolVector<Face3> faces = get_faces();
|
||||||
|
@ -550,7 +577,7 @@ Vector<Ref<Shape>> Mesh::convex_decompose() const {
|
||||||
f3.write[i] = f[i];
|
f3.write[i] = f[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Vector<Face3>> decomposed = convex_composition_function(f3);
|
Vector<Vector<Face3>> decomposed = convex_composition_function(f3, p_max_convex_hulls);
|
||||||
|
|
||||||
Vector<Ref<Shape>> ret;
|
Vector<Ref<Shape>> ret;
|
||||||
|
|
||||||
|
@ -1428,7 +1455,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_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("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_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("create_outline", "margin"), &ArrayMesh::create_outline);
|
||||||
ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps);
|
ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps);
|
||||||
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
||||||
|
|
|
@ -137,7 +137,7 @@ public:
|
||||||
void generate_debug_mesh_indices(Vector<Vector3> &r_points);
|
void generate_debug_mesh_indices(Vector<Vector3> &r_points);
|
||||||
|
|
||||||
Ref<Shape> create_trimesh_shape() const;
|
Ref<Shape> create_trimesh_shape() const;
|
||||||
Ref<Shape> create_convex_shape() const;
|
Ref<Shape> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
|
||||||
|
|
||||||
Ref<Mesh> create_outline(float p_margin) const;
|
Ref<Mesh> create_outline(float p_margin) const;
|
||||||
|
|
||||||
|
@ -147,11 +147,11 @@ public:
|
||||||
Size2 get_lightmap_size_hint() const;
|
Size2 get_lightmap_size_hint() const;
|
||||||
void clear_cache() const;
|
void clear_cache() const;
|
||||||
|
|
||||||
typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &);
|
typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &p_faces, int p_max_convex_hulls);
|
||||||
|
|
||||||
static ConvexDecompositionFunc convex_composition_function;
|
static ConvexDecompositionFunc convex_composition_function;
|
||||||
|
|
||||||
Vector<Ref<Shape>> convex_decompose() const;
|
Vector<Ref<Shape>> convex_decompose(int p_max_convex_hulls = -1) const;
|
||||||
|
|
||||||
Mesh();
|
Mesh();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue