summaryrefslogtreecommitdiff
path: root/thirdparty/thekla_atlas/nvmath/Basis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/thekla_atlas/nvmath/Basis.cpp')
-rw-r--r--thirdparty/thekla_atlas/nvmath/Basis.cpp270
1 files changed, 0 insertions, 270 deletions
diff --git a/thirdparty/thekla_atlas/nvmath/Basis.cpp b/thirdparty/thekla_atlas/nvmath/Basis.cpp
deleted file mode 100644
index 0824179633..0000000000
--- a/thirdparty/thekla_atlas/nvmath/Basis.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-// This code is in the public domain -- Ignacio Castaņo <castano@gmail.com>
-
-#include "Basis.h"
-
-using namespace nv;
-
-
-/// Normalize basis vectors.
-void Basis::normalize(float epsilon /*= NV_EPSILON*/)
-{
- normal = ::normalizeSafe(normal, Vector3(0.0f), epsilon);
- tangent = ::normalizeSafe(tangent, Vector3(0.0f), epsilon);
- bitangent = ::normalizeSafe(bitangent, Vector3(0.0f), epsilon);
-}
-
-
-/// Gram-Schmidt orthogonalization.
-/// @note Works only if the vectors are close to orthogonal.
-void Basis::orthonormalize(float epsilon /*= NV_EPSILON*/)
-{
- // N' = |N|
- // T' = |T - (N' dot T) N'|
- // B' = |B - (N' dot B) N' - (T' dot B) T'|
-
- normal = ::normalize(normal, epsilon);
-
- tangent -= normal * dot(normal, tangent);
- tangent = ::normalize(tangent, epsilon);
-
- bitangent -= normal * dot(normal, bitangent);
- bitangent -= tangent * dot(tangent, bitangent);
- bitangent = ::normalize(bitangent, epsilon);
-}
-
-
-
-
-/// Robust orthonormalization.
-/// Returns an orthonormal basis even when the original is degenerate.
-void Basis::robustOrthonormalize(float epsilon /*= NV_EPSILON*/)
-{
- // Normalize all vectors.
- normalize(epsilon);
-
- if (lengthSquared(normal) < epsilon*epsilon)
- {
- // Build normal from tangent and bitangent.
- normal = cross(tangent, bitangent);
-
- if (lengthSquared(normal) < epsilon*epsilon)
- {
- // Arbitrary basis.
- tangent = Vector3(1, 0, 0);
- bitangent = Vector3(0, 1, 0);
- normal = Vector3(0, 0, 1);
- return;
- }
-
- normal = nv::normalize(normal, epsilon);
- }
-
- // Project tangents to normal plane.
- tangent -= normal * dot(normal, tangent);
- bitangent -= normal * dot(normal, bitangent);
-
- if (lengthSquared(tangent) < epsilon*epsilon)
- {
- if (lengthSquared(bitangent) < epsilon*epsilon)
- {
- // Arbitrary basis.
- buildFrameForDirection(normal);
- }
- else
- {
- // Build tangent from bitangent.
- bitangent = nv::normalize(bitangent, epsilon);
-
- tangent = cross(bitangent, normal);
- nvDebugCheck(isNormalized(tangent, epsilon));
- }
- }
- else
- {
- tangent = nv::normalize(tangent, epsilon);
-#if 0
- bitangent -= tangent * dot(tangent, bitangent);
-
- if (lengthSquared(bitangent) < epsilon*epsilon)
- {
- bitangent = cross(tangent, normal);
- nvDebugCheck(isNormalized(bitangent, epsilon));
- }
- else
- {
- bitangent = nv::normalize(bitangent, epsilon);
- }
-#else
- if (lengthSquared(bitangent) < epsilon*epsilon)
- {
- // Build bitangent from tangent.
- bitangent = cross(tangent, normal);
- nvDebugCheck(isNormalized(bitangent, epsilon));
- }
- else
- {
- bitangent = nv::normalize(bitangent, epsilon);
-
- // At this point tangent and bitangent are orthogonal to normal, but we don't know whether their orientation.
-
- Vector3 bisector;
- if (lengthSquared(tangent + bitangent) < epsilon*epsilon)
- {
- bisector = tangent;
- }
- else
- {
- bisector = nv::normalize(tangent + bitangent);
- }
- Vector3 axis = nv::normalize(cross(bisector, normal));
-
- //nvDebugCheck(isNormalized(axis, epsilon));
- nvDebugCheck(equal(dot(axis, tangent), -dot(axis, bitangent), epsilon));
-
- if (dot(axis, tangent) > 0)
- {
- tangent = bisector + axis;
- bitangent = bisector - axis;
- }
- else
- {
- tangent = bisector - axis;
- bitangent = bisector + axis;
- }
-
- // Make sure the resulting tangents are still perpendicular to the normal.
- tangent -= normal * dot(normal, tangent);
- bitangent -= normal * dot(normal, bitangent);
-
- // Double check.
- nvDebugCheck(equal(dot(normal, tangent), 0.0f, epsilon));
- nvDebugCheck(equal(dot(normal, bitangent), 0.0f, epsilon));
-
- // Normalize.
- tangent = nv::normalize(tangent);
- bitangent = nv::normalize(bitangent);
-
- // If tangent and bitangent are not orthogonal, then derive bitangent from tangent, just in case...
- if (!equal(dot(tangent, bitangent), 0.0f, epsilon)) {
- bitangent = cross(tangent, normal);
- bitangent = nv::normalize(bitangent);
- }
- }
-#endif
- }
-
- /*// Check vector lengths.
- if (!isNormalized(normal, epsilon))
- {
- nvDebug("%f %f %f\n", normal.x, normal.y, normal.z);
- nvDebug("%f %f %f\n", tangent.x, tangent.y, tangent.z);
- nvDebug("%f %f %f\n", bitangent.x, bitangent.y, bitangent.z);
- }*/
-
- nvDebugCheck(isNormalized(normal, epsilon));
- nvDebugCheck(isNormalized(tangent, epsilon));
- nvDebugCheck(isNormalized(bitangent, epsilon));
-
- // Check vector angles.
- nvDebugCheck(equal(dot(normal, tangent), 0.0f, epsilon));
- nvDebugCheck(equal(dot(normal, bitangent), 0.0f, epsilon));
- nvDebugCheck(equal(dot(tangent, bitangent), 0.0f, epsilon));
-
- // Check vector orientation.
- const float det = dot(cross(normal, tangent), bitangent);
- nvDebugCheck(equal(det, 1.0f, epsilon) || equal(det, -1.0f, epsilon));
-}
-
-
-/// Build an arbitrary frame for the given direction.
-void Basis::buildFrameForDirection(Vector3::Arg d, float angle/*= 0*/)
-{
- nvCheck(isNormalized(d));
- normal = d;
-
- // Choose minimum axis.
- if (fabsf(normal.x) < fabsf(normal.y) && fabsf(normal.x) < fabsf(normal.z))
- {
- tangent = Vector3(1, 0, 0);
- }
- else if (fabsf(normal.y) < fabsf(normal.z))
- {
- tangent = Vector3(0, 1, 0);
- }
- else
- {
- tangent = Vector3(0, 0, 1);
- }
-
- // Ortogonalize
- tangent -= normal * dot(normal, tangent);
- tangent = ::normalize(tangent);
-
- bitangent = cross(normal, tangent);
-
- // Rotate frame around normal according to angle.
- if (angle != 0.0f) {
- float c = cosf(angle);
- float s = sinf(angle);
- Vector3 tmp = c * tangent - s * bitangent;
- bitangent = s * tangent + c * bitangent;
- tangent = tmp;
- }
-}
-
-bool Basis::isValid() const
-{
- if (equal(normal, Vector3(0.0f))) return false;
- if (equal(tangent, Vector3(0.0f))) return false;
- if (equal(bitangent, Vector3(0.0f))) return false;
-
- if (equal(determinant(), 0.0f)) return false;
-
- return true;
-}
-
-
-/// Transform by this basis. (From this basis to object space).
-Vector3 Basis::transform(Vector3::Arg v) const
-{
- Vector3 o = tangent * v.x;
- o += bitangent * v.y;
- o += normal * v.z;
- return o;
-}
-
-/// Transform by the transpose. (From object space to this basis).
-Vector3 Basis::transformT(Vector3::Arg v)
-{
- return Vector3(dot(tangent, v), dot(bitangent, v), dot(normal, v));
-}
-
-/// Transform by the inverse. (From object space to this basis).
-/// @note Uses Cramer's rule so the inverse is not accurate if the basis is ill-conditioned.
-Vector3 Basis::transformI(Vector3::Arg v) const
-{
- const float det = determinant();
- nvDebugCheck(!equal(det, 0.0f, 0.0f));
-
- const float idet = 1.0f / det;
-
- // Rows of the inverse matrix.
- Vector3 r0(
- (bitangent.y * normal.z - bitangent.z * normal.y),
- -(bitangent.x * normal.z - bitangent.z * normal.x),
- (bitangent.x * normal.y - bitangent.y * normal.x));
-
- Vector3 r1(
- -(tangent.y * normal.z - tangent.z * normal.y),
- (tangent.x * normal.z - tangent.z * normal.x),
- -(tangent.x * normal.y - tangent.y * normal.x));
-
- Vector3 r2(
- (tangent.y * bitangent.z - tangent.z * bitangent.y),
- -(tangent.x * bitangent.z - tangent.z * bitangent.x),
- (tangent.x * bitangent.y - tangent.y * bitangent.x));
-
- return Vector3(dot(v, r0), dot(v, r1), dot(v, r2)) * idet;
-}
-
-