diff options
Diffstat (limited to 'thirdparty/thekla_atlas/nvmath/Basis.cpp')
-rw-r--r-- | thirdparty/thekla_atlas/nvmath/Basis.cpp | 270 |
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; -} - - |