From be2b0fcddc981e5e5491cc626ef793a167772a48 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 2 Nov 2023 14:12:35 -0700 Subject: [PATCH] Update thirdparty/meshoptimizer with distance-only error metric This change replicates the distance-only metric patch which is now much smaller and cleaner, as upstream simplifier already tracks distance and attribute quadrics separately - it just doesn't store both errors in the collapse structures. The old two patches were removed as they are no longer needed. --- ...-aware-simplify-distance-only-metric.patch | 176 ------------ .../patches/attribute-aware-simplify.patch | 263 ------------------ .../patches/distance-only-metric.patch | 39 +++ thirdparty/meshoptimizer/simplifier.cpp | 7 +- 4 files changed, 45 insertions(+), 440 deletions(-) delete mode 100644 thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch delete mode 100644 thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch create mode 100644 thirdparty/meshoptimizer/patches/distance-only-metric.patch diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch deleted file mode 100644 index 5cac985dc51..00000000000 --- a/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch +++ /dev/null @@ -1,176 +0,0 @@ -diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp -index d8d4a67391..3847afc736 100644 ---- a/thirdparty/meshoptimizer/simplifier.cpp -+++ b/thirdparty/meshoptimizer/simplifier.cpp -@@ -20,7 +20,7 @@ - #define TRACESTATS(i) (void)0 - #endif - --#define ATTRIBUTES 8 -+#define ATTRIBUTES 3 - - // This work is based on: - // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997 -@@ -458,6 +458,7 @@ struct Collapse - float error; - unsigned int errorui; - }; -+ float distance_error; - }; - - static float normalize(Vector3& v) -@@ -538,6 +539,34 @@ static float quadricError(const Quadric& Q, const Vector3& v) - return fabsf(r) * s; - } - -+static float quadricErrorNoAttributes(const Quadric& Q, const Vector3& v) -+{ -+ float rx = Q.b0; -+ float ry = Q.b1; -+ float rz = Q.b2; -+ -+ rx += Q.a10 * v.y; -+ ry += Q.a21 * v.z; -+ rz += Q.a20 * v.x; -+ -+ rx *= 2; -+ ry *= 2; -+ rz *= 2; -+ -+ rx += Q.a00 * v.x; -+ ry += Q.a11 * v.y; -+ rz += Q.a22 * v.z; -+ -+ float r = Q.c; -+ r += rx * v.x; -+ r += ry * v.y; -+ r += rz * v.z; -+ -+ float s = Q.w == 0.f ? 0.f : 1.f / Q.w; -+ -+ return fabsf(r) * s; -+} -+ - static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, float w) - { - float aw = a * w; -@@ -693,7 +722,7 @@ static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3 - } - #endif - --static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap) -+static void fillFaceQuadrics(Quadric* vertex_quadrics, Quadric* vertex_no_attrib_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap) - { - for (size_t i = 0; i < index_count; i += 3) - { -@@ -703,6 +732,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic - - Quadric Q; - quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f); -+ quadricAdd(vertex_no_attrib_quadrics[remap[i0]], Q); -+ quadricAdd(vertex_no_attrib_quadrics[remap[i1]], Q); -+ quadricAdd(vertex_no_attrib_quadrics[remap[i2]], Q); - - #if ATTRIBUTES - quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w); -@@ -713,7 +745,7 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic - } - } - --static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap, const unsigned char* vertex_kind, const unsigned int* loop, const unsigned int* loopback) -+static void fillEdgeQuadrics(Quadric* vertex_quadrics, Quadric* vertex_no_attrib_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap, const unsigned char* vertex_kind, const unsigned int* loop, const unsigned int* loopback) - { - for (size_t i = 0; i < index_count; i += 3) - { -@@ -757,6 +789,9 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic - - quadricAdd(vertex_quadrics[remap[i0]], Q); - quadricAdd(vertex_quadrics[remap[i1]], Q); -+ -+ quadricAdd(vertex_no_attrib_quadrics[remap[i0]], Q); -+ quadricAdd(vertex_no_attrib_quadrics[remap[i1]], Q); - } - } - } -@@ -861,7 +896,7 @@ static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices - return collapse_count; - } - --static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const Vector3* vertex_positions, const Quadric* vertex_quadrics, const unsigned int* remap) -+static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const Vector3* vertex_positions, const Quadric* vertex_quadrics, const Quadric* vertex_no_attrib_quadrics, const unsigned int* remap) - { - for (size_t i = 0; i < collapse_count; ++i) - { -@@ -881,10 +916,14 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const - float ei = quadricError(qi, vertex_positions[i1]); - float ej = quadricError(qj, vertex_positions[j1]); - -+ const Quadric& naqi = vertex_no_attrib_quadrics[remap[i0]]; -+ const Quadric& naqj = vertex_no_attrib_quadrics[remap[j0]]; -+ - // pick edge direction with minimal error - c.v0 = ei <= ej ? i0 : j0; - c.v1 = ei <= ej ? i1 : j1; - c.error = ei <= ej ? ei : ej; -+ c.distance_error = ei <= ej ? quadricErrorNoAttributes(naqi, vertex_positions[i1]) : quadricErrorNoAttributes(naqj, vertex_positions[j1]); - } - } - -@@ -981,7 +1020,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse - } - } - --static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, Quadric* vertex_quadrics, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, const Vector3* vertex_positions, const EdgeAdjacency& adjacency, size_t triangle_collapse_goal, float error_limit, float& result_error) -+static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, Quadric* vertex_quadrics, Quadric* vertex_no_attrib_quadrics, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, const Vector3* vertex_positions, const EdgeAdjacency& adjacency, size_t triangle_collapse_goal, float error_limit, float& result_error) - { - size_t edge_collapses = 0; - size_t triangle_collapses = 0; -@@ -1043,6 +1082,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* - assert(collapse_remap[r1] == r1); - - quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]); -+ quadricAdd(vertex_no_attrib_quadrics[r1], vertex_no_attrib_quadrics[r0]); - - if (vertex_kind[i0] == Kind_Complex) - { -@@ -1080,7 +1120,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* - triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2; - edge_collapses++; - -- result_error = result_error < c.error ? c.error : result_error; -+ result_error = result_error < c.distance_error ? c.distance_error : result_error; - } - - #if TRACE -@@ -1469,9 +1509,11 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned - - Quadric* vertex_quadrics = allocator.allocate(vertex_count); - memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric)); -+ Quadric* vertex_no_attrib_quadrics = allocator.allocate(vertex_count); -+ memset(vertex_no_attrib_quadrics, 0, vertex_count * sizeof(Quadric)); - -- fillFaceQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap); -- fillEdgeQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap, vertex_kind, loop, loopback); -+ fillFaceQuadrics(vertex_quadrics, vertex_no_attrib_quadrics, indices, index_count, vertex_positions, remap); -+ fillEdgeQuadrics(vertex_quadrics, vertex_no_attrib_quadrics, indices, index_count, vertex_positions, remap, vertex_kind, loop, loopback); - - if (result != indices) - memcpy(result, indices, index_count * sizeof(unsigned int)); -@@ -1502,7 +1544,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned - if (edge_collapse_count == 0) - break; - -- rankEdgeCollapses(edge_collapses, edge_collapse_count, vertex_positions, vertex_quadrics, remap); -+ rankEdgeCollapses(edge_collapses, edge_collapse_count, vertex_positions, vertex_quadrics, vertex_no_attrib_quadrics, remap); - - #if TRACE > 1 - dumpEdgeCollapses(edge_collapses, edge_collapse_count, vertex_kind); -@@ -1521,7 +1563,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned - printf("pass %d: ", int(pass_count++)); - #endif - -- size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, vertex_quadrics, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, vertex_positions, adjacency, triangle_collapse_goal, error_limit, result_error); -+ size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, vertex_quadrics, vertex_no_attrib_quadrics, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, vertex_positions, adjacency, triangle_collapse_goal, error_limit, result_error); - - // no edges can be collapsed any more due to hitting the error limit or triangle collapse limit - if (collapses == 0) diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch deleted file mode 100644 index c065026a7d0..00000000000 --- a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch +++ /dev/null @@ -1,263 +0,0 @@ -diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h -index d95725dd71..46d28d3ea3 100644 ---- a/thirdparty/meshoptimizer/meshoptimizer.h -+++ b/thirdparty/meshoptimizer/meshoptimizer.h -@@ -321,6 +321,11 @@ enum - meshopt_SimplifyLockBorder = 1 << 0, - }; - -+/** -+ * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex) -+ */ -+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count); -+ - /** - * Mesh simplifier - * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible -diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp -index 5f0e9bac31..797329b010 100644 ---- a/thirdparty/meshoptimizer/simplifier.cpp -+++ b/thirdparty/meshoptimizer/simplifier.cpp -@@ -20,6 +20,8 @@ - #define TRACESTATS(i) (void)0 - #endif - -+#define ATTRIBUTES 8 -+ - // This work is based on: - // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997 - // Michael Garland. Quadric-based polygonal surface simplification. 1999 -@@ -376,6 +378,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned - struct Vector3 - { - float x, y, z; -+ -+#if ATTRIBUTES -+ float a[ATTRIBUTES]; -+#endif - }; - - static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride) -@@ -432,6 +438,13 @@ struct Quadric - float a10, a20, a21; - float b0, b1, b2, c; - float w; -+ -+#if ATTRIBUTES -+ float gx[ATTRIBUTES]; -+ float gy[ATTRIBUTES]; -+ float gz[ATTRIBUTES]; -+ float gw[ATTRIBUTES]; -+#endif - }; - - struct Collapse -@@ -474,6 +487,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R) - Q.b2 += R.b2; - Q.c += R.c; - Q.w += R.w; -+ -+#if ATTRIBUTES -+ for (int k = 0; k < ATTRIBUTES; ++k) -+ { -+ Q.gx[k] += R.gx[k]; -+ Q.gy[k] += R.gy[k]; -+ Q.gz[k] += R.gz[k]; -+ Q.gw[k] += R.gw[k]; -+ } -+#endif - } - - static float quadricError(const Quadric& Q, const Vector3& v) -@@ -499,6 +522,17 @@ static float quadricError(const Quadric& Q, const Vector3& v) - r += ry * v.y; - r += rz * v.z; - -+#if ATTRIBUTES -+ // see quadricUpdateAttributes for general derivation; here we need to add the parts of (eval(pos) - attr)^2 that depend on attr -+ for (int k = 0; k < ATTRIBUTES; ++k) -+ { -+ float a = v.a[k]; -+ -+ r += a * a * Q.w; -+ r -= 2 * a * (v.x * Q.gx[k] + v.y * Q.gy[k] + v.z * Q.gz[k] + Q.gw[k]); -+ } -+#endif -+ - float s = Q.w == 0.f ? 0.f : 1.f / Q.w; - - return fabsf(r) * s; -@@ -522,6 +556,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo - Q.b2 = c * dw; - Q.c = d * dw; - Q.w = w; -+ -+#if ATTRIBUTES -+ memset(Q.gx, 0, sizeof(Q.gx)); -+ memset(Q.gy, 0, sizeof(Q.gy)); -+ memset(Q.gz, 0, sizeof(Q.gz)); -+ memset(Q.gw, 0, sizeof(Q.gw)); -+#endif - } - - static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w) -@@ -574,6 +615,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3 - quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight); - } - -+#if ATTRIBUTES -+static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float w) -+{ -+ // for each attribute we want to encode the following function into the quadric: -+ // (eval(pos) - attr)^2 -+ // where eval(pos) interpolates attribute across the triangle like so: -+ // eval(pos) = pos.x * gx + pos.y * gy + pos.z * gz + gw -+ // where gx/gy/gz/gw are gradients -+ Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z}; -+ Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z}; -+ -+ // we compute gradients using barycentric coordinates; barycentric coordinates can be computed as follows: -+ // v = (d11 * d20 - d01 * d21) / denom -+ // w = (d00 * d21 - d01 * d20) / denom -+ // u = 1 - v - w -+ // here v0, v1 are triangle edge vectors, v2 is a vector from point to triangle corner, and dij = dot(vi, vj) -+ const Vector3& v0 = p10; -+ const Vector3& v1 = p20; -+ float d00 = v0.x * v0.x + v0.y * v0.y + v0.z * v0.z; -+ float d01 = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z; -+ float d11 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z; -+ float denom = d00 * d11 - d01 * d01; -+ float denomr = denom == 0 ? 0.f : 1.f / denom; -+ -+ // precompute gradient factors -+ // these are derived by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w and factoring out common factors that are shared between attributes -+ float gx1 = (d11 * v0.x - d01 * v1.x) * denomr; -+ float gx2 = (d00 * v1.x - d01 * v0.x) * denomr; -+ float gy1 = (d11 * v0.y - d01 * v1.y) * denomr; -+ float gy2 = (d00 * v1.y - d01 * v0.y) * denomr; -+ float gz1 = (d11 * v0.z - d01 * v1.z) * denomr; -+ float gz2 = (d00 * v1.z - d01 * v0.z) * denomr; -+ -+ for (int k = 0; k < ATTRIBUTES; ++k) -+ { -+ float a0 = p0.a[k], a1 = p1.a[k], a2 = p2.a[k]; -+ -+ // compute gradient of eval(pos) for x/y/z/w -+ // the formulas below are obtained by directly computing derivative of eval(pos) = a0 * u + a1 * v + a2 * w -+ float gx = gx1 * (a1 - a0) + gx2 * (a2 - a0); -+ float gy = gy1 * (a1 - a0) + gy2 * (a2 - a0); -+ float gz = gz1 * (a1 - a0) + gz2 * (a2 - a0); -+ float gw = a0 - p0.x * gx - p0.y * gy - p0.z * gz; -+ -+ // quadric encodes (eval(pos)-attr)^2; this means that the resulting expansion needs to compute, for example, pos.x * pos.y * K -+ // since quadrics already encode factors for pos.x * pos.y, we can accumulate almost everything in basic quadric fields -+ Q.a00 += w * (gx * gx); -+ Q.a11 += w * (gy * gy); -+ Q.a22 += w * (gz * gz); -+ -+ Q.a10 += w * (gy * gx); -+ Q.a20 += w * (gz * gx); -+ Q.a21 += w * (gz * gy); -+ -+ Q.b0 += w * (gx * gw); -+ Q.b1 += w * (gy * gw); -+ Q.b2 += w * (gz * gw); -+ -+ Q.c += w * (gw * gw); -+ -+ // the only remaining sum components are ones that depend on attr; these will be addded during error evaluation, see quadricError -+ Q.gx[k] = w * gx; -+ Q.gy[k] = w * gy; -+ Q.gz[k] = w * gz; -+ Q.gw[k] = w * gw; -+ -+#if TRACE > 2 -+ printf("attr%d: %e %e %e\n", -+ k, -+ (gx * p0.x + gy * p0.y + gz * p0.z + gw - a0), -+ (gx * p1.x + gy * p1.y + gz * p1.z + gw - a1), -+ (gx * p2.x + gy * p2.y + gz * p2.z + gw - a2) -+ ); -+#endif -+ } -+} -+#endif -+ - static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap) - { - for (size_t i = 0; i < index_count; i += 3) -@@ -585,6 +704,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic - Quadric Q; - quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f); - -+#if ATTRIBUTES -+ quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w); -+#endif - quadricAdd(vertex_quadrics[remap[i0]], Q); - quadricAdd(vertex_quadrics[remap[i1]], Q); - quadricAdd(vertex_quadrics[remap[i2]], Q); -@@ -1278,14 +1400,20 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0; - #endif - - size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) -+{ -+ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, options, out_result_error, 0, 0, 0); -+} -+ -+size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count) - { - using namespace meshopt; - - assert(index_count % 3 == 0); -- assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); -- assert(vertex_positions_stride % sizeof(float) == 0); -+ assert(vertex_stride >= 12 && vertex_stride <= 256); -+ assert(vertex_stride % sizeof(float) == 0); - assert(target_index_count <= index_count); - assert((options & ~(meshopt_SimplifyLockBorder)) == 0); -+ assert(attribute_count <= ATTRIBUTES); - - meshopt_Allocator allocator; - -@@ -1299,7 +1427,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, - // build position remap that maps each vertex to the one with identical position - unsigned int* remap = allocator.allocate(vertex_count); - unsigned int* wedge = allocator.allocate(vertex_count); -- buildPositionRemap(remap, wedge, vertex_positions_data, vertex_count, vertex_positions_stride, allocator); -+ buildPositionRemap(remap, wedge, vertex_data, vertex_count, vertex_stride, allocator); - - // classify vertices; vertex kind determines collapse rules, see kCanCollapse - unsigned char* vertex_kind = allocator.allocate(vertex_count); -@@ -1323,7 +1451,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, - #endif - - Vector3* vertex_positions = allocator.allocate(vertex_count); -- rescalePositions(vertex_positions, vertex_positions_data, vertex_count, vertex_positions_stride); -+ rescalePositions(vertex_positions, vertex_data, vertex_count, vertex_stride); -+ -+#if ATTRIBUTES -+ for (size_t i = 0; i < vertex_count; ++i) -+ { -+ memset(vertex_positions[i].a, 0, sizeof(vertex_positions[i].a)); -+ -+ for (size_t k = 0; k < attribute_count; ++k) -+ { -+ float a = attributes[i * attribute_count + k]; -+ -+ vertex_positions[i].a[k] = a * attribute_weights[k]; -+ } -+ } -+#endif - - Quadric* vertex_quadrics = allocator.allocate(vertex_count); - memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric)); -@@ -1415,7 +1557,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, - - // result_error is quadratic; we need to remap it back to linear - if (out_result_error) -+ { - *out_result_error = sqrtf(result_error); -+ } - - return result_count; - } diff --git a/thirdparty/meshoptimizer/patches/distance-only-metric.patch b/thirdparty/meshoptimizer/patches/distance-only-metric.patch new file mode 100644 index 00000000000..651bdba5ef7 --- /dev/null +++ b/thirdparty/meshoptimizer/patches/distance-only-metric.patch @@ -0,0 +1,39 @@ +diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp +index 5ba8570076..6f8b0e520e 100644 +--- a/thirdparty/meshoptimizer/simplifier.cpp ++++ b/thirdparty/meshoptimizer/simplifier.cpp +@@ -476,6 +476,8 @@ struct Collapse + float error; + unsigned int errorui; + }; ++ ++ float distance_error; + }; + + static float normalize(Vector3& v) +@@ -941,6 +943,8 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const + float ei = quadricError(vertex_quadrics[remap[i0]], vertex_positions[i1]); + float ej = quadricError(vertex_quadrics[remap[j0]], vertex_positions[j1]); + ++ float dei = ei, dej = ej; ++ + if (attribute_count) + { + ei += quadricError(attribute_quadrics[remap[i0]], &attribute_gradients[remap[i0] * attribute_count], attribute_count, vertex_positions[i1], &vertex_attributes[i1 * attribute_count]); +@@ -951,6 +955,7 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const + c.v0 = ei <= ej ? i0 : j0; + c.v1 = ei <= ej ? i1 : j1; + c.error = ei <= ej ? ei : ej; ++ c.distance_error = ei <= ej ? dei : dej; + } + } + +@@ -1097,7 +1102,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* + triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2; + edge_collapses++; + +- result_error = result_error < c.error ? c.error : result_error; ++ result_error = result_error < c.distance_error ? c.distance_error : result_error; + } + + #if TRACE diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp index 5ba8570076e..6f8b0e520ed 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp @@ -476,6 +476,8 @@ struct Collapse float error; unsigned int errorui; }; + + float distance_error; }; static float normalize(Vector3& v) @@ -941,6 +943,8 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const float ei = quadricError(vertex_quadrics[remap[i0]], vertex_positions[i1]); float ej = quadricError(vertex_quadrics[remap[j0]], vertex_positions[j1]); + float dei = ei, dej = ej; + if (attribute_count) { ei += quadricError(attribute_quadrics[remap[i0]], &attribute_gradients[remap[i0] * attribute_count], attribute_count, vertex_positions[i1], &vertex_attributes[i1 * attribute_count]); @@ -951,6 +955,7 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const c.v0 = ei <= ej ? i0 : j0; c.v1 = ei <= ej ? i1 : j1; c.error = ei <= ej ? ei : ej; + c.distance_error = ei <= ej ? dei : dej; } } @@ -1097,7 +1102,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2; edge_collapses++; - result_error = result_error < c.error ? c.error : result_error; + result_error = result_error < c.distance_error ? c.distance_error : result_error; } #if TRACE