#include "vector3.h" namespace stingray_plugin_foundation { enum Elements { xx, xy, xz, xw, yx, yy, yz, yw, zx, zy, zz, zw, tx, ty, tz, tw }; // Operators __forceinline Matrix4x4 operator *(const Matrix4x4& lhs, const Matrix4x4 &rhs) { Matrix4x4 m = {{ lhs.v[xx]*rhs.v[xx] + lhs.v[xy]*rhs.v[yx] + lhs.v[xz]*rhs.v[zx] + lhs.v[xw]*rhs.v[tx], lhs.v[xx]*rhs.v[xy] + lhs.v[xy]*rhs.v[yy] + lhs.v[xz]*rhs.v[zy] + lhs.v[xw]*rhs.v[ty], lhs.v[xx]*rhs.v[xz] + lhs.v[xy]*rhs.v[yz] + lhs.v[xz]*rhs.v[zz] + lhs.v[xw]*rhs.v[tz], lhs.v[xx]*rhs.v[xw] + lhs.v[xy]*rhs.v[yw] + lhs.v[xz]*rhs.v[zw] + lhs.v[xw]*rhs.v[tw], lhs.v[yx]*rhs.v[xx] + lhs.v[yy]*rhs.v[yx] + lhs.v[yz]*rhs.v[zx] + lhs.v[yw]*rhs.v[tx], lhs.v[yx]*rhs.v[xy] + lhs.v[yy]*rhs.v[yy] + lhs.v[yz]*rhs.v[zy] + lhs.v[yw]*rhs.v[ty], lhs.v[yx]*rhs.v[xz] + lhs.v[yy]*rhs.v[yz] + lhs.v[yz]*rhs.v[zz] + lhs.v[yw]*rhs.v[tz], lhs.v[yx]*rhs.v[xw] + lhs.v[yy]*rhs.v[yw] + lhs.v[yz]*rhs.v[zw] + lhs.v[yw]*rhs.v[tw], lhs.v[zx]*rhs.v[xx] + lhs.v[zy]*rhs.v[yx] + lhs.v[zz]*rhs.v[zx] + lhs.v[zw]*rhs.v[tx], lhs.v[zx]*rhs.v[xy] + lhs.v[zy]*rhs.v[yy] + lhs.v[zz]*rhs.v[zy] + lhs.v[zw]*rhs.v[ty], lhs.v[zx]*rhs.v[xz] + lhs.v[zy]*rhs.v[yz] + lhs.v[zz]*rhs.v[zz] + lhs.v[zw]*rhs.v[tz], lhs.v[zx]*rhs.v[xw] + lhs.v[zy]*rhs.v[yw] + lhs.v[zz]*rhs.v[zw] + lhs.v[zw]*rhs.v[tw], lhs.v[tx]*rhs.v[xx] + lhs.v[ty]*rhs.v[yx] + lhs.v[tz]*rhs.v[zx] + lhs.v[tw]*rhs.v[tx], lhs.v[tx]*rhs.v[xy] + lhs.v[ty]*rhs.v[yy] + lhs.v[tz]*rhs.v[zy] + lhs.v[tw]*rhs.v[ty], lhs.v[tx]*rhs.v[xz] + lhs.v[ty]*rhs.v[yz] + lhs.v[tz]*rhs.v[zz] + lhs.v[tw]*rhs.v[tz], lhs.v[tx]*rhs.v[xw] + lhs.v[ty]*rhs.v[yw] + lhs.v[tz]*rhs.v[zw] + lhs.v[tw]*rhs.v[tw] }}; return m; } __forceinline Matrix4x4 operator +(const Matrix4x4& lhs, const Matrix4x4 &rhs) { Matrix4x4 m = {{ lhs.v[xx] + rhs.v[xx], lhs.v[xy] + rhs.v[xy], lhs.v[xz] + rhs.v[xz], lhs.v[xw] + rhs.v[xw], lhs.v[yx] + rhs.v[yx], lhs.v[yy] + rhs.v[yy], lhs.v[yz] + rhs.v[yz], lhs.v[yw] + rhs.v[yw], lhs.v[zx] + rhs.v[zx], lhs.v[zy] + rhs.v[zy], lhs.v[zz] + rhs.v[zz], lhs.v[zw] + rhs.v[zw], lhs.v[tx] + rhs.v[tx], lhs.v[ty] + rhs.v[ty], lhs.v[tz] + rhs.v[tz], lhs.v[tw] + rhs.v[tw] }}; return m; } __forceinline Matrix4x4 operator -(const Matrix4x4& lhs, const Matrix4x4 &rhs) { Matrix4x4 m = {{ lhs.v[xx] - rhs.v[xx], lhs.v[xy] - rhs.v[xy], lhs.v[xz] - rhs.v[xz], lhs.v[xw] - rhs.v[xw], lhs.v[yx] - rhs.v[yx], lhs.v[yy] - rhs.v[yy], lhs.v[yz] - rhs.v[yz], lhs.v[yw] - rhs.v[yw], lhs.v[zx] - rhs.v[zx], lhs.v[zy] - rhs.v[zy], lhs.v[zz] - rhs.v[zz], lhs.v[zw] - rhs.v[zw], lhs.v[tx] - rhs.v[tx], lhs.v[ty] - rhs.v[ty], lhs.v[tz] - rhs.v[tz], lhs.v[tw] - rhs.v[tw] }}; return m; } __forceinline void operator *=(Matrix4x4& lhs, const Matrix4x4 &rhs) { Matrix4x4 tmp = lhs * rhs; lhs = tmp; } __forceinline void operator +=(Matrix4x4& lhs, const Matrix4x4 &rhs) { lhs.v[xx] += rhs.v[xx]; lhs.v[xy] += rhs.v[xy]; lhs.v[xz] += rhs.v[xz]; lhs.v[xw] += rhs.v[xw]; lhs.v[yx] += rhs.v[yx]; lhs.v[yy] += rhs.v[yy]; lhs.v[yz] += rhs.v[yz]; lhs.v[yw] += rhs.v[yw]; lhs.v[zx] += rhs.v[zx]; lhs.v[zy] += rhs.v[zy]; lhs.v[zz] += rhs.v[zz]; lhs.v[zw] += rhs.v[zw]; lhs.v[tx] += rhs.v[tx]; lhs.v[ty] += rhs.v[ty]; lhs.v[tz] += rhs.v[tz]; lhs.v[tw] += rhs.v[tw]; } __forceinline void operator -=(Matrix4x4& lhs, const Matrix4x4 &rhs) { lhs.v[xx] -= rhs.v[xx]; lhs.v[xy] -= rhs.v[xy]; lhs.v[xz] -= rhs.v[xz]; lhs.v[xw] -= rhs.v[xw]; lhs.v[yx] -= rhs.v[yx]; lhs.v[yy] += rhs.v[yy]; lhs.v[yz] -= rhs.v[yz]; lhs.v[yw] -= rhs.v[yw]; lhs.v[zx] -= rhs.v[zx]; lhs.v[zy] += rhs.v[zy]; lhs.v[zz] -= rhs.v[zz]; lhs.v[zw] -= rhs.v[zw]; lhs.v[tx] -= rhs.v[tx]; lhs.v[ty] -= rhs.v[ty]; lhs.v[tz] -= rhs.v[tz]; lhs.v[tw] -= rhs.v[tw]; } __forceinline Matrix4x4 operator *(const Matrix4x4& lhs, float rhs) { Matrix4x4 m = {{ lhs.v[xx] * rhs, lhs.v[xy] * rhs, lhs.v[xz] * rhs, lhs.v[xw] * rhs, lhs.v[yx] * rhs, lhs.v[yy] * rhs, lhs.v[yz] * rhs, lhs.v[yw] * rhs, lhs.v[zx] * rhs, lhs.v[zy] * rhs, lhs.v[zz] * rhs, lhs.v[zw] * rhs, lhs.v[tx] * rhs, lhs.v[ty] * rhs, lhs.v[tz] * rhs, lhs.v[tw] * rhs }}; return m; } __forceinline Matrix4x4 operator *(float lhs, const Matrix4x4 &rhs) { return rhs * lhs; } __forceinline bool operator==(const Matrix4x4 &lhs, const Matrix4x4 &rhs) { for (int i=0; i<16; ++i) if (lhs.v[i] != rhs.v[i]) return false; return true; } __forceinline bool operator!=(const Matrix4x4 &lhs, const Matrix4x4 &rhs) { return !(lhs == rhs); } // Methods __forceinline void set_to_zero_matrix(Matrix4x4 &m) { m.v[xx]=m.v[xy]=m.v[xz]=m.v[xw]=0.f; m.v[yx]=m.v[yy]=m.v[yz]=m.v[yw]=0.f; m.v[zx]=m.v[zy]=m.v[zz]=m.v[zw]=0.f; m.v[tx]=m.v[ty]=m.v[tz]=m.v[tw]=0.f; } __forceinline void set_to_identity_matrix(Matrix4x4 &m) { m = matrix4x4_identity(); } __forceinline const Matrix4x4 &matrix4x4_zero() { static Matrix4x4 zero = {{ 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }}; return zero; } __forceinline const Matrix4x4 &matrix4x4_identity() { static Matrix4x4 id = {{ 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f }}; return id; } __forceinline void set_to_scale_matrix(Matrix4x4 &m, const Vector3 &s) { set_to_identity_matrix(m); m.v[xx] = s.x; m.v[yy] = s.y; m.v[zz] = s.z; } __forceinline void set_to_translation_matrix(Matrix4x4 &m, const Vector3 &t) { set_to_identity_matrix(m); m.v[tx] = t.x; m.v[ty] = t.y; m.v[tz] = t.z; } __forceinline void normalize(Matrix4x4 &m) { Vector3 &x = x_axis(m); Vector3 &y = y_axis(m); Vector3 &z = z_axis(m); x = normalize(x); y -= x*dot(x, y); y = normalize(y); z = cross(x,y); } __forceinline float determinant(const Matrix4x4 &m) { // return m.v[xx]*m.v[yy]*m.v[zz] + m.v[xy]*m.v[yz]*m.v[zx] + m.v[xz]*m.v[yx]*m.v[zy] - // m.v[xz]*m.v[yy]*m.v[zx] - m.v[xy]*m.v[yx]*m.v[zz] - m.v[xx]*m.v[yz]*m.v[zy]; return m.v[3] * m.v[6] * m.v[ 9] * m.v[12] - m.v[2] * m.v[7] * m.v[ 9] * m.v[12] - m.v[3] * m.v[5] * m.v[10] * m.v[12] + m.v[1] * m.v[7] * m.v[10] * m.v[12] + m.v[2] * m.v[5] * m.v[11] * m.v[12] - m.v[1] * m.v[6] * m.v[11] * m.v[12] - m.v[3] * m.v[6] * m.v[ 8] * m.v[13] + m.v[2] * m.v[7] * m.v[ 8] * m.v[13] + m.v[3] * m.v[4] * m.v[10] * m.v[13] - m.v[0] * m.v[7] * m.v[10] * m.v[13] - m.v[2] * m.v[4] * m.v[11] * m.v[13] + m.v[0] * m.v[6] * m.v[11] * m.v[13] + m.v[3] * m.v[5] * m.v[ 8] * m.v[14] - m.v[1] * m.v[7] * m.v[ 8] * m.v[14] - m.v[3] * m.v[4] * m.v[ 9] * m.v[14] + m.v[0] * m.v[7] * m.v[ 9] * m.v[14] + m.v[1] * m.v[4] * m.v[11] * m.v[14] - m.v[0] * m.v[5] * m.v[11] * m.v[14] - m.v[2] * m.v[5] * m.v[ 8] * m.v[15] + m.v[1] * m.v[6] * m.v[ 8] * m.v[15] + m.v[2] * m.v[4] * m.v[ 9] * m.v[15] - m.v[0] * m.v[6] * m.v[ 9] * m.v[15] - m.v[1] * m.v[4] * m.v[10] * m.v[15] + m.v[0] * m.v[5] * m.v[10] * m.v[15]; } __forceinline bool has_mirroring(const Matrix4x4 &m) { return (determinant(m) < 0.0f); } __forceinline float & element(Matrix4x4 &m, int i, int j) { return m.v[i*4 + j]; } __forceinline const float & element(const Matrix4x4 &m, int i, int j) { return m.v[i*4 + j]; } __forceinline void transpose(Matrix4x4 &m) { #define SWAP(a,b) {float temp = a; a = b; b = temp;} SWAP(m.v[1], m.v[4]); SWAP(m.v[2], m.v[8]); SWAP(m.v[3], m.v[12]); SWAP(m.v[6], m.v[9]); SWAP(m.v[7], m.v[13]); SWAP(m.v[11], m.v[14]); #undef SWAP } // Vector3 helper access __forceinline Vector3 &translation(Matrix4x4 &m) { return *reinterpret_cast(&m.v[tx]); } __forceinline Vector3 &x_axis(Matrix4x4 &m) { return *reinterpret_cast(&m.v[xx]); } __forceinline Vector3 &y_axis(Matrix4x4 &m) { return *reinterpret_cast(&m.v[yx]); } __forceinline Vector3 &z_axis(Matrix4x4 &m) { return *reinterpret_cast(&m.v[zx]); } __forceinline const Vector3 &translation(const Matrix4x4 &m) { return *reinterpret_cast(&m.v[tx]); } __forceinline const Vector3 &x_axis(const Matrix4x4 &m){ return *reinterpret_cast(&m.v[xx]); } __forceinline const Vector3 &y_axis(const Matrix4x4 &m){ return *reinterpret_cast(&m.v[yx]); } __forceinline const Vector3 &z_axis(const Matrix4x4 &m){ return *reinterpret_cast(&m.v[zx]); } __forceinline Vector3 &forward_axis(Matrix4x4 &m) { return y_axis(m); } __forceinline Vector3 &up_axis(Matrix4x4 &m) { return z_axis(m); } __forceinline Vector3 &right_axis(Matrix4x4 &m) { return x_axis(m); } __forceinline const Vector3 &forward_axis(const Matrix4x4 &m){ return y_axis(m); } __forceinline const Vector3 &up_axis(const Matrix4x4 &m){ return z_axis(m); } __forceinline const Vector3 &right_axis(const Matrix4x4 &m){ return x_axis(m); } __forceinline Vector3 &axis(Matrix4x4 &m, int i) { return *reinterpret_cast(&m.v[xx] + i*4); } __forceinline const Vector3 &axis(const Matrix4x4 &m, int i) { return *reinterpret_cast(&m.v[xx] + i*4); } __forceinline Vector4 &row(Matrix4x4 &m, int i) { return *reinterpret_cast(&m.v[xx] + i*4); } __forceinline const Vector4 &row(const Matrix4x4 &m, int i) { return *reinterpret_cast(&m.v[xx] + i*4); } __forceinline void set_translation(Matrix4x4 &m, const Vector3 &t) { translation(m) = t; } __forceinline Vector3 transform(const Matrix4x4 &m, const Vector3 &p) { Vector3 pt; pt.x = m.v[xx] * p.x + m.v[yx] * p.y + m.v[zx] * p.z + m.v[tx]; pt.y = m.v[xy] * p.x + m.v[yy] * p.y + m.v[zy] * p.z + m.v[ty]; pt.z = m.v[xz] * p.x + m.v[yz] * p.y + m.v[zz] * p.z + m.v[tz]; return pt; } __forceinline Vector3 transform_without_translation(const Matrix4x4 &m, const Vector3 &p) { Vector3 pt; pt.x = m.v[xx] * p.x + m.v[yx] * p.y + m.v[zx] * p.z; pt.y = m.v[xy] * p.x + m.v[yy] * p.y + m.v[zy] * p.z; pt.z = m.v[xz] * p.x + m.v[yz] * p.y + m.v[zz] * p.z; return pt; } __forceinline Vector4 transform(const Matrix4x4 &m, const Vector4 &p) { Vector4 pt; pt.x = m.v[xx] * p.x + m.v[yx] * p.y + m.v[zx] * p.z + p.w * m.v[tx]; pt.y = m.v[xy] * p.x + m.v[yy] * p.y + m.v[zy] * p.z + p.w * m.v[ty]; pt.z = m.v[xz] * p.x + m.v[yz] * p.y + m.v[zz] * p.z + p.w * m.v[tz]; pt.w = m.v[xw] * p.x + m.v[yw] * p.y + m.v[zw] * p.z + p.w * m.v[tw]; return pt; } __forceinline Matrix4x4 rotation(const Matrix4x4 &m) { Matrix4x4 out = m; out.v[xw] = out.v[yw] = out.v[zw] = out.v[tx] = out.v[ty] = out.v[tz] = 0; out.v[tw] = 1; return out; } __forceinline void set_rotation(Matrix4x4 &m, const Matrix4x4 &rot) { x_axis(m) = x_axis(rot); y_axis(m) = y_axis(rot); z_axis(m) = z_axis(rot); } __forceinline Vector3 scale(const Matrix4x4 &m) { Vector3 s; s.x = length(x_axis(m)); s.y = length(y_axis(m)); s.z = length(z_axis(m)); return s; } __forceinline void set_scale(Matrix4x4 &m, const Vector3 &s) { Vector3 p = scale(m); x_axis(m) *= s.x / p.x; y_axis(m) *= s.y / p.y; z_axis(m) *= s.z / p.z; } inline Matrix4x4 inverse(const Matrix4x4 &m) { Matrix4x4 inv = matrix4x4_identity(); Matrix4x4 temp = m; int i, j, k, swap; float *v = (float *)&temp.v[xx]; float *v2 = (float *)&inv.v[xx]; for(i=0; i!=4; ++i) { swap=i; for(j=i+1; j!=4; ++j) { if(fabs(v[(j<<2)+i]) > fabs(v[(swap<<2)+i])) swap = j; } if (swap != i) { for(k=0; k!=4; ++k) { const float t = v[(i<<2)+k]; v[(i<<2)+k] = v[(swap<<2)+k]; v[(swap<<2)+k] = t; const float t2 = v2[(i<<2)+k]; v2[(i<<2)+k] = v2[(swap<<2)+k]; v2[(swap<<2)+k] = t2; } } if (v[(i<<2)+i] == 0) return inv; const float t = v[(i<<2)+i]; for (k=0; k!=4; ++k) { v[(i<<2)+k] /= t; v2[(i<<2)+k] /= t; } for (j=0; j!=4; ++j) { if(j!=i) { const float t = v[(j<<2)+i]; for(k=0; k<4; k++) { v[(j<<2)+k] -= v[(i<<2)+k]*t; v2[(j<<2)+k] -= v2[(i<<2)+k]*t; } } } } return inv; } }