Click here to Skip to main content
15,889,116 members
Articles / Multimedia / DirectX

A New Perspective on Viewing

Rate me:
Please Sign up or sign in to vote.
4.93/5 (44 votes)
6 Oct 2009CPOL16 min read 110.4K   2.6K   90  
Simple yet comprehensive viewing code for OpenGL and Direct3D.
// 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

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder Spatial Freedom
Australia Australia
Software engineer, mechanical engineer, electronics engineer, inventor, manager, entrepreneur, husband, father, friend.
B.Sc. B.E.(Hons) M.Eng.Sc.
Some things I've done
- Invented the Spaceball(R)/1983 and Astroid(R)/2002 3D mice
- Patents: 3D mouse, data compression, acoustic transducer
- Wrote animation software in mid 1980s for TV commercials
- Wrote a basic CAD drawing program in 1980s
- Lived in Boston, Massachusetts for 11 years
- Architected and managed full custom ASIC chip
- Reviewed bionic eye technology for investment purposes
- Product development on CPR aid for heart attacks
- Developed an electronic sports whistle
- Was actually stranded on a deserted Pacific island
- Software: lots - embedded, device driver, applications
Some things I want to do
- Develop more cool hardware/software products
- Solve the 3D mouse software barrier to proliferate 3D mice
- Help bring 3D to the masses
- Help others

Comments and Discussions