Merge internal branch.
parent
18c452a2a6
commit
98b2377a11
@ -0,0 +1,45 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#include <nvcore/TextWriter.h>
|
||||
|
||||
using namespace nv;
|
||||
|
||||
|
||||
/// Constructor
|
||||
TextWriter::TextWriter(Stream * s) :
|
||||
s(s),
|
||||
str(1024)
|
||||
{
|
||||
nvCheck(s != NULL);
|
||||
nvCheck(s->isSaving());
|
||||
}
|
||||
|
||||
void TextWriter::writeString(const char * str)
|
||||
{
|
||||
nvDebugCheck(s != NULL);
|
||||
s->serialize(const_cast<char *>(str), strlen(str));
|
||||
}
|
||||
|
||||
void TextWriter::writeString(const char * str, uint len)
|
||||
{
|
||||
nvDebugCheck(s != NULL);
|
||||
s->serialize(const_cast<char *>(str), len);
|
||||
}
|
||||
|
||||
void TextWriter::write(const char * format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg,format);
|
||||
str.format(format, arg);
|
||||
writeString(str.str(), str.length());
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void TextWriter::write(const char * format, va_list arg)
|
||||
{
|
||||
va_list tmp;
|
||||
va_copy(tmp, arg);
|
||||
str.format(format, arg);
|
||||
writeString(str.str(), str.length());
|
||||
va_end(tmp);
|
||||
}
|
@ -1,173 +1,173 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#include <nvmath/Basis.h>
|
||||
|
||||
using namespace nv;
|
||||
|
||||
|
||||
/// Normalize basis vectors.
|
||||
void Basis::normalize(float epsilon /*= NV_EPSILON*/)
|
||||
{
|
||||
normal = ::normalize(normal, epsilon);
|
||||
tangent = ::normalize(tangent, epsilon);
|
||||
bitangent = ::normalize(bitangent, 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*/)
|
||||
{
|
||||
if (length(normal) < epsilon)
|
||||
{
|
||||
normal = cross(tangent, bitangent);
|
||||
|
||||
if (length(normal) < epsilon)
|
||||
{
|
||||
tangent = Vector3(1, 0, 0);
|
||||
bitangent = Vector3(0, 1, 0);
|
||||
normal = Vector3(0, 0, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
normal = ::normalize(normal, epsilon);
|
||||
|
||||
tangent -= normal * dot(normal, tangent);
|
||||
bitangent -= normal * dot(normal, bitangent);
|
||||
|
||||
if (length(tangent) < epsilon)
|
||||
{
|
||||
if (length(bitangent) < epsilon)
|
||||
{
|
||||
buildFrameForDirection(normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = cross(bitangent, normal);
|
||||
nvCheck(isNormalized(tangent, epsilon));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = ::normalize(tangent, epsilon);
|
||||
bitangent -= tangent * dot(tangent, bitangent);
|
||||
|
||||
if (length(bitangent) < epsilon)
|
||||
{
|
||||
bitangent = cross(tangent, normal);
|
||||
nvCheck(isNormalized(bitangent));
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = ::normalize(tangent, epsilon);
|
||||
}
|
||||
}
|
||||
|
||||
// Check vector lengths.
|
||||
nvCheck(isNormalized(normal, epsilon));
|
||||
nvCheck(isNormalized(tangent, epsilon));
|
||||
nvCheck(isNormalized(bitangent, epsilon));
|
||||
|
||||
// Check vector angles.
|
||||
nvCheck(equal(dot(normal, tangent), 0.0f, epsilon));
|
||||
nvCheck(equal(dot(normal, bitangent), 0.0f, epsilon));
|
||||
nvCheck(equal(dot(tangent, bitangent), 0.0f, epsilon));
|
||||
|
||||
// Check vector orientation.
|
||||
const float det = dot(cross(normal, tangent), bitangent);
|
||||
nvCheck(equal(det, 1.0f, epsilon) || equal(det, -1.0f, epsilon));
|
||||
}
|
||||
|
||||
|
||||
/// Build an arbitrary frame for the given direction.
|
||||
void Basis::buildFrameForDirection(Vector3::Arg d)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/// 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 Kramer'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();
|
||||
nvCheck(!equalf(det, 0.0f));
|
||||
|
||||
const float idet = 1.0f / det;
|
||||
|
||||
// Rows of the inverse matrix.
|
||||
Vector3 r0, r1, r2;
|
||||
r0.x = (bitangent.y() * normal.z() - bitangent.z() * normal.y()) * idet;
|
||||
r0.y = -(bitangent.x() * normal.z() - bitangent.z() * normal.x()) * idet;
|
||||
r0.z = (bitangent.x() * normal.y() - bitangent.y() * normal.x()) * idet;
|
||||
|
||||
r1.x = -(tangent.y() * normal.z() - tangent.z() * normal.y()) * idet;
|
||||
r1.y = (tangent.x() * normal.z() - tangent.z() * normal.x()) * idet;
|
||||
r1.z = -(tangent.x() * normal.y() - tangent.y() * normal.x()) * idet;
|
||||
|
||||
r2.x = (tangent.y() * bitangent.z() - tangent.z() * bitangent.y()) * idet;
|
||||
r2.y = -(tangent.x() * bitangent.z() - tangent.z() * bitangent.x()) * idet;
|
||||
r2.z = (tangent.x() * bitangent.y() - tangent.y() * bitangent.x()) * idet;
|
||||
|
||||
return Vector3(dot(v, r0), dot(v, r1), dot(v, r2));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#include <nvmath/Basis.h>
|
||||
|
||||
using namespace nv;
|
||||
|
||||
|
||||
/// Normalize basis vectors.
|
||||
void Basis::normalize(float epsilon /*= NV_EPSILON*/)
|
||||
{
|
||||
normal = ::normalize(normal, epsilon);
|
||||
tangent = ::normalize(tangent, epsilon);
|
||||
bitangent = ::normalize(bitangent, 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*/)
|
||||
{
|
||||
if (length(normal) < epsilon)
|
||||
{
|
||||
normal = cross(tangent, bitangent);
|
||||
|
||||
if (length(normal) < epsilon)
|
||||
{
|
||||
tangent = Vector3(1, 0, 0);
|
||||
bitangent = Vector3(0, 1, 0);
|
||||
normal = Vector3(0, 0, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
normal = ::normalize(normal, epsilon);
|
||||
|
||||
tangent -= normal * dot(normal, tangent);
|
||||
bitangent -= normal * dot(normal, bitangent);
|
||||
|
||||
if (length(tangent) < epsilon)
|
||||
{
|
||||
if (length(bitangent) < epsilon)
|
||||
{
|
||||
buildFrameForDirection(normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = cross(bitangent, normal);
|
||||
nvCheck(isNormalized(tangent, epsilon));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = ::normalize(tangent, epsilon);
|
||||
bitangent -= tangent * dot(tangent, bitangent);
|
||||
|
||||
if (length(bitangent) < epsilon)
|
||||
{
|
||||
bitangent = cross(tangent, normal);
|
||||
nvCheck(isNormalized(bitangent));
|
||||
}
|
||||
else
|
||||
{
|
||||
tangent = ::normalize(tangent, epsilon);
|
||||
}
|
||||
}
|
||||
|
||||
// Check vector lengths.
|
||||
nvCheck(isNormalized(normal, epsilon));
|
||||
nvCheck(isNormalized(tangent, epsilon));
|
||||
nvCheck(isNormalized(bitangent, epsilon));
|
||||
|
||||
// Check vector angles.
|
||||
nvCheck(equal(dot(normal, tangent), 0.0f, epsilon));
|
||||
nvCheck(equal(dot(normal, bitangent), 0.0f, epsilon));
|
||||
nvCheck(equal(dot(tangent, bitangent), 0.0f, epsilon));
|
||||
|
||||
// Check vector orientation.
|
||||
const float det = dot(cross(normal, tangent), bitangent);
|
||||
nvCheck(equal(det, 1.0f, epsilon) || equal(det, -1.0f, epsilon));
|
||||
}
|
||||
|
||||
|
||||
/// Build an arbitrary frame for the given direction.
|
||||
void Basis::buildFrameForDirection(Vector3::Arg d)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/// 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 Kramer'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();
|
||||
nvCheck(!equalf(det, 0.0f));
|
||||
|
||||
const float idet = 1.0f / det;
|
||||
|
||||
// Rows of the inverse matrix.
|
||||
Vector3 r0, r1, r2;
|
||||
r0.x = (bitangent.y() * normal.z() - bitangent.z() * normal.y()) * idet;
|
||||
r0.y = -(bitangent.x() * normal.z() - bitangent.z() * normal.x()) * idet;
|
||||
r0.z = (bitangent.x() * normal.y() - bitangent.y() * normal.x()) * idet;
|
||||
|
||||
r1.x = -(tangent.y() * normal.z() - tangent.z() * normal.y()) * idet;
|
||||
r1.y = (tangent.x() * normal.z() - tangent.z() * normal.x()) * idet;
|
||||
r1.z = -(tangent.x() * normal.y() - tangent.y() * normal.x()) * idet;
|
||||
|
||||
r2.x = (tangent.y() * bitangent.z() - tangent.z() * bitangent.y()) * idet;
|
||||
r2.y = -(tangent.x() * bitangent.z() - tangent.z() * bitangent.x()) * idet;
|
||||
r2.z = (tangent.x() * bitangent.y() - tangent.y() * bitangent.x()) * idet;
|
||||
|
||||
return Vector3(dot(v, r0), dot(v, r1), dot(v, r2));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
@ -1,78 +1,78 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#ifndef NV_MATH_BASIS_H
|
||||
#define NV_MATH_BASIS_H
|
||||
|
||||
#include <nvmath/nvmath.h>
|
||||
#include <nvmath/Vector.h>
|
||||
#include <nvmath/Matrix.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
|
||||
/// Basis class to compute tangent space basis, ortogonalizations and to
|
||||
/// transform vectors from one space to another.
|
||||
struct Basis
|
||||
{
|
||||
/// Create a null basis.
|
||||
Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
|
||||
|
||||
/// Create a basis given three vectors.
|
||||
Basis(Vector3::Arg n, Vector3::Arg t, Vector3::Arg b) : tangent(t), bitangent(b), normal(n) {}
|
||||
|
||||
/// Create a basis with the given tangent vectors and the handness.
|
||||
Basis(Vector3::Arg n, Vector3::Arg t, float sign)
|
||||
{
|
||||
build(n, t, sign);
|
||||
}
|
||||
|
||||
NVMATH_API void normalize(float epsilon = NV_EPSILON);
|
||||
NVMATH_API void orthonormalize(float epsilon = NV_EPSILON);
|
||||
NVMATH_API void robustOrthonormalize(float epsilon = NV_EPSILON);
|
||||
NVMATH_API void buildFrameForDirection(Vector3::Arg d);
|
||||
|
||||
/// Calculate the determinant [ F G N ] to obtain the handness of the basis.
|
||||
float handness() const
|
||||
{
|
||||
return determinant() > 0.0f ? 1.0f : -1.0f;
|
||||
}
|
||||
|
||||
/// Build a basis from 2 vectors and a handness flag.
|
||||
void build(Vector3::Arg n, Vector3::Arg t, float sign)
|
||||
{
|
||||
normal = n;
|
||||
tangent = t;
|
||||
bitangent = sign * cross(t, n);
|
||||
}
|
||||
|
||||
/// Compute the determinant of this basis.
|
||||
float determinant() const
|
||||
{
|
||||
return
|
||||
tangent.x() * bitangent.y() * normal.z() - tangent.z() * bitangent.y() * normal.x() +
|
||||
tangent.y() * bitangent.z() * normal.x() - tangent.y() * bitangent.x() * normal.z() +
|
||||
tangent.z() * bitangent.x() * normal.y() - tangent.x() * bitangent.z() * normal.y();
|
||||
}
|
||||
|
||||
/*
|
||||
// Get transform matrix for this basis.
|
||||
NVMATH_API Matrix matrix() const;
|
||||
|
||||
// Transform by this basis. (From this basis to object space).
|
||||
NVMATH_API Vector3 transform(Vector3::Arg v) const;
|
||||
|
||||
// Transform by the transpose. (From object space to this basis).
|
||||
NVMATH_API Vector3 transformT(Vector3::Arg v);
|
||||
|
||||
// Transform by the inverse. (From object space to this basis).
|
||||
NVMATH_API Vector3 transformI(Vector3::Arg v) const;
|
||||
*/
|
||||
|
||||
Vector3 tangent;
|
||||
Vector3 bitangent;
|
||||
Vector3 normal;
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_MATH_BASIS_H
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#ifndef NV_MATH_BASIS_H
|
||||
#define NV_MATH_BASIS_H
|
||||
|
||||
#include <nvmath/nvmath.h>
|
||||
#include <nvmath/Vector.h>
|
||||
#include <nvmath/Matrix.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
|
||||
/// Basis class to compute tangent space basis, ortogonalizations and to
|
||||
/// transform vectors from one space to another.
|
||||
struct Basis
|
||||
{
|
||||
/// Create a null basis.
|
||||
Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
|
||||
|
||||
/// Create a basis given three vectors.
|
||||
Basis(Vector3::Arg n, Vector3::Arg t, Vector3::Arg b) : tangent(t), bitangent(b), normal(n) {}
|
||||
|
||||
/// Create a basis with the given tangent vectors and the handness.
|
||||
Basis(Vector3::Arg n, Vector3::Arg t, float sign)
|
||||
{
|
||||
build(n, t, sign);
|
||||
}
|
||||
|
||||
NVMATH_API void normalize(float epsilon = NV_EPSILON);
|
||||
NVMATH_API void orthonormalize(float epsilon = NV_EPSILON);
|
||||
NVMATH_API void robustOrthonormalize(float epsilon = NV_EPSILON);
|
||||
NVMATH_API void buildFrameForDirection(Vector3::Arg d);
|
||||
|
||||
/// Calculate the determinant [ F G N ] to obtain the handness of the basis.
|
||||
float handness() const
|
||||
{
|
||||
return determinant() > 0.0f ? 1.0f : -1.0f;
|
||||
}
|
||||
|
||||
/// Build a basis from 2 vectors and a handness flag.
|
||||
void build(Vector3::Arg n, Vector3::Arg t, float sign)
|
||||
{
|
||||
normal = n;
|
||||
tangent = t;
|
||||
bitangent = sign * cross(t, n);
|
||||
}
|
||||
|
||||
/// Compute the determinant of this basis.
|
||||
float determinant() const
|
||||
{
|
||||
return
|
||||
tangent.x() * bitangent.y() * normal.z() - tangent.z() * bitangent.y() * normal.x() +
|
||||
tangent.y() * bitangent.z() * normal.x() - tangent.y() * bitangent.x() * normal.z() +
|
||||
tangent.z() * bitangent.x() * normal.y() - tangent.x() * bitangent.z() * normal.y();
|
||||
}
|
||||
|
||||
/*
|
||||
// Get transform matrix for this basis.
|
||||
NVMATH_API Matrix matrix() const;
|
||||
|
||||
// Transform by this basis. (From this basis to object space).
|
||||
NVMATH_API Vector3 transform(Vector3::Arg v) const;
|
||||
|
||||
// Transform by the transpose. (From object space to this basis).
|
||||
NVMATH_API Vector3 transformT(Vector3::Arg v);
|
||||
|
||||
// Transform by the inverse. (From object space to this basis).
|
||||
NVMATH_API Vector3 transformI(Vector3::Arg v) const;
|
||||
*/
|
||||
|
||||
Vector3 tangent;
|
||||
Vector3 bitangent;
|
||||
Vector3 normal;
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_MATH_BASIS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,128 +1,128 @@
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#ifndef NV_MATH_QUATERNION_H
|
||||
#define NV_MATH_QUATERNION_H
|
||||
|
||||
#include <nvmath/nvmath.h>
|
||||
#include <nvmath/Vector.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
|
||||
class NVMATH_CLASS Quaternion
|
||||
{
|
||||
public:
|
||||
typedef Quaternion const & Arg;
|
||||
|
||||
Quaternion();
|
||||
explicit Quaternion(zero_t);
|
||||
Quaternion(float x, float y, float z, float w);
|
||||
Quaternion(Vector4::Arg v);
|
||||
|
||||
const Quaternion & operator=(Quaternion::Arg v);
|
||||
|
||||
scalar x() const;
|
||||
scalar y() const;
|
||||
scalar z() const;
|
||||
scalar w() const;
|
||||
|
||||
const Vector4 & asVector() const;
|
||||
Vector4 & asVector();
|
||||
|
||||
private:
|
||||
Vector4 q;
|
||||
};
|
||||
|
||||
inline Quaternion::Quaternion() {}
|
||||
inline Quaternion::Quaternion(zero_t) : q(zero) {}
|
||||
inline Quaternion::Quaternion(float x, float y, float z, float w) : q(x, y, z, w) {}
|
||||
inline Quaternion::Quaternion(Vector4::Arg v) : q(v) {}
|
||||
|
||||
inline const Quaternion & Quaternion::operator=(Quaternion::Arg v) { q = v.q; return *this; }
|
||||
|
||||
inline scalar Quaternion::x() const { return q.x(); }
|
||||
inline scalar Quaternion::y() const { return q.y(); }
|
||||
inline scalar Quaternion::z() const { return q.z(); }
|
||||
inline scalar Quaternion::w() const { return q.w(); }
|
||||
|
||||
inline const Vector4 & Quaternion::asVector() const { return q; }
|
||||
inline Vector4 & Quaternion::asVector() { return q; }
|
||||
|
||||
|
||||
inline Quaternion mul(Quaternion::Arg a, Quaternion::Arg b)
|
||||
{
|
||||
// @@ Efficient SIMD implementation?
|
||||
return Quaternion(
|
||||
+ a.x() * b.w() + a.y()*b.z() - a.z()*b.y() + a.w()*b.x(),
|
||||
- a.x() * b.z() + a.y()*b.w() + a.z()*b.x() + a.w()*b.y(),
|
||||
+ a.x() * b.y() - a.y()*b.x() + a.z()*b.w() + a.w()*b.z(),
|
||||
- a.x() * b.x() - a.y()*b.y() - a.z()*b.z() + a.w()*b.w());
|
||||
}
|
||||
|
||||
inline Quaternion scale(Quaternion::Arg q, float s)
|
||||
{
|
||||
return scale(q.asVector(), s);
|
||||
}
|
||||
inline Quaternion operator *(Quaternion::Arg q, float s)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
inline Quaternion operator *(float s, Quaternion::Arg q)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
|
||||
inline Quaternion scale(Quaternion::Arg q, Vector4::Arg s)
|
||||
{
|
||||
return scale(q.asVector(), s);
|
||||
}
|
||||
inline Quaternion operator *(Quaternion::Arg q, Vector4::Arg s)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
inline Quaternion operator *(Vector4::Arg s, Quaternion::Arg q)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
|
||||
inline Quaternion conjugate(Quaternion::Arg q)
|
||||
{
|
||||
return q * Vector4(-1, -1, -1, 1);
|
||||
}
|
||||
|
||||
inline float length(Quaternion::Arg q)
|
||||
{
|
||||
return length(q.asVector());
|
||||
}
|
||||
|
||||
inline bool isNormalized(Quaternion::Arg q, float epsilon = NV_NORMAL_EPSILON)
|
||||
{
|
||||
return equal(length(q), 1, epsilon);
|
||||
}
|
||||
|
||||
inline Quaternion normalize(Quaternion::Arg q, float epsilon = NV_EPSILON)
|
||||
{
|
||||
float l = length(q);
|
||||
nvDebugCheck(!isZero(l, epsilon));
|
||||
Quaternion n = scale(q, 1.0f / l);
|
||||
nvDebugCheck(isNormalized(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
inline Quaternion inverse(Quaternion::Arg q)
|
||||
{
|
||||
return conjugate(normalize(q));
|
||||
}
|
||||
|
||||
/// Create a rotation quaternion for @a angle alpha around normal vector @a v.
|
||||
inline Quaternion axisAngle(Vector3::Arg v, float alpha)
|
||||
{
|
||||
float s = sinf(alpha * 0.5f);
|
||||
float c = cosf(alpha * 0.5f);
|
||||
return Quaternion(Vector4(v * s, c));
|
||||
}
|
||||
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_MATH_QUATERNION_H
|
||||
// This code is in the public domain -- castanyo@yahoo.es
|
||||
|
||||
#ifndef NV_MATH_QUATERNION_H
|
||||
#define NV_MATH_QUATERNION_H
|
||||
|
||||
#include <nvmath/nvmath.h>
|
||||
#include <nvmath/Vector.h>
|
||||
|
||||
namespace nv
|
||||
{
|
||||
|
||||
class NVMATH_CLASS Quaternion
|
||||
{
|
||||
public:
|
||||
typedef Quaternion const & Arg;
|
||||
|
||||
Quaternion();
|
||||
explicit Quaternion(zero_t);
|
||||
Quaternion(float x, float y, float z, float w);
|
||||
Quaternion(Vector4::Arg v);
|
||||
|
||||
const Quaternion & operator=(Quaternion::Arg v);
|
||||
|
||||
scalar x() const;
|
||||
scalar y() const;
|
||||
scalar z() const;
|
||||
scalar w() const;
|
||||
|
||||
const Vector4 & asVector() const;
|
||||
Vector4 & asVector();
|
||||
|
||||
private:
|
||||
Vector4 q;
|
||||
};
|
||||
|
||||
inline Quaternion::Quaternion() {}
|
||||
inline Quaternion::Quaternion(zero_t) : q(zero) {}
|
||||
inline Quaternion::Quaternion(float x, float y, float z, float w) : q(x, y, z, w) {}
|
||||
inline Quaternion::Quaternion(Vector4::Arg v) : q(v) {}
|
||||
|
||||
inline const Quaternion & Quaternion::operator=(Quaternion::Arg v) { q = v.q; return *this; }
|
||||
|
||||
inline scalar Quaternion::x() const { return q.x(); }
|
||||
inline scalar Quaternion::y() const { return q.y(); }
|
||||
inline scalar Quaternion::z() const { return q.z(); }
|
||||
inline scalar Quaternion::w() const { return q.w(); }
|
||||
|
||||
inline const Vector4 & Quaternion::asVector() const { return q; }
|
||||
inline Vector4 & Quaternion::asVector() { return q; }
|
||||
|
||||
|
||||
inline Quaternion mul(Quaternion::Arg a, Quaternion::Arg b)
|
||||
{
|
||||
// @@ Efficient SIMD implementation?
|
||||
return Quaternion(
|
||||
+ a.x() * b.w() + a.y()*b.z() - a.z()*b.y() + a.w()*b.x(),
|
||||
- a.x() * b.z() + a.y()*b.w() + a.z()*b.x() + a.w()*b.y(),
|
||||
+ a.x() * b.y() - a.y()*b.x() + a.z()*b.w() + a.w()*b.z(),
|
||||
- a.x() * b.x() - a.y()*b.y() - a.z()*b.z() + a.w()*b.w());
|
||||
}
|
||||
|
||||
inline Quaternion scale(Quaternion::Arg q, float s)
|
||||
{
|
||||
return scale(q.asVector(), s);
|
||||
}
|
||||
inline Quaternion operator *(Quaternion::Arg q, float s)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
inline Quaternion operator *(float s, Quaternion::Arg q)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
|
||||
inline Quaternion scale(Quaternion::Arg q, Vector4::Arg s)
|
||||
{
|
||||
return scale(q.asVector(), s);
|
||||
}
|
||||
/*inline Quaternion operator *(Quaternion::Arg q, Vector4::Arg s)
|
||||
{
|
||||
return scale(q, s);
|
||||
}
|
||||
inline Quaternion operator *(Vector4::Arg s, Quaternion::Arg q)
|
||||
{
|
||||
return scale(q, s);
|
||||
}*/
|
||||
|
||||
inline Quaternion conjugate(Quaternion::Arg q)
|
||||
{
|
||||
return scale(q, Vector4(-1, -1, -1, 1));
|
||||
}
|
||||
|
||||
inline float length(Quaternion::Arg q)
|
||||
{
|
||||
return length(q.asVector());
|
||||
}
|
||||
|
||||
inline bool isNormalized(Quaternion::Arg q, float epsilon = NV_NORMAL_EPSILON)
|
||||
{
|
||||
return equal(length(q), 1, epsilon);
|
||||
}
|
||||
|
||||
inline Quaternion normalize(Quaternion::Arg q, float epsilon = NV_EPSILON)
|
||||
{
|
||||
float l = length(q);
|
||||
nvDebugCheck(!isZero(l, epsilon));
|
||||
Quaternion n = scale(q, 1.0f / l);
|
||||
nvDebugCheck(isNormalized(n));
|
||||
return n;
|
||||
}
|
||||
|
||||
inline Quaternion inverse(Quaternion::Arg q)
|
||||
{
|
||||
return conjugate(normalize(q));
|
||||
}
|
||||
|
||||
/// Create a rotation quaternion for @a angle alpha around normal vector @a v.
|
||||
inline Quaternion axisAngle(Vector3::Arg v, float alpha)
|
||||
{
|
||||
float s = sinf(alpha * 0.5f);
|
||||
float c = cosf(alpha * 0.5f);
|
||||
return Quaternion(Vector4(v * s, c));
|
||||
}
|
||||
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#endif // NV_MATH_QUATERNION_H
|
||||
|
Loading…
Reference in New Issue