diff options
Diffstat (limited to 'thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp')
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp | 323 |
1 files changed, 0 insertions, 323 deletions
diff --git a/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp b/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp deleted file mode 100644 index 683ee603cd..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com> - -#include "nvmesh.h" // pch - -#include "ParameterizationQuality.h" - -#include "nvmesh/halfedge/Mesh.h" -#include "nvmesh/halfedge/Face.h" -#include "nvmesh/halfedge/Vertex.h" -#include "nvmesh/halfedge/Edge.h" - -#include "nvmath/Vector.inl" - -#include "nvcore/Debug.h" - -#include <float.h> - - -using namespace nv; - -#if 0 -/* -float triangleConformalEnergy(Vector3 q[3], Vector2 p[3]) -{ -const Vector3 v1 = q[0]; -const Vector3 v2 = q[1]; -const Vector3 v3 = q[2]; - -const Vector2 w1 = p[0]; -const Vector2 w2 = p[1]; -const Vector2 w3 = p[2]; - -float x1 = v2.x() - v1.x(); -float x2 = v3.x() - v1.x(); -float y1 = v2.y() - v1.y(); -float y2 = v3.y() - v1.y(); -float z1 = v2.z() - v1.z(); -float z2 = v3.z() - v1.z(); - -float s1 = w2.x() - w1.x(); -float s2 = w3.x() - w1.x(); -float t1 = w2.y() - w1.y(); -float t2 = w3.y() - w1.y(); - -float r = 1.0f / (s1 * t2 - s2 * t1); -Vector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); -Vector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); - -Vector3 N = cross(v3-v1, v2-v1); - -// Rotate 90 around N. -} -*/ - -static float triangleConformalEnergy(Vector3 q[3], Vector2 p[3]) -{ - // Using Denis formulas: - Vector3 c0 = q[1] - q[2]; - Vector3 c1 = q[2] - q[0]; - Vector3 c2 = q[0] - q[1]; - - Vector3 N = cross(-c0, c1); - float T = length(N); // 2T - N = normalize(N, 0); - - float cot_alpha0 = dot(-c1, c2) / length(cross(-c1, c2)); - float cot_alpha1 = dot(-c2, c0) / length(cross(-c2, c0)); - float cot_alpha2 = dot(-c0, c1) / length(cross(-c0, c1)); - - Vector3 t0 = -cot_alpha1 * c1 + cot_alpha2 * c2; - Vector3 t1 = -cot_alpha2 * c2 + cot_alpha0 * c0; - Vector3 t2 = -cot_alpha0 * c0 + cot_alpha1 * c1; - - nvCheck(equal(length(t0), length(c0))); - nvCheck(equal(length(t1), length(c1))); - nvCheck(equal(length(t2), length(c2))); - nvCheck(equal(dot(t0, c0), 0)); - nvCheck(equal(dot(t1, c1), 0)); - nvCheck(equal(dot(t2, c2), 0)); - - // Gradients - Vector3 grad_u = 1.0f / T * (p[0].x * t0 + p[1].x * t1 + p[2].x * t2); - Vector3 grad_v = 1.0f / T * (p[0].y * t0 + p[1].y * t1 + p[2].y * t2); - - // Rotated gradients - Vector3 Jgrad_u = 1.0f / T * (p[0].x * c0 + p[1].x * c1 + p[2].x * c2); - Vector3 Jgrad_v = 1.0f / T * (p[0].y * c0 + p[1].y * c1 + p[2].y * c2); - - // Using Lengyel's formulas: - { - const Vector3 v1 = q[0]; - const Vector3 v2 = q[1]; - const Vector3 v3 = q[2]; - - const Vector2 w1 = p[0]; - const Vector2 w2 = p[1]; - const Vector2 w3 = p[2]; - - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; - - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; - - float r = 1.0f / (s1 * t2 - s2 * t1); - Vector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); - Vector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); - - Vector3 Jsdir = cross(N, sdir); - Vector3 Jtdir = cross(N, tdir); - - float x = 3; - } - - // check: sdir == grad_u - // check: tdir == grad_v - - return length(grad_u - Jgrad_v); -} -#endif // 0 - - -ParameterizationQuality::ParameterizationQuality() -{ - m_totalTriangleCount = 0; - m_flippedTriangleCount = 0; - m_zeroAreaTriangleCount = 0; - - m_parametricArea = 0.0f; - m_geometricArea = 0.0f; - - m_stretchMetric = 0.0f; - m_maxStretchMetric = 0.0f; - - m_conformalMetric = 0.0f; - m_authalicMetric = 0.0f; -} - -ParameterizationQuality::ParameterizationQuality(const HalfEdge::Mesh * mesh) -{ - nvDebugCheck(mesh != NULL); - - m_totalTriangleCount = 0; - m_flippedTriangleCount = 0; - m_zeroAreaTriangleCount = 0; - - m_parametricArea = 0.0f; - m_geometricArea = 0.0f; - - m_stretchMetric = 0.0f; - m_maxStretchMetric = 0.0f; - - m_conformalMetric = 0.0f; - m_authalicMetric = 0.0f; - - const uint faceCount = mesh->faceCount(); - for (uint f = 0; f < faceCount; f++) - { - const HalfEdge::Face * face = mesh->faceAt(f); - const HalfEdge::Vertex * vertex0 = NULL; - - Vector3 p[3]; - Vector2 t[3]; - - for (HalfEdge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) - { - const HalfEdge::Edge * edge = it.current(); - - if (vertex0 == NULL) - { - vertex0 = edge->vertex; - - p[0] = vertex0->pos; - t[0] = vertex0->tex; - } - else if (edge->to() != vertex0) - { - p[1] = edge->from()->pos; - p[2] = edge->to()->pos; - t[1] = edge->from()->tex; - t[2] = edge->to()->tex; - - processTriangle(p, t); - } - } - } - - if (m_flippedTriangleCount + m_zeroAreaTriangleCount == faceCount) - { - // If all triangles are flipped, then none is. - m_flippedTriangleCount = 0; - } - - nvDebugCheck(isFinite(m_parametricArea) && m_parametricArea >= 0); - nvDebugCheck(isFinite(m_geometricArea) && m_geometricArea >= 0); - nvDebugCheck(isFinite(m_stretchMetric)); - nvDebugCheck(isFinite(m_maxStretchMetric)); - nvDebugCheck(isFinite(m_conformalMetric)); - nvDebugCheck(isFinite(m_authalicMetric)); -} - -bool ParameterizationQuality::isValid() const -{ - return m_flippedTriangleCount == 0; // @@ Does not test for self-overlaps. -} - -float ParameterizationQuality::rmsStretchMetric() const -{ - if (m_geometricArea == 0) return 0.0f; - float normFactor = sqrtf(m_parametricArea / m_geometricArea); - return sqrtf(m_stretchMetric / m_geometricArea) * normFactor; -} - -float ParameterizationQuality::maxStretchMetric() const -{ - if (m_geometricArea == 0) return 0.0f; - float normFactor = sqrtf(m_parametricArea / m_geometricArea); - return m_maxStretchMetric * normFactor; -} - -float ParameterizationQuality::rmsConformalMetric() const -{ - if (m_geometricArea == 0) return 0.0f; - return sqrtf(m_conformalMetric / m_geometricArea); -} - -float ParameterizationQuality::maxAuthalicMetric() const -{ - if (m_geometricArea == 0) return 0.0f; - return sqrtf(m_authalicMetric / m_geometricArea); -} - -void ParameterizationQuality::operator += (const ParameterizationQuality & pq) -{ - m_totalTriangleCount += pq.m_totalTriangleCount; - m_flippedTriangleCount += pq.m_flippedTriangleCount; - m_zeroAreaTriangleCount += pq.m_zeroAreaTriangleCount; - - m_parametricArea += pq.m_parametricArea; - m_geometricArea += pq.m_geometricArea; - - m_stretchMetric += pq.m_stretchMetric; - m_maxStretchMetric = max(m_maxStretchMetric, pq.m_maxStretchMetric); - - m_conformalMetric += pq.m_conformalMetric; - m_authalicMetric += pq.m_authalicMetric; -} - - -void ParameterizationQuality::processTriangle(Vector3 q[3], Vector2 p[3]) -{ - m_totalTriangleCount++; - - // Evaluate texture stretch metric. See: - // - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe - // - "Mesh Parameterization: Theory and Practice", Siggraph'07 Course Notes, Hormann, Levy & Sheffer. - - float t1 = p[0].x; - float s1 = p[0].y; - float t2 = p[1].x; - float s2 = p[1].y; - float t3 = p[2].x; - float s3 = p[2].y; - - float geometricArea = length(cross(q[1] - q[0], q[2] - q[0])) / 2; - float parametricArea = ((s2 - s1)*(t3 - t1) - (s3 - s1)*(t2 - t1)) / 2; - - if (isZero(parametricArea)) - { - m_zeroAreaTriangleCount++; - return; - } - - Vector3 Ss = (q[0] * (t2- t3) + q[1] * (t3 - t1) + q[2] * (t1 - t2)) / (2 * parametricArea); - Vector3 St = (q[0] * (s3- s2) + q[1] * (s1 - s3) + q[2] * (s2 - s1)) / (2 * parametricArea); - - float a = dot(Ss, Ss); // E - float b = dot(Ss, St); // F - float c = dot(St, St); // G - - // Compute eigen-values of the first fundamental form: - float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue. - float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue. - nvCheck(sigma2 >= sigma1); - - // isometric: sigma1 = sigma2 = 1 - // conformal: sigma1 / sigma2 = 1 - // authalic: sigma1 * sigma2 = 1 - - float rmsStretch = sqrtf((a + c) * 0.5f); - float rmsStretch2 = sqrtf((square(sigma1) + square(sigma2)) * 0.5f); - nvDebugCheck(equal(rmsStretch, rmsStretch2, 0.01f)); - - if (parametricArea < 0.0f) - { - // Count flipped triangles. - m_flippedTriangleCount++; - - parametricArea = fabsf(parametricArea); - } - - m_stretchMetric += square(rmsStretch) * geometricArea; - m_maxStretchMetric = max(m_maxStretchMetric, sigma2); - - if (!isZero(sigma1, 0.000001f)) { - // sigma1 is zero when geometricArea is zero. - m_conformalMetric += (sigma2 / sigma1) * geometricArea; - } - m_authalicMetric += (sigma1 * sigma2) * geometricArea; - - // Accumulate total areas. - m_geometricArea += geometricArea; - m_parametricArea += parametricArea; - - - //triangleConformalEnergy(q, p); -} |