diff --git a/fast_quadratic_mesh_simplifier.cpp b/fast_quadratic_mesh_simplifier.cpp index 4303155..0114aac 100644 --- a/fast_quadratic_mesh_simplifier.cpp +++ b/fast_quadratic_mesh_simplifier.cpp @@ -27,6 +27,48 @@ SOFTWARE. #include "scene/resources/mesh.h" +int FastQuadraticMeshSimplifier::get_max_iteration_count() const { + return _max_iteration_count; +} +void FastQuadraticMeshSimplifier::set_max_iteration_count(const int value) { + _max_iteration_count = value; +} + +double FastQuadraticMeshSimplifier::get_agressiveness() const { + return _agressiveness; +} +void FastQuadraticMeshSimplifier::set_agressiveness(const double value) { + _agressiveness = value; +} + +bool FastQuadraticMeshSimplifier::get_enable_smart_link() const { + return _enable_smart_link; +} +void FastQuadraticMeshSimplifier::set_enable_smart_link(const bool value) { + _enable_smart_link = value; +} + +bool FastQuadraticMeshSimplifier::get_preserve_border_dges() const { + return _preserve_border_dges; +} +void FastQuadraticMeshSimplifier::set_preserve_border_dges(const bool value) { + _preserve_border_dges = value; +} + +bool FastQuadraticMeshSimplifier::get_preserve_uv_seam_edges() const { + return _preserve_uv_seam_edges; +} +void FastQuadraticMeshSimplifier::set_preserve_uv_seam_edges(const bool value) { + _preserve_uv_seam_edges = value; +} + +bool FastQuadraticMeshSimplifier::get_preserve_uv_foldover_edges() const { + return _preserve_uv_foldover_edges; +} +void FastQuadraticMeshSimplifier::set_preserve_uv_foldover_edges(const bool value) { + _preserve_uv_foldover_edges = value; +} + void FastQuadraticMeshSimplifier::initialize(const Array &arrays) { ERR_FAIL_COND(arrays.size() != ArrayMesh::ARRAY_MAX); @@ -100,12 +142,50 @@ Array FastQuadraticMeshSimplifier::get_arrays() { arr.resize(ArrayMesh::ARRAY_MAX); - arr.set(ArrayMesh::ARRAY_VERTEX, _vertices); - arr.set(ArrayMesh::ARRAY_NORMAL, _normals); - arr.set(ArrayMesh::ARRAY_COLOR, _colors); - arr.set(ArrayMesh::ARRAY_TEX_UV, _uvs); - arr.set(ArrayMesh::ARRAY_TEX_UV2, _uv2s); - arr.set(ArrayMesh::ARRAY_INDEX, _indices); + PoolVector vertices; + PoolVector normals; + PoolVector colors; + PoolVector uvs; + PoolVector uv2s; + PoolVector indices; + + vertices.resize(_vertices.size()); + normals.resize(_normals.size()); + colors.resize(_colors.size()); + uvs.resize(_uvs.size()); + uv2s.resize(_uv2s.size()); + indices.resize(_indices.size()); + + for (int i = 0; i < vertices.size(); ++i) { + vertices.set(i, _vertices[i]); + } + + for (int i = 0; i < normals.size(); ++i) { + normals.set(i, _normals[i]); + } + + for (int i = 0; i < colors.size(); ++i) { + colors.set(i, _colors[i]); + } + + for (int i = 0; i < uvs.size(); ++i) { + uvs.set(i, _uvs[i]); + } + + for (int i = 0; i < uv2s.size(); ++i) { + uv2s.set(i, _uv2s[i]); + } + + for (int i = 0; i < indices.size(); ++i) { + indices.set(i, _indices[i]); + } + + arr.set(ArrayMesh::ARRAY_VERTEX, vertices); + arr.set(ArrayMesh::ARRAY_NORMAL, normals); + arr.set(ArrayMesh::ARRAY_COLOR, colors); + arr.set(ArrayMesh::ARRAY_TEX_UV, uvs); + arr.set(ArrayMesh::ARRAY_TEX_UV2, uv2s); + arr.set(ArrayMesh::ARRAY_INDEX, indices); return arr; } @@ -208,7 +288,7 @@ void FastQuadraticMeshSimplifier::update_mesh(int iteration) { for (int i = 0; i < _mu_triangles.size(); ++i) { if (!_mu_triangles[i].deleted) { if (dst != i) { - _mu_triangles[dst] = _mu_triangles[i]; + _mu_triangles.set(dst, _mu_triangles[i]); } dst++; } @@ -226,7 +306,7 @@ void FastQuadraticMeshSimplifier::update_mesh(int iteration) { vids.resize(8); int vsize = 0; - for (int i = 0; i < _mu_vertices.size(); i++) { + for (int i = 0; i < _mu_vertices.size(); ++i) { MUVertex v = _mu_vertices[i]; v.border_edge = false; @@ -239,12 +319,14 @@ void FastQuadraticMeshSimplifier::update_mesh(int iteration) { int ofs = 0; int id = 0; int borderVertexCount = 0; - double borderMinX = std::numeric_limits::max(); - double borderMaxX = std::numeric_limits::min(); + double borderMinX = std::numeric_limits::min(); + double borderMaxX = std::numeric_limits::max(); for (int i = 0; i < _mu_vertices.size(); i++) { - int tstart = _mu_vertices[i].tstart; - int tcount = _mu_vertices[i].tcount; + MUVertex v = _mu_vertices[i]; + + int tstart = v.tstart; + int tcount = v.tcount; vcount.resize(0); vids.resize(0); vsize = 0; @@ -278,10 +360,9 @@ void FastQuadraticMeshSimplifier::update_mesh(int iteration) { if (vcount[j] == 1) { id = vids[j]; - MUVertex v = _mu_vertices[id]; - - v.border_edge = true; - _mu_vertices.set(id, v); + MUVertex vv = _mu_vertices[id]; + vv.border_edge = true; + _mu_vertices.set(id, vv); ++borderVertexCount; @@ -339,7 +420,9 @@ void FastQuadraticMeshSimplifier::update_mesh(int iteration) { double sqrMagnitude = sqrX + sqrY + sqrZ; if (sqrMagnitude <= _vertex_link_distance_sqr) { - borderVertices.get(j).set_index(-1); // NOTE: This makes sure that the "other" vertex is not processed again + BorderVertex b = borderVertices[j]; // NOTE: This makes sure that the "other" vertex is not processed again + b.index = -1; + borderVertices.set(j, b); MUVertex miv = _mu_vertices[myIndex]; MUVertex oiv = _mu_vertices[otherIndex]; @@ -382,32 +465,50 @@ void FastQuadraticMeshSimplifier::update_mesh(int iteration) { // recomputing during the simplification is not required, // but mostly improves the result for closed meshes for (int i = 0; i < _mu_vertices.size(); ++i) { - _mu_vertices[i].q.reset(); + MUVertex v = _mu_vertices[i]; + + v.q.reset(); + + _mu_vertices.set(i, v); } int v0, v1, v2; Vector3 n, p0, p1, p2, p10, p20, dummy; SymmetricMatrix sm; for (int i = 0; i < _mu_triangles.size(); ++i) { - v0 = _mu_triangles[i].v0; - v1 = _mu_triangles[i].v1; - v2 = _mu_triangles[i].v2; + MUTriangle t = _mu_triangles[i]; - p0 = _mu_vertices[v0].p; - p1 = _mu_vertices[v1].p; - p2 = _mu_vertices[v2].p; + v0 = t.v0; + v1 = t.v1; + v2 = t.v2; + + MUVertex vt0 = _mu_vertices[v0]; + MUVertex vt1 = _mu_vertices[v1]; + MUVertex vt2 = _mu_vertices[v2]; + + p0 = vt0.p; + p1 = vt1.p; + p2 = vt2.p; p10 = p1 - p0; p20 = p2 - p0; n = p10.cross(p20); n.normalize(); - _mu_triangles[i].n = n; + + t.n = n; + + _mu_triangles.set(i, t); sm.from_plane(n.x, n.y, n.z, -n.dot(p0)); - _mu_vertices[v0].q += sm; - _mu_vertices[v1].q += sm; - _mu_vertices[v2].q += sm; + + vt0.q += sm; + vt1.q += sm; + vt2.q += sm; + + _mu_vertices.set(v0, vt0); + _mu_vertices.set(v1, vt1); + _mu_vertices.set(v2, vt2); } for (int i = 0; i < _mu_triangles.size(); ++i) { @@ -575,13 +676,14 @@ void FastQuadraticMeshSimplifier::compact_mesh() { if (vert.tcount > 0) { vert.tstart = dst; - _mu_vertices[i] = vert; + _mu_vertices.set(i, vert); if (dst != i) { - _mu_vertices[dst].p = vert.p; + MUVertex dv = _mu_vertices[dst]; + dv.p = vert.p; + _mu_vertices.set(dst, dv); if (_normals.size() > 0) _normals.set(dst, _normals[i]); - if (_colors.size() > 0) _colors.set(dst, _colors[i]); if (_uvs.size() > 0) _uvs.set(dst, _uvs[i]); if (_uv2s.size() > 0) _uv2s.set(dst, _uv2s[i]); @@ -597,7 +699,7 @@ void FastQuadraticMeshSimplifier::compact_mesh() { triangle.v0 = _mu_vertices[triangle.v0].tstart; triangle.v1 = _mu_vertices[triangle.v1].tstart; triangle.v2 = _mu_vertices[triangle.v2].tstart; - _mu_triangles[i] = triangle; + _mu_triangles.set(i, triangle); } //vertexCount = dst; @@ -810,7 +912,7 @@ void FastQuadraticMeshSimplifier::update_triangles(int i0, int ia0, const MUVert t.err2 = calculate_error(_mu_vertices[t.v2], _mu_vertices[t.v0], &p); t.err3 = FastQuadraticMeshSimplifier::min3(t.err0, t.err1, t.err2); - _mu_triangles[tid] = t; + _mu_triangles.set(tid, t); _mu_refs.push_back(r); } @@ -824,7 +926,7 @@ bool FastQuadraticMeshSimplifier::flipped(const Vector3 &p, int i0, int i1, cons MURef r = _mu_refs[v0.tstart + k]; MUTriangle t = _mu_triangles[r.tid]; - if (_mu_triangles[r.tid].deleted) + if (t.deleted) continue; int s = r.tvertex; @@ -846,7 +948,7 @@ bool FastQuadraticMeshSimplifier::flipped(const Vector3 &p, int i0, int i1, cons Vector3 n = d1.cross(d2); n.normalize(); deleted->set(k, false); - dot = n.dot(_mu_triangles[r.tid].n); + dot = n.dot(t.n); if (dot < 0.2) return true; } @@ -869,21 +971,21 @@ Vector3 FastQuadraticMeshSimplifier::calculate_barycentric_coords(Vector3 const return Vector3(u, v, w); } -void FastQuadraticMeshSimplifier::interpolate_vertex_attributes(int dst, int i0, int i1, int i2, Vector3 &barycentricCoord) { +void FastQuadraticMeshSimplifier::interpolate_vertex_attributes(int dst, int i0, int i1, int i2, const Vector3 &barycentricCoord) { if (_normals.size() > 0) { - _normals[dst] = (_normals[i0] * barycentricCoord.x) + (_normals[i1] * barycentricCoord.y) + (_normals[i2] * barycentricCoord.z).normalized(); + _normals.set(dst, (_normals[i0] * barycentricCoord.x) + (_normals[i1] * barycentricCoord.y) + (_normals[i2] * barycentricCoord.z).normalized()); } if (_uvs.size() > 0) { - _uvs[dst] = (_uvs[i0] * barycentricCoord.x) + (_uvs[i1] * barycentricCoord.y) + (_uvs[i2] * barycentricCoord.z); + _uvs.set(dst, (_uvs[i0] * barycentricCoord.x) + (_uvs[i1] * barycentricCoord.y) + (_uvs[i2] * barycentricCoord.z)); } if (_uv2s.size() > 0) { - _uv2s[dst] = (_uv2s[i0] * barycentricCoord.x) + (_uv2s[i1] * barycentricCoord.y) + (_uv2s[i2] * barycentricCoord.z); + _uv2s.set(dst, (_uv2s[i0] * barycentricCoord.x) + (_uv2s[i1] * barycentricCoord.y) + (_uv2s[i2] * barycentricCoord.z)); } if (_colors.size() > 0) { - _colors[dst] = (_colors[i0] * barycentricCoord.x) + (_colors[i1] * barycentricCoord.y) + (_colors[i2] * barycentricCoord.z); + _colors.set(dst, (_colors[i0] * barycentricCoord.x) + (_colors[i1] * barycentricCoord.y) + (_colors[i2] * barycentricCoord.z)); } } @@ -902,7 +1004,27 @@ void FastQuadraticMeshSimplifier::_bind_methods() { ClassDB::bind_method(D_METHOD("simplify_mesh", "quality"), &FastQuadraticMeshSimplifier::simplify_mesh); ClassDB::bind_method(D_METHOD("simplify_mesh_lossless"), &FastQuadraticMeshSimplifier::simplify_mesh_lossless); - // ClassDB::bind_method(D_METHOD("get_body_path"), &FastQuadraticMeshSimplifier::get_body_path); - // ClassDB::bind_method(D_METHOD("set_body_path", "value"), &FastQuadraticMeshSimplifier::set_body_path); - // ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "body_path"), "set_body_path", "get_body_path"); + ClassDB::bind_method(D_METHOD("get_max_iteration_count"), &FastQuadraticMeshSimplifier::get_max_iteration_count); + ClassDB::bind_method(D_METHOD("set_max_iteration_count", "value"), &FastQuadraticMeshSimplifier::set_max_iteration_count); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_iteration_count"), "set_max_iteration_count", "get_max_iteration_count"); + + ClassDB::bind_method(D_METHOD("get_agressiveness"), &FastQuadraticMeshSimplifier::get_agressiveness); + ClassDB::bind_method(D_METHOD("set_agressiveness", "value"), &FastQuadraticMeshSimplifier::set_agressiveness); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "agressiveness"), "set_agressiveness", "get_agressiveness"); + + ClassDB::bind_method(D_METHOD("get_enable_smart_link"), &FastQuadraticMeshSimplifier::get_enable_smart_link); + ClassDB::bind_method(D_METHOD("set_enable_smart_link", "value"), &FastQuadraticMeshSimplifier::set_enable_smart_link); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_smart_link"), "set_enable_smart_link", "get_enable_smart_link"); + + ClassDB::bind_method(D_METHOD("get_preserve_border_dges"), &FastQuadraticMeshSimplifier::get_preserve_border_dges); + ClassDB::bind_method(D_METHOD("set_preserve_border_dges", "value"), &FastQuadraticMeshSimplifier::set_preserve_border_dges); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_border_dges"), "set_preserve_border_dges", "get_preserve_border_dges"); + + ClassDB::bind_method(D_METHOD("get_preserve_uv_seam_edges"), &FastQuadraticMeshSimplifier::get_preserve_uv_seam_edges); + ClassDB::bind_method(D_METHOD("set_preserve_uv_seam_edges", "value"), &FastQuadraticMeshSimplifier::set_preserve_uv_seam_edges); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_uv_seam_edges"), "set_preserve_uv_seam_edges", "get_preserve_uv_seam_edges"); + + ClassDB::bind_method(D_METHOD("get_preserve_uv_foldover_edges"), &FastQuadraticMeshSimplifier::get_preserve_uv_foldover_edges); + ClassDB::bind_method(D_METHOD("set_preserve_uv_foldover_edges", "value"), &FastQuadraticMeshSimplifier::set_preserve_uv_foldover_edges); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_uv_foldover_edges"), "set_preserve_uv_foldover_edges", "get_preserve_uv_foldover_edges"); } \ No newline at end of file diff --git a/fast_quadratic_mesh_simplifier.h b/fast_quadratic_mesh_simplifier.h index 67b8894..fe0cbad 100644 --- a/fast_quadratic_mesh_simplifier.h +++ b/fast_quadratic_mesh_simplifier.h @@ -40,6 +40,24 @@ class FastQuadraticMeshSimplifier : public Reference { GDCLASS(FastQuadraticMeshSimplifier, Reference); public: + int get_max_iteration_count() const; + void set_max_iteration_count(const int value); + + double get_agressiveness() const; + void set_agressiveness(const double value); + + bool get_enable_smart_link() const; + void set_enable_smart_link(const bool value); + + bool get_preserve_border_dges() const; + void set_preserve_border_dges(const bool value); + + bool get_preserve_uv_seam_edges() const; + void set_preserve_uv_seam_edges(const bool value); + + bool get_preserve_uv_foldover_edges() const; + void set_preserve_uv_foldover_edges(const bool value); + void initialize(const Array &arrays); Array get_arrays(); void simplify_mesh(float quality); @@ -56,7 +74,7 @@ public: void update_triangles(int i0, int ia0, const MUVertex &v, PoolVector *deleted, int *deletedTriangles); bool flipped(const Vector3 &p, int i0, int i1, const MUVertex &v0, PoolVector *deleted); static Vector3 calculate_barycentric_coords(Vector3 const &point, Vector3 const &a, Vector3 const &b, Vector3 const &c); - void interpolate_vertex_attributes(int dst, int i0, int i1, int i2, Vector3 &barycentricCoord); + void interpolate_vertex_attributes(int dst, int i0, int i1, int i2, const Vector3 &barycentricCoord); static double min3(double val1, double val2, double val3) { return (val1 < val2 ? (val1 < val3 ? val1 : val3) : (val2 < val3 ? val2 : val3)); diff --git a/mesh_utils.h b/mesh_utils.h index 168d2ee..c9ae882 100644 --- a/mesh_utils.h +++ b/mesh_utils.h @@ -408,10 +408,6 @@ struct BorderVertex { int index; int hash; - _FORCE_INLINE_ void set_index(int p_value) { - index = p_value; - } - BorderVertex() { index = 0; hash = 0;