Skip to content

Commit

Permalink
Clean convex hull decomposition code
Browse files Browse the repository at this point in the history
Remove unnecessary conversion between triangle data and vertex data
whenever possible.
  • Loading branch information
pouleyKetchoupp committed Sep 15, 2021
1 parent cd5a8f8 commit 2ca94e5
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 127 deletions.
6 changes: 4 additions & 2 deletions core/math/triangle_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
class TriangleMesh : public RefCounted {
GDCLASS(TriangleMesh, RefCounted);

public:
struct Triangle {
Vector3 normal;
int indices[3];
};

private:
Vector<Triangle> triangles;
Vector<Vector3> vertices;

Expand Down Expand Up @@ -86,8 +88,8 @@ class TriangleMesh : public RefCounted {
Vector3 get_area_normal(const AABB &p_aabb) const;
Vector<Face3> get_faces() const;

Vector<Triangle> get_triangles() const { return triangles; }
Vector<Vector3> get_vertices() const { return vertices; }
const Vector<Triangle> &get_triangles() const { return triangles; }
const Vector<Vector3> &get_vertices() const { return vertices; }
void get_indices(Vector<int> *r_triangles_indices) const;

void create(const Vector<Vector3> &p_faces);
Expand Down
51 changes: 31 additions & 20 deletions editor/import/scene_importer_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,35 +525,46 @@ Vector<Face3> EditorSceneImporterMesh::get_faces() const {
}

Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const {
ERR_FAIL_COND_V(!Mesh::convex_composition_function, Vector<Ref<Shape3D>>());
ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>());

const Vector<Face3> faces = get_faces();
int face_count = faces.size();

Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces, p_settings);
Vector<Vector3> vertices;
uint32_t vertex_count = 0;
vertices.resize(face_count * 3);
Vector<uint32_t> indices;
indices.resize(face_count * 3);
{
Map<Vector3, uint32_t> vertex_map;
Vector3 *vertex_w = vertices.ptrw();
uint32_t *index_w = indices.ptrw();
for (int i = 0; i < face_count; i++) {
for (int j = 0; j < 3; j++) {
const Vector3 &vertex = faces[i].vertex[j];
Map<Vector3, uint32_t>::Element *found_vertex = vertex_map.find(vertex);
uint32_t index;
if (found_vertex) {
index = found_vertex->get();
} else {
index = ++vertex_count;
vertex_map[vertex] = index;
vertex_w[index] = vertex;
}
index_w[i * 3 + j] = index;
}
}
}
vertices.resize(vertex_count);

Vector<Vector<Vector3>> decomposed = Mesh::convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), face_count, p_settings, nullptr);

Vector<Ref<Shape3D>> 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]);
}

Vector<Vector3> convex_points;
convex_points.resize(points.size());
{
Vector3 *w = convex_points.ptrw();
int idx = 0;
for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) {
w[idx++] = E->get();
}
}

Ref<ConvexPolygonShape3D> shape;
shape.instantiate();
shape->set_points(convex_points);
shape->set_points(decomposed[i]);
ret.push_back(shape);
}

Expand Down
52 changes: 24 additions & 28 deletions modules/vhacd/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include "scene/resources/mesh.h"
#include "thirdparty/vhacd/public/VHACD.h"

static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, const Mesh::ConvexDecompositionSettings &p_settings) {
static Vector<Vector<Vector3>> convex_decompose(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const Mesh::ConvexDecompositionSettings &p_settings, Vector<Vector<uint32_t>> *r_convex_indices) {
VHACD::IVHACD::Parameters params;
params.m_concavity = p_settings.max_concavity;
params.m_alpha = p_settings.symmetry_planes_clipping_bias;
Expand All @@ -49,42 +49,38 @@ static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, cons
params.m_maxConvexHulls = p_settings.max_convex_hulls;
params.m_projectHullVertices = p_settings.project_hull_vertices;

Vector<real_t> 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;
}
}

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<Vector<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;

Vector<Vector3> &points = ret.write[i];
points.resize(hull.m_nPoints);

Vector3 *w = points.ptrw();
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) {
Vector<uint32_t> &indices = r_convex_indices->write[i];
indices.resize(hull.m_nTriangles * 3);

memcpy(indices.ptrw(), hull.m_triangles, hull.m_nTriangles * 3 * sizeof(uint32_t));
}
}

decomposer->Clean();
Expand All @@ -94,9 +90,9 @@ static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, cons
}

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;
}
98 changes: 23 additions & 75 deletions scene/resources/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,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()) {
Expand Down Expand Up @@ -167,59 +167,6 @@ Vector<Face3> Mesh::get_faces() const {
return tm->get_faces();
}
return Vector<Face3>();
/*
for (int i=0;i<surfaces.size();i++) {
if (RenderingServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != RenderingServer::PRIMITIVE_TRIANGLES )
continue;
Vector<int> indices;
Vector<Vector3> vertices;
vertices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_VERTEX);
int len=RenderingServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i);
bool has_indices;
if (len>0) {
indices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_INDEX);
has_indices=true;
} else {
len=vertices.size();
has_indices=false;
}
if (len<=0)
continue;
const int* indicesr = indices.ptr();
const int *indicesptr = indicesr.ptr();
const Vector3* verticesr = vertices.ptr();
const Vector3 *verticesptr = verticesr.ptr();
int old_faces=faces.size();
int new_faces=old_faces+(len/3);
faces.resize(new_faces);
Face3* facesw = faces.ptrw();
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<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
Expand Down Expand Up @@ -568,35 +515,36 @@ void Mesh::clear_cache() const {
}

Vector<Ref<Shape3D>> Mesh::convex_decompose(const ConvexDecompositionSettings &p_settings) const {
ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape3D>>());

const Vector<Face3> faces = get_faces();
ERR_FAIL_COND_V(!convex_decomposition_function, Vector<Ref<Shape3D>>());

const Vector<Vector<Face3>> decomposed = convex_composition_function(faces, p_settings);

Vector<Ref<Shape3D>> ret;
Ref<TriangleMesh> tm = generate_triangle_mesh();
ERR_FAIL_COND_V(!tm.is_valid(), Vector<Ref<Shape3D>>());

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]);
}
const Vector<TriangleMesh::Triangle> &triangles = tm->get_triangles();
int triangle_count = triangles.size();

Vector<Vector3> convex_points;
convex_points.resize(points.size());
{
Vector3 *w = convex_points.ptrw();
int idx = 0;
for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) {
w[idx++] = E->get();
Vector<uint32_t> indices;
{
indices.resize(triangle_count * 3);
uint32_t *w = indices.ptrw();
for (int i = 0; i < triangle_count; i++) {
for (int j = 0; j < 3; j++) {
w[i * 3 + j] = triangles[i].indices[j];
}
}
}

const Vector<Vector3> &vertices = tm->get_vertices();
int vertex_count = vertices.size();

Vector<Vector<Vector3>> decomposed = convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), triangle_count, p_settings, nullptr);

Vector<Ref<Shape3D>> ret;

for (int i = 0; i < decomposed.size(); i++) {
Ref<ConvexPolygonShape3D> shape;
shape.instantiate();
shape->set_points(convex_points);
shape->set_points(decomposed[i]);
ret.push_back(shape);
}

Expand Down
4 changes: 2 additions & 2 deletions scene/resources/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@ class Mesh : public Resource {
uint32_t max_convex_hulls = 1;
bool project_hull_vertices = true;
};
typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &p_faces, const ConvexDecompositionSettings &p_settings);
typedef Vector<Vector<Vector3>> (*ConvexDecompositionFunc)(const real_t *p_vertices, int p_vertex_count, const uint32_t *p_triangles, int p_triangle_count, const ConvexDecompositionSettings &p_settings, Vector<Vector<uint32_t>> *r_convex_indices);

static ConvexDecompositionFunc convex_composition_function;
static ConvexDecompositionFunc convex_decomposition_function;

Vector<Ref<Shape3D>> convex_decompose(const ConvexDecompositionSettings &p_settings) const;

Expand Down

0 comments on commit 2ca94e5

Please sign in to comment.