Przeglądaj źródła

Merge pull request #50405 from nekomatata/clean-convex-hull-decomposition-3.x

[3.x] Clean convex hull decomposition code
Camille Mohr-Daurat 4 lat temu
rodzic
commit
8608ece42f

+ 4 - 2
core/math/triangle_mesh.h

@@ -37,11 +37,13 @@
 class TriangleMesh : public Reference {
 	GDCLASS(TriangleMesh, Reference);
 
+public:
 	struct Triangle {
 		Vector3 normal;
 		int indices[3];
 	};
 
+private:
 	PoolVector<Triangle> triangles;
 	PoolVector<Vector3> vertices;
 
@@ -86,8 +88,8 @@ public:
 	Vector3 get_area_normal(const AABB &p_aabb) const;
 	PoolVector<Face3> get_faces() const;
 
-	PoolVector<Triangle> get_triangles() const { return triangles; }
-	PoolVector<Vector3> get_vertices() const { return vertices; }
+	const PoolVector<Triangle> &get_triangles() const { return triangles; }
+	const PoolVector<Vector3> &get_vertices() const { return vertices; }
 	void get_indices(PoolVector<int> *r_triangles_indices) const;
 
 	void create(const PoolVector<Vector3> &p_faces);

+ 24 - 28
modules/vhacd/register_types.cpp

@@ -32,48 +32,44 @@
 #include "scene/resources/mesh.h"
 #include "thirdparty/vhacd/public/VHACD.h"
 
-static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, int p_max_convex_hulls = -1) {
-	Vector<float> vertices;
-	vertices.resize(p_faces.size() * 9);
-	Vector<uint32_t> indices;
-	indices.resize(p_faces.size() * 3);
-
-	for (int i = 0; i < p_faces.size(); i++) {
-		for (int j = 0; j < 3; j++) {
-			vertices.write[i * 9 + j * 3 + 0] = p_faces[i].vertex[j].x;
-			vertices.write[i * 9 + j * 3 + 1] = p_faces[i].vertex[j].y;
-			vertices.write[i * 9 + j * 3 + 2] = p_faces[i].vertex[j].z;
-			indices.write[i * 3 + j] = i * 3 + j;
-		}
-	}
-
+static Vector<PoolVector<Vector3>> convex_decompose(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, int p_max_convex_hulls = -1, Vector<PoolVector<uint32_t>> *r_convex_indices = nullptr) {
 	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(p_vertices, p_vertex_count, p_triangles, p_triangle_count, params);
 
 	int hull_count = decomposer->GetNConvexHulls();
 
-	Vector<Vector<Face3>> ret;
+	Vector<PoolVector<Vector3>> ret;
+	ret.resize(hull_count);
+
+	if (r_convex_indices) {
+		r_convex_indices->resize(hull_count);
+	}
 
 	for (int i = 0; i < hull_count; i++) {
-		Vector<Face3> triangles;
 		VHACD::IVHACD::ConvexHull hull;
 		decomposer->GetConvexHull(i, hull);
-		triangles.resize(hull.m_nTriangles);
-		for (uint32_t j = 0; j < hull.m_nTriangles; j++) {
-			Face3 f;
+
+		PoolVector<Vector3> &points = ret.write[i];
+		points.resize(hull.m_nPoints);
+
+		PoolVector<Vector3>::Write w = points.write();
+		for (uint32_t j = 0; j < hull.m_nPoints; ++j) {
 			for (int k = 0; k < 3; k++) {
-				for (int l = 0; l < 3; l++) {
-					f.vertex[k][l] = hull.m_points[hull.m_triangles[j * 3 + k] * 3 + l];
-				}
+				w[j][k] = hull.m_points[j * 3 + k];
 			}
-			triangles.write[j] = f;
 		}
-		ret.push_back(triangles);
+
+		if (r_convex_indices) {
+			PoolVector<uint32_t> &indices = r_convex_indices->write[i];
+			indices.resize(hull.m_nTriangles * 3);
+
+			memcpy(indices.write().ptr(), hull.m_triangles, hull.m_nTriangles * 3 * sizeof(uint32_t));
+		}
 	}
 
 	decomposer->Clean();
@@ -83,9 +79,9 @@ static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, int
 }
 
 void register_vhacd_types() {
-	Mesh::convex_composition_function = convex_decompose;
+	Mesh::convex_decomposition_function = convex_decompose;
 }
 
 void unregister_vhacd_types() {
-	Mesh::convex_composition_function = nullptr;
+	Mesh::convex_decomposition_function = nullptr;
 }

+ 23 - 85
scene/resources/mesh.cpp

@@ -40,7 +40,7 @@
 
 #include <stdlib.h>
 
-Mesh::ConvexDecompositionFunc Mesh::convex_composition_function = nullptr;
+Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr;
 
 Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
 	if (triangle_mesh.is_valid()) {
@@ -170,64 +170,6 @@ PoolVector<Face3> Mesh::get_faces() const {
 		return tm->get_faces();
 	}
 	return PoolVector<Face3>();
-	/*
-	for (int i=0;i<surfaces.size();i++) {
-
-		if (VisualServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES )
-			continue;
-
-		PoolVector<int> indices;
-		PoolVector<Vector3> vertices;
-
-		vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX);
-
-		int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i);
-		bool has_indices;
-
-		if (len>0) {
-
-			indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX);
-			has_indices=true;
-
-		} else {
-
-			len=vertices.size();
-			has_indices=false;
-		}
-
-		if (len<=0)
-			continue;
-
-		PoolVector<int>::Read indicesr = indices.read();
-		const int *indicesptr = indicesr.ptr();
-
-		PoolVector<Vector3>::Read verticesr = vertices.read();
-		const Vector3 *verticesptr = verticesr.ptr();
-
-		int old_faces=faces.size();
-		int new_faces=old_faces+(len/3);
-
-		faces.resize(new_faces);
-
-		PoolVector<Face3>::Write facesw = faces.write();
-		Face3 *facesptr=facesw.ptr();
-
-
-		for (int i=0;i<len/3;i++) {
-
-			Face3 face;
-
-			for (int j=0;j<3;j++) {
-
-				int idx=i*3+j;
-				face.vertex[j] = has_indices ? verticesptr[ indicesptr[ idx ] ] : verticesptr[idx];
-			}
-
-			facesptr[i+old_faces]=face;
-		}
-
-	}
-*/
 }
 
 Ref<Shape> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
@@ -568,41 +510,37 @@ void Mesh::clear_cache() 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_decomposition_function, Vector<Ref<Shape>>());
 
-	PoolVector<Face3> faces = get_faces();
-	Vector<Face3> f3;
-	f3.resize(faces.size());
-	PoolVector<Face3>::Read f = faces.read();
-	for (int i = 0; i < f3.size(); i++) {
-		f3.write[i] = f[i];
+	Ref<TriangleMesh> tm = generate_triangle_mesh();
+	ERR_FAIL_COND_V(!tm.is_valid(), Vector<Ref<Shape>>());
+
+	const PoolVector<TriangleMesh::Triangle> &triangles = tm->get_triangles();
+	int triangle_count = triangles.size();
+
+	PoolVector<uint32_t> indices;
+	{
+		indices.resize(triangle_count * 3);
+		PoolVector<uint32_t>::Write w = indices.write();
+		PoolVector<TriangleMesh::Triangle>::Read triangles_read = triangles.read();
+		for (int i = 0; i < triangle_count; i++) {
+			for (int j = 0; j < 3; j++) {
+				w[i * 3 + j] = triangles_read[i].indices[j];
+			}
+		}
 	}
 
-	Vector<Vector<Face3>> decomposed = convex_composition_function(f3, p_max_convex_hulls);
+	const PoolVector<Vector3> &vertices = tm->get_vertices();
+	int vertex_count = vertices.size();
+
+	Vector<PoolVector<Vector3>> decomposed = convex_decomposition_function((real_t *)vertices.read().ptr(), vertex_count, indices.read().ptr(), triangle_count, p_max_convex_hulls, nullptr);
 
 	Vector<Ref<Shape>> ret;
 
 	for (int i = 0; i < decomposed.size(); i++) {
-		Set<Vector3> points;
-		for (int j = 0; j < decomposed[i].size(); j++) {
-			points.insert(decomposed[i][j].vertex[0]);
-			points.insert(decomposed[i][j].vertex[1]);
-			points.insert(decomposed[i][j].vertex[2]);
-		}
-
-		PoolVector<Vector3> convex_points;
-		convex_points.resize(points.size());
-		{
-			PoolVector<Vector3>::Write w = convex_points.write();
-			int idx = 0;
-			for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) {
-				w[idx++] = E->get();
-			}
-		}
-
 		Ref<ConvexPolygonShape> shape;
 		shape.instance();
-		shape->set_points(convex_points);
+		shape->set_points(decomposed[i]);
 		ret.push_back(shape);
 	}
 

+ 2 - 2
scene/resources/mesh.h

@@ -148,9 +148,9 @@ public:
 	Size2 get_lightmap_size_hint() const;
 	void clear_cache() const;
 
-	typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &p_faces, int p_max_convex_hulls);
+	typedef Vector<PoolVector<Vector3>> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, int p_max_convex_hulls, Vector<PoolVector<uint32_t>> *r_convex_indices);
 
-	static ConvexDecompositionFunc convex_composition_function;
+	static ConvexDecompositionFunc convex_decomposition_function;
 
 	Vector<Ref<Shape>> convex_decompose(int p_max_convex_hulls = -1) const;