attribute-aware-simplify-distance-only-metric.patch 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
  2. index d8d4a67391..3847afc736 100644
  3. --- a/thirdparty/meshoptimizer/simplifier.cpp
  4. +++ b/thirdparty/meshoptimizer/simplifier.cpp
  5. @@ -20,7 +20,7 @@
  6. #define TRACESTATS(i) (void)0
  7. #endif
  8. -#define ATTRIBUTES 8
  9. +#define ATTRIBUTES 3
  10. // This work is based on:
  11. // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
  12. @@ -458,6 +458,7 @@ struct Collapse
  13. float error;
  14. unsigned int errorui;
  15. };
  16. + float distance_error;
  17. };
  18. static float normalize(Vector3& v)
  19. @@ -538,6 +539,34 @@ static float quadricError(const Quadric& Q, const Vector3& v)
  20. return fabsf(r) * s;
  21. }
  22. +static float quadricErrorNoAttributes(const Quadric& Q, const Vector3& v)
  23. +{
  24. + float rx = Q.b0;
  25. + float ry = Q.b1;
  26. + float rz = Q.b2;
  27. +
  28. + rx += Q.a10 * v.y;
  29. + ry += Q.a21 * v.z;
  30. + rz += Q.a20 * v.x;
  31. +
  32. + rx *= 2;
  33. + ry *= 2;
  34. + rz *= 2;
  35. +
  36. + rx += Q.a00 * v.x;
  37. + ry += Q.a11 * v.y;
  38. + rz += Q.a22 * v.z;
  39. +
  40. + float r = Q.c;
  41. + r += rx * v.x;
  42. + r += ry * v.y;
  43. + r += rz * v.z;
  44. +
  45. + float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
  46. +
  47. + return fabsf(r) * s;
  48. +}
  49. +
  50. static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, float w)
  51. {
  52. float aw = a * w;
  53. @@ -693,7 +722,7 @@ static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3
  54. }
  55. #endif
  56. -static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
  57. +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)
  58. {
  59. for (size_t i = 0; i < index_count; i += 3)
  60. {
  61. @@ -703,6 +732,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
  62. Quadric Q;
  63. quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
  64. + quadricAdd(vertex_no_attrib_quadrics[remap[i0]], Q);
  65. + quadricAdd(vertex_no_attrib_quadrics[remap[i1]], Q);
  66. + quadricAdd(vertex_no_attrib_quadrics[remap[i2]], Q);
  67. #if ATTRIBUTES
  68. quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w);
  69. @@ -713,7 +745,7 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
  70. }
  71. }
  72. -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)
  73. +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)
  74. {
  75. for (size_t i = 0; i < index_count; i += 3)
  76. {
  77. @@ -757,6 +789,9 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
  78. quadricAdd(vertex_quadrics[remap[i0]], Q);
  79. quadricAdd(vertex_quadrics[remap[i1]], Q);
  80. +
  81. + quadricAdd(vertex_no_attrib_quadrics[remap[i0]], Q);
  82. + quadricAdd(vertex_no_attrib_quadrics[remap[i1]], Q);
  83. }
  84. }
  85. }
  86. @@ -861,7 +896,7 @@ static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices
  87. return collapse_count;
  88. }
  89. -static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const Vector3* vertex_positions, const Quadric* vertex_quadrics, const unsigned int* remap)
  90. +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)
  91. {
  92. for (size_t i = 0; i < collapse_count; ++i)
  93. {
  94. @@ -881,10 +916,14 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const
  95. float ei = quadricError(qi, vertex_positions[i1]);
  96. float ej = quadricError(qj, vertex_positions[j1]);
  97. + const Quadric& naqi = vertex_no_attrib_quadrics[remap[i0]];
  98. + const Quadric& naqj = vertex_no_attrib_quadrics[remap[j0]];
  99. +
  100. // pick edge direction with minimal error
  101. c.v0 = ei <= ej ? i0 : j0;
  102. c.v1 = ei <= ej ? i1 : j1;
  103. c.error = ei <= ej ? ei : ej;
  104. + c.distance_error = ei <= ej ? quadricErrorNoAttributes(naqi, vertex_positions[i1]) : quadricErrorNoAttributes(naqj, vertex_positions[j1]);
  105. }
  106. }
  107. @@ -981,7 +1020,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse
  108. }
  109. }
  110. -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)
  111. +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)
  112. {
  113. size_t edge_collapses = 0;
  114. size_t triangle_collapses = 0;
  115. @@ -1043,6 +1082,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
  116. assert(collapse_remap[r1] == r1);
  117. quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]);
  118. + quadricAdd(vertex_no_attrib_quadrics[r1], vertex_no_attrib_quadrics[r0]);
  119. if (vertex_kind[i0] == Kind_Complex)
  120. {
  121. @@ -1080,7 +1120,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
  122. triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2;
  123. edge_collapses++;
  124. - result_error = result_error < c.error ? c.error : result_error;
  125. + result_error = result_error < c.distance_error ? c.distance_error : result_error;
  126. }
  127. #if TRACE
  128. @@ -1469,9 +1509,11 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
  129. Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
  130. memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
  131. + Quadric* vertex_no_attrib_quadrics = allocator.allocate<Quadric>(vertex_count);
  132. + memset(vertex_no_attrib_quadrics, 0, vertex_count * sizeof(Quadric));
  133. - fillFaceQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap);
  134. - fillEdgeQuadrics(vertex_quadrics, indices, index_count, vertex_positions, remap, vertex_kind, loop, loopback);
  135. + fillFaceQuadrics(vertex_quadrics, vertex_no_attrib_quadrics, indices, index_count, vertex_positions, remap);
  136. + fillEdgeQuadrics(vertex_quadrics, vertex_no_attrib_quadrics, indices, index_count, vertex_positions, remap, vertex_kind, loop, loopback);
  137. if (result != indices)
  138. memcpy(result, indices, index_count * sizeof(unsigned int));
  139. @@ -1502,7 +1544,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
  140. if (edge_collapse_count == 0)
  141. break;
  142. - rankEdgeCollapses(edge_collapses, edge_collapse_count, vertex_positions, vertex_quadrics, remap);
  143. + rankEdgeCollapses(edge_collapses, edge_collapse_count, vertex_positions, vertex_quadrics, vertex_no_attrib_quadrics, remap);
  144. #if TRACE > 1
  145. dumpEdgeCollapses(edge_collapses, edge_collapse_count, vertex_kind);
  146. @@ -1521,7 +1563,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
  147. printf("pass %d: ", int(pass_count++));
  148. #endif
  149. - 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);
  150. + 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);
  151. // no edges can be collapsed any more due to hitting the error limit or triangle collapse limit
  152. if (collapses == 0)