// SpatialMath.h
//
// Yet another spatial math module.
//
// Copyright (C) 2009 John Hilton
//
// Aggregates are provided for 3D vectors, 3x3 and 3x4 matrices and
// a scale/rotate/translate transformation. Classes are derived to provide
// constructors to initialize the aggregates. Relevant operators are defined
// and declared to use the aggregates. Only simple constructors are provided.
//
// Extensive use of unnamed aggregates is used to readily access the relevant
// component. Namespace level operators are provided for the aggregates.
//
// EXAMPLES
// AVec3f myvec3 = CVec3f( 1, 3.4f, -8.2f ); // initialization
// AVec3f vec3 = myvec DOT CVec3f(1,1,1); // dot product
// vec3a = vec3b * xform; // scales/rotates/translates vec3b by xform
// vec3a = vec3b / xform; // inverse scale/rotate/translate
//
// SUMMARY
// 3D vector - AVec3, CVec3
// CVec3(x,y,z)
// .v3[3], .x, .y, .z
// 3x3 matrix - AMat3x3, CMat3x3 (typically a pure rotation)
// CMat3x3(xx,xy,xz,
// yx,yy,yz,
// zx,zy,zz)
// .v[9], .m3x3[3][3]
// .right, .up, .back, .v3x, .v3y, .v3z .vec3x, .vec3y, .vec3z
// .xx, .xy, .xz, .yx, .yy, .yz, .zx, .zy, .zz
// 4x3 matrix - AMat4x3, CMat4x3
// CMat4x3(xx,xy,xz,
// yx,yy,yz,
// zx,zy,zz,
// wx,wy,wz)
// .v12[12], .m4x3[4][3], .mat3x3, .rot, .trn,
// plus all the 3x3 matrix and 3D vector components
// scale/rotate/translate transformation - AXform, CXform
// CXform( scale,
// xx,xy,xz,
// yx,yy,yz,
// zx,zy,zz,
// wx,wy,wz)
// .v13[13], .scale
// plus all the 4x3 matrix components
//
//
#pragma once
// Allow the nameless struct/union nonstandard extension to be used
#pragma warning( disable : 4201 )
namespace SpatialMath
{
#pragma region spatial types
#define AVEC3(T) union { T v3[3]; struct { T x,y,z; }; }
#define AMAT3x3(T) union { \
T v9[9], m3x3[3][3]; \
struct { T v3x[3], v3y[3], v3z[3]; }; \
struct { AVec3<T> vecx, vecy, vecz; }; \
struct { AVec3<T> right, up, back; }; \
struct { T xx, xy, xz, yx, yy, yz, zx, zy, zz; }; \
}
#define AMAT4x3(T) union { \
T v16[12], m4x3[4][3]; \
struct { AMat3x3<T> mat3x3; AVec3<T> vec3; }; \
struct { AMat3x3<T> rot; AVec3<T> trn; }; \
struct { AMAT3x3(T); AVEC3(T); }; \
}
#define AXFORM(T) union { \
T v17[13]; \
struct { \
T scale; \
union { AMat3x3<T> mat4x3; AMAT4x3(T); }; \
}; \
}
// Vec3
template< typename T > struct AVec3 { AVEC3(T); };
template< typename T > struct CVec3 : public AVec3<T>
{
CVec3() {}
CVec3( T x_, T y_, T z_ ) { x = x_; y = y_; z = z_; }
};
typedef AVec3<float> AVec3f;
typedef AVec3<double> AVec3d;
typedef CVec3<float> CVec3f;
typedef CVec3<double> CVec3d;
// Mat3x3
template< typename T > struct AMat3x3 { AMAT3x3(T); };
template< typename T > struct CMat3x3 : public AMat3x3<T>
{
CMat3x3() {}
CMat3x3( T xx_, T xy_, T xz_,
T yx_, T yy_, T yz_,
T zx_, T zy_, T zz_ )
{
xx = xx_; xy = xy_; xz = xz_;
yx = yx_; yy = yy_; yz = yz_;
zx = zx_; zy = zy_; zz = zz_;
}
// Provide a spin angle and axis constructor
CMat3x3( T SpinAngle, const AVec3<T>& SpinAxis );
};
typedef AMat3x3<float> AMat3x3f;
typedef AMat3x3<double> AMat3x3d;
typedef CMat3x3<float> CMat3x3f;
typedef CMat3x3<double> CMat3x3d;
// Mat4x3
template< typename T > struct AMat4x3 { AMAT4x3(T); };
template< typename T > struct CMat4x3 : public AMat4x3<T>
{
CMat4x3() {}
CMat4x3( T xx_, T xy_, T xz_,
T yx_, T yy_, T yz_,
T zx_, T zy_, T zz_,
T x_, T y_, T z_ )
{
xx = xx_; xy = xy_; xz = xz_;
yx = yx_; yy = yy_; yz = yz_;
zx = zx_; zy = zy_; zz = zz_;
x = x_; y = y_; z = z_;
}
};
typedef AMat4x3<float> AMat4x3f;
typedef AMat4x3<double> AMat4x3d;
typedef CMat4x3<float> CMat4x3f;
typedef CMat4x3<double> CMat4x3d;
// Xform
template< typename T > struct AXform { AXFORM(T); };
template< typename T > struct CXform: public AXform<T>
{
CXform( T scale_,
T xx_, T xy_, T xz_,
T yx_, T yy_, T yz_,
T zx_, T zy_, T zz_,
T x_, T y_, T z_ )
{
scale = scale_;
xx = xx_; xy = xy_; xz = xz_;
yx = yx_; yy = yy_; yz = yz_;
zx = zx_; zy = zy_; zz = zz_;
x = x_; y = y_; z = z_;
}
};
typedef AXform<float> AXformf;
typedef AXform<double> AXformd;
typedef CXform<float> CXformf;
typedef CXform<double> CXformd;
#undef AVEC3
#undef AMAT3x3
#undef AMAT4x3
#undef AXFORM
#pragma endregion
template< typename T > class CSpatialMath
{
public:
typedef AVec3<T> AVec3;
typedef AMat3x3<T> AMat3x3;
typedef AMat4x3<T> AMat4x3;
typedef AXform<T> AXform;
static const AXform m_Identity;
static const T m_kVerySmall;
};
typedef CSpatialMath<float> CSpatialMathf;
typedef CSpatialMath<double> CSpatialMathd;
// Define readable spatial math operators and follow correct precedence
#ifndef SPATIALMATH_DONT_USE_MATH_DEFINES
#define INVERT43 ~
#define TRANSPOSE ~
#define DETERMINANT !
#define CROSS *
#define LENGTH !
#define DOT %
#endif
#pragma region operators
// LENGTH Vec3
template< typename T > T operator!( const AVec3<T>& a );
// Scl * Vec3, Vec3 * Scl, Vec3 *= Scl
// Vec3 / Scl, Vec3 /= Scl
template< typename T > AVec3<T> operator*( T s, const AVec3<T>& a )
{ return CVec3<T>( s*a.x, s*a.y, s*a.z ); }
template< typename T > AVec3<T> operator*( const AVec3<T>& a, T s )
{ return s*a; }
template< typename T > AVec3<T>& operator*=( AVec3<T>& a, T s )
{ a.x *= s; a.y *= s; a.z *= s; return a; }
template< typename T > AVec3<T> operator/( const AVec3<T>& a, T s )
{ return (1/s)*a; }
template< typename T > AVec3<T>& operator/=( AVec3<T>& a, T s )
{ return a*=1/s; }
// Vec3 + Vec3, Vec3 += Vec3
// Vec3 - Vec3, Vec3 -= Vec3
// Vec3 DOT Vec3
// Vec3 CROSS Vec3, Vec3 CROSS= Vec3
template< typename T > AVec3<T> operator+( const AVec3<T>& a, const AVec3<T>& b )
{ return CVec3<T>( a.x+b.x, a.y+b.y, a.z+b.z ); }
template< typename T > AVec3<T>& operator+=( AVec3<T>& a, const AVec3<T>& b )
{ a.x+=b.x; a.y+=b.y; a.z+=b.z; return a; }
template< typename T > AVec3<T> operator-( const AVec3<T>& a, const AVec3<T>& b )
{ return CVec3<T>( a.x-b.x, a.y-b.y, a.z-b.z ); }
template< typename T > AVec3<T>& operator-=( AVec3<T>& a, const AVec3<T>& b )
{ a.x-=b.x; a.y-=b.y; a.z-=b.z; return a; }
template< typename T > T operator%( const AVec3<T>& a, const AVec3<T>& b )
{ return a.x*b.x+a.y*b.y+a.z*b.z ; }
template< typename T > AVec3<T> operator*( const AVec3<T>& a, const AVec3<T>& b )
{ return CVec3<T>( a.y*b.z - a.z*b.y,
a.z*b.x - a.x*b.z,
a.x*b.y - a.y*b.x );
}
template< typename T > AVec3<T>& operator*=( AVec3<T>& a, const AVec3<T>& b )
{
CVec3<T> r( a.y*b.z - a.z*b.y,
a.z*b.x - a.x*b.z,
a.x*b.y - a.y*b.x );
a = r;
return a;
}
// Vec3 * Mat3x3, Vec3 *= Mat3x3
// Vec3 / Mat3x3, Vec3 /= Mat3x3 - times transpose(inverse of rotation)
template< typename T > AVec3<T> operator*( const AVec3<T>& a, const AMat3x3<T>& m );
template< typename T > AVec3<T>& operator*=( AVec3<T>& a, const AMat3x3<T>& m );
template< typename T > AVec3<T> operator/( const AVec3<T>& a, const AMat3x3<T>& m );
template< typename T > AVec3<T>& operator/=( AVec3<T>& a, const AMat3x3<T>& m );
// Vec3 * Mat4x3, Vec3 *= Mat4x3
// Vec3 / Mat4x3, Vec3 /= Mat4x3 - neg .trn then times .rot transpose(inverse of rotation)
template< typename T > AVec3<T> operator*( const AVec3<T>& a, const AMat4x3<T>& m );
template< typename T > AVec3<T>& operator*=( AVec3<T>& a, const AMat4x3<T>& m );
template< typename T > AVec3<T> operator/( const AVec3<T>& a, const AMat4x3<T>& m );
template< typename T > AVec3<T>& operator/=( AVec3<T>& a, const AMat4x3<T>& m );
// Vec3 * Xform, Vec3 *= Xform
// Vec3 / Xform, Vec3 /= Xform - times transpose(inverse of rotation)
template< typename T > AVec3<T> operator*( const AVec3<T>& a, const AXform<T>& xf );
template< typename T > AVec3<T>& operator*=( AVec3<T>& a, const AXform<T>& xf );
template< typename T > AVec3<T> operator/( const AVec3<T>& a, const AXform<T>& xf );
template< typename T > AVec3<T>& operator/=( AVec3<T>& a, const AXform<T>& xf );
// Mat3x3 * Mat3x3, Mat3x3 *= Mat3x3
// Mat3x3 / Mat3x3, Mat3x3 /= Mat3x3 - times transpose(inverse of rotation)
template< typename T > AMat3x3<T> operator*( const AMat3x3<T>& a, const AMat3x3<T>& b );
template< typename T > AMat3x3<T>& operator*=( AMat3x3<T>& a, const AMat3x3<T>& b );
template< typename T > AMat3x3<T> operator/( const AMat3x3<T>& a, const AMat3x3<T>& b );
template< typename T > AMat3x3<T>& operator/=( AMat3x3<T>& a, const AMat3x3<T>& b );
// Mat4x3 * Mat4x3, Mat4x3 *= Mat4x3
// Mat4x3 / Mat4x3, Mat4x3 /= Mat4x3
template< typename T > AMat4x3<T> operator*( const AMat4x3<T>& a, const AMat4x3<T>& b );
template< typename T > AMat4x3<T>& operator*=( AMat4x3<T>& a, const AMat4x3<T>& b );
template< typename T > AMat4x3<T> operator/( const AMat4x3<T>& a, const AMat4x3<T>& b );
template< typename T > AMat4x3<T>& operator/=( AMat4x3<T>& a, const AMat4x3<T>& b );
// Xform * Xform, Xform *= Xform
// Xform / Xform, Xform /= Xform
template< typename T > AXform<T> operator*( const AXform<T>& a, const AXform<T>& b );
template< typename T > AXform<T>& operator*=( AXform<T>& a, const AXform<T>& b );
template< typename T > AXform<T> operator/( const AXform<T>& a, const AXform<T>& b );
template< typename T > AXform<T>& operator/=( AXform<T>& a, const AXform<T>& b );
#pragma endregion
} // namespace SpatialMath
#ifndef SPATIALMATH_NO_USING
using namespace SpatialMath;
#endif