From 7f0a8c6a9850515df8b0c58d6e2fb1e8a9c9e382 Mon Sep 17 00:00:00 2001 From: Morris Tabor <80684659+mortarroad@users.noreply.github.com> Date: Thu, 25 Mar 2021 12:07:18 +0100 Subject: [PATCH] Use Bullet's convex hull computer in place of QuickHull when available. --- core/math/geometry.cpp | 10 ++++ core/math/geometry.h | 4 ++ editor/spatial_editor_gizmos.cpp | 3 +- main/tests/test_physics.cpp | 3 +- main/tests/test_render.cpp | 3 +- modules/recast/navigation_mesh_generator.cpp | 3 +- modules/vhacd/register_types.cpp | 54 ++++++++++++++++++++ scene/resources/convex_polygon_shape.cpp | 4 +- servers/physics/shape_sw.cpp | 5 +- 9 files changed, 76 insertions(+), 13 deletions(-) diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index dedf1e0bc29d..ade4bb92139f 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -30,6 +30,7 @@ #include "geometry.h" +#include "core/math/quick_hull.h" #include "core/print_string.h" #include "thirdparty/misc/clipper.hpp" @@ -39,6 +40,8 @@ #define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON. +Geometry::ConvexHullFunc Geometry::convex_hull_function = NULL; + // This implementation is very inefficient, commenting unless bugs happen. See the other one. /* bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector &p_polygon) { @@ -862,6 +865,13 @@ Geometry::MeshData Geometry::build_convex_mesh(const PoolVector &p_planes return mesh; } +Error Geometry::build_convex_hull(const Vector &p_points, Geometry::MeshData &r_mesh) { + if (!convex_hull_function) { + return QuickHull::build(p_points, r_mesh); + } + return convex_hull_function(p_points, r_mesh); +} + PoolVector Geometry::build_box_planes(const Vector3 &p_extents) { PoolVector planes; diff --git a/core/math/geometry.h b/core/math/geometry.h index a3d44fbfbc7f..f00b2e09038a 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -1037,6 +1037,7 @@ class Geometry { static Vector > decompose_polygon_in_convex(Vector polygon); static MeshData build_convex_mesh(const PoolVector &p_planes); + static Error build_convex_hull(const Vector &p_points, MeshData &r_mesh); static PoolVector build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); static PoolVector build_box_planes(const Vector3 &p_extents); static PoolVector build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); @@ -1053,6 +1054,9 @@ class Geometry { static Vector compute_convex_mesh_points(const Plane *p_planes, int p_plane_count); + typedef Error (*ConvexHullFunc)(const Vector &, MeshData &); + static ConvexHullFunc convex_hull_function; + private: static Vector > _polypaths_do_operation(PolyBooleanOperation p_op, const Vector &p_polypath_a, const Vector &p_polypath_b, bool is_a_open = false); static Vector > _polypath_offset(const Vector &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 7aec7e7afe6d..7009f529df02 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -31,7 +31,6 @@ #include "spatial_editor_gizmos.h" #include "core/math/geometry.h" -#include "core/math/quick_hull.h" #include "scene/3d/audio_stream_player_3d.h" #include "scene/3d/baked_lightmap.h" #include "scene/3d/collision_polygon.h" @@ -3671,7 +3670,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Vector varr = Variant(points); Geometry::MeshData md; - Error err = QuickHull::build(varr, md); + Error err = Geometry::build_convex_hull(varr, md); if (err == OK) { Vector points2; points2.resize(md.edges.size() * 2); diff --git a/main/tests/test_physics.cpp b/main/tests/test_physics.cpp index 83ceeb9c0464..47d47829bf52 100644 --- a/main/tests/test_physics.cpp +++ b/main/tests/test_physics.cpp @@ -32,7 +32,6 @@ #include "core/map.h" #include "core/math/math_funcs.h" -#include "core/math/quick_hull.h" #include "core/os/main_loop.h" #include "core/os/os.h" #include "core/print_string.h" @@ -176,7 +175,7 @@ class TestPhysicsMainLoop : public MainLoop { RID convex_mesh = vs->mesh_create(); Geometry::MeshData convex_data = Geometry::build_convex_mesh(convex_planes); - QuickHull::build(convex_data.vertices, convex_data); + Geometry::build_convex_hull(convex_data.vertices, convex_data); vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data); type_mesh_map[PhysicsServer::SHAPE_CONVEX_POLYGON] = convex_mesh; diff --git a/main/tests/test_render.cpp b/main/tests/test_render.cpp index 57b18d7a4d69..4b2055dee582 100644 --- a/main/tests/test_render.cpp +++ b/main/tests/test_render.cpp @@ -31,7 +31,6 @@ #include "test_render.h" #include "core/math/math_funcs.h" -#include "core/math/quick_hull.h" #include "core/os/keyboard.h" #include "core/os/main_loop.h" #include "core/os/os.h" @@ -121,7 +120,7 @@ class TestMainLoop : public MainLoop { vts.push_back(Vector3(-1, -1, -1)); Geometry::MeshData md; - Error err = QuickHull::build(vts, md); + Error err = Geometry::build_convex_hull(vts, md); print_line("ERR: " + itos(err)); test_cube = vs->mesh_create(); vs->mesh_add_surface_from_mesh_data(test_cube, md); diff --git a/modules/recast/navigation_mesh_generator.cpp b/modules/recast/navigation_mesh_generator.cpp index e677c499658a..2c70dc8be835 100644 --- a/modules/recast/navigation_mesh_generator.cpp +++ b/modules/recast/navigation_mesh_generator.cpp @@ -29,7 +29,6 @@ /*************************************************************************/ #include "navigation_mesh_generator.h" -#include "core/math/quick_hull.h" #include "core/os/thread.h" #include "editor/editor_settings.h" #include "scene/3d/collision_shape.h" @@ -217,7 +216,7 @@ void EditorNavigationMeshGenerator::_parse_geometry(Transform p_accumulated_tran Vector varr = Variant(convex_polygon->get_points()); Geometry::MeshData md; - Error err = QuickHull::build(varr, md); + Error err = Geometry::build_convex_hull(varr, md); if (err == OK) { PoolVector3Array faces; diff --git a/modules/vhacd/register_types.cpp b/modules/vhacd/register_types.cpp index c3d32df18e86..cef63b0fa316 100644 --- a/modules/vhacd/register_types.cpp +++ b/modules/vhacd/register_types.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "register_types.h" +#include "core/math/geometry.h" #include "scene/resources/mesh.h" +#include "thirdparty/vhacd/inc/btConvexHullComputer.h" #include "thirdparty/vhacd/public/VHACD.h" static Vector > convex_decompose(const Vector &p_faces) { @@ -79,10 +81,62 @@ static Vector > convex_decompose(const Vector &p_faces) { return ret; } +static Error convex_hull(const Vector &p_points, Geometry::MeshData &r_mesh) { + // build the convex hull using the convex hull computer from bullet. + // simply copies the data over to Godot's types + + r_mesh = Geometry::MeshData(); // clear + + if (p_points.size() == 0) { + return FAILED; // matches QuickHull + } + + VHACD::btConvexHullComputer ch; + ch.compute(&p_points.ptr()[0][0], sizeof(p_points.ptr()[0]), p_points.size(), -1.0, -1.0); + + Geometry::MeshData ret; + r_mesh.vertices.resize(ch.vertices.size()); + for (int i = 0; i < ch.vertices.size(); i++) { + r_mesh.vertices.write[i].x = ch.vertices[i].getX(); + r_mesh.vertices.write[i].y = ch.vertices[i].getY(); + r_mesh.vertices.write[i].z = ch.vertices[i].getZ(); + } + + r_mesh.edges.resize(ch.edges.size()); + for (int i = 0; i < ch.edges.size(); i++) { + r_mesh.edges.write[i].a = (&ch.edges[i])->getSourceVertex(); + r_mesh.edges.write[i].b = (&ch.edges[i])->getTargetVertex(); + } + + r_mesh.faces.resize(ch.faces.size()); + for (int i = 0; i < ch.faces.size(); i++) { + const VHACD::btConvexHullComputer::Edge *e_start = &ch.edges[ch.faces[i]]; + const VHACD::btConvexHullComputer::Edge *e = e_start; + Geometry::MeshData::Face &face = r_mesh.faces.write[i]; + + do { + face.indices.push_back(e->getTargetVertex()); + + e = e->getNextEdgeOfFace(); + } while (e != e_start); + + // compute normal + if (face.indices.size() >= 3) { + face.plane = Plane(r_mesh.vertices[face.indices[0]], r_mesh.vertices[face.indices[2]], r_mesh.vertices[face.indices[1]]); + } else { + WARN_PRINT("Too few vertices per face."); + } + } + + return OK; +} + void register_vhacd_types() { Mesh::convex_composition_function = convex_decompose; + Geometry::convex_hull_function = convex_hull; } void unregister_vhacd_types() { Mesh::convex_composition_function = NULL; + Geometry::convex_hull_function = NULL; } diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp index d05ed15fc41f..86755f7bbcbf 100644 --- a/scene/resources/convex_polygon_shape.cpp +++ b/scene/resources/convex_polygon_shape.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "convex_polygon_shape.h" -#include "core/math/quick_hull.h" +#include "core/math/geometry.h" #include "servers/physics_server.h" Vector ConvexPolygonShape::get_debug_mesh_lines() { @@ -40,7 +40,7 @@ Vector ConvexPolygonShape::get_debug_mesh_lines() { Vector varr = Variant(points); Geometry::MeshData md; - Error err = QuickHull::build(varr, md); + Error err = Geometry::build_convex_hull(varr, md); if (err == OK) { Vector lines; lines.resize(md.edges.size() * 2); diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index 025e7b15b223..c80bd3df9115 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -31,7 +31,6 @@ #include "shape_sw.h" #include "core/math/geometry.h" -#include "core/math/quick_hull.h" #include "core/sort_array.h" #define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002 @@ -1149,9 +1148,9 @@ Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { void ConvexPolygonShapeSW::_setup(const Vector &p_vertices) { - Error err = QuickHull::build(p_vertices, mesh); + Error err = Geometry::build_convex_hull(p_vertices, mesh); if (err != OK) - ERR_PRINT("Failed to build QuickHull"); + ERR_PRINT("Failed to build convex hull"); AABB _aabb;