summaryrefslogtreecommitdiff
path: root/thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp')
-rw-r--r--thirdparty/thekla_atlas/nvmesh/param/ParameterizationQuality.cpp323
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);
-}