Merge pull request #57411 from Scony/fix-threaded-navmesh-baking-3.x

Fix navmesh baking
This commit is contained in:
Rémi Verschelde 2022-04-05 19:59:32 +02:00 committed by GitHub
commit cfdb99a741
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 60 deletions

View file

@ -126,6 +126,28 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform
} }
} }
void NavigationMeshGenerator::_add_mesh_array(const Array &p_array, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices) {
PoolVector<Vector3> mesh_vertices = p_array[Mesh::ARRAY_VERTEX];
PoolVector<Vector3>::Read vr = mesh_vertices.read();
PoolVector<int> mesh_indices = p_array[Mesh::ARRAY_INDEX];
PoolVector<int>::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<float> &p_vertices, Vector<int> &p_indices) { void NavigationMeshGenerator::_add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices) {
int face_count = p_faces.size() / 3; int face_count = p_faces.size() / 3;
int current_vertex_count = p_vertices.size() / 3; int current_vertex_count = p_vertices.size() / 3;
@ -189,43 +211,38 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform,
Transform transform = p_navmesh_xform * static_body->get_global_transform() * col_shape->get_transform(); Transform transform = p_navmesh_xform * static_body->get_global_transform() * col_shape->get_transform();
Ref<Mesh> mesh;
Ref<Shape> s = col_shape->get_shape(); Ref<Shape> s = col_shape->get_shape();
BoxShape *box = Object::cast_to<BoxShape>(*s); BoxShape *box = Object::cast_to<BoxShape>(*s);
if (box) { if (box) {
Ref<CubeMesh> cube_mesh; Array arr;
cube_mesh.instance(); arr.resize(VS::ARRAY_MAX);
cube_mesh->set_size(box->get_extents() * 2.0); CubeMesh::create_mesh_array(arr, box->get_extents() * 2.0);
mesh = cube_mesh; _add_mesh_array(arr, transform, p_vertices, p_indices);
} }
CapsuleShape *capsule = Object::cast_to<CapsuleShape>(*s); CapsuleShape *capsule = Object::cast_to<CapsuleShape>(*s);
if (capsule) { if (capsule) {
Ref<CapsuleMesh> capsule_mesh; Array arr;
capsule_mesh.instance(); arr.resize(VS::ARRAY_MAX);
capsule_mesh->set_radius(capsule->get_radius()); CapsuleMesh::create_mesh_array(arr, capsule->get_radius(), capsule->get_height() / 2.0);
capsule_mesh->set_mid_height(capsule->get_height() / 2.0); _add_mesh_array(arr, transform, p_vertices, p_indices);
mesh = capsule_mesh;
} }
CylinderShape *cylinder = Object::cast_to<CylinderShape>(*s); CylinderShape *cylinder = Object::cast_to<CylinderShape>(*s);
if (cylinder) { if (cylinder) {
Ref<CylinderMesh> cylinder_mesh; Array arr;
cylinder_mesh.instance(); arr.resize(VS::ARRAY_MAX);
cylinder_mesh->set_height(cylinder->get_height()); CylinderMesh::create_mesh_array(arr, cylinder->get_radius(), cylinder->get_radius(), cylinder->get_height());
cylinder_mesh->set_bottom_radius(cylinder->get_radius()); _add_mesh_array(arr, transform, p_vertices, p_indices);
cylinder_mesh->set_top_radius(cylinder->get_radius());
mesh = cylinder_mesh;
} }
SphereShape *sphere = Object::cast_to<SphereShape>(*s); SphereShape *sphere = Object::cast_to<SphereShape>(*s);
if (sphere) { if (sphere) {
Ref<SphereMesh> sphere_mesh; Array arr;
sphere_mesh.instance(); arr.resize(VS::ARRAY_MAX);
sphere_mesh->set_radius(sphere->get_radius()); SphereMesh::create_mesh_array(arr, sphere->get_radius(), sphere->get_radius() * 2.0);
sphere_mesh->set_height(sphere->get_radius() * 2.0); _add_mesh_array(arr, transform, p_vertices, p_indices);
mesh = sphere_mesh;
} }
ConcavePolygonShape *concave_polygon = Object::cast_to<ConcavePolygonShape>(*s); ConcavePolygonShape *concave_polygon = Object::cast_to<ConcavePolygonShape>(*s);
@ -256,10 +273,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform,
_add_faces(faces, transform, p_vertices, p_indices); _add_faces(faces, transform, p_vertices, p_indices);
} }
} }
if (mesh.is_valid()) {
_add_mesh(mesh, transform, p_vertices, p_indices);
}
} }
} }
} }
@ -287,44 +300,39 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform,
RID shape = shapes[i + 1]; RID shape = shapes[i + 1];
PhysicsServer::ShapeType type = PhysicsServer::get_singleton()->shape_get_type(shape); PhysicsServer::ShapeType type = PhysicsServer::get_singleton()->shape_get_type(shape);
Variant data = PhysicsServer::get_singleton()->shape_get_data(shape); Variant data = PhysicsServer::get_singleton()->shape_get_data(shape);
Ref<Mesh> mesh;
switch (type) { switch (type) {
case PhysicsServer::SHAPE_SPHERE: { case PhysicsServer::SHAPE_SPHERE: {
real_t radius = data; real_t radius = data;
Ref<SphereMesh> sphere_mesh; Array arr;
sphere_mesh.instance(); arr.resize(VS::ARRAY_MAX);
sphere_mesh->set_radius(radius); SphereMesh::create_mesh_array(arr, radius, radius * 2.0);
sphere_mesh->set_height(radius * 2.0); _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
mesh = sphere_mesh;
} break; } break;
case PhysicsServer::SHAPE_BOX: { case PhysicsServer::SHAPE_BOX: {
Vector3 extents = data; Vector3 extents = data;
Ref<CubeMesh> box_mesh; Array arr;
box_mesh.instance(); arr.resize(VS::ARRAY_MAX);
box_mesh->set_size(2.0 * extents); CubeMesh::create_mesh_array(arr, extents * 2.0);
mesh = box_mesh; _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
} break; } break;
case PhysicsServer::SHAPE_CAPSULE: { case PhysicsServer::SHAPE_CAPSULE: {
Dictionary dict = data; Dictionary dict = data;
real_t radius = dict["radius"]; real_t radius = dict["radius"];
real_t height = dict["height"]; real_t height = dict["height"];
Ref<CapsuleMesh> capsule_mesh; Array arr;
capsule_mesh.instance(); arr.resize(VS::ARRAY_MAX);
capsule_mesh->set_radius(radius); CapsuleMesh::create_mesh_array(arr, radius, height * 0.5);
capsule_mesh->set_mid_height(0.5 * height); _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
mesh = capsule_mesh;
} break; } break;
case PhysicsServer::SHAPE_CYLINDER: { case PhysicsServer::SHAPE_CYLINDER: {
Dictionary dict = data; Dictionary dict = data;
real_t radius = dict["radius"]; real_t radius = dict["radius"];
real_t height = dict["height"]; real_t height = dict["height"];
Ref<CylinderMesh> cylinder_mesh; Array arr;
cylinder_mesh.instance(); arr.resize(VS::ARRAY_MAX);
cylinder_mesh->set_height(height); CylinderMesh::create_mesh_array(arr, radius, radius, height);
cylinder_mesh->set_bottom_radius(radius); _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
cylinder_mesh->set_top_radius(radius);
mesh = cylinder_mesh;
} break; } break;
case PhysicsServer::SHAPE_CONVEX_POLYGON: { case PhysicsServer::SHAPE_CONVEX_POLYGON: {
PoolVector3Array vertices = data; PoolVector3Array vertices = data;
@ -356,10 +364,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform &p_navmesh_xform,
WARN_PRINT("Unsupported collision shape type."); WARN_PRINT("Unsupported collision shape type.");
} break; } break;
} }
if (mesh.is_valid()) {
_add_mesh(mesh, shapes[i], p_vertices, p_indices);
}
} }
} }
} }

View file

@ -51,6 +51,7 @@ protected:
static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_vertices); static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_vertices);
static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices); static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _add_mesh_array(const Array &p_array, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices); static void _add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _parse_geometry(const Transform &p_navmesh_xform, Node *p_node, Vector<float> &p_vertices, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children); static void _parse_geometry(const Transform &p_navmesh_xform, Node *p_node, Vector<float> &p_vertices, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);

View file

@ -270,6 +270,10 @@ PrimitiveMesh::~PrimitiveMesh() {
*/ */
void CapsuleMesh::_create_mesh_array(Array &p_arr) const { 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; int i, j, prevrow, thisrow, point;
float x, y, z, u, v, w; float x, y, z, u, v, w;
float onethird = 1.0 / 3.0; float onethird = 1.0 / 3.0;
@ -472,8 +476,8 @@ CapsuleMesh::CapsuleMesh() {
// defaults // defaults
radius = 1.0; radius = 1.0;
mid_height = 1.0; mid_height = 1.0;
radial_segments = 64; radial_segments = default_radial_segments;
rings = 8; rings = default_rings;
} }
/** /**
@ -481,6 +485,10 @@ CapsuleMesh::CapsuleMesh() {
*/ */
void CubeMesh::_create_mesh_array(Array &p_arr) const { 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; int i, j, prevrow, thisrow, point;
float x, y, z; float x, y, z;
float onethird = 1.0 / 3.0; float onethird = 1.0 / 3.0;
@ -728,9 +736,9 @@ int CubeMesh::get_subdivide_depth() const {
CubeMesh::CubeMesh() { CubeMesh::CubeMesh() {
// defaults // defaults
size = Vector3(2.0, 2.0, 2.0); size = Vector3(2.0, 2.0, 2.0);
subdivide_w = 0; subdivide_w = default_subdivide_w;
subdivide_h = 0; subdivide_h = default_subdivide_h;
subdivide_d = 0; subdivide_d = default_subdivide_d;
} }
/** /**
@ -738,6 +746,10 @@ CubeMesh::CubeMesh() {
*/ */
void CylinderMesh::_create_mesh_array(Array &p_arr) const { 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; int i, j, prevrow, thisrow, point;
float x, y, z, u, v, radius; float x, y, z, u, v, radius;
@ -943,8 +955,8 @@ CylinderMesh::CylinderMesh() {
top_radius = 1.0; top_radius = 1.0;
bottom_radius = 1.0; bottom_radius = 1.0;
height = 2.0; height = 2.0;
radial_segments = 64; radial_segments = default_radial_segments;
rings = 4; rings = default_rings;
} }
/** /**
@ -1453,6 +1465,10 @@ Vector3 QuadMesh::get_center_offset() const {
*/ */
void SphereMesh::_create_mesh_array(Array &p_arr) 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; int i, j, prevrow, thisrow, point;
float x, y, z; float x, y, z;
@ -1595,9 +1611,9 @@ SphereMesh::SphereMesh() {
// defaults // defaults
radius = 1.0; radius = 1.0;
height = 2.0; height = 2.0;
radial_segments = 64; radial_segments = default_radial_segments;
rings = 32; rings = default_rings;
is_hemisphere = false; is_hemisphere = default_is_hemisphere;
} }
/** /**

View file

@ -100,6 +100,10 @@ public:
class CapsuleMesh : public PrimitiveMesh { class CapsuleMesh : public PrimitiveMesh {
GDCLASS(CapsuleMesh, PrimitiveMesh); GDCLASS(CapsuleMesh, PrimitiveMesh);
private:
static constexpr int default_radial_segments = 64;
static constexpr int default_rings = 8;
private: private:
float radius; float radius;
float mid_height; float mid_height;
@ -111,6 +115,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const; virtual void _create_mesh_array(Array &p_arr) const;
public: public:
static void create_mesh_array(Array &p_arr, float radius, float mid_height, int radial_segments = default_radial_segments, int rings = default_rings);
void set_radius(const float p_radius); void set_radius(const float p_radius);
float get_radius() const; float get_radius() const;
@ -132,6 +138,11 @@ public:
class CubeMesh : public PrimitiveMesh { class CubeMesh : public PrimitiveMesh {
GDCLASS(CubeMesh, PrimitiveMesh); GDCLASS(CubeMesh, PrimitiveMesh);
private:
static constexpr int default_subdivide_w = 0;
static constexpr int default_subdivide_h = 0;
static constexpr int default_subdivide_d = 0;
private: private:
Vector3 size; Vector3 size;
int subdivide_w; int subdivide_w;
@ -143,6 +154,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const; virtual void _create_mesh_array(Array &p_arr) const;
public: public:
static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = default_subdivide_w, int subdivide_h = default_subdivide_h, int subdivide_d = default_subdivide_d);
void set_size(const Vector3 &p_size); void set_size(const Vector3 &p_size);
Vector3 get_size() const; Vector3 get_size() const;
@ -165,6 +178,10 @@ public:
class CylinderMesh : public PrimitiveMesh { class CylinderMesh : public PrimitiveMesh {
GDCLASS(CylinderMesh, PrimitiveMesh); GDCLASS(CylinderMesh, PrimitiveMesh);
private:
static constexpr int default_radial_segments = 64;
static constexpr int default_rings = 4;
private: private:
float top_radius; float top_radius;
float bottom_radius; float bottom_radius;
@ -177,6 +194,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const; virtual void _create_mesh_array(Array &p_arr) const;
public: public:
static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = default_radial_segments, int rings = default_rings);
void set_top_radius(const float p_radius); void set_top_radius(const float p_radius);
float get_top_radius() const; float get_top_radius() const;
@ -294,6 +313,11 @@ public:
class SphereMesh : public PrimitiveMesh { class SphereMesh : public PrimitiveMesh {
GDCLASS(SphereMesh, PrimitiveMesh); GDCLASS(SphereMesh, PrimitiveMesh);
private:
static constexpr int default_radial_segments = 64;
static constexpr int default_rings = 32;
static constexpr bool default_is_hemisphere = false;
private: private:
float radius; float radius;
float height; float height;
@ -306,6 +330,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const; virtual void _create_mesh_array(Array &p_arr) const;
public: public:
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = default_radial_segments, int rings = default_rings, bool is_hemisphere = default_is_hemisphere);
void set_radius(const float p_radius); void set_radius(const float p_radius);
float get_radius() const; float get_radius() const;