Merge internal branch.

2.0
castano 17 years ago
parent 18c452a2a6
commit 98b2377a11

@ -17,6 +17,7 @@ SET(CORE_SRCS
TextReader.h
TextReader.cpp
TextWriter.h
TextWriter.cpp
Tokenizer.h
Tokenizer.cpp
Radix.h

@ -23,12 +23,6 @@ Do not use memmove in insert & remove, use copy ctors instead.
#include <string.h> // memmove
#include <new> // for placement new
#ifndef USE_TU_CONTAINERS
#define USE_TU_CONTAINERS 1
#endif
#if USE_TU_CONTAINERS
#if NV_CC_GNUC // If typeof is available:
@ -57,7 +51,7 @@ struct PseudoIndexWrapper {
return *reinterpret_cast<const typename T::PseudoIndex *>(memory);
}
uint8 memory[8]; // Increase the size if we have bigger enumerators.
uint8 memory[4]; // Increase the size if we have bigger enumerators.
};
#define NV_FOREACH(i, container) \
@ -70,7 +64,6 @@ struct PseudoIndexWrapper {
# define foreach NV_FOREACH
#endif
#endif // USE_TU_CONTAINERS
namespace nv
@ -193,7 +186,6 @@ namespace nv
virtual T current();
};
#if USE_TU_CONTAINERS
/**
* Replacement for std::vector that is easier to debug and provides
@ -1060,8 +1052,8 @@ namespace nv
};
#endif // USE_TU_CONTAINERS
} // nv namespace
#endif // NV_CORE_CONTAINER_H

@ -314,7 +314,12 @@ public:
{
return m_s->isError();
}
virtual void clearError()
{
m_s->clearError();
}
virtual bool isAtEnd() const
{
return m_s->isAtEnd();

@ -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);
}

@ -7,9 +7,6 @@
#include <nvcore/Stream.h>
#include <nvcore/StrLib.h>
// @@ NOT IMPLEMENTED !!!
namespace nv
{
@ -18,16 +15,12 @@ namespace nv
{
public:
/// Ctor.
TextWriter(Stream * s) : s(s), str(1024) {
nvDebugCheck(s != NULL);
nvCheck(s->IsSaving());
}
void write( const char * str, uint len );
void write( const char * format, ... ) __attribute__((format (printf, 2, 3)));
void write( const char * format, va_list arg );
TextWriter(Stream * s);
void writeString(const char * str);
void writeString(const char * str, uint len);
void write(const char * format, ...) __attribute__((format (printf, 2, 3)));
void write(const char * format, va_list arg);
private:
@ -38,7 +31,35 @@ namespace nv
};
inline TextWriter & operator<<( TextWriter & tw, int i)
{
tw.write("%d", i);
return tw;
}
inline TextWriter & operator<<( TextWriter & tw, uint i)
{
tw.write("%u", i);
return tw;
}
inline TextWriter & operator<<( TextWriter & tw, float f)
{
tw.write("%f", f);
return tw;
}
inline TextWriter & operator<<( TextWriter & tw, const char * str)
{
tw.writeString(str);
return tw;
}
} // nv namespace
#endif // NVCORE_TEXTWRITER_H

@ -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

@ -13,7 +13,7 @@
/********************************************************/
#include <nvmath/Vector.h>
//#include <nvmath/Triangle.h>
#include <nvmath/Triangle.h>
using namespace nv;
@ -96,7 +96,7 @@ static bool planeBoxOverlap(Vector3::Arg normal, Vector3::Arg vert, Vector3::Arg
if(min>rad || max<-rad) return false;
bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * triverts)
bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & tri)
{
// use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions:
@ -111,9 +111,9 @@ bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vecto
// This is the fastest branch on Sun.
// move everything so that the boxcenter is in (0,0,0)
v0 = triverts[0] - boxcenter;
v1 = triverts[1] - boxcenter;
v2 = triverts[2] - boxcenter;
v0 = tri.v[0] - boxcenter;
v1 = tri.v[1] - boxcenter;
v2 = tri.v[2] - boxcenter;
// Compute triangle edges.
e0 = v1 - v0; // tri edge 0
@ -170,7 +170,7 @@ bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vecto
}
bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * triverts)
bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & tri)
{
// use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions:
@ -185,9 +185,9 @@ bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, con
// This is the fastest branch on Sun.
// move everything so that the boxcenter is in (0,0,0)
v0 = triverts[0] - boxcenter;
v1 = triverts[1] - boxcenter;
v2 = triverts[2] - boxcenter;
v0 = tri.v[0] - boxcenter;
v1 = tri.v[1] - boxcenter;
v2 = tri.v[2] - boxcenter;
// Compute triangle edges.
e0 = v1 - v0; // tri edge 0

@ -6,26 +6,23 @@ using namespace nv;
/// Tomas Möller, barycentric ray-triangle test.
bool Triangle::TestRay_Moller(Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v)
bool rayTest_Moller(const Triangle & t, Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v)
{
Vector3 e1, e2, tvec, pvec, qvec;
float det, inv_det;
// find vectors for two edges sharing vert0
e1 = v[1] - v[0];
e2 = v[2] - v[0];
Vector3 e1 = t.v[1] - t.v[0];
Vector3 e2 = t.v[2] - t.v[0];
// begin calculating determinant - also used to calculate U parameter
pvec = cross(dir, e2);
Vector3 pvec = cross(dir, e2);
// if determinant is near zero, ray lies in plane of triangle
det = dot(e1, pvec);
float det = dot(e1, pvec);
if (det < -NV_EPSILON) {
return false;
}
// calculate distance from vert0 to ray origin
tvec = orig - v[0];
Vector3 tvec = orig - t.v[0];
// calculate U parameter and test bounds
float u = dot(tvec, pvec);
@ -34,7 +31,7 @@ bool Triangle::TestRay_Moller(Vector3::Arg orig, Vector3::Arg dir, float * out_t
}
// prepare to test V parameter
qvec = cross(tvec, e1);
Vector3 qvec = cross(tvec, e1);
// calculate V parameter and test bounds
float v = dot(dir, qvec);
@ -43,7 +40,7 @@ bool Triangle::TestRay_Moller(Vector3::Arg orig, Vector3::Arg dir, float * out_t
}
// calculate t, scale parameters, ray intersects triangle
inv_det = 1.0f / det;
float inv_det = 1.0f / det;
*out_t = dot(e2, qvec) * inv_det;
*out_u = u * inv_det; // v
*out_v = v * inv_det; // 1-(u+v)

@ -3,146 +3,78 @@
#ifndef NV_MATH_TRIANGLE_H
#define NV_MATH_TRIANGLE_H
#include <nvmath/nvmath.h>
#include <nvmath/Vector.h>
#include <nvmath/Box.h>
//#include <nvmath/Plane.h>
namespace nv
{
// Tomas Akenine-Möller box-triangle test.
NVMATH_API bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * restrict triverts);
NVMATH_API bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Vector3 * restrict triverts);
/// Triangle class with three vertices.
class Triangle
{
public:
Triangle() {};
Triangle(const Vector3 & v0, const Vector3 & v1, const Vector3 & v2)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
/// Get the bounds of the triangle.
Box bounds() const {
Box bounds;
bounds.clearBounds();
bounds.addPointToBounds(v[0]);
bounds.addPointToBounds(v[1]);
bounds.addPointToBounds(v[2]);
return bounds;
}
/*
/// Get barycentric coordinates of the given point in this triangle.
Vector3 barycentricCoordinates(Vector3::Arg p)
/// Triangle class with three vertices.
class Triangle
{
Vector3 bar;
// p must lie in the triangle plane.
Plane plane;
plane.set(v[0], v[1], v[2]);
nvCheck( equalf(plane.Distance(p), 0.0f) );
Vector3 n;
// Compute signed area of triangle <v0, v1, p>
n = cross(v[1] - v[0], p - v[0]);
bar.x = length(n);
if (dot(n, plane.vector) < 0) {
bar->x = -bar->x;
public:
Triangle() {};
Triangle(Vector3::Arg v0, Vector3::Arg v1, Vector3::Arg v2)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
}
// Compute signed area of triangle <v1, v2, p>
n = cross(v[2] - v[1], p - v[1]);
bar->y = length(cross(e, d));
if (dot(n, plane.vector) < 0) {
bar->y = -bar->y;
/// Get the bounds of the triangle.
Box bounds() const
{
Box bounds;
bounds.clearBounds();
bounds.addPointToBounds(v[0]);
bounds.addPointToBounds(v[1]);
bounds.addPointToBounds(v[2]);
return bounds;
}
// Compute signed area of triangle <v2, v0, p>
n = cross(v[0] - v[2], p - v[2]);
bar->z = length(n);
if (dot(n, plane.vector) < 0) {
bar->z = -bar->z;
Vector4 plane() const
{
Vector3 n = cross(v[1]-v[0], v[2]-v[0]);
return Vector4(n, dot(n, v[0]));
}
// We cannot just do this because we need the signed areas.
// bar->x = Vector3Area(e0, d0);
// bar->y = Vector3Area(e1, d1);
// bar->z = Vector3Area(e2, d2);
// bar->x = Vector3TripleProduct(v[1], v[2], p);
// bar->y = Vector3TripleProduct(v[2], v[0], p);
// bar->z = Vector3TripleProduct(v[0], v[1], p);
}
*/
// Moller ray triangle test.
bool TestRay_Moller(const Vector3 & orig, const Vector3 & dir, float * out_t, float * out_u, float * out_v);
Vector3 v[3];
};
Vector3 v[3];
};
// Tomas Akenine-Möller box-triangle test.
NVMATH_API bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & triangle);
NVMATH_API bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & triangle);
#if 0
/** A planar triangle. */
class Triangle2 {
public:
// Moller ray triangle test.
NVMATH_API bool rayTest_Moller(const Triangle & t, Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v);
Triangle2() {};
Triangle2(const Vec2 & v0, const Vec2 & v1, const Vec2 & v2) {
v[0] = v0;
v[1] = v1;
v[2] = v2;
inline bool rayTest(const Triangle & t, Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v)
{
rayTest_Moller(t, orig, dir, out_t, out_u, out_v);
}
/** Get the barycentric coordinates of the given point for this triangle.
* http://stevehollasch.com/cgindex/math/barycentric.html
*/
void GetBarycentricCoordinates(const Vec2 & p, Vector3 * bar) const {
float denom = 1.0f / (v[1].x - v[0].x) * (v[2].y - v[0].y) - (v[2].x - v[0].x) * (v[1].y - v[0].y);
bar->x = ((v[1].x - p.x) * (v[2].y - p.y) - (v[2].x - p.x) * (v[1].y - p.y)) * denom;
bar->y = ((v[2].x - p.x) * (v[0].y - p.y) - (v[0].x - p.x) * (v[2].y - p.y)) * denom;
//bar->z = ((v[0].x - p.x) * (v[1].y - p.y) - (v[1].x - p.x) * (v[0].y - p.y)) * denom;
bar->z = 1 - bar->x - bar->y;
inline bool overlap(const Triangle & t, const Box & b)
{
Vector3 center = b.center();
Vector3 extents = b.extents();
return triBoxOverlap(center, extents, t);
}
inline bool overlap(const Box & b, const Triangle & t)
{
return overlap(t, b);
}
Vec2 v[3];
};
#endif // 0
inline bool overlap(const Triangle & t, const Box & b)
{
Vector3 center = b.center();
Vector3 extents = b.extents();
return triBoxOverlap(center, extents, t.v);
}
inline bool Overlap(const Box & b, const Triangle & t)
{
return overlap(t, b);
}
inline bool overlapNoBounds(const Triangle & t, const Box & b)
{
Vector3 center = b.center();
Vector3 extents = b.extents();
return triBoxOverlapNoBounds(center, extents, t.v);
}
inline bool overlapNoBounds(const Triangle & t, const Box & b)
{
Vector3 center = b.center();
Vector3 extents = b.extents();
return triBoxOverlapNoBounds(center, extents, t);
}
} // nv namespace

Loading…
Cancel
Save