2014-01-31 08:23:00 +13:00
|
|
|
|
|
|
|
|
#ifndef GEOM_H
|
|
|
|
|
#define GEOM_H
|
|
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
|
|
class Vector;
|
|
|
|
|
class Line;
|
|
|
|
|
class Plane;
|
|
|
|
|
class Matrix;
|
|
|
|
|
class Transform;
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
static float PI = 3.14159265359f; //180 degrees
|
|
|
|
|
static float TWOPI = PI*2.0f; //360 degrees
|
|
|
|
|
static float HALFPI = PI*.5f; //90 degrees
|
|
|
|
|
static float QUARTERPI = PI*.25f; //45 degrees
|
|
|
|
|
//static float FLT_EPSILON=.000001f; //small value
|
|
|
|
|
//static float INFINITY=10000000.0f; //big value
|
|
|
|
|
|
|
|
|
|
class Vector {
|
2014-01-31 08:23:00 +13:00
|
|
|
public:
|
2016-05-04 09:58:44 +02:00
|
|
|
float x, y, z;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector() :x(0), y(0), z(0) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector(float x, float y, float z) :x(x), y(y), z(z) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
operator float*() {
|
2014-01-31 08:23:00 +13:00
|
|
|
return &x;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
operator const float *() {
|
2014-01-31 08:23:00 +13:00
|
|
|
return &x;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float &operator[](int n) {
|
|
|
|
|
return (&x)[n];
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float operator[](int n)const {
|
|
|
|
|
return (&x)[n];
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator-()const {
|
|
|
|
|
return Vector(-x, -y, -z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator*(float scale)const {
|
|
|
|
|
return Vector(x*scale, y*scale, z*scale);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator*(const Vector &q)const {
|
|
|
|
|
return Vector(x*q.x, y*q.y, z*q.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator/(float scale)const {
|
|
|
|
|
return Vector(x / scale, y / scale, z / scale);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator/(const Vector &q)const {
|
|
|
|
|
return Vector(x / q.x, y / q.y, z / q.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator+(const Vector &q)const {
|
|
|
|
|
return Vector(x + q.x, y + q.y, z + q.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator-(const Vector &q)const {
|
|
|
|
|
return Vector(x - q.x, y - q.y, z - q.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator*=(float scale) {
|
|
|
|
|
x *= scale; y *= scale; z *= scale; return *this;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator*=(const Vector &q) {
|
|
|
|
|
x *= q.x; y *= q.y; z *= q.z; return *this;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator/=(float scale) {
|
|
|
|
|
x /= scale; y /= scale; z /= scale; return *this;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator/=(const Vector &q) {
|
|
|
|
|
x /= q.x; y /= q.y; z /= q.z; return *this;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator+=(const Vector &q) {
|
|
|
|
|
x += q.x; y += q.y; z += q.z; return *this;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator-=(const Vector &q) {
|
|
|
|
|
x -= q.x; y -= q.y; z -= q.z; return *this;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator<(const Vector &q)const {
|
2016-05-07 22:49:54 +02:00
|
|
|
if (fabs(x - q.x) > FLT_EPSILON) return x < q.x ? true : false;
|
|
|
|
|
if (fabs(y - q.y) > FLT_EPSILON) return y < q.y ? true : false;
|
|
|
|
|
return fabs(z - q.z) > FLT_EPSILON && z < q.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator==(const Vector &q)const {
|
2016-05-07 22:49:54 +02:00
|
|
|
return fabs(x - q.x) <= FLT_EPSILON && fabs(y - q.y) <= FLT_EPSILON && fabs(z - q.z) <= FLT_EPSILON;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator!=(const Vector &q)const {
|
2016-05-07 22:49:54 +02:00
|
|
|
return fabs(x - q.x) > FLT_EPSILON || fabs(y - q.y) > FLT_EPSILON || fabs(z - q.z) > FLT_EPSILON;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float dot(const Vector &q)const {
|
|
|
|
|
return x*q.x + y*q.y + z*q.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector cross(const Vector &q)const {
|
|
|
|
|
return Vector(y*q.z - z*q.y, z*q.x - x*q.z, x*q.y - y*q.x);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float length()const {
|
|
|
|
|
return sqrtf(x*x + y*y + z*z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float distance(const Vector &q)const {
|
|
|
|
|
float dx = x - q.x, dy = y - q.y, dz = z - q.z; return sqrtf(dx*dx + dy*dy + dz*dz);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector normalized()const {
|
|
|
|
|
float l = length(); return Vector(x / l, y / l, z / l);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void normalize() {
|
|
|
|
|
float l = length(); x /= l; y /= l; z /= l;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float yaw()const {
|
|
|
|
|
return -atan2f(x, z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float pitch()const {
|
|
|
|
|
return -atan2f(y, sqrtf(x*x + z*z));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void clear() {
|
|
|
|
|
x = y = z = 0;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
class Line {
|
2014-01-31 08:23:00 +13:00
|
|
|
public:
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector o, d;
|
|
|
|
|
Line() {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Line(const Vector &o, const Vector &d) :o(o), d(d) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Line operator+(const Vector &q)const {
|
|
|
|
|
return Line(o + q, d);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Line operator-(const Vector &q)const {
|
|
|
|
|
return Line(o - q, d);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator*(float q)const {
|
|
|
|
|
return o + d*q;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector nearest(const Vector &q)const {
|
|
|
|
|
return o + d*(d.dot(q - o) / d.dot(d));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
class Plane {
|
2014-01-31 08:23:00 +13:00
|
|
|
public:
|
|
|
|
|
Vector n;
|
|
|
|
|
float d;
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
Plane() :d(0) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
//normal/offset form
|
2016-05-04 09:58:44 +02:00
|
|
|
Plane(const Vector &n, float d) :n(n), d(d) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
//point/normal form
|
2016-05-04 09:58:44 +02:00
|
|
|
Plane(const Vector &p, const Vector &n) :n(n), d(-n.dot(p)) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
//create plane from tri
|
2016-05-04 09:58:44 +02:00
|
|
|
Plane(const Vector &v0, const Vector &v1, const Vector &v2) {
|
|
|
|
|
n = (v1 - v0).cross(v2 - v0).normalized(); d = -n.dot(v0);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Plane operator-()const {
|
|
|
|
|
return Plane(-n, -d);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float t_intersect(const Line &q)const {
|
|
|
|
|
return -distance(q.o) / n.dot(q.d);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector intersect(const Line &q)const {
|
2014-01-31 08:23:00 +13:00
|
|
|
return q*t_intersect(q);
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Line intersect(const Plane &q)const {
|
|
|
|
|
Vector lv = n.cross(q.n).normalized();
|
|
|
|
|
return Line(q.intersect(Line(nearest(n*-d), n.cross(lv))), lv);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector nearest(const Vector &q)const {
|
|
|
|
|
return q - n*distance(q);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void negate() {
|
|
|
|
|
n = -n; d = -d;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float distance(const Vector &q)const {
|
|
|
|
|
return n.dot(q) + d;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
struct Quat {
|
2014-01-31 08:23:00 +13:00
|
|
|
float w;
|
|
|
|
|
Vector v;
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat() :w(1) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat(float w, const Vector &v) :w(w), v(v) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat operator-()const {
|
|
|
|
|
return Quat(w, -v);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat operator+(const Quat &q)const {
|
|
|
|
|
return Quat(w + q.w, v + q.v);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat operator-(const Quat &q)const {
|
|
|
|
|
return Quat(w - q.w, v - q.v);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat operator*(const Quat &q)const {
|
|
|
|
|
return Quat(w*q.w - v.dot(q.v), q.v.cross(v) + q.v*w + v*q.w);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator*(const Vector &q)const {
|
|
|
|
|
return (*this * Quat(0, q) * -*this).v;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat operator*(float q)const {
|
|
|
|
|
return Quat(w*q, v*q);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat operator/(float q)const {
|
|
|
|
|
return Quat(w / q, v / q);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float dot(const Quat &q)const {
|
|
|
|
|
return v.x*q.v.x + v.y*q.v.y + v.z*q.v.z + w*q.w;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float length()const {
|
|
|
|
|
return sqrtf(w*w + v.x*v.x + v.y*v.y + v.z*v.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void normalize() {
|
|
|
|
|
*this = *this / length();
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat normalized()const {
|
|
|
|
|
return *this / length();
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat slerpTo(const Quat &q, float a)const {
|
|
|
|
|
Quat t = q;
|
|
|
|
|
float d = dot(q), b = 1 - a;
|
|
|
|
|
if (d < 0) { t.w = -t.w; t.v = -t.v; d = -d; }
|
2016-05-07 22:49:54 +02:00
|
|
|
if (d < 1 - FLT_EPSILON) {
|
2016-05-04 09:58:44 +02:00
|
|
|
float om = acosf(d);
|
|
|
|
|
float si = sinf(om);
|
|
|
|
|
a = sinf(a*om) / si;
|
|
|
|
|
b = sinf(b*om) / si;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
return *this*b + t*a;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector i()const {
|
|
|
|
|
float xz = v.x*v.z, wy = w*v.y;
|
|
|
|
|
float xy = v.x*v.y, wz = w*v.z;
|
|
|
|
|
float yy = v.y*v.y, zz = v.z*v.z;
|
|
|
|
|
return Vector(1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector j()const {
|
|
|
|
|
float yz = v.y*v.z, wx = w*v.x;
|
|
|
|
|
float xy = v.x*v.y, wz = w*v.z;
|
|
|
|
|
float xx = v.x*v.x, zz = v.z*v.z;
|
|
|
|
|
return Vector(2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector k()const {
|
|
|
|
|
float xz = v.x*v.z, wy = w*v.y;
|
|
|
|
|
float yz = v.y*v.z, wx = w*v.x;
|
|
|
|
|
float xx = v.x*v.x, yy = v.y*v.y;
|
|
|
|
|
return Vector(2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
class Matrix {
|
2014-01-31 08:23:00 +13:00
|
|
|
static Matrix tmps[64];
|
2016-05-04 09:58:44 +02:00
|
|
|
static Matrix &alloc_tmp() { static int tmp = 0; return tmps[tmp++ & 63]; }
|
2014-01-31 08:23:00 +13:00
|
|
|
friend class Transform;
|
|
|
|
|
public:
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector i, j, k;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix() :i(Vector(1, 0, 0)), j(Vector(0, 1, 0)), k(Vector(0, 0, 1)) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix(const Vector &i, const Vector &j, const Vector &k) :i(i), j(j), k(k) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix(const Quat &q) {
|
|
|
|
|
float xx = q.v.x*q.v.x, yy = q.v.y*q.v.y, zz = q.v.z*q.v.z;
|
|
|
|
|
float xy = q.v.x*q.v.y, xz = q.v.x*q.v.z, yz = q.v.y*q.v.z;
|
|
|
|
|
float wx = q.w*q.v.x, wy = q.w*q.v.y, wz = q.w*q.v.z;
|
|
|
|
|
i = Vector(1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy)),
|
|
|
|
|
j = Vector(2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx)),
|
|
|
|
|
k = Vector(2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix(float angle, const Vector &axis) {
|
|
|
|
|
const Vector &u = axis;
|
|
|
|
|
float c = cosf(angle), s = sinf(angle);
|
|
|
|
|
float x2 = axis.x*axis.x, y2 = axis.y*axis.y, z2 = axis.z*axis.z;
|
|
|
|
|
i = Vector(x2 + c*(1 - x2), u.x*u.y*(1 - c) - u.z*s, u.z*u.x*(1 - c) + u.y*s);
|
|
|
|
|
j = Vector(u.x*u.y*(1 - c) + u.z*s, y2 + c*(1 - y2), u.y*u.z*(1 - c) - u.x*s);
|
|
|
|
|
k = Vector(u.z*u.x*(1 - c) - u.y*s, u.y*u.z*(1 - c) + u.x*s, z2 + c*(1 - z2));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector &operator[](int n) {
|
|
|
|
|
return (&i)[n];
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
const Vector &operator[](int n)const {
|
2014-01-31 08:23:00 +13:00
|
|
|
return (&i)[n];
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix &operator~()const {
|
|
|
|
|
Matrix &m = alloc_tmp();
|
|
|
|
|
m.i.x = i.x; m.i.y = j.x; m.i.z = k.x;
|
|
|
|
|
m.j.x = i.y; m.j.y = j.y; m.j.z = k.y;
|
|
|
|
|
m.k.x = i.z; m.k.y = j.z; m.k.z = k.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
return m;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float determinant()const {
|
|
|
|
|
return i.x*(j.y*k.z - j.z*k.y) - i.y*(j.x*k.z - j.z*k.x) + i.z*(j.x*k.y - j.y*k.x);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix &operator-()const {
|
|
|
|
|
Matrix &m = alloc_tmp();
|
|
|
|
|
float t = 1.0f / determinant();
|
|
|
|
|
m.i.x = t*(j.y*k.z - j.z*k.y); m.i.y = -t*(i.y*k.z - i.z*k.y); m.i.z = t*(i.y*j.z - i.z*j.y);
|
|
|
|
|
m.j.x = -t*(j.x*k.z - j.z*k.x); m.j.y = t*(i.x*k.z - i.z*k.x); m.j.z = -t*(i.x*j.z - i.z*j.x);
|
|
|
|
|
m.k.x = t*(j.x*k.y - j.y*k.x); m.k.y = -t*(i.x*k.y - i.y*k.x); m.k.z = t*(i.x*j.y - i.y*j.x);
|
2014-01-31 08:23:00 +13:00
|
|
|
return m;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix &cofactor()const {
|
|
|
|
|
Matrix &m = alloc_tmp();
|
|
|
|
|
m.i.x = (j.y*k.z - j.z*k.y); m.i.y = -(j.x*k.z - j.z*k.x); m.i.z = (j.x*k.y - j.y*k.x);
|
|
|
|
|
m.j.x = -(i.y*k.z - i.z*k.y); m.j.y = (i.x*k.z - i.z*k.x); m.j.z = -(i.x*k.y - i.y*k.x);
|
|
|
|
|
m.k.x = (i.y*j.z - i.z*j.y); m.k.y = -(i.x*j.z - i.z*j.x); m.k.z = (i.x*j.y - i.y*j.x);
|
2014-01-31 08:23:00 +13:00
|
|
|
return m;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator==(const Matrix &q)const {
|
|
|
|
|
return i == q.i && j == q.j && k == q.k;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator!=(const Matrix &q)const {
|
|
|
|
|
return i != q.i || j != q.j || k != q.k;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator*(const Vector &q)const {
|
|
|
|
|
return Vector(i.x*q.x + j.x*q.y + k.x*q.z, i.y*q.x + j.y*q.y + k.y*q.z, i.z*q.x + j.z*q.y + k.z*q.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix &operator*(const Matrix &q)const {
|
|
|
|
|
Matrix &m = alloc_tmp();
|
|
|
|
|
m.i.x = i.x*q.i.x + j.x*q.i.y + k.x*q.i.z; m.i.y = i.y*q.i.x + j.y*q.i.y + k.y*q.i.z; m.i.z = i.z*q.i.x + j.z*q.i.y + k.z*q.i.z;
|
|
|
|
|
m.j.x = i.x*q.j.x + j.x*q.j.y + k.x*q.j.z; m.j.y = i.y*q.j.x + j.y*q.j.y + k.y*q.j.z; m.j.z = i.z*q.j.x + j.z*q.j.y + k.z*q.j.z;
|
|
|
|
|
m.k.x = i.x*q.k.x + j.x*q.k.y + k.x*q.k.z; m.k.y = i.y*q.k.x + j.y*q.k.y + k.y*q.k.z; m.k.z = i.z*q.k.x + j.z*q.k.y + k.z*q.k.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
return m;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void orthogonalize() {
|
2014-01-31 08:23:00 +13:00
|
|
|
k.normalize();
|
2016-05-04 09:58:44 +02:00
|
|
|
i = j.cross(k).normalized();
|
|
|
|
|
j = k.cross(i);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Matrix &orthogonalized()const {
|
|
|
|
|
Matrix &m = alloc_tmp();
|
|
|
|
|
m = *this; m.orthogonalize();
|
2014-01-31 08:23:00 +13:00
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
class Box {
|
2014-01-31 08:23:00 +13:00
|
|
|
public:
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector a, b;
|
|
|
|
|
Box() :a(Vector(INFINITY, INFINITY, INFINITY)), b(Vector(-INFINITY, -INFINITY, -INFINITY)) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Box(const Vector &q) :a(q), b(q) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Box(const Vector &a, const Vector &b) :a(a), b(b) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Box(const Line &l) :a(l.o), b(l.o) {
|
|
|
|
|
update(l.o + l.d);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void clear() {
|
|
|
|
|
a.x = a.y = a.z = INFINITY;
|
|
|
|
|
b.x = b.y = b.z = -INFINITY;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool empty()const {
|
|
|
|
|
return b.x < a.x || b.y < a.y || b.z < a.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector centre()const {
|
|
|
|
|
return Vector((a.x + b.x)*.5f, (a.y + b.y)*.5f, (a.z + b.z)*.5f);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector corner(int n)const {
|
|
|
|
|
return Vector(((n & 1) ? b : a).x, ((n & 2) ? b : a).y, ((n & 4) ? b : a).z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void update(const Vector &q) {
|
|
|
|
|
if (q.x < a.x) a.x = q.x; if (q.y < a.y) a.y = q.y; if (q.z < a.z) a.z = q.z;
|
|
|
|
|
if (q.x > b.x) b.x = q.x; if (q.y > b.y) b.y = q.y; if (q.z > b.z) b.z = q.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void update(const Box &q) {
|
|
|
|
|
if (q.a.x < a.x) a.x = q.a.x; if (q.a.y < a.y) a.y = q.a.y; if (q.a.z < a.z) a.z = q.a.z;
|
|
|
|
|
if (q.b.x > b.x) b.x = q.b.x; if (q.b.y > b.y) b.y = q.b.y; if (q.b.z > b.z) b.z = q.b.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool overlaps(const Box &q)const {
|
2014-01-31 08:23:00 +13:00
|
|
|
return
|
2016-05-04 09:58:44 +02:00
|
|
|
(b.x < q.b.x ? b.x : q.b.x) >= (a.x > q.a.x ? a.x : q.a.x) &&
|
|
|
|
|
(b.y < q.b.y ? b.y : q.b.y) >= (a.y > q.a.y ? a.y : q.a.y) &&
|
|
|
|
|
(b.z < q.b.z ? b.z : q.b.z) >= (a.z > q.a.z ? a.z : q.a.z);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
void expand(float n) {
|
|
|
|
|
a.x -= n; a.y -= n; a.z -= n; b.x += n; b.y += n; b.z += n;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float width()const {
|
|
|
|
|
return b.x - a.x;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float height()const {
|
|
|
|
|
return b.y - a.y;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
float depth()const {
|
|
|
|
|
return b.z - a.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool contains(const Vector &q) {
|
|
|
|
|
return q.x >= a.x && q.x <= b.x && q.y >= a.y && q.y <= b.y && q.z >= a.z && q.z <= b.z;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
class Transform {
|
2014-01-31 08:23:00 +13:00
|
|
|
static Transform tmps[64];
|
2016-05-04 09:58:44 +02:00
|
|
|
static Transform &alloc_tmp() { static int tmp = 0; return tmps[tmp++ & 63]; }
|
2014-01-31 08:23:00 +13:00
|
|
|
public:
|
|
|
|
|
Matrix m;
|
|
|
|
|
Vector v;
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform() {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform(const Matrix &m) :m(m) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform(const Vector &v) :v(v) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform(const Matrix &m, const Vector &v) :m(m), v(v) {
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform &operator-()const {
|
|
|
|
|
Transform &t = alloc_tmp();
|
|
|
|
|
t.m = -m; t.v = t.m*-v;
|
2014-01-31 08:23:00 +13:00
|
|
|
return t;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform &operator~()const {
|
|
|
|
|
Transform &t = alloc_tmp();
|
|
|
|
|
t.m = ~m; t.v = t.m*-v;
|
2014-01-31 08:23:00 +13:00
|
|
|
return t;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Vector operator*(const Vector &q)const {
|
|
|
|
|
return m*q + v;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Line operator*(const Line &q)const {
|
|
|
|
|
Vector t = (*this)*q.o;
|
|
|
|
|
return Line(t, (*this)*(q.o + q.d) - t);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Box operator*(const Box &q)const {
|
|
|
|
|
Box t((*this*q.corner(0)));
|
|
|
|
|
for (int k = 1; k < 8; ++k) t.update(*this*q.corner(k));
|
2014-01-31 08:23:00 +13:00
|
|
|
return t;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
Transform &operator*(const Transform &q)const {
|
|
|
|
|
Transform &t = alloc_tmp();
|
|
|
|
|
t.m = m*q.m; t.v = m*q.v + v;
|
2014-01-31 08:23:00 +13:00
|
|
|
return t;
|
|
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator==(const Transform &q)const {
|
|
|
|
|
return m == q.m && v == q.v;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2016-05-04 09:58:44 +02:00
|
|
|
bool operator!=(const Transform &q)const {
|
|
|
|
|
return !operator==(q);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float transformRadius(float r, const Matrix &t) {
|
|
|
|
|
static const float sq_3 = sqrtf(1.0f / 3.0f);
|
|
|
|
|
return (t * Vector(sq_3, sq_3, sq_3)).length()*r;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix pitchMatrix(float q) {
|
|
|
|
|
return Matrix(Vector(1, 0, 0), Vector(0, cosf(q), sinf(q)), Vector(0, -sinf(q), cosf(q)));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix yawMatrix(float q) {
|
|
|
|
|
return Matrix(Vector(cosf(q), 0, sinf(q)), Vector(0, 1, 0), Vector(-sinf(q), 0, cosf(q)));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix rollMatrix(float q) {
|
|
|
|
|
return Matrix(Vector(cosf(q), sinf(q), 0), Vector(-sinf(q), cosf(q), 0), Vector(0, 0, 1));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float matrixPitch(const Matrix &m) {
|
2014-01-31 08:23:00 +13:00
|
|
|
return m.k.pitch();
|
2016-05-04 09:58:44 +02:00
|
|
|
// return asinf( -m.k.y );
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float matrixYaw(const Matrix &m) {
|
2014-01-31 08:23:00 +13:00
|
|
|
return m.k.yaw();
|
|
|
|
|
//return atan2f( -m.k.x,m.k.z );
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float matrixRoll(const Matrix &m) {
|
|
|
|
|
return atan2f(m.i.y, m.j.y);
|
2014-01-31 08:23:00 +13:00
|
|
|
//Matrix t=pitchMatrix( -matrixPitch(m) )*yawMatrix( -matrixYaw(m) )*m;
|
|
|
|
|
//return atan2f( t.i.y,t.i.x );
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix scaleMatrix(float x, float y, float z) {
|
|
|
|
|
return Matrix(Vector(x, 0, 0), Vector(0, y, 0), Vector(0, 0, z));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix scaleMatrix(const Vector &scale) {
|
|
|
|
|
return Matrix(Vector(scale.x, 0, 0), Vector(0, scale.y, 0), Vector(0, 0, scale.z));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Quat pitchQuat(float p) {
|
|
|
|
|
return Quat(cosf(p / -2), Vector(sinf(p / -2), 0, 0));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Quat yawQuat(float y) {
|
|
|
|
|
return Quat(cosf(y / 2), Vector(0, sinf(y / 2), 0));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Quat rollQuat(float r) {
|
|
|
|
|
return Quat(cosf(r / -2), Vector(0, 0, sinf(r / -2)));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//inline Quat rotationQuat( float p,float y,float r ){
|
|
|
|
|
// return yawQuat(y)*pitchQuat(p)*rollQuat(r);
|
|
|
|
|
//}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
Quat rotationQuat(float p, float y, float r);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix rotationMatrix(float p, float y, float r) {
|
2014-01-31 08:23:00 +13:00
|
|
|
return yawMatrix(y)*pitchMatrix(p)*rollMatrix(r);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Matrix rotationMatrix(const Vector &rot) {
|
2014-01-31 08:23:00 +13:00
|
|
|
return yawMatrix(rot.y)*pitchMatrix(rot.x)*rollMatrix(rot.z);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float quatPitch(const Quat &q) {
|
2014-01-31 08:23:00 +13:00
|
|
|
return q.k().pitch();
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float quatYaw(const Quat &q) {
|
2014-01-31 08:23:00 +13:00
|
|
|
return q.k().yaw();
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline float quatRoll(const Quat &q) {
|
|
|
|
|
// Vector i=q.i(),j=q.j();
|
|
|
|
|
// return atan2f( i.y,j.y );
|
|
|
|
|
return matrixRoll(q);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2016-05-04 09:58:44 +02:00
|
|
|
inline Quat matrixQuat(const Matrix &p) {
|
|
|
|
|
Matrix m = p;
|
2014-01-31 08:23:00 +13:00
|
|
|
m.orthogonalize();
|
2016-05-04 09:58:44 +02:00
|
|
|
float t = m.i.x + m.j.y + m.k.z, w, x, y, z;
|
2016-05-07 22:49:54 +02:00
|
|
|
if (t > FLT_EPSILON) {
|
2016-05-04 09:58:44 +02:00
|
|
|
t = sqrtf(t + 1) * 2;
|
|
|
|
|
x = (m.k.y - m.j.z) / t;
|
|
|
|
|
y = (m.i.z - m.k.x) / t;
|
|
|
|
|
z = (m.j.x - m.i.y) / t;
|
|
|
|
|
w = t / 4;
|
|
|
|
|
} else if (m.i.x > m.j.y && m.i.x > m.k.z) {
|
|
|
|
|
t = sqrtf(m.i.x - m.j.y - m.k.z + 1) * 2;
|
|
|
|
|
x = t / 4;
|
|
|
|
|
y = (m.j.x + m.i.y) / t;
|
|
|
|
|
z = (m.i.z + m.k.x) / t;
|
|
|
|
|
w = (m.k.y - m.j.z) / t;
|
|
|
|
|
} else if (m.j.y > m.k.z) {
|
|
|
|
|
t = sqrtf(m.j.y - m.k.z - m.i.x + 1) * 2;
|
|
|
|
|
x = (m.j.x + m.i.y) / t;
|
|
|
|
|
y = t / 4;
|
|
|
|
|
z = (m.k.y + m.j.z) / t;
|
|
|
|
|
w = (m.i.z - m.k.x) / t;
|
|
|
|
|
} else {
|
|
|
|
|
t = sqrtf(m.k.z - m.j.y - m.i.x + 1) * 2;
|
|
|
|
|
x = (m.i.z + m.k.x) / t;
|
|
|
|
|
y = (m.k.y + m.j.z) / t;
|
|
|
|
|
z = t / 4;
|
|
|
|
|
w = (m.j.x - m.i.y) / t;
|
|
|
|
|
}
|
|
|
|
|
return Quat(w, Vector(x, y, z));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|