From 35eabcb84647d1e091f1311c75abe11553ccf437 Mon Sep 17 00:00:00 2001 From: Relintai Date: Mon, 25 Jul 2022 22:57:51 +0200 Subject: [PATCH] Ported: Fix navmesh baking, fixes #57148 - improved mesh data calculation from standalone static colliders so that no VisualServer calls are performed - and thus no VS mutexes need to be locked in case of on-thread baking - improved the same for GridMap's static colliders - Scony https://github.com/godotengine/godot/commit/3035b9c44c5b026e2bf6f6faa6589271f90de320 --- .../navigation/navigation_mesh_generator.cpp | 63 +++++++++++-------- .../navigation/navigation_mesh_generator.h | 1 + scene/resources/primitive_meshes.cpp | 16 +++++ scene/resources/primitive_meshes.h | 8 +++ 4 files changed, 63 insertions(+), 25 deletions(-) diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 4acc30862..0932bc758 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -122,6 +122,28 @@ void NavigationMeshGenerator::_add_mesh(const Ref &p_mesh, const Transform } } +void NavigationMeshGenerator::_add_mesh_array(const Array &p_array, const Transform &p_xform, Vector &p_vertices, Vector &p_indices) { + PoolVector mesh_vertices = p_array[Mesh::ARRAY_VERTEX]; + PoolVector::Read vr = mesh_vertices.read(); + + PoolVector mesh_indices = p_array[Mesh::ARRAY_INDEX]; + PoolVector::Read ir = mesh_indices.read(); + + const int face_count = mesh_indices.size() / 3; + const int current_vertex_count = p_vertices.size() / 3; + + for (int j = 0; j < mesh_vertices.size(); j++) { + _add_vertex(p_xform.xform(vr[j]), p_vertices); + } + + for (int j = 0; j < face_count; j++) { + // CCW + p_indices.push_back(current_vertex_count + (ir[j * 3 + 0])); + p_indices.push_back(current_vertex_count + (ir[j * 3 + 2])); + p_indices.push_back(current_vertex_count + (ir[j * 3 + 1])); + } +} + void NavigationMeshGenerator::_add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector &p_vertices, Vector &p_indices) { int face_count = p_faces.size() / 3; int current_vertex_count = p_vertices.size() / 3; @@ -172,43 +194,38 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform, Transform transform = p_navmesh_xform * static_body->get_global_transform() * col_shape->get_transform(); - Ref mesh; Ref s = col_shape->get_shape(); BoxShape *box = Object::cast_to(*s); if (box) { - Ref cube_mesh; - cube_mesh.instance(); - cube_mesh->set_size(box->get_extents() * 2.0); - mesh = cube_mesh; + Array arr; + arr.resize(VS::ARRAY_MAX); + CubeMesh::create_mesh_array(arr, box->get_extents() * 2.0); + _add_mesh_array(arr, transform, p_vertices, p_indices); } CapsuleShape *capsule = Object::cast_to(*s); if (capsule) { - Ref capsule_mesh; - capsule_mesh.instance(); - capsule_mesh->set_radius(capsule->get_radius()); - capsule_mesh->set_mid_height(capsule->get_height() / 2.0); - mesh = capsule_mesh; + Array arr; + arr.resize(VS::ARRAY_MAX); + CapsuleMesh::create_mesh_array(arr, capsule->get_radius(), capsule->get_height() / 2.0); + _add_mesh_array(arr, transform, p_vertices, p_indices); } CylinderShape *cylinder = Object::cast_to(*s); if (cylinder) { - Ref cylinder_mesh; - cylinder_mesh.instance(); - cylinder_mesh->set_height(cylinder->get_height()); - cylinder_mesh->set_bottom_radius(cylinder->get_radius()); - cylinder_mesh->set_top_radius(cylinder->get_radius()); - mesh = cylinder_mesh; + Array arr; + arr.resize(VS::ARRAY_MAX); + CylinderMesh::create_mesh_array(arr, cylinder->get_radius(), cylinder->get_radius(), cylinder->get_height()); + _add_mesh_array(arr, transform, p_vertices, p_indices); } SphereShape *sphere = Object::cast_to(*s); if (sphere) { - Ref sphere_mesh; - sphere_mesh.instance(); - sphere_mesh->set_radius(sphere->get_radius()); - sphere_mesh->set_height(sphere->get_radius() * 2.0); - mesh = sphere_mesh; + Array arr; + arr.resize(VS::ARRAY_MAX); + SphereMesh::create_mesh_array(arr, sphere->get_radius(), sphere->get_radius() * 2.0); + _add_mesh_array(arr, transform, p_vertices, p_indices); } ConcavePolygonShape *concave_polygon = Object::cast_to(*s); @@ -239,10 +256,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform, _add_faces(faces, transform, p_vertices, p_indices); } } - - if (mesh.is_valid()) { - _add_mesh(mesh, transform, p_vertices, p_indices); - } } } } diff --git a/modules/navigation/navigation_mesh_generator.h b/modules/navigation/navigation_mesh_generator.h index 21e5c8cf6..b2fa75293 100644 --- a/modules/navigation/navigation_mesh_generator.h +++ b/modules/navigation/navigation_mesh_generator.h @@ -50,6 +50,7 @@ protected: static void _add_vertex(const Vector3 &p_vec3, Vector &p_vertices); static void _add_mesh(const Ref &p_mesh, const Transform &p_xform, Vector &p_vertices, Vector &p_indices); + static void _add_mesh_array(const Array &p_array, const Transform &p_xform, Vector &p_vertices, Vector &p_indices); static void _add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector &p_vertices, Vector &p_indices); static void _parse_geometry(const Transform &p_navmesh_xform, Node *p_node, Vector &p_vertices, Vector &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 9d3b44c7b..7edbe13e6 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -270,6 +270,10 @@ PrimitiveMesh::~PrimitiveMesh() { */ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { + create_mesh_array(p_arr, radius, mid_height, radial_segments, rings); +} + +void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float mid_height, const int radial_segments, const int rings) { int i, j, prevrow, thisrow, point; float x, y, z, u, v, w; float onethird = 1.0 / 3.0; @@ -481,6 +485,10 @@ CapsuleMesh::CapsuleMesh() { */ void CubeMesh::_create_mesh_array(Array &p_arr) const { + create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d); +} + +void CubeMesh::create_mesh_array(Array &p_arr, const Vector3 size, const int subdivide_w, const int subdivide_h, const int subdivide_d) { int i, j, prevrow, thisrow, point; float x, y, z; float onethird = 1.0 / 3.0; @@ -738,6 +746,10 @@ CubeMesh::CubeMesh() { */ void CylinderMesh::_create_mesh_array(Array &p_arr) const { + create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings); +} + +void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings) { int i, j, prevrow, thisrow, point; float x, y, z, u, v, radius; @@ -1453,6 +1465,10 @@ Vector3 QuadMesh::get_center_offset() const { */ void SphereMesh::_create_mesh_array(Array &p_arr) const { + create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere); +} + +void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) { int i, j, prevrow, thisrow, point; float x, y, z; diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 4c124cddc..533e43005 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -110,6 +110,8 @@ protected: virtual void _create_mesh_array(Array &p_arr) const; public: + static void create_mesh_array(Array &p_arr, float radius, float mid_height, int radial_segments = 64, int rings = 8); + void set_radius(const float p_radius); float get_radius() const; @@ -142,6 +144,8 @@ protected: virtual void _create_mesh_array(Array &p_arr) const; public: + static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0); + void set_size(const Vector3 &p_size); Vector3 get_size() const; @@ -176,6 +180,8 @@ protected: virtual void _create_mesh_array(Array &p_arr) const; public: + static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4); + void set_top_radius(const float p_radius); float get_top_radius() const; @@ -305,6 +311,8 @@ protected: virtual void _create_mesh_array(Array &p_arr) const; public: + static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false); + void set_radius(const float p_radius); float get_radius() const;