librw/tests/gl/math.cpp

1228 lines
19 KiB
C++
Raw Normal View History

2015-01-17 20:51:04 +00:00
#include "math/math.h"
/*
* Vec3
*/
std::ostream&
operator<<(std::ostream& of, const Vec3 &v)
{
v.print(of);
return of;
}
Vec3::Vec3(void)
: x(0.0f), y(0.0f), z(0.0f)
{
}
Vec3::Vec3(float x, float y, float z)
: x(x), y(y), z(z)
{
}
Vec3::Vec3(float *v)
: x(v[0]), y(v[1]), z(v[2])
{
}
float*
Vec3::ptr(void)
{
return &x;
}
Vec3
Vec3::operator-(void) const
{
return Vec3(-x, -y, -z);
}
Vec3
Vec3::operator+(const Vec3 &rhs) const
{
return Vec3(this->x+rhs.x, this->y+rhs.y, this->z+rhs.z);
}
Vec3
Vec3::operator-(const Vec3 &rhs) const
{
return Vec3(this->x-rhs.x, this->y-rhs.y, this->z-rhs.z);
}
Vec3
Vec3::operator*(float rhs) const
{
return Vec3(this->x*rhs, this->y*rhs, this->z*rhs);
}
Vec3
Vec3::operator/(float rhs) const
{
return Vec3(this->x/rhs, this->y/rhs, this->z/rhs);
}
Vec3&
Vec3::operator+=(const Vec3 &rhs)
{
*this = *this + rhs;
return *this;
}
Vec3&
Vec3::operator-=(const Vec3 &rhs)
{
*this = *this - rhs;
return *this;
}
Vec3&
Vec3::operator*=(float rhs)
{
*this = *this * rhs;
return *this;
}
Vec3&
Vec3::operator/=(float rhs)
{
*this = *this / rhs;
return *this;
}
bool
Vec3::operator==(const Vec3 &rhs) const
{
return (this->x == rhs.x) &&
(this->y == rhs.y) &&
(this->z == rhs.z);
}
bool
Vec3::operator!=(const Vec3 &rhs) const
{
return (this->x != rhs.x) ||
(this->y != rhs.y) ||
(this->z != rhs.z);
}
float
Vec3::norm(void) const
{
return sqrt(normsq());
}
float
Vec3::normsq(void) const
{
return x*x + y*y + z*z;
}
Vec3
Vec3::normalized(void) const
{
return Vec3(*this)/norm();
}
float
Vec3::dot(const Vec3 &rhs) const
{
return this->x*rhs.x + this->y*rhs.y + this->z*rhs.z;
}
Vec3
Vec3::cross(const Vec3 &rhs) const
{
return Vec3(this->y*rhs.z - this->z*rhs.y,
this->z*rhs.x - this->x*rhs.z,
this->x*rhs.y - this->y*rhs.x);
}
void
Vec3::print(std::ostream &of) const
{
of << "V3(" << x << ", " << y << ", " << z << ")";
}
/*
* Vec4
*/
std::ostream&
operator<<(std::ostream& of, const Vec4 &v)
{
v.print(of);
return of;
}
Vec4::Vec4(void)
: x(0.0f), y(0.0f), z(0.0f), w(0.0f)
{
}
Vec4::Vec4(float x, float y, float z, float w)
: x(x), y(y), z(z), w(w)
{
}
Vec4::Vec4(float *v)
: x(v[0]), y(v[1]), z(v[2]), w(v[3])
{
}
float*
Vec4::ptr(void)
{
return &x;
}
Vec4
Vec4::operator-(void) const
{
return Vec4(-x, -y, -z, -w);
}
Vec4
Vec4::operator+(const Vec4 &rhs) const
{
return Vec4(this->x+rhs.x, this->y+rhs.y, this->z+rhs.z, this->w+rhs.w);
}
Vec4
Vec4::operator-(const Vec4 &rhs) const
{
return Vec4(this->x-rhs.x, this->y-rhs.y, this->z-rhs.z, this->w-rhs.w);
}
Vec4
Vec4::operator*(float rhs) const
{
return Vec4(this->x*rhs, this->y*rhs, this->z*rhs, this->w*rhs);
}
Vec4
Vec4::operator/(float rhs) const
{
return Vec4(this->x/rhs, this->y/rhs, this->z/rhs, this->w/rhs);
}
Vec4&
Vec4::operator+=(const Vec4 &rhs)
{
*this = *this + rhs;
return *this;
}
Vec4&
Vec4::operator-=(const Vec4 &rhs)
{
*this = *this - rhs;
return *this;
}
Vec4&
Vec4::operator*=(float rhs)
{
*this = *this * rhs;
return *this;
}
Vec4&
Vec4::operator/=(float rhs)
{
*this = *this / rhs;
return *this;
}
bool
Vec4::operator==(const Vec4 &rhs) const
{
return (this->x == rhs.x) &&
(this->y == rhs.y) &&
(this->z == rhs.z) &&
(this->w == rhs.w);
}
bool
Vec4::operator!=(const Vec4 &rhs) const
{
return (this->x != rhs.x) ||
(this->y != rhs.y) ||
(this->z != rhs.z) ||
(this->w != rhs.w);
}
float
Vec4::norm(void) const
{
return sqrt(normsq());
}
float
Vec4::normsq(void) const
{
return x*x + y*y + z*z + w*w;
}
Vec4
Vec4::normalized(void) const
{
return Vec4(*this)/norm();
}
float
Vec4::dot(const Vec4 &rhs) const
{
return this->x*rhs.x + this->y*rhs.y + this->z*rhs.z + this->w*rhs.w;
}
void
Vec4::print(std::ostream &of) const
{
of << "V4(" << x << ", " << y << ", " << z << ", " << w << ")";
}
/*
* Quat
*/
std::ostream&
operator<<(std::ostream& of, const Quat &v)
{
v.print(of);
return of;
}
Quat::Quat(void)
: w(0.0f), x(0.0f), y(0.0f), z(0.0f)
{
}
Quat::Quat(float w)
: w(w), x(0.0f), y(0.0f), z(0.0f)
{
}
Quat::Quat(float x, float y, float z)
: w(0.0f), x(x), y(y), z(z)
{
}
Quat::Quat(float w, float x, float y, float z)
: w(w), x(x), y(y), z(z)
{
}
float*
Quat::ptr(void)
{
return &w;
}
Quat
Quat::operator-(void) const
{
return Quat(-w, -x, -y, -z);
}
Quat
Quat::operator+(const Quat &rhs) const
{
return Quat(this->w+rhs.w, this->x+rhs.x, this->y+rhs.y, this->z+rhs.z);
}
Quat
Quat::operator-(const Quat &rhs) const
{
return Quat(this->w-rhs.w, this->x-rhs.x, this->y-rhs.y, this->z-rhs.z);
}
Quat
Quat::operator*(const Quat &rhs) const
{
return Quat(
this->w*rhs.w - this->x*rhs.x - this->y*rhs.y - this->z*rhs.z,
this->w*rhs.x + this->x*rhs.w + this->y*rhs.z - this->z*rhs.y,
this->w*rhs.y + this->y*rhs.w + this->z*rhs.x - this->x*rhs.z,
this->w*rhs.z + this->z*rhs.w + this->x*rhs.y - this->y*rhs.x);
}
Quat
Quat::operator*(float rhs) const
{
return Quat(this->w*rhs, this->x*rhs, this->y*rhs, this->z*rhs);
}
Quat
Quat::operator/(float rhs) const
{
return Quat(this->w/rhs, this->x/rhs, this->y/rhs, this->z/rhs);
}
Quat&
Quat::operator+=(const Quat &rhs)
{
*this = *this + rhs;
return *this;
}
Quat&
Quat::operator-=(const Quat &rhs)
{
*this = *this - rhs;
return *this;
}
Quat&
Quat::operator*=(const Quat &rhs)
{
*this = *this * rhs;
return *this;
}
Quat&
Quat::operator*=(float rhs)
{
*this = *this * rhs;
return *this;
}
Quat&
Quat::operator/=(float rhs)
{
*this = *this / rhs;
return *this;
}
bool
Quat::operator==(const Quat &rhs) const
{
return (this->w == rhs.w) &&
(this->x == rhs.x) &&
(this->y == rhs.y) &&
(this->z == rhs.z);
}
bool
Quat::operator!=(const Quat &rhs) const
{
return (this->w != rhs.w) ||
(this->x != rhs.x) ||
(this->y != rhs.y) ||
(this->z != rhs.z);
}
Quat
Quat::inv(void) const
{
return K() / N();
}
Quat
Quat::K(void) const
{
return Quat(w, -x, -y, -z);
}
Quat
Quat::S(void) const
{
return Quat(w);
}
Quat
Quat::V(void) const
{
return Quat(x, y, z);
}
float
Quat::T(void) const
{
return sqrt(N());
}
float
Quat::N(void) const
{
return w*w + x*x + y*y + z*z;
}
Quat
Quat::U(void) const
{
return Quat(*this)/T();
}
Quat
Quat::wedge(const Quat &rhs) const
{
return Quat(0.0f,
this->y*rhs.z - this->z*rhs.y,
this->z*rhs.x - this->x*rhs.z,
this->x*rhs.y - this->y*rhs.x);
}
float
Quat::inner(const Quat &rhs) const
{
return this->w*rhs.w + this->x*rhs.x + this->y*rhs.y + this->z*rhs.z;
}
Quat
Quat::lerp(const Quat &q2, float t) const
{
Quat q1 = *this;
float cos = q1.inner(q2);
if(cos < 0)
q1 = -q1;
return (q1*(1.0f - t) + q2*t).U();
}
Quat
Quat::slerp(const Quat &q2, float t) const
{
Quat q1 = *this;
float cos = q1.inner(q2);
if(cos < 0){
cos = -cos;
q1 = -q1;
}
float phi = acos(cos);
if(phi > 0.00001){
float s = sin(phi);
q1 = q1*sin((1.0f-t)*phi)/s + q2*sin(t*phi)/s;
}
return q1;
}
void
Quat::print(std::ostream &of) const
{
of << "Q(" << w << ", " << x << ", " << y << ", " << z << ")";
}
/*
* Quat
*/
std::ostream&
operator<<(std::ostream& of, const DQuat &v)
{
v.print(of);
return of;
}
DQuat::DQuat(void)
: q1(), q2()
{
}
DQuat::DQuat(const Quat &q1, const Quat &q2)
: q1(q1), q2(q2)
{
}
DQuat
DQuat::operator-(void) const
{
return DQuat(-q1, -q2);
}
DQuat
DQuat::operator+(const DQuat &rhs) const
{
return DQuat(this->q1+rhs.q1, this->q2+rhs.q2);
}
DQuat
DQuat::operator-(const DQuat &rhs) const
{
return DQuat(this->q1-rhs.q1, this->q2-rhs.q2);
}
DQuat
DQuat::operator*(const DQuat &rhs) const
{
return DQuat(this->q1*rhs.q1, this->q1*rhs.q2 + this->q2*rhs.q1);
}
DQuat
DQuat::operator*(float rhs) const
{
return DQuat(this->q1*rhs, this->q2*rhs);
}
DQuat
DQuat::operator/(float rhs) const
{
return DQuat(this->q1/rhs, this->q2/rhs);
}
DQuat&
DQuat::operator+=(const DQuat &rhs)
{
*this = *this + rhs;
return *this;
}
DQuat&
DQuat::operator-=(const DQuat &rhs)
{
*this = *this - rhs;
return *this;
}
DQuat&
DQuat::operator*=(const DQuat &rhs)
{
*this = *this * rhs;
return *this;
}
DQuat&
DQuat::operator*=(float rhs)
{
*this = *this * rhs;
return *this;
}
DQuat&
DQuat::operator/=(float rhs)
{
*this = *this / rhs;
return *this;
}
bool
DQuat::operator==(const DQuat &rhs) const
{
return (this->q1 == rhs.q1) &&
(this->q2 == rhs.q2);
}
bool
DQuat::operator!=(const DQuat &rhs) const
{
return (this->q1 != rhs.q1) ||
(this->q2 != rhs.q2);
}
DQuat
DQuat::K(void) const
{
return DQuat(q1.K(), -q2.K());
}
void
DQuat::print(std::ostream &of) const
{
of << "DQ(" << q1 << ", " << q2 << ")";
}
/*
* Mat3
*/
std::ostream&
operator<<(std::ostream& of, const Mat3 &v)
{
v.print(of);
return of;
}
Mat3::Mat3(void)
{
for(int i = 0; i < 3*3; i++)
cr[i] = 0.0f;
}
Mat3::Mat3(float f)
{
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
e[i][j] = (i == j) ? f : 0.0f;
}
Mat3::Mat3(float *f)
{
for(int i = 0; i < 3*3; i++)
cr[i] = f[i];
}
Mat3::Mat3(float e00, float e10, float e20,
float e01, float e11, float e21,
float e02, float e12, float e22)
{
e[0][0] = e00; e[1][0] = e10; e[2][0] = e20;
e[0][1] = e01; e[1][1] = e11; e[2][1] = e21;
e[0][2] = e02; e[1][2] = e12; e[2][2] = e22;
}
float*
Mat3::ptr(void)
{
return &e[0][0];
}
Mat3
Mat3::rotation(float theta, const Vec3 &v)
{
Mat3 m(1.0f);
float c = cos(theta);
float s = sin(theta);
m.e[0][0] = v.x*v.x*(1-c) + c;
m.e[1][0] = v.x*v.y*(1-c) - v.z*s;
m.e[2][0] = v.x*v.z*(1-c) + v.y*s;
m.e[0][1] = v.y*v.x*(1-c) + v.z*s;
m.e[1][1] = v.y*v.y*(1-c) + c;
m.e[2][1] = v.y*v.z*(1-c) - v.x*s;
m.e[0][2] = v.z*v.x*(1-c) - v.y*s;
m.e[1][2] = v.z*v.y*(1-c) + v.x*s;
m.e[2][2] = v.z*v.z*(1-c) + c;
return m;
}
Mat3
Mat3::scale(const Vec3 &v)
{
Mat3 m(1.0f);
m.e[0][0] = v.x;
m.e[1][1] = v.y;
m.e[2][2] = v.z;
return m;
}
Mat3
Mat3::transpose(void) const
{
float e[3][3];
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++){
e[j][i] = this->e[i][j];
e[i][j] = this->e[j][i];
}
return Mat3(&e[0][0]);
}
Mat3
Mat3::operator+(const Mat3 &rhs) const
{
float e[9];
for(int i = 0; i < 3*3; i++)
e[i] = this->cr[i] + rhs.cr[i];
return Mat3(e);
}
Mat3
Mat3::operator-(const Mat3 &rhs) const
{
float e[9];
for(int i = 0; i < 3*3; i++)
e[i] = this->cr[i] - rhs.cr[i];
return Mat3(e);
}
Mat3
Mat3::operator*(float rhs) const
{
float e[9];
for(int i = 0; i < 3*3; i++)
e[i] = this->cr[i]*rhs;
return Mat3(e);
}
Mat3
Mat3::operator/(float rhs) const
{
float e[9];
for(int i = 0; i < 3*3; i++)
e[i] = this->cr[i]/rhs;
return Mat3(e);
}
Mat3
Mat3::operator*(const Mat3 &rhs) const
{
float e[3][3];
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
e[i][j] = this->e[0][j]*rhs.e[i][0] +
this->e[1][j]*rhs.e[i][1] +
this->e[2][j]*rhs.e[i][2];
return Mat3(&e[0][0]);
}
Vec3
Mat3::operator*(const Vec3 &rhs) const
{
float e[3];
for(int i = 0; i < 3; i++)
e[i] = this->e[0][i]*rhs.x +
this->e[1][i]*rhs.y +
this->e[2][i]*rhs.z;
return Vec3(e);
}
Mat3&
Mat3::operator+=(const Mat3 &rhs)
{
*this = *this + rhs;
return *this;
}
Mat3&
Mat3::operator-=(const Mat3 &rhs)
{
*this = *this - rhs;
return *this;
}
Mat3&
Mat3::operator*=(float rhs)
{
*this = *this * rhs;
return *this;
}
Mat3&
Mat3::operator/=(float rhs)
{
*this = *this / rhs;
return *this;
}
Mat3&
Mat3::operator*=(const Mat3 &rhs)
{
*this = *this * rhs;
return *this;
}
void
Mat3::print(std::ostream &of) const
{
#define CM << ", " <<
of << "M3(" << e[0][0] CM e[1][0] CM e[2][0] << std::endl;
of << " " << e[0][1] CM e[1][1] CM e[2][1] << std::endl;
of << " " << e[0][2] CM e[1][2] CM e[2][2] << ")";
#undef CM
}
/*
* Mat3
*/
std::ostream&
operator<<(std::ostream& of, const Mat4 &v)
{
v.print(of);
return of;
}
Mat4::Mat4(void)
{
for(int i = 0; i < 4*4; i++)
cr[i] = 0.0f;
}
Mat4::Mat4(float f)
{
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
e[i][j] = (i == j) ? f : 0.0f;
}
Mat4::Mat4(float *f)
{
for(int i = 0; i < 4*4; i++)
cr[i] = f[i];
}
Mat4::Mat4(float e00, float e10, float e20, float e30,
float e01, float e11, float e21, float e31,
float e02, float e12, float e22, float e32,
float e03, float e13, float e23, float e33)
{
e[0][0] = e00; e[1][0] = e10; e[2][0] = e20; e[3][0] = e30;
e[0][1] = e01; e[1][1] = e11; e[2][1] = e21; e[3][1] = e31;
e[0][2] = e02; e[1][2] = e12; e[2][2] = e22; e[3][2] = e32;
e[0][3] = e03; e[1][3] = e13; e[2][3] = e23; e[3][3] = e33;
}
float*
Mat4::ptr(void)
{
return &e[0][0];
}
Mat4
Mat4::perspective(float fov, float aspect, float n, float f)
{
float r = n*tan(fov*3.14159f/360.0f);
float t = r/aspect;
return frustum(-r, r, -t, t, n, f);
}
Mat4
Mat4::frustum(float l, float r, float b, float t,
float n, float f)
{
Mat4 m(1.0f);
m.e[0][0] = (2.0f*n)/(r-l);
m.e[1][1] = (2.0f*n)/(t-b);
m.e[2][0] = (r+l)/(r-l);
m.e[2][1] = (t+b)/(t-b);
m.e[2][2] = -(f+n)/(f-n);
m.e[2][3] = -1.0f;
m.e[3][2] = -2.0f*f*n/(f-n);
m.e[3][3] = 0.0f;
return m;
}
Mat4
Mat4::ortho(float l, float r, float b, float t,
float n, float f)
{
Mat4 m(1.0f);
m.e[0][0] = 2.0f/(r-l);
m.e[3][0] = -(r+l)/(r-l);
m.e[1][1] = 2.0f/(t-b);
m.e[3][1] = -(t+b)/(t-b);
m.e[2][2] = -2.0f/(f-n);
m.e[3][2] = -(f+n)/(f-n);
return m;
}
Mat4
Mat4::lookat(const Vec3 &pos, const Vec3 &target, const Vec3 &up)
{
Vec3 forward = (target - pos).normalized();
Vec3 side = forward.cross(up).normalized();
Vec3 nup = side.cross(forward);
Mat4 m(1.0f);
m.e[0][0] = side.x;
m.e[1][0] = side.y;
m.e[2][0] = side.z;
m.e[0][1] = nup.x;
m.e[1][1] = nup.y;
m.e[2][1] = nup.z;
m.e[0][2] = -forward.x;
m.e[1][2] = -forward.y;
m.e[2][2] = -forward.z;
return m*Mat4::translation(-pos);
}
Mat4
Mat4::translation(const Vec3 &v)
{
Mat4 m(1.0f);
m.e[3][0] = v.x;
m.e[3][1] = v.y;
m.e[3][2] = v.z;
return m;
}
Mat4
Mat4::rotation(float theta, const Vec3 &v)
{
Mat4 m(1.0f);
float c = cos(theta);
float s = sin(theta);
m.e[0][0] = v.x*v.x*(1-c) + c;
m.e[1][0] = v.x*v.y*(1-c) - v.z*s;
m.e[2][0] = v.x*v.z*(1-c) + v.y*s;
m.e[0][1] = v.y*v.x*(1-c) + v.z*s;
m.e[1][1] = v.y*v.y*(1-c) + c;
m.e[2][1] = v.y*v.z*(1-c) - v.x*s;
m.e[0][2] = v.z*v.x*(1-c) - v.y*s;
m.e[1][2] = v.z*v.y*(1-c) + v.x*s;
m.e[2][2] = v.z*v.z*(1-c) + c;
return m;
}
Mat4
Mat4::scale(const Vec3 &v)
{
Mat4 m(1.0f);
m.e[0][0] = v.x;
m.e[1][1] = v.y;
m.e[2][2] = v.z;
return m;
}
Mat4
Mat4::transpose(void) const
{
float e[4][4];
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++){
e[j][i] = this->e[i][j];
e[i][j] = this->e[j][i];
}
return Mat4(&e[0][0]);
}
Mat4
Mat4::operator+(const Mat4 &rhs) const
{
float e[16];
for(int i = 0; i < 4*4; i++)
e[i] = this->cr[i] + rhs.cr[i];
return Mat4(e);
}
Mat4
Mat4::operator-(const Mat4 &rhs) const
{
float e[16];
for(int i = 0; i < 4*4; i++)
e[i] = this->cr[i] - rhs.cr[i];
return Mat4(e);
}
Mat4
Mat4::operator*(float rhs) const
{
float e[16];
for(int i = 0; i < 4*4; i++)
e[i] = this->cr[i]*rhs;
return Mat4(e);
}
Mat4
Mat4::operator/(float rhs) const
{
float e[16];
for(int i = 0; i < 4*4; i++)
e[i] = this->cr[i]/rhs;
return Mat4(e);
}
Mat4
Mat4::operator*(const Mat4 &rhs) const
{
float e[4][4];
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
e[i][j] = this->e[0][j]*rhs.e[i][0] +
this->e[1][j]*rhs.e[i][1] +
this->e[2][j]*rhs.e[i][2] +
this->e[3][j]*rhs.e[i][3];
return Mat4(&e[0][0]);
}
Vec4
Mat4::operator*(const Vec4 &rhs) const
{
float e[4];
for(int i = 0; i < 4; i++)
e[i] = this->e[0][i]*rhs.x +
this->e[1][i]*rhs.y +
this->e[2][i]*rhs.z +
this->e[3][i]*rhs.w;
return Vec4(e);
}
Mat4&
Mat4::operator+=(const Mat4 &rhs)
{
*this = *this + rhs;
return *this;
}
Mat4&
Mat4::operator-=(const Mat4 &rhs)
{
*this = *this - rhs;
return *this;
}
Mat4&
Mat4::operator*=(float rhs)
{
*this = *this * rhs;
return *this;
}
Mat4&
Mat4::operator/=(float rhs)
{
*this = *this / rhs;
return *this;
}
Mat4&
Mat4::operator*=(const Mat4 &rhs)
{
*this = *this * rhs;
return *this;
}
void
Mat4::print(std::ostream &of) const
{
#define CM << ", " <<
of << "M4(" << e[0][0] CM e[1][0] CM e[2][0] CM e[3][0] << std::endl;
of << " " << e[0][1] CM e[1][1] CM e[2][1] CM e[3][1] << std::endl;
of << " " << e[0][2] CM e[1][2] CM e[2][2] CM e[3][2] << std::endl;
of << " " << e[0][3] CM e[1][3] CM e[2][3] CM e[3][3] << ")";
#undef CM
}
Vec3::Vec3(const Vec4 &v)
: x(v.x), y(v.y), z(v.z)
{
}
Vec3::Vec3(const Quat &q)
: x(q.x), y(q.y), z(q.z)
{
}
Vec4::Vec4(const Vec3 &v, float w)
: x(v.x), y(v.y), z(v.z), w(w)
{
}
Vec4::Vec4(const Quat &q)
: x(q.x), y(q.y), z(q.z), w(q.w)
{
}
Quat::Quat(const Vec3 &v)
: w(0), x(v.x), y(v.y), z(v.z)
{
}
Quat::Quat(float w, const Vec3 &v)
: w(w), x(v.x), y(v.y), z(v.z)
{
}
Quat::Quat(const Vec4 &v)
: w(v.w), x(v.x), y(v.y), z(v.z)
{
}
Quat::Quat(const Mat3 &m)
{
float trace, s, q[4];
int i, j, k;
int nxt[3] = {1, 2, 0};
trace = m.e[0][0] + m.e[1][1] + m.e[2][2];
if(trace > 0.0f){
s = sqrt(trace + 1.0f);
this->w = s / 2.0f;
s = 0.5f / s;
this->x = (m.e[2][1] - m.e[1][2]) * s;
this->y = (m.e[0][2] - m.e[2][0]) * s;
this->z = (m.e[1][0] - m.e[0][1]) * s;
}else{
i = 0;
if(m.e[1][1] > m.e[0][0]) i = 1;
if(m.e[2][2] > m.e[i][i]) i = 2;
j = nxt[i];
k = nxt[j];
s = sqrt((m.e[i][i] - m.e[j][j] - m.e[k][k]) + 1.0);
q[i] = s*0.5f;
if(q[i] != 0.0f) s = 0.5f / s;
q[3] = (m.e[k][j] - m.e[j][k]) * s;
q[j] = (m.e[j][i] + m.e[i][j]) * s;
q[k] = (m.e[k][i] + m.e[i][k]) * s;
this->w = q[3];
this->x = q[0];
this->y = q[1];
this->z = q[2];
}
}
Mat3::Mat3(const Mat4 &m)
{
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
this->e[i][j] = m.e[i][j];
}
Mat4::Mat4(const Mat3 &m)
{
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
this->e[i][j] = m.e[i][j];
this->e[0][3] = 0.0f;
this->e[1][3] = 0.0f;
this->e[2][3] = 0.0f;
this->e[3][3] = 1.0f;
this->e[3][2] = 0.0f;
this->e[3][1] = 0.0f;
this->e[3][0] = 0.0f;
}
Mat3
Mat3::rotation(const Quat &v)
{
Mat3 m(1.0f);
m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z;
m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z;
m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z;
m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y;
m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z;
m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x;
m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y;
m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z;
m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z;
return m;
}
Mat4
Mat4::rotation(const Quat &q)
{
Mat4 m(1.0f);
m.e[0][0] = q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z;
m.e[1][0] = 2*q.x*q.y - 2*q.w*q.z;
m.e[2][0] = 2*q.w*q.y + 2*q.x*q.z;
m.e[0][1] = 2*q.w*q.z + 2*q.x*q.y;
m.e[1][1] = q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z;
m.e[2][1] = 2*q.y*q.z - 2*q.w*q.x;
m.e[0][2] = 2*q.x*q.z - 2*q.w*q.y;
m.e[1][2] = 2*q.w*q.x + 2*q.y*q.z;
m.e[2][2] = q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z;
return m;
}
Mat4
Mat4::transrot(const DQuat &q)
{
const Quat &q1 = q.q1;
const Quat &q2 = q.q2;
Mat4 m(1.0f);
m.e[0][0] = q1.w*q1.w + q1.x*q1.x - q1.y*q1.y - q1.z*q1.z;
m.e[1][0] = 2*q1.x*q1.y - 2*q1.w*q1.z;
m.e[2][0] = 2*q1.w*q1.y + 2*q1.x*q1.z;
m.e[0][1] = 2*q1.w*q1.z + 2*q1.x*q1.y;
m.e[1][1] = q1.w*q1.w - q1.x*q1.x + q1.y*q1.y - q1.z*q1.z;
m.e[2][1] = 2*q1.y*q1.z - 2*q1.w*q1.x;
m.e[0][2] = 2*q1.x*q1.z - 2*q1.w*q1.y;
m.e[1][2] = 2*q1.w*q1.x + 2*q1.y*q1.z;
m.e[2][2] = q1.w*q1.w - q1.x*q1.x - q1.y*q1.y + q1.z*q1.z;
m.e[3][0] = 2*(q1.w*q2.x - q2.w*q1.x + q1.y*q2.z - q1.z*q2.y);
m.e[3][1] = 2*(q1.w*q2.y - q2.w*q1.y + q1.z*q2.x - q1.x*q2.z);
m.e[3][2] = 2*(q1.w*q2.z - q2.w*q1.z + q1.x*q2.y - q1.y*q2.x);
return m;
}