Remove unused celmath files
parent
80d098f3c9
commit
dc2a506839
13
devguide.txt
13
devguide.txt
|
@ -106,18 +106,9 @@ File Overview
|
|||
Astronomical conversions and a Date class for converting from dd/mm/yyyy
|
||||
to Julian date.
|
||||
|
||||
* vecmath.h
|
||||
Templatized classes for Points, Vectors, and Matrices
|
||||
|
||||
* quaternion.h
|
||||
Templatized quaternion class
|
||||
|
||||
* vecgl.h
|
||||
A handful of template functions which make it easy to use types from
|
||||
vecmath.h with OpenGL
|
||||
|
||||
* aabox.h
|
||||
Axis-aligned bounding box class.
|
||||
Eigen with OpenGL
|
||||
|
||||
* glext.h
|
||||
* glext.cpp
|
||||
|
@ -162,7 +153,7 @@ a pointer to a star from the database.
|
|||
Stars
|
||||
-----
|
||||
Since there are so many stars in a star database, it's important that the
|
||||
size of the Star class be kept to a minimum. Thus, in order to avoid the
|
||||
size of the Star class be kept to a minimum. Thus, in order to avoid the
|
||||
4 byte vtable overhead Star is not a derived class, even though it might
|
||||
be somewhat useful to have a common base class for stars and planets. All
|
||||
stars have a unique catalog number, a position, a stellar class, and a
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
// vertexbuf.h
|
||||
//
|
||||
// Copyright (C) 2001, Chris Laurel
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#ifndef _VERTEXBUF_H_
|
||||
#define _VERTEXBUF_H_
|
||||
|
||||
#include <celutil/color.h>
|
||||
#include <celmath/vecmath.h>
|
||||
#include <celmath/aabox.h>
|
||||
|
||||
|
||||
class VertexBuffer
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
VertexNormal = 0x01,
|
||||
VertexColor = 0x02,
|
||||
VertexColor0 = 0x02,
|
||||
VertexColor1 = 0x04,
|
||||
TexCoord0 = 0x08,
|
||||
TexCoord1 = 0x10,
|
||||
};
|
||||
|
||||
class Vertex
|
||||
{
|
||||
public:
|
||||
Point3f point;
|
||||
Vec3f normal;
|
||||
Color color;
|
||||
Point2f texCoords[2];
|
||||
};
|
||||
|
||||
union VertexPart
|
||||
{
|
||||
float f;
|
||||
unsigned char c[4];
|
||||
};
|
||||
|
||||
public:
|
||||
VertexList(uint32_t _parts, uint32_t initialVertexPoolSize = 0);
|
||||
~VertexList();
|
||||
|
||||
void addVertex(const Vertex& v);
|
||||
|
||||
Color getDiffuseColor() const;
|
||||
void setDiffuseColor(Color);
|
||||
|
||||
void render();
|
||||
|
||||
AxisAlignedBox getBoundingBox() const;
|
||||
void transform(Vec3f translation, float scale);
|
||||
|
||||
private:
|
||||
uint32_t parts;
|
||||
uint32_t vertexSize;
|
||||
|
||||
uint32_t nVertices;
|
||||
uint32_t maxVertices;
|
||||
VertexPart* vertices;
|
||||
|
||||
Color diffuseColor;
|
||||
|
||||
AxisAlignedBox bbox;
|
||||
};
|
||||
|
||||
#endif // _VERTEXBUF_H_
|
|
@ -283,94 +283,3 @@ astro::PrecObliquity_P03(double T)
|
|||
|
||||
return prec;
|
||||
}
|
||||
|
||||
|
||||
#define TEST 0
|
||||
|
||||
#if TEST
|
||||
|
||||
#include <celmath/quaternion.h>
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
double step = 10.0;
|
||||
|
||||
for (int i = -100; i <= 100; i++)
|
||||
{
|
||||
// Get time in Julian centuries from J2000
|
||||
double T = (double) i * step / 100;
|
||||
|
||||
astro::EclipticPole ecl = astro::EclipticPrecession_P03LP(T);
|
||||
astro::EclipticPole eclP03 = astro::EclipticPrecession_P03(T);
|
||||
astro::EclipticAngles eclAnglesP03 = astro::EclipticPrecessionAngles_P03(T);
|
||||
|
||||
//clog << ecl.PA - eclP03.PA << ", " << ecl.QA - eclP03.QA << endl;
|
||||
ecl = eclP03;
|
||||
Vec3d v(0.0, 0.0, 0.0);
|
||||
v.x = ecl.PA * 2.0 * PI / 1296000;
|
||||
v.y = -ecl.QA * 2.0 * PI / 1296000;
|
||||
v.z = sqrt(1.0 - v.x * v.x - v.y * v.y);
|
||||
|
||||
Quatd eclRotation = Quatd::vecToVecRotation(Vec3d(0.0, 0.0, 1.0), v);
|
||||
Quatd eclRotation2 = Quatd::zrotation(-degToRad(eclAnglesP03.PiA / 3600.0)) *
|
||||
Quatd::xrotation(degToRad(eclAnglesP03.piA / 3600.0)) *
|
||||
Quatd::zrotation(degToRad(eclAnglesP03.PiA / 3600.0));
|
||||
Quatd eclRotation3;
|
||||
{
|
||||
// Calculate the angles pi and Pi from the ecliptic pole coordinates
|
||||
// P and Q:
|
||||
// P = sin(pi)*sin(Pi)
|
||||
// Q = sin(pi)*cos(Pi)
|
||||
double P = eclP03.PA * 2.0 * PI / 1296000;
|
||||
double Q = eclP03.QA * 2.0 * PI / 1296000;
|
||||
double piA = asin(sqrt(P * P + Q * Q));
|
||||
double PiA = atan2(P, Q);
|
||||
|
||||
// Calculate the rotation from the J2000 ecliptic to the ecliptic
|
||||
// of date.
|
||||
eclRotation3 = Quatd::zrotation(-PiA) *
|
||||
Quatd::xrotation(piA) *
|
||||
Quatd::zrotation(PiA);
|
||||
|
||||
piA = radToDeg(piA) * 3600;
|
||||
PiA = radToDeg(PiA) * 3600;
|
||||
clog << "Pi: " << PiA << ", " << eclAnglesP03.PiA << endl;
|
||||
clog << "pi: " << piA << ", " << eclAnglesP03.piA << endl;
|
||||
}
|
||||
|
||||
astro::PrecessionAngles prec = astro::PrecObliquity_P03LP(T);
|
||||
Quatd p03lpRot = Quatd::xrotation(degToRad(prec.epsA / 3600.0)) *
|
||||
Quatd::zrotation(-degToRad(prec.pA / 3600.0));
|
||||
p03lpRot = p03lpRot * ~eclRotation3;
|
||||
|
||||
astro::PrecessionAngles prec2 = astro::PrecObliquity_P03(T);
|
||||
//clog << prec.epsA - prec2.epsA << ", " << prec.pA - prec2.pA << endl;
|
||||
|
||||
astro::EquatorialPrecessionAngles precP03 = astro::EquatorialPrecessionAngles_P03(T);
|
||||
Quatd p03Rot = Quatd::zrotation(-degToRad(precP03.zA / 3600.0)) *
|
||||
Quatd::yrotation( degToRad(precP03.thetaA / 3600.0)) *
|
||||
Quatd::zrotation(-degToRad(precP03.zetaA / 3600.0));
|
||||
p03Rot = p03Rot * Quatd::xrotation(degToRad(eps0 / 3600.0));
|
||||
|
||||
Vec3d xaxis(0, 0, 1);
|
||||
Vec3d v0 = xaxis * p03lpRot.toMatrix3();
|
||||
Vec3d v1 = xaxis * p03Rot.toMatrix3();
|
||||
|
||||
// Show the angle between the J2000 ecliptic pole and the ecliptic
|
||||
// pole at T centuries from J2000
|
||||
double theta0 = acos(xaxis * v0);
|
||||
double theta1 = acos(xaxis * v1);
|
||||
|
||||
clog << T * 100 << ": "
|
||||
<< radToDeg(acos(v0 * v1)) * 3600 << ", "
|
||||
<< radToDeg(theta0) << ", "
|
||||
<< radToDeg(theta1) << ", "
|
||||
<< radToDeg(theta1 - theta0) * 3600
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
// aabox.h
|
||||
//
|
||||
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// Axis-aligned bounding box class
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#ifndef _AABOX_H_
|
||||
#define _AABOX_H_
|
||||
|
||||
#include <celmath/vecmath.h>
|
||||
|
||||
class AxisAlignedBox
|
||||
{
|
||||
public:
|
||||
inline AxisAlignedBox();
|
||||
AxisAlignedBox(Point3f _min, Point3f _max) :
|
||||
minimum(_min), maximum(_max) {};
|
||||
AxisAlignedBox(Point3f center) :
|
||||
minimum(center), maximum(center) {};
|
||||
|
||||
inline Point3f getMinimum() const;
|
||||
inline Point3f getMaximum() const;
|
||||
inline Point3f getCenter() const;
|
||||
inline Vec3f getExtents() const;
|
||||
|
||||
inline bool empty() const;
|
||||
inline bool contains(const Point3f&) const;
|
||||
|
||||
inline void include(const Point3f&);
|
||||
inline void include(const AxisAlignedBox&);
|
||||
|
||||
private:
|
||||
Point3f minimum;
|
||||
Point3f maximum;
|
||||
};
|
||||
|
||||
|
||||
AxisAlignedBox::AxisAlignedBox() :
|
||||
minimum(1.0e20f, 1.0e20f, 1.0e20f),
|
||||
maximum(-1.0e20f, -1.0e20f, -1.0e20f)
|
||||
{
|
||||
}
|
||||
|
||||
Point3f AxisAlignedBox::getMinimum() const
|
||||
{
|
||||
return minimum;
|
||||
}
|
||||
|
||||
Point3f AxisAlignedBox::getMaximum() const
|
||||
{
|
||||
return maximum;
|
||||
}
|
||||
|
||||
Point3f AxisAlignedBox::getCenter() const
|
||||
{
|
||||
return Point3f((minimum.x + maximum.x) * 0.5f,
|
||||
(minimum.y + maximum.y) * 0.5f,
|
||||
(minimum.z + maximum.z) * 0.5f);
|
||||
}
|
||||
|
||||
Vec3f AxisAlignedBox::getExtents() const
|
||||
{
|
||||
return maximum - minimum;
|
||||
}
|
||||
|
||||
bool AxisAlignedBox::empty() const
|
||||
{
|
||||
return maximum.x < minimum.x || maximum.y < minimum.y || maximum.z < minimum.z;
|
||||
}
|
||||
|
||||
bool AxisAlignedBox::contains(const Point3f& p) const
|
||||
{
|
||||
return (p.x >= minimum.x && p.x <= maximum.x &&
|
||||
p.y >= minimum.y && p.y <= maximum.y &&
|
||||
p.z >= minimum.z && p.z <= maximum.z);
|
||||
}
|
||||
|
||||
|
||||
void AxisAlignedBox::include(const Point3f& p)
|
||||
{
|
||||
if (p.x < minimum.x) minimum.x = p.x;
|
||||
if (p.x > maximum.x) maximum.x = p.x;
|
||||
if (p.y < minimum.y) minimum.y = p.y;
|
||||
if (p.y > maximum.y) maximum.y = p.y;
|
||||
if (p.z < minimum.z) minimum.z = p.z;
|
||||
if (p.z > maximum.z) maximum.z = p.z;
|
||||
}
|
||||
|
||||
void AxisAlignedBox::include(const AxisAlignedBox& b)
|
||||
{
|
||||
if (b.minimum.x < minimum.x) minimum.x = b.minimum.x;
|
||||
if (b.maximum.x > maximum.x) maximum.x = b.maximum.x;
|
||||
if (b.minimum.y < minimum.y) minimum.y = b.minimum.y;
|
||||
if (b.maximum.y > maximum.y) maximum.y = b.maximum.y;
|
||||
if (b.minimum.z < minimum.z) minimum.z = b.minimum.z;
|
||||
if (b.maximum.z > maximum.z) maximum.z = b.maximum.z;
|
||||
}
|
||||
|
||||
#if 0
|
||||
AxisAlignedBox union(const AxisAlignedBox& a, const AxisAlignedBox& b)
|
||||
{
|
||||
AxisAlignedBox box(a);
|
||||
box.union(b);
|
||||
return box;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _AABOX_H_
|
|
@ -1,57 +0,0 @@
|
|||
// capsule.h
|
||||
//
|
||||
// Implementation of a capsule bounding volume. A capsule is a sphere
|
||||
// swept along a line, parameterized in this class as a starting point,
|
||||
// an axis, and a radius.
|
||||
//
|
||||
// Copyright (C) 2007, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#ifndef _CELMATH_CAPSULE_H_
|
||||
#define _CELMATH_CAPSULE_H_
|
||||
|
||||
#include "vecmath.h"
|
||||
|
||||
template<class T> class Capsule
|
||||
{
|
||||
public:
|
||||
Capsule();
|
||||
Capsule(const Vector3<T>& _axis, T _radius);
|
||||
Capsule(const Point3<T>& _origin, const Vector3<T>& _axis, T _radius);
|
||||
|
||||
public:
|
||||
Point3<T> origin;
|
||||
Vector3<T> axis;
|
||||
T radius;
|
||||
};
|
||||
|
||||
typedef Capsule<float> Capsulef;
|
||||
typedef Capsule<double> Capsuled;
|
||||
|
||||
|
||||
template<class T> Capsule<T>::Capsule() :
|
||||
origin(0, 0, 0), axis(0, 0, 0), radius(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<class T> Capsule<T>::Capsule(const Vector3<T>& _axis,
|
||||
T _radius) :
|
||||
origin(0, 0, 0), axis(_axis), radius(_radius)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<class T> Capsule<T>::Capsule(const Point3<T>& _origin,
|
||||
const Vector3<T>& _axis,
|
||||
T _radius) :
|
||||
origin(_origin), axis(_axis), radius(_radius)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // _CELMATH_CAPSULE_H_
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
// plane.h
|
||||
//
|
||||
// Copyright (C) 2000-2008, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#ifndef _CELMATH_PLANE_H_
|
||||
#define _CELMATH_PLANE_H_
|
||||
|
||||
#include <celmath/mathlib.h>
|
||||
#include <celmath/vecmath.h>
|
||||
|
||||
|
||||
template<class T> class Plane
|
||||
{
|
||||
public:
|
||||
inline Plane();
|
||||
inline Plane(const Plane<T>&);
|
||||
inline Plane(const Vector3<T>&, T);
|
||||
inline Plane(const Vector3<T>&, const Point3<T>&);
|
||||
|
||||
T distanceTo(const Point3<T>&) const;
|
||||
T distanceToSegment(const Point3<T>&, const Vector3<T>&) const;
|
||||
|
||||
static Point3<T> intersection(const Plane<T>&,
|
||||
const Plane<T>&,
|
||||
const Plane<T>&);
|
||||
|
||||
public:
|
||||
Vector3<T> normal;
|
||||
T d;
|
||||
};
|
||||
|
||||
|
||||
typedef Plane<float> Planef;
|
||||
typedef Plane<double> Planed;
|
||||
|
||||
|
||||
template<class T> Plane<T>::Plane() : normal(0, 0, 1), d(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Plane<T>::Plane(const Plane<T>& p) :
|
||||
normal(p.normal), d(p.d)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Plane<T>::Plane(const Vector3<T>& _normal, T _d) :
|
||||
normal(_normal), d(_d)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Plane<T>::Plane(const Vector3<T>& _normal, const Point3<T>& _point) :
|
||||
normal(_normal)
|
||||
{
|
||||
d = _normal.x * _point.x + _normal.y * _point.y + _normal.z * _point.z;
|
||||
}
|
||||
|
||||
template<class T> T Plane<T>::distanceTo(const Point3<T>& p) const
|
||||
{
|
||||
return normal.x * p.x + normal.y * p.y + normal.z * p.z + d;
|
||||
}
|
||||
|
||||
// Distance between a plane and a segment defined by orig+dir*t, t <= 0 <= 1
|
||||
template<class T> T Plane<T>::distanceToSegment(const Point3<T>& origin,
|
||||
const Vector3<T>& direction) const
|
||||
{
|
||||
T u = (direction * normal);
|
||||
T dist;
|
||||
|
||||
// Avoid divide by zero; near-zero values shouldn't cause problems
|
||||
if (u == 0)
|
||||
{
|
||||
// All points equidistant; we can just compute distance to origin
|
||||
dist = distanceTo(origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
T t = -(d + Vector3<T>(origin.x, origin.y, origin.z) * normal) / u;
|
||||
if (t < 0)
|
||||
{
|
||||
dist = distanceTo(origin);
|
||||
}
|
||||
else if (t > 1)
|
||||
{
|
||||
dist = distanceTo(origin + direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Segment intersects plane
|
||||
dist = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
|
||||
template<class T> Plane<T> operator*(const Matrix3<T>& m, const Plane<T>& p)
|
||||
{
|
||||
Vector3<T> v = m * p.normal;
|
||||
return Plane<T>(v, p.d);
|
||||
}
|
||||
|
||||
template<class T> Plane<T> operator*(const Plane<T>& p, const Matrix3<T>& m)
|
||||
{
|
||||
Vector3<T> v = p.normal * m;
|
||||
return Plane<T>(v, p.d);
|
||||
}
|
||||
|
||||
template<class T> Plane<T> operator*(const Matrix4<T>& m, const Plane<T>& p)
|
||||
{
|
||||
Vector4<T> v = m * Vector4<T>(p.normal.x, p.normal.y, p.normal.z, p.d);
|
||||
return Plane<T>(Vector3<T>(v.x, v.y, v.z), v.w);
|
||||
}
|
||||
|
||||
template<class T> Plane<T> operator*(const Plane<T>& p, const Matrix4<T>& m)
|
||||
{
|
||||
Vector4<T> v = Vector4<T>(p.normal.x, p.normal.y, p.normal.z, p.d) * m;
|
||||
return Plane<T>(Vector3<T>(v.x, v.y, v.z), v.w);
|
||||
}
|
||||
|
||||
template<class T> Point3<T> Plane<T>::intersection(const Plane<T>& p0,
|
||||
const Plane<T>& p1,
|
||||
const Plane<T>& p2)
|
||||
{
|
||||
T d = Matrix3<T>(p0.normal, p1.normal, p2.normal).determinant();
|
||||
|
||||
Vector3<T> v = (p0.d * cross(p1.normal, p2.normal) +
|
||||
p1.d * cross(p2.normal, p0.normal) +
|
||||
p2.d * cross(p0.normal, p1.normal)) * (1.0f / d);
|
||||
return Point3<T>(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
#endif // _CELMATH_PLANE_H_
|
|
@ -1,755 +0,0 @@
|
|||
// quaternion.h
|
||||
//
|
||||
// Copyright (C) 2000-2006, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// Template-ized quaternion math library.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
#ifndef _QUATERNION_H_
|
||||
#define _QUATERNION_H_
|
||||
|
||||
#include <limits>
|
||||
#include <celmath/mathlib.h>
|
||||
#include <celmath/vecmath.h>
|
||||
|
||||
|
||||
template<class T> class Quat
|
||||
{
|
||||
public:
|
||||
inline Quat();
|
||||
inline Quat(const Quat<T>&);
|
||||
inline Quat(T);
|
||||
inline Quat(const Vector3<T>&);
|
||||
inline Quat(T, const Vector3<T>&);
|
||||
inline Quat(T, T, T, T);
|
||||
|
||||
inline Quat(const Matrix3<T>&);
|
||||
|
||||
inline Quat& operator+=(Quat);
|
||||
inline Quat& operator-=(Quat);
|
||||
inline Quat& operator*=(T);
|
||||
Quat& operator*=(Quat);
|
||||
|
||||
inline Quat operator~() const; // conjugate
|
||||
inline Quat operator-() const;
|
||||
inline Quat operator+() const;
|
||||
|
||||
void setAxisAngle(Vector3<T> axis, T angle);
|
||||
|
||||
void getAxisAngle(Vector3<T>& axis, T& angle) const;
|
||||
Matrix4<T> toMatrix4() const;
|
||||
Matrix3<T> toMatrix3() const;
|
||||
|
||||
static Quat<T> slerp(const Quat<T>&, const Quat<T>&, T);
|
||||
static Quat<T> vecToVecRotation(const Vector3<T>& v0,
|
||||
const Vector3<T>& v1);
|
||||
static Quat<T> matrixToQuaternion(const Matrix3<T>& m);
|
||||
|
||||
void rotate(Vector3<T> axis, T angle);
|
||||
void xrotate(T angle);
|
||||
void yrotate(T angle);
|
||||
void zrotate(T angle);
|
||||
|
||||
bool isPure() const;
|
||||
bool isReal() const;
|
||||
T normalize();
|
||||
|
||||
static Quat<T> xrotation(T);
|
||||
static Quat<T> yrotation(T);
|
||||
static Quat<T> zrotation(T);
|
||||
|
||||
static Quat<T> lookAt(const Point3<T>& from, const Point3<T>& to, const Vector3<T>& up);
|
||||
|
||||
T w, x, y, z;
|
||||
};
|
||||
|
||||
|
||||
typedef Quat<float> Quatf;
|
||||
typedef Quat<double> Quatd;
|
||||
|
||||
|
||||
template<class T> Quat<T>::Quat() : w(0), x(0), y(0), z(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Quat<T>::Quat(const Quat<T>& q) :
|
||||
w(q.w), x(q.x), y(q.y), z(q.z)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Quat<T>::Quat(T re) :
|
||||
w(re), x(0), y(0), z(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Create a 'pure' quaternion
|
||||
template<class T> Quat<T>::Quat(const Vector3<T>& im) :
|
||||
w(0), x(im.x), y(im.y), z(im.z)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Quat<T>::Quat(T re, const Vector3<T>& im) :
|
||||
w(re), x(im.x), y(im.y), z(im.z)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> Quat<T>::Quat(T _w, T _x, T _y, T _z) :
|
||||
w(_w), x(_x), y(_y), z(_z)
|
||||
{
|
||||
}
|
||||
|
||||
// Create a quaternion from a rotation matrix
|
||||
// TODO: purge this from code--it is replaced by the matrixToQuaternion()
|
||||
// function.
|
||||
template<class T> Quat<T>::Quat(const Matrix3<T>& m)
|
||||
{
|
||||
T trace = m[0][0] + m[1][1] + m[2][2];
|
||||
T root;
|
||||
|
||||
if (trace >= (T) -1.0 + 1.0e-4f)
|
||||
{
|
||||
root = (T) sqrt(trace + 1);
|
||||
w = (T) 0.5 * root;
|
||||
root = (T) 0.5 / root;
|
||||
x = (m[2][1] - m[1][2]) * root;
|
||||
y = (m[0][2] - m[2][0]) * root;
|
||||
z = (m[1][0] - m[0][1]) * root;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Identify the largest element of the diagonal
|
||||
int i = 0;
|
||||
if (m[1][1] > m[i][i])
|
||||
i = 1;
|
||||
if (m[2][2] > m[i][i])
|
||||
i = 2;
|
||||
int j = (i == 2) ? 0 : i + 1;
|
||||
int k = (j == 2) ? 0 : j + 1;
|
||||
|
||||
root = (T) sqrt(m[i][i] - m[j][j] - m[k][k] + 1);
|
||||
T* xyz[3] = { &x, &y, &z };
|
||||
*xyz[i] = (T) 0.5 * root;
|
||||
root = (T) 0.5 / root;
|
||||
w = (m[k][j] - m[j][k]) * root;
|
||||
*xyz[j] = (m[j][i] + m[i][j]) * root;
|
||||
*xyz[k] = (m[k][i] + m[i][k]) * root;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> Quat<T>& Quat<T>::operator+=(Quat<T> a)
|
||||
{
|
||||
x += a.x; y += a.y; z += a.z; w += a.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> Quat<T>& Quat<T>::operator-=(Quat<T> a)
|
||||
{
|
||||
x -= a.x; y -= a.y; z -= a.z; w -= a.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> Quat<T>& Quat<T>::operator*=(Quat<T> q)
|
||||
{
|
||||
*this = Quat<T>(w * q.w - x * q.x - y * q.y - z * q.z,
|
||||
w * q.x + x * q.w + y * q.z - z * q.y,
|
||||
w * q.y + y * q.w + z * q.x - x * q.z,
|
||||
w * q.z + z * q.w + x * q.y - y * q.x);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> Quat<T>& Quat<T>::operator*=(T s)
|
||||
{
|
||||
x *= s; y *= s; z *= s; w *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// conjugate operator
|
||||
template<class T> Quat<T> Quat<T>::operator~() const
|
||||
{
|
||||
return Quat<T>(w, -x, -y, -z);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> Quat<T>::operator-() const
|
||||
{
|
||||
return Quat<T>(-w, -x, -y, -z);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> Quat<T>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T> Quat<T> operator+(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return Quat<T>(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> operator-(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return Quat<T>(a.w - b.w, a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> operator*(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return Quat<T>(a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
|
||||
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
|
||||
a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z,
|
||||
a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> operator*(T s, Quat<T> q)
|
||||
{
|
||||
return Quat<T>(s * q.w, s * q.x, s * q.y, s * q.z);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> operator*(Quat<T> q, T s)
|
||||
{
|
||||
return Quat<T>(s * q.w, s * q.x, s * q.y, s * q.z);
|
||||
}
|
||||
|
||||
// equivalent to multiplying by the quaternion (0, v)
|
||||
template<class T> Quat<T> operator*(Vector3<T> v, Quat<T> q)
|
||||
{
|
||||
return Quat<T>(-v.x * q.x - v.y * q.y - v.z * q.z,
|
||||
v.x * q.w + v.y * q.z - v.z * q.y,
|
||||
v.y * q.w + v.z * q.x - v.x * q.z,
|
||||
v.z * q.w + v.x * q.y - v.y * q.x);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> operator/(Quat<T> q, T s)
|
||||
{
|
||||
return q * (1 / s);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> operator/(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return a * (~b / abs(b));
|
||||
}
|
||||
|
||||
|
||||
template<class T> bool operator==(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
|
||||
}
|
||||
|
||||
template<class T> bool operator!=(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w;
|
||||
}
|
||||
|
||||
|
||||
// elementary functions
|
||||
template<class T> Quat<T> conjugate(Quat<T> q)
|
||||
{
|
||||
return Quat<T>(q.w, -q.x, -q.y, -q.z);
|
||||
}
|
||||
|
||||
template<class T> T norm(Quat<T> q)
|
||||
{
|
||||
return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
|
||||
}
|
||||
|
||||
template<class T> T abs(Quat<T> q)
|
||||
{
|
||||
return (T) sqrt(norm(q));
|
||||
}
|
||||
|
||||
template<class T> Quat<T> exp(Quat<T> q)
|
||||
{
|
||||
if (q.isReal())
|
||||
{
|
||||
return Quat<T>((T) exp(q.w));
|
||||
}
|
||||
else
|
||||
{
|
||||
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
|
||||
T s = (T) sin(l);
|
||||
T c = (T) cos(l);
|
||||
T e = (T) exp(q.w);
|
||||
T t = e * s / l;
|
||||
return Quat<T>(e * c, t * q.x, t * q.y, t * q.z);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> Quat<T> log(Quat<T> q)
|
||||
{
|
||||
if (q.isReal())
|
||||
{
|
||||
if (q.w > 0)
|
||||
{
|
||||
return Quat<T>((T) log(q.w));
|
||||
}
|
||||
else if (q.w < 0)
|
||||
{
|
||||
// The log of a negative purely real quaternion has
|
||||
// infinitely many values, all of the form (ln(-w), PI * I),
|
||||
// where I is any unit vector. We arbitrarily choose an I
|
||||
// of (1, 0, 0) here and whereever else a similar choice is
|
||||
// necessary. Geometrically, the set of roots is a sphere
|
||||
// of radius PI centered at ln(-w) on the real axis.
|
||||
return Quat<T>((T) log(-q.w), (T) PI, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// error . . . ln(0) not defined
|
||||
return Quat<T>(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
|
||||
T r = (T) sqrt(l * l + q.w * q.w);
|
||||
T theta = (T) atan2(l, q.w);
|
||||
T t = theta / l;
|
||||
return Quat<T>((T) log(r), t * q.x, t * q.y, t * q.z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T> Quat<T> pow(Quat<T> q, T s)
|
||||
{
|
||||
return exp(s * log(q));
|
||||
}
|
||||
|
||||
|
||||
template<class T> Quat<T> pow(Quat<T> q, Quat<T> p)
|
||||
{
|
||||
return exp(p * log(q));
|
||||
}
|
||||
|
||||
|
||||
template<class T> Quat<T> sin(Quat<T> q)
|
||||
{
|
||||
if (q.isReal())
|
||||
{
|
||||
return Quat<T>((T) sin(q.w));
|
||||
}
|
||||
else
|
||||
{
|
||||
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
|
||||
T m = q.w;
|
||||
T s = (T) sin(m);
|
||||
T c = (T) cos(m);
|
||||
T il = 1 / l;
|
||||
T e0 = (T) exp(-l);
|
||||
T e1 = (T) exp(l);
|
||||
|
||||
T c0 = (T) -0.5 * e0 * il * c;
|
||||
T c1 = (T) 0.5 * e1 * il * c;
|
||||
|
||||
return Quat<T>((T) 0.5 * e0 * s, c0 * q.x, c0 * q.y, c0 * q.z) +
|
||||
Quat<T>((T) 0.5 * e1 * s, c1 * q.x, c1 * q.y, c1 * q.z);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> Quat<T> cos(Quat<T> q)
|
||||
{
|
||||
if (q.isReal())
|
||||
{
|
||||
return Quat<T>((T) cos(q.w));
|
||||
}
|
||||
else
|
||||
{
|
||||
T l = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
|
||||
T m = q.w;
|
||||
T s = (T) sin(m);
|
||||
T c = (T) cos(m);
|
||||
T il = 1 / l;
|
||||
T e0 = (T) exp(-l);
|
||||
T e1 = (T) exp(l);
|
||||
|
||||
T c0 = (T) 0.5 * e0 * il * s;
|
||||
T c1 = (T) -0.5 * e1 * il * s;
|
||||
|
||||
return Quat<T>((T) 0.5 * e0 * c, c0 * q.x, c0 * q.y, c0 * q.z) +
|
||||
Quat<T>((T) 0.5 * e1 * c, c1 * q.x, c1 * q.y, c1 * q.z);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> Quat<T> sqrt(Quat<T> q)
|
||||
{
|
||||
// In general, the square root of a quaternion has two values, one
|
||||
// of which is the negative of the other. However, any negative purely
|
||||
// real quaternion has an infinite number of square roots.
|
||||
// This function returns the positive root for positive reals and
|
||||
// the root on the positive i axis for negative reals.
|
||||
if (q.isReal())
|
||||
{
|
||||
if (q.w >= 0)
|
||||
return Quat<T>((T) sqrt(q.w), 0, 0, 0);
|
||||
else
|
||||
return Quat<T>(0, (T) sqrt(-q.w), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
T b = (T) sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
|
||||
T r = (T) sqrt(q.w * q.w + b * b);
|
||||
if (q.w >= 0)
|
||||
{
|
||||
T m = (T) sqrt((T) 0.5 * (r + q.w));
|
||||
T l = b / (2 * m);
|
||||
T t = l / b;
|
||||
return Quat<T>(m, q.x * t, q.y * t, q.z * t);
|
||||
}
|
||||
else
|
||||
{
|
||||
T l = (T) sqrt((T) 0.5 * (r - q.w));
|
||||
T m = b / (2 * l);
|
||||
T t = l / b;
|
||||
return Quat<T>(m, q.x * t, q.y * t, q.z * t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> T real(Quat<T> q)
|
||||
{
|
||||
return q.w;
|
||||
}
|
||||
|
||||
template<class T> Vector3<T> imag(Quat<T> q)
|
||||
{
|
||||
return Vector3<T>(q.x, q.y, q.z);
|
||||
}
|
||||
|
||||
|
||||
// Quat methods
|
||||
|
||||
template<class T> bool Quat<T>::isReal() const
|
||||
{
|
||||
return (x == 0 && y == 0 && z == 0);
|
||||
}
|
||||
|
||||
template<class T> bool Quat<T>::isPure() const
|
||||
{
|
||||
return w == 0;
|
||||
}
|
||||
|
||||
template<class T> T Quat<T>::normalize()
|
||||
{
|
||||
T s = (T) sqrt(w * w + x * x + y * y + z * z);
|
||||
T invs = (T) 1 / (T) s;
|
||||
x *= invs;
|
||||
y *= invs;
|
||||
z *= invs;
|
||||
w *= invs;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// Set to the unit quaternion representing an axis angle rotation. Assume
|
||||
// that axis is a unit vector
|
||||
template<class T> void Quat<T>::setAxisAngle(Vector3<T> axis, T angle)
|
||||
{
|
||||
T s, c;
|
||||
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
x = s * axis.x;
|
||||
y = s * axis.y;
|
||||
z = s * axis.z;
|
||||
w = c;
|
||||
}
|
||||
|
||||
|
||||
// Assuming that this a unit quaternion, return the in axis/angle form the
|
||||
// orientation which it represents.
|
||||
template<class T> void Quat<T>::getAxisAngle(Vector3<T>& axis,
|
||||
T& angle) const
|
||||
{
|
||||
// The quaternion has the form:
|
||||
// w = cos(angle/2), (x y z) = sin(angle/2)*axis
|
||||
|
||||
T magSquared = x * x + y * y + z * z;
|
||||
if (magSquared > (T) 1e-10)
|
||||
{
|
||||
T s = (T) 1 / (T) sqrt(magSquared);
|
||||
axis.x = x * s;
|
||||
axis.y = y * s;
|
||||
axis.z = z * s;
|
||||
if (w <= -1 || w >= 1)
|
||||
angle = 0;
|
||||
else
|
||||
angle = (T) acos(w) * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The angle is zero, so we pick an arbitrary unit axis
|
||||
axis.x = 1;
|
||||
axis.y = 0;
|
||||
axis.z = 0;
|
||||
angle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Convert this (assumed to be normalized) quaternion to a rotation matrix
|
||||
template<class T> Matrix4<T> Quat<T>::toMatrix4() const
|
||||
{
|
||||
T wx = w * x * 2;
|
||||
T wy = w * y * 2;
|
||||
T wz = w * z * 2;
|
||||
T xx = x * x * 2;
|
||||
T xy = x * y * 2;
|
||||
T xz = x * z * 2;
|
||||
T yy = y * y * 2;
|
||||
T yz = y * z * 2;
|
||||
T zz = z * z * 2;
|
||||
|
||||
return Matrix4<T>(Vector4<T>(1 - yy - zz, xy - wz, xz + wy, 0),
|
||||
Vector4<T>(xy + wz, 1 - xx - zz, yz - wx, 0),
|
||||
Vector4<T>(xz - wy, yz + wx, 1 - xx - yy, 0),
|
||||
Vector4<T>(0, 0, 0, 1));
|
||||
}
|
||||
|
||||
|
||||
// Convert this (assumed to be normalized) quaternion to a rotation matrix
|
||||
template<class T> Matrix3<T> Quat<T>::toMatrix3() const
|
||||
{
|
||||
T wx = w * x * 2;
|
||||
T wy = w * y * 2;
|
||||
T wz = w * z * 2;
|
||||
T xx = x * x * 2;
|
||||
T xy = x * y * 2;
|
||||
T xz = x * z * 2;
|
||||
T yy = y * y * 2;
|
||||
T yz = y * z * 2;
|
||||
T zz = z * z * 2;
|
||||
|
||||
return Matrix3<T>(Vector3<T>(1 - yy - zz, xy - wz, xz + wy),
|
||||
Vector3<T>(xy + wz, 1 - xx - zz, yz - wx),
|
||||
Vector3<T>(xz - wy, yz + wx, 1 - xx - yy));
|
||||
}
|
||||
|
||||
|
||||
template<class T> T dot(Quat<T> a, Quat<T> b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
}
|
||||
|
||||
|
||||
/*! Spherical linear interpolation of two unit quaternions. Designed for
|
||||
* interpolating rotations, so shortest path between rotations will be
|
||||
* taken.
|
||||
*/
|
||||
template<class T> Quat<T> Quat<T>::slerp(const Quat<T>& q0,
|
||||
const Quat<T>& q1,
|
||||
T t)
|
||||
{
|
||||
const double Nlerp_Threshold = 0.99999;
|
||||
|
||||
T cosAngle = dot(q0, q1);
|
||||
|
||||
// Assuming the quaternions representat rotations, ensure that we interpolate
|
||||
// through the shortest path by inverting one of the quaternions if the
|
||||
// angle between them is negative.
|
||||
Quat qstart;
|
||||
if (cosAngle < 0)
|
||||
{
|
||||
qstart = -q0;
|
||||
cosAngle = -cosAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
qstart = q0;
|
||||
}
|
||||
|
||||
// Avoid precision troubles when we're near the limit of acos range and
|
||||
// perform a linear interpolation followed by a normalize when interpolating
|
||||
// very small angles.
|
||||
if (cosAngle > (T) Nlerp_Threshold)
|
||||
{
|
||||
Quat<T> q = (1 - t) * qstart + t * q1;
|
||||
q.normalize();
|
||||
return q;
|
||||
}
|
||||
|
||||
// Below code unnecessary since we've already inverted cosAngle if it's negative.
|
||||
// It will be necessary if we change slerp to not assume that we want the shortest
|
||||
// path between two rotations.
|
||||
#if 0
|
||||
// Because of potential rounding errors, we must clamp c to the domain of acos.
|
||||
if (cosAngle < (T) -1.0)
|
||||
cosAngle = (T) -1.0;
|
||||
#endif
|
||||
|
||||
T angle = (T) acos(cosAngle);
|
||||
T interpolatedAngle = t * angle;
|
||||
|
||||
// qstart and q2 will form an orthonormal basis in the plane of interpolation.
|
||||
Quat q2 = q1 - qstart * cosAngle;
|
||||
q2.normalize();
|
||||
|
||||
return qstart * (T) cos(interpolatedAngle) + q2 * (T) sin(interpolatedAngle);
|
||||
#if 0
|
||||
T s = (T) sin(angle);
|
||||
T is = (T) 1.0 / s;
|
||||
|
||||
return q0 * ((T) sin((1 - t) * angle) * is) +
|
||||
q1 * ((T) sin(t * angle) * is);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*! Return a unit quaternion that representing a rotation that will
|
||||
* rotation v0 to v1 about the axis perpendicular to them both. If the
|
||||
* vectors point in opposite directions, there is no unique axis and
|
||||
* (arbitrarily) a rotation about the x axis will be chosen.
|
||||
*/
|
||||
template<class T> Quat<T> Quat<T>::vecToVecRotation(const Vector3<T>& v0,
|
||||
const Vector3<T>& v1)
|
||||
{
|
||||
// We need sine and cosine of half the angle between v0 and v1, so
|
||||
// compute the vector halfway between v0 and v1. The cross product of
|
||||
// half and v1 gives the imaginary part of the quaternion
|
||||
// (axis * sin(angle/2)), and the dot product of half and v1 gives
|
||||
// the real part.
|
||||
Vector3<T> half = (v0 + v1) * (T) 0.5;
|
||||
|
||||
T hl = half.length();
|
||||
if (hl > (T) 0.0)
|
||||
{
|
||||
half = half / hl; // normalize h
|
||||
|
||||
// The magnitude of rotAxis is the sine of half the angle between
|
||||
// v0 and v1.
|
||||
Vector3<T> rotAxis = half ^ v1;
|
||||
T cosAngle = half * v1;
|
||||
return Quat<T>(cosAngle, rotAxis.x, rotAxis.y, rotAxis.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The vectors point in exactly opposite directions, so there is
|
||||
// no unique axis of rotation. Rotating v0 180 degrees about any
|
||||
// axis will map it to v1; we'll choose the x-axis.
|
||||
return Quat<T>((T) 0.0, (T) 1.0, (T) 0.0, (T) 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Create a quaternion from a rotation matrix
|
||||
*/
|
||||
template<class T> Quat<T> Quat<T>::matrixToQuaternion(const Matrix3<T>& m)
|
||||
{
|
||||
Quat<T> q;
|
||||
T trace = m[0][0] + m[1][1] + m[2][2];
|
||||
T root;
|
||||
T epsilon = std::numeric_limits<T>::epsilon() * (T) 1e3;
|
||||
|
||||
if (trace >= epsilon - 1)
|
||||
{
|
||||
root = (T) sqrt(trace + 1);
|
||||
q.w = (T) 0.5 * root;
|
||||
root = (T) 0.5 / root;
|
||||
q.x = (m[2][1] - m[1][2]) * root;
|
||||
q.y = (m[0][2] - m[2][0]) * root;
|
||||
q.z = (m[1][0] - m[0][1]) * root;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set i to the largest element of the diagonal
|
||||
int i = 0;
|
||||
if (m[1][1] > m[i][i])
|
||||
i = 1;
|
||||
if (m[2][2] > m[i][i])
|
||||
i = 2;
|
||||
int j = (i == 2) ? 0 : i + 1;
|
||||
int k = (j == 2) ? 0 : j + 1;
|
||||
|
||||
root = (T) sqrt(m[i][i] - m[j][j] - m[k][k] + 1);
|
||||
T* xyz[3] = { &q.x, &q.y, &q.z };
|
||||
*xyz[i] = (T) 0.5 * root;
|
||||
root = (T) 0.5 / root;
|
||||
q.w = (m[k][j] - m[j][k]) * root;
|
||||
*xyz[j] = (m[j][i] + m[i][j]) * root;
|
||||
*xyz[k] = (m[k][i] + m[i][k]) * root;
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
/*! Assuming that this is a unit quaternion representing an orientation,
|
||||
* apply a rotation of angle radians about the specfied axis
|
||||
*/
|
||||
template<class T> void Quat<T>::rotate(Vector3<T> axis, T angle)
|
||||
{
|
||||
Quat q;
|
||||
q.setAxisAngle(axis, angle);
|
||||
*this = q * *this;
|
||||
}
|
||||
|
||||
|
||||
// Assuming that this is a unit quaternion representing an orientation,
|
||||
// apply a rotation of angle radians about the x-axis
|
||||
template<class T> void Quat<T>::xrotate(T angle)
|
||||
{
|
||||
T s, c;
|
||||
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
*this = Quat<T>(c, s, 0, 0) * *this;
|
||||
}
|
||||
|
||||
// Assuming that this is a unit quaternion representing an orientation,
|
||||
// apply a rotation of angle radians about the y-axis
|
||||
template<class T> void Quat<T>::yrotate(T angle)
|
||||
{
|
||||
T s, c;
|
||||
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
*this = Quat<T>(c, 0, s, 0) * *this;
|
||||
}
|
||||
|
||||
// Assuming that this is a unit quaternion representing an orientation,
|
||||
// apply a rotation of angle radians about the z-axis
|
||||
template<class T> void Quat<T>::zrotate(T angle)
|
||||
{
|
||||
T s, c;
|
||||
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
*this = Quat<T>(c, 0, 0, s) * *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T> Quat<T> Quat<T>::xrotation(T angle)
|
||||
{
|
||||
T s, c;
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
return Quat<T>(c, s, 0, 0);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> Quat<T>::yrotation(T angle)
|
||||
{
|
||||
T s, c;
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
return Quat<T>(c, 0, s, 0);
|
||||
}
|
||||
|
||||
template<class T> Quat<T> Quat<T>::zrotation(T angle)
|
||||
{
|
||||
T s, c;
|
||||
Math<T>::sincos(angle * (T) 0.5, s, c);
|
||||
return Quat<T>(c, 0, 0, s);
|
||||
}
|
||||
|
||||
/*! Determine an orientation that will make the negative z-axis point from
|
||||
* from the observer to the target, with the y-axis pointing in direction
|
||||
* of the component of 'up' that is orthogonal to the z-axis.
|
||||
*/
|
||||
template<class T> Quat<T>
|
||||
Quat<T>::lookAt(const Point3<T>& from, const Point3<T>& to, const Vector3<T>& up)
|
||||
{
|
||||
Vector3<T> n = to - from;
|
||||
n.normalize();
|
||||
Vector3<T> v = n ^ up;
|
||||
v.normalize();
|
||||
Vector3<T> u = v ^ n;
|
||||
|
||||
return Quat<T>::matrixToQuaternion(Matrix3<T>(v, u, -n));
|
||||
}
|
||||
|
||||
#endif // _QUATERNION_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,8 @@
|
|||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <celmath/vecmath.h>
|
||||
#include <Eigen/Core>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -103,8 +104,8 @@ inline float sampleBilinear(const float samples[],
|
|||
|
||||
// subdiv is the number of rows in the triangle
|
||||
void triangleSection(unsigned int subdiv,
|
||||
Vec3f v0, Vec3f v1, Vec3f v2,
|
||||
Vec2f tex0, Vec2f tex1, Vec2f tex2)
|
||||
Eigen::Vector3f v0, Eigen::Vector3f v1, Eigen::Vector3f v2,
|
||||
Eigen::Vector2f tex0, Eigen::Vector2f tex1, Eigen::Vector2f tex2)
|
||||
{
|
||||
float ssamp = (float) (longSamples - 1) + 0.99f;
|
||||
float tsamp = (float) (latSamples - 1) + 0.99f;
|
||||
|
@ -116,19 +117,19 @@ void triangleSection(unsigned int subdiv,
|
|||
float u = (i == 0) ? 0.0f : (float) j / (float) i;
|
||||
float v = (float) i / (float) subdiv;
|
||||
|
||||
Vec3f w0 = (1.0f - v) * v0 + v * v1;
|
||||
Vec3f w1 = (1.0f - v) * v0 + v * v2;
|
||||
Vec3f w = (1.0f - u) * w0 + u * w1;
|
||||
Eigen::Vector3f w0 = (1.0f - v) * v0 + v * v1;
|
||||
Eigen::Vector3f w1 = (1.0f - v) * v0 + v * v2;
|
||||
Eigen::Vector3f w = (1.0f - u) * w0 + u * w1;
|
||||
|
||||
Vec2f t((1.0f - u) * tex1.x + u * tex2.x,
|
||||
(1.0f - v) * tex0.y + v * tex1.y);
|
||||
Eigen::Vector2f t((1.0f - u) * tex1.x() + u * tex2.x(),
|
||||
(1.0f - v) * tex0.y() + v * tex1.y());
|
||||
|
||||
w.normalize();
|
||||
|
||||
if (samples != nullptr)
|
||||
{
|
||||
float theta = (float) acos(w.y);
|
||||
float phi = (float) atan2(-w.z, w.x);
|
||||
float theta = (float) acos(w.y());
|
||||
float phi = (float) atan2(-w.z(), w.x());
|
||||
float s = phi / (2.0f * pi) + 0.5f;
|
||||
float t = theta / pi;
|
||||
|
||||
|
@ -137,8 +138,8 @@ void triangleSection(unsigned int subdiv,
|
|||
w = w * r;
|
||||
}
|
||||
|
||||
cout << w.x << " " << w.y << " " << w.z << " "
|
||||
<< t.x << " " << t.y << "\n";
|
||||
cout << w.x() << " " << w.y() << " " << w.z() << " "
|
||||
<< t.x() << " " << t.y() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,62 +238,62 @@ int main(int argc, char* argv[])
|
|||
cout << "vertices " << vertexCount << "\n";
|
||||
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, 1.0f, 0.0f),
|
||||
Vec3f(1.0f, 0.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, -1.0f),
|
||||
Vec2f(0.0f, 0.0f),
|
||||
Vec2f(0.00f, 0.5f),
|
||||
Vec2f(0.25f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
|
||||
Eigen::Vector3f(1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, -1.0f),
|
||||
Eigen::Vector2f(0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.00f, 0.5f),
|
||||
Eigen::Vector2f(0.25f, 0.5f));
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, 1.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, 1.0f),
|
||||
Vec3f(1.0f, 0.0f, 0.0f),
|
||||
Vec2f(0.0f, 0.0f),
|
||||
Vec2f(0.75f, 0.5f),
|
||||
Vec2f(1.00f, 0.5f));;
|
||||
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, 1.0f),
|
||||
Eigen::Vector3f(1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.75f, 0.5f),
|
||||
Eigen::Vector2f(1.00f, 0.5f));;
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, 1.0f, 0.0f),
|
||||
Vec3f(-1.0f, 0.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, 1.0f),
|
||||
Vec2f(0.0f, 0.0f),
|
||||
Vec2f(0.50f, 0.5f),
|
||||
Vec2f(0.75f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
|
||||
Eigen::Vector3f(-1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, 1.0f),
|
||||
Eigen::Vector2f(0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.50f, 0.5f),
|
||||
Eigen::Vector2f(0.75f, 0.5f));
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, 1.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, -1.0f),
|
||||
Vec3f(-1.0f, 0.0f, 0.0f),
|
||||
Vec2f(0.0f, 0.0f),
|
||||
Vec2f(0.25f, 0.5f),
|
||||
Vec2f(0.50f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, 1.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, -1.0f),
|
||||
Eigen::Vector3f(-1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.25f, 0.5f),
|
||||
Eigen::Vector2f(0.50f, 0.5f));
|
||||
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, -1.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, -1.0f),
|
||||
Vec3f(1.0f, 0.0f, 0.0f),
|
||||
Vec2f(0.0f, 1.0f),
|
||||
Vec2f(0.25f, 0.5f),
|
||||
Vec2f(0.00f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, -1.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, -1.0f),
|
||||
Eigen::Vector3f(1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.0f, 1.0f),
|
||||
Eigen::Vector2f(0.25f, 0.5f),
|
||||
Eigen::Vector2f(0.00f, 0.5f));
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, -1.0f, 0.0f),
|
||||
Vec3f(1.0f, 0.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, 1.0f),
|
||||
Vec2f(0.0f, 1.0f),
|
||||
Vec2f(1.00f, 0.5f),
|
||||
Vec2f(0.75f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, -1.0f, 0.0f),
|
||||
Eigen::Vector3f(1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, 1.0f),
|
||||
Eigen::Vector2f(0.0f, 1.0f),
|
||||
Eigen::Vector2f(1.00f, 0.5f),
|
||||
Eigen::Vector2f(0.75f, 0.5f));
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, -1.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, 1.0f),
|
||||
Vec3f(-1.0f, 0.0f, 0.0f),
|
||||
Vec2f(0.0f, 1.0f),
|
||||
Vec2f(0.75f, 0.5f),
|
||||
Vec2f(0.50f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, -1.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, 1.0f),
|
||||
Eigen::Vector3f(-1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector2f(0.0f, 1.0f),
|
||||
Eigen::Vector2f(0.75f, 0.5f),
|
||||
Eigen::Vector2f(0.50f, 0.5f));
|
||||
triangleSection(subdiv,
|
||||
Vec3f(0.0f, -1.0f, 0.0f),
|
||||
Vec3f(-1.0f, 0.0f, 0.0f),
|
||||
Vec3f(0.0f, 0.0f, -1.0f),
|
||||
Vec2f(0.0f, 1.0f),
|
||||
Vec2f(0.50f, 0.5f),
|
||||
Vec2f(0.25f, 0.5f));
|
||||
Eigen::Vector3f(0.0f, -1.0f, 0.0f),
|
||||
Eigen::Vector3f(-1.0f, 0.0f, 0.0f),
|
||||
Eigen::Vector3f(0.0f, 0.0f, -1.0f),
|
||||
Eigen::Vector2f(0.0f, 1.0f),
|
||||
Eigen::Vector2f(0.50f, 0.5f),
|
||||
Eigen::Vector2f(0.25f, 0.5f));
|
||||
|
||||
cout << "trilist 0 " << triangleCount * 3 << "\n";
|
||||
|
||||
|
|
Loading…
Reference in New Issue