This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Random Unit Vectors Submitted by

In some parts of your 3D engine it is very handy to generate random unit vectors. For example, when you want to test some code for reliability, or you want to give something a new random direction every time, or you want to slerp between random orientations... The following RandVec function returns a random unit vector:

    const float M_2PIf = 6.283185307179586476925286766559f;

    float rand(float min, float max)
    {
        return min + (max - min) * rand() / (float)RAND_MAX;
    }

    Vector RandVec()
    {
        float z = rand(-1.0f, 1.0f);
        float a = rand(0.0f, M_2PIf);

        float r = sqrtf(1.0f - z*z);

        float x = r * cosf(a);
        float y = r * sinf(a);

        return Vector(x, y, z);
    }

The float rand(float min, float max) function is just a handy extention of the ANSI rand() function, and returns a random number between min and max. The class Vector is a general 3D vector class (I could have included these functions in the Vector class but that would have made it less readable for this COTD). To make a random vector, two random numbers are generated. The first one, z, is the 'height' on a unit spere. Imagine slicing a circle with radius r of the unit sphere at this height. Then an angle a is chosen to select one point on the circle. To convince you this is a correct method of constructing a random unit vector I present you a simple test application: a starfield generator. It shows the random-ness of my unit vector generator very well and uses quaternions to let you look around. The program uses DirectX to set your screen resolution to 1024x768x32. After that it will construct 8192 random points and diplay them as a starfield. You can use the mouse to look around, and pressing escape will stop the application. A debug.log file will be created, just ignore it (I used a very old version of my current engine and threw out all unnecessary parts for this test program). You can download it here: RandVec.zip (100k) In this file you will find the executable and the full source in case you want to experiment with it. You can make some cool effects by altering the RandVec function (interchanging z and a gives really strange effects, or using tan instead of sqrt or sin). You can also increase the number of stars, but be aware that the startup and rendering time could become very long. My second method of convincing you is a mathematical proof (skip this part if only the results are important for you): First, one point P(x, y, z) is constructed from two random numbers (z, a). Then we construct a second point by adding an infinitesimal value dz and da to z and a respectively. Between these two points a rectangular surface can be constructed (two other corners defined by (z, a + da) and (z + dz, a)). Now let's calculate the area of this rectangle. It's width (z constant) is equal to r·da, and it's height (a constant) is equal to (1/sqrt(1-z²))·dz. It's easy to see that the area of the rectangle is da·dz. This means that for any (random) z and a, the area of the rectangle constructed this way is constant. So what does this learn us? Well, if we take a surface of the unit sphere, then the number of points lying in it that can be constructed with the above method will be in proportion to the area of the surface we've taken. This means the points are distributed evenly according to the area. There's only one thing wrong in this proof: we need to construct an infinite number of points. Since we can't do this we go to be happy with a good approximation. For a good approximation we need a lot of points and a good random number generator. Since no random number generator is perfect, you will see that, very locally, the density will be a little sparse or dense. Regards, Nicolas "Nick" Capens

Currently browsing [RandVec.zip] (100,350 bytes) - [DebugLog.h] - (1,057 bytes)

    #ifndef DEBUGLOG_H
    #define DEBUGLOG_H

    #include <stdio.h>

    #define DEBUG_LOG "debug.log"

    class DebugLog
    {
       const char *File;
    	FILE *hFile;

    	void New();   // Make and initialise a new file

    public:
    	DebugLog(const char *file);

    	void __cdecl printf(const char *format, ...);   // Write a formatted message to the debug file

    	DebugLog &operator<<(char ch);
    	DebugLog &operator<<(unsigned char uch);
    	DebugLog &operator<<(signed char sch);
    	DebugLog &operator<<(const char* psz);
    	DebugLog &operator<<(const unsigned char* pusz);
    	DebugLog &operator<<(const signed char* pssz);
    	DebugLog &operator<<(short s);
    	DebugLog &operator<<(unsigned short us);
    	DebugLog &operator<<(int n);
    	DebugLog &operator<<(unsigned int un);
    	DebugLog &operator<<(long l);
    	DebugLog &operator<<(unsigned long ul);
    	DebugLog &operator<<(float f);
    	DebugLog &operator<<(double d);
    	DebugLog &operator<<(long double ld);
    	DebugLog &operator<<(const void* pv);
    };

    extern DebugLog Log;   // Standard global debug log

    #endif   // DEBUGLOG_H

Currently browsing [RandVec.zip] (100,350 bytes) - [DIDevice.h] - (307 bytes)

    #ifndef DIDEVICE_H
    #define DIDEVICE_H

    #include "dinput.h"

    class DIDevice
    {
    public:
    	HWND hWnd;   // Window handle

    	static IDirectInput *DirectInput;

    	DIDevice();
    	~DIDevice();

    	void Init(HWND Handle);
    	void ReleaseDirectInput();
    };

    extern DIDevice Input;

    #endif   // DIDEVICE_H

Currently browsing [RandVec.zip] (100,350 bytes) - [DIKeyboard.h] - (386 bytes)

    #ifndef DIKEYBOARD_H
    #define DIKEYBOARD_H

    #include "DIDevice.h"

    class DIKeyboard : DIDevice
    {
    	static IDirectInputDevice *Keyboard;

    public:
    	char Key[256];

    	DIKeyboard();
    	~DIKeyboard();

    	void Init();
    	void SetAcquire();
    	void Input();
    	bool KeyPressed(int k);
    	void DIKeyboard::ReleaseKeyboard();
    };

    extern DIKeyboard Keyboard;

    #endif   // DIKEYBOARD_H

Currently browsing [RandVec.zip] (100,350 bytes) - [DIMouse.h] - (382 bytes)

    #ifndef DIMOUSE_H
    #define DIMOUSE_H

    #include "DIDevice.h"

    class DIMouse : public DIDevice
    {
    	static IDirectInputDevice *Mouse;

    public:
       int dx;
    	int dy;
    	int dz;
    	char b1;
    	char b2;
    	char b3;
    	char b4;

    	DIMouse();
    	~DIMouse();

    	void Init();
    	void SetAcquire();
    	void Input();
    	void ReleaseMouse();
    };

    extern DIMouse Mouse;

    #endif   // DIMOUSE_H

Currently browsing [RandVec.zip] (100,350 bytes) - [FPSCounter.h] - (227 bytes)

    #ifndef FPSCOUNTER_H
    #define FPSCOUNTER_H

    #define FPS_UPDATE 1.0

    class FPSCounter
    {
    public:
    	float CurrentFPS;
    	int FPSFrame;
    	double StartTime;

    	FPSCounter();

    	void NewFrame();
    };

    #endif   // PFSCOUNTER_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Main.h] - (52 bytes)

    #ifndef DD3D_H
    #define DD3D_H

    #endif   // DD3D_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Matrix.h] - (4,097 bytes)

    #ifndef MATRIX_H
    #define MATRIX_H

    class Vector;
    class Point;
    class Quaternion;

    class Matrix
    {
    	// Row major order
    	float _11; float _12; float _13; float _14;
    	float _21; float _22; float _23; float _24;
    	float _31; float _32; float _33; float _34;
    	float _41; float _42; float _43; float _44;

    public:
    	Matrix();
    	Matrix(const int i);
    	Matrix(const float a[16]);
    	Matrix(const float a[4][4]);
    	Matrix(float A_11, float A_12, float A_13,
    	       float A_21, float A_22, float A_23,
    	       float A_31, float A_32, float A_33);
    	Matrix(float A_11, float A_12, float A_13, float A_14,
    	       float A_21, float A_22, float A_23, float A_24,
    	       float A_31, float A_32, float A_33, float A_34,
    	       float A_41, float A_42, float A_43, float A_44);
    	Matrix(const Vector &v1, const Vector &v2, const Vector &v3);   // Column vectors

    	Matrix &operator=(const Matrix &B);

    	friend Matrix diag(float A_11, float A_22, float A_33, float A_44);

    	operator float*();

    	Matrix operator+() const;
    	Matrix operator-() const;

    	Matrix operator!() const;   // Inverse
    	Matrix operator~() const;   // Transpose

    	Matrix &operator+=(const Matrix &B);
    	Matrix &operator-=(const Matrix &B);
    	Matrix &operator*=(float s);
    	Matrix &operator*=(const Matrix &B);
    	Matrix &operator/=(float s);

    	float *operator[](int i);          // Access element [row, col], starting with [0][0]
    	float &operator()(int i, int j);   // Access element (row, col), starting with (1, 1)

    	const float *operator[](int i) const;          // Access elements [row, col] starting with [0][0]
    	const float &operator()(int i, int j) const;   // Access elements (row, col) starting with (1, 1)

    	friend bool operator==(const Matrix &A, const Matrix &B);
    	friend bool operator!=(const Matrix &A, const Matrix &B);

    	friend Matrix operator+(const Matrix &A, const Matrix &B);
    	friend Matrix operator-(const Matrix &A, const Matrix &B);
    	friend Matrix operator*(float s, const Matrix &A);
    	friend Matrix operator*(const Matrix &A, const Matrix &B);
    	friend Matrix operator/(const Matrix &A, float s);
    	friend Matrix operator^(const Matrix &A, const int n);

    	Vector operator*(const Vector& v) const;
    	Point operator*(const Point& P) const;
    	Quaternion operator*(const Quaternion& Q) const;

    	friend Vector operator*(const Vector &v, const Matrix &A);
    	friend Point operator*(const Point &P, const Matrix &A);
    	friend Quaternion operator*(const Quaternion &Q, const Matrix &A);

    	friend Vector &operator*=(Vector &v, const Matrix &A);
    	friend Point &operator*=(Point &P, const Matrix &A);
    	friend Quaternion &operator*=(Quaternion &Q, const Matrix &A);

    	friend float det(const Matrix &A);
    	friend float det(float A_11);
    	friend float det(float A_11, float A_12,
    	                 float A_21, float A_22);
    	friend float det(float A_11, float A_12, float A_13,
    	                 float A_21, float A_22, float A_23,
    	                 float A_31, float A_32, float A_33);
    	friend float det(float A_11, float A_12, float A_13, float A_14,
    	                 float A_21, float A_22, float A_23, float A_24,
    	                 float A_31, float A_32, float A_33, float A_34,
    	                 float A_41, float A_42, float A_43, float A_44);
    	friend float det(const Vector &v1, const Vector &v2, const Vector &v3);

    	friend float tr(const Matrix &A);
    };

    inline float *Matrix::operator[](int i)
    {
    	return (float*)(&_11 + (i << 2));
    }

    inline float &Matrix::operator()(int i, int j)
    {
    	return *((float*)(&_11 + (((i - 1) & 3) << 2) + ((j - 1) & 3)));
    }

    inline const float *Matrix::operator[](int i) const
    {
    	return (float*)(&_11 + (i << 2));
    }

    inline const float &Matrix::operator()(int i, int j) const
    {
    	return *((float*)(&_11 + (((i - 1) & 3) << 2) + ((j - 1) & 3)));
    }

    inline Matrix operator^(const Matrix &A, const int n)
    {
    	// Switch will be resolved at compile time!

    	switch(n)
    	{
    		case -1: return !A;
    		case  0: return 0;
    		case  1: return A;
    		case  2: return A*A;
    		default: return A;
    	}
    }

    #endif   // MATRIX_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Point.h] - (745 bytes)

    #ifndef POINT_H
    #define POINT_H

    #include "Tuple.h"

    class Vector;

    class Point : Tuple<3>
    {
    public:
    	float x;
    	float y;
    	float z;

    	Point();
    	Point(const Point &P);
    	Point(const Vector &v);
    	Point(float x, float y, float z);

    	Point &operator=(const Point &P);

    	Point &operator+=(const Vector &v);
    	Point &operator-=(const Vector &v);

    	friend Point operator+(const Point &P, const Vector &v);
    	friend Point operator-(const Point &P, const Vector &v);

    	friend Vector operator-(const Point &P, const Point &Q);

    	friend float d(const Point &P, const Point &Q);   // Distance between two points
    	friend float d2(const Point &P, const Point &Q);   // Squared distance between two points
    };

    #endif   // POINT_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Quaternion.h] - (2,148 bytes)

    #ifndef QUATERNION_H
    #define QUATERNION_H

    #include "Vector.h"

    class Point;
    class Matrix;

    // TODO: derive from Tuple<4>

    class Quaternion
    {
    public:
    	union
    	{
    		struct
    		{
    			float x;
    			float y;
    			float z;
    		};
    		struct
    		{
    			Vector v;
    		};
    	};
    	float w;

    	Quaternion(){};
    	Quaternion(float w);
    	Quaternion(const Vector &v);
    	Quaternion(const Quaternion &Q);
    	Quaternion(const Quaternion &Q, const Quaternion &R, float t);   // Slerp
    	Quaternion(const Vector &v, float w = 0.0f);
    	Quaternion(const Point &v, float w = 1.0f);
    	Quaternion(const Matrix &A);   // Must be a rotation Matrix
    	Quaternion(float Qx, float Qy, float Qz, float Qw);

    	Quaternion &operator=(const Quaternion &Q);

    	operator float() const;
    	operator Vector() const;
    	operator Matrix() const;

    	Quaternion operator+() const;
    	Quaternion operator-() const;

    	Quaternion operator!() const;   // Inverse
    	Quaternion operator~() const;   // Conjugate

    	Quaternion &operator+=(const Quaternion &V);
    	Quaternion &operator-=(const Quaternion &V);
    	Quaternion &operator*=(float s);
    	Quaternion &operator*=(const Quaternion &Q);
    	Quaternion &operator/=(float s);

    	friend bool operator==(const Quaternion &Q, const Quaternion &R);
    	friend bool operator!=(const Quaternion &Q, const Quaternion &R);

    	friend Quaternion operator+(const Quaternion &Q, const Quaternion &R);
    	friend Quaternion operator-(const Quaternion &Q, const Quaternion &R);
    	friend Quaternion operator*(const Quaternion &Q, const Quaternion &R);
    	friend Quaternion operator*(float s, const Quaternion &Q);
    	friend Quaternion operator*(const Quaternion &Q, float s);
    	friend Quaternion operator/(const Quaternion &Q, float s);

    	friend float N(const Quaternion &Q);   // Norm
    	friend Quaternion slerp(const Quaternion &Q, const Quaternion &R, float t);

    	Quaternion &normalize();
    };

    const Quaternion i(1, 0, 0, 0);   // Imaginary unit
    const Quaternion j(0, 1, 0, 0);
    const Quaternion k(0, 0, 1, 0);

    inline Quaternion slerp(const Quaternion &Q, const Quaternion &R, float t)
    {
    	return Quaternion(Q, R, t);
    }

    #endif   // QUATERNION_H

Currently browsing [RandVec.zip] (100,350 bytes) - [RandVec.h] - (136 bytes)

    #ifndef RANDVEC_H
    #define RANDVEC_H

    class Vector;

    float rand(float min, float max);

    Vector RandVec();

    #endif   // RANDVEC_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Render.h] - (78 bytes)

    #ifndef RENDER_H
    #define RENDER_H

    void Render();

    #endif   // RENDER_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Timer.h] - (142 bytes)

    #ifndef TIMER_H
    #define TIMER_H

    class Timer
    {
    public:
    	static double Ticks();
    	static void Pause(double p);
    };

    #endif   // TIMER_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Tuple.h] - (1,298 bytes)

    #ifndef TUPLE_H
    #define TUPLE_H

    template<unsigned int n, class Type = float>
    class Tuple
    {
    protected:
    	Type Element[n];

    public:
    	Tuple();
    	Tuple(Type e[n]);

    	Tuple &operator=(const Tuple &T);

    	float &operator[](int i);
    	float &operator()(int i);

    	const float &operator[](int i) const;
    	const float &operator()(int i) const;
    };

    template<unsigned int n, class Type>
    inline Tuple<n, Type>::Tuple()
    {
    }

    template<unsigned int n, class Type>
    inline Tuple<n, Type>::Tuple(Type e[n])
    {
    	for(int i = 0; i < n; i++)
    		Element[i] = e[i];
    }

    template<unsigned int n, class Type>
    inline Tuple<n, Type> &Tuple<n, Type>::operator=(const Tuple<n, Type> &T)
    {
    	for(int i = 0; i < n; i++)
    		Element[i] = T.Element[i];

    	return *this;
    }

    template<unsigned int n, class Type>
    inline float &Tuple<n, Type>::operator[](int i)
    {
    	return Element[i];
    }

    template<unsigned int n, class Type>
    inline float &Tuple<n, Type>::operator()(int i)
    {
    	return Element[(i - 1) & 3];
    }

    template<unsigned int n, class Type>
    inline const float &Tuple<n, Type>::operator[](int i) const
    {
    	return Element[i];
    }

    template<unsigned int n, class Type>
    inline const float &Tuple<n, Type>::operator()(int i) const
    {
    	return Element[(i - 1) & 3];
    }

    #endif   // TUPLE_H

Currently browsing [RandVec.zip] (100,350 bytes) - [Vector.h] - (1,566 bytes)

    #ifndef VECTOR_H
    #define VECTOR_H

    #include "Tuple.h"

    class Point;

    class Vector : public Tuple<3>
    {
    public:
    	float &x;
    	float &y;
    	float &z;

    	Vector();
    	Vector(const int i);
    	Vector(const Vector &v);
    	Vector(const Point &p);
    	Vector(float x, float y, float z);

    	Vector &operator=(const Vector &v);

    	Vector operator+() const;
    	Vector operator-() const;

    	Vector &operator+=(const Vector &v);
    	Vector &operator-=(const Vector &v);
    	Vector &operator*=(float s);
    	Vector &operator/=(float s);

    	friend bool operator==(const Vector &u, const Vector &v);
    	friend bool operator!=(const Vector &u, const Vector &v);
    	friend bool operator>(const Vector &u, const Vector &v);   // Compare length
    	friend bool operator<(const Vector &u, const Vector &v);   // Compare length

    	friend Vector operator+(const Vector &u, const Vector &v);
    	friend Vector operator-(const Vector &u, const Vector &v);
    	friend float operator*(const Vector &u, const Vector &v);   // Dot product
    	friend Vector operator*(float s, const Vector &v);
    	friend Vector operator*(const Vector &v, float s);
    	friend Vector operator/(const Vector &v, float s);
    	friend float operator^(const Vector &v, const int n);
    	friend float operator^(const Vector &u, const Vector &v);   // Angle between vectors
    	friend Vector operator%(const Vector &u, const Vector &v);   // Cross product

    	friend float N(const Vector &v);   // Norm
    	friend float N2(const Vector &v);   // Squared norm

    	float length() const;

    	Vector &normalize();
    };

    #endif   // VECTOR_H

Currently browsing [RandVec.zip] (100,350 bytes) - [DDDisplay.cpp] - (11,782 bytes)

    #include "DDDisplay.h"
    DDDisplay Display;

    #include <stdio.h>
    #include <stdarg.h>

    DDDisplay::DDDisplay()
    {
       DirectDraw = NULL;
       PrimarySurface = NULL;
       BackSurface = NULL;

    	Active = false;
    	Locked = false;
    }

    DDDisplay::~DDDisplay()
    {
    	ReleaseAllObjects();

    	Active = false;
    	Locked = false;
    }

    void DDDisplay::Init(HWND Handle, unsigned long Width = 640, unsigned long Height = 480, unsigned long Bitdepth = 8)
    {
       hWnd = Handle;

       DDRVal = DirectDrawCreate(NULL, &DirectDraw, NULL);
       CheckDDRVal("DirectDrawCreate");

    	DDRVal = DirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);

       CheckDDRVal("SetCooperativeLevel");

    	DDDisplay::Width = Width;
    	DDDisplay::Height = Height;
    	DDDisplay::Bitdepth = Bitdepth;

    	DDRVal = DirectDraw->SetDisplayMode(Width, Height, Bitdepth);
    	CheckDDRVal("SetDisplayMode");

       DDSURFACEDESC DDSD;

    	ZeroMemory(&DDSD, sizeof(DDSD));
    	DDSD.dwSize = sizeof(DDSD);

    	DDSD.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    	DDSD.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;

    	DDSD.dwBackBufferCount = 1;

       DDRVal = DirectDraw->CreateSurface(&DDSD, &PrimarySurface, NULL);
       CheckDDRVal("CreateSurface");

       DDSCAPS DDSCaps;

       ZeroMemory(&DDSCaps, sizeof(DDSCaps));

    	DDSCaps.dwCaps = DDSCAPS_BACKBUFFER;

    	DDRVal = PrimarySurface->GetAttachedSurface(&DDSCaps, &BackSurface);
    	CheckDDRVal("GetAttachedSurface");

    	ClearBack();
    	Flip();
    	ClearBack();

    	// Allocate depth buffer memory
    	DepthBuffer = new unsigned short[Width * Height];
    	ClearDepth();

       Active = true;
    }

    void DDDisplay::Flip()
    {
       if(Locked)
          Unlock();

    	DDRVal = PrimarySurface->Flip(NULL, DDFLIP_WAIT);
    	CheckDDRVal("Flip");
    }

    void DDDisplay::ClearDepth()
    {
    	memset(DepthBuffer, 0x00, Width * Height * 2);
    }

    void DDDisplay::ClearBack(int fill)
    {
       Lock();

    	memset(BackBuffer, fill, Pitch * Height);

       Unlock();
    }

    void DDDisplay::Lock()
    {
       if(Locked)
          return;

       DDSURFACEDESC DDSD;

       DDSD.dwSize = sizeof(DDSD);

       BackSurface->Lock(NULL, &DDSD, DDLOCK_WAIT ,NULL);

       CheckDDRVal("Lock");

       Width = DDSD.dwWidth;
       Height = DDSD.dwHeight;
       Bitdepth = DDSD.ddpfPixelFormat.dwRGBBitCount;

       BackBuffer = DDSD.lpSurface;
       Pitch = DDSD.lPitch;

    	Stride = Pitch / (Bitdepth >> 3);

       Locked = true;
    }

    void DDDisplay::Unlock()
    {
       if(!Locked)
          return;

       DDRVal = BackSurface->Unlock(NULL);
       CheckDDRVal("Unlock");

       Locked = false;
    }

    void __cdecl DDDisplay::Text(int x, int y, const char *Message, ...)
    {
       char buf[256];
       va_list arglist;

       va_start(arglist, Message);
       vsprintf(buf, Message, arglist);
       va_end(arglist);

       HDC hdc;

       DDDisplay::BackSurface->GetDC(&hdc);

       SetBkColor(hdc, RGB(0, 0, 255));
       SetTextColor(hdc, RGB(255, 255, 255));

       TextOut(hdc, x, y, buf, lstrlen(buf));

       DDDisplay::BackSurface->ReleaseDC(hdc);
    }

    char *DDDisplay::DDRValToString(HRESULT DDRVal)
    {
    	switch(DDRVal)
    	{
          case DDERR_ALREADYINITIALIZED:           return "DDERR_ALREADYINITIALIZED";
          case DDERR_CANNOTATTACHSURFACE:          return "DDERR_CANNOTATTACHSURFACE";
          case DDERR_CANNOTDETACHSURFACE:          return "DDERR_CANNOTDETACHSURFACE";
          case DDERR_CURRENTLYNOTAVAIL:            return "DDERR_CURRENTLYNOTAVAIL";
          case DDERR_EXCEPTION:                    return "DDERR_EXCEPTION";
          case DDERR_GENERIC:                      return "DDERR_GENERIC";
          case DDERR_HEIGHTALIGN:                  return "DDERR_HEIGHTALIGN";
          case DDERR_INCOMPATIBLEPRIMARY:          return "DDERR_INCOMPATIBLEPRIMARY";
          case DDERR_INVALIDCAPS:                  return "DDERR_INVALIDCAPS";
          case DDERR_INVALIDCLIPLIST:              return "DDERR_INVALIDCLIPLIST";
          case DDERR_INVALIDMODE:                  return "DDERR_INVALIDMODE";
    	   case DDERR_INVALIDOBJECT:                return "DDERR_INVALIDOBJECT";
    	   case DDERR_INVALIDPARAMS:                return "DDERR_INVALIDPARAMS";
    	   case DDERR_INVALIDPIXELFORMAT:           return "DDERR_INVALIDPIXELFORMAT";
    	   case DDERR_INVALIDRECT:                  return "DDERR_INVALIDRECT";
    	   case DDERR_LOCKEDSURFACES:               return "DDERR_LOCKEDSURFACES";
    	   case DDERR_NO3D:                         return "DDERR_NO3D";
    	   case DDERR_NOALPHAHW:                    return "DDERR_NOALPHAHW";
    	   case DDERR_NOCLIPLIST:                   return "DDERR_NOCLIPLIST";
    	   case DDERR_NOCOLORCONVHW:                return "DDERR_NOCOLORCONVHW";
    	   case DDERR_NOCOOPERATIVELEVELSET:        return "DDERR_NOCOOPERATIVELEVELSET";
    	   case DDERR_NOCOLORKEY:                   return "DDERR_NOCOLORKEY";
    	   case DDERR_NOCOLORKEYHW:                 return "DDERR_NOCOLORKEYHW";
    	   case DDERR_NODIRECTDRAWSUPPORT:          return "DDERR_NODIRECTDRAWSUPPORT";
    	   case DDERR_NOEXCLUSIVEMODE:              return "DDERR_NOEXCLUSIVEMODE";
    	   case DDERR_NOFLIPHW:                     return "DDERR_NOFLIPHW";
    	   case DDERR_NOGDI:                        return "DDERR_NOGDI";
    	   case DDERR_NOMIRRORHW:                   return "DDERR_NOMIRRORHW";
    	   case DDERR_NOTFOUND:                     return "DDERR_NOTFOUND";
    	   case DDERR_NOOVERLAYHW:                  return "DDERR_NOOVERLAYHW";
    	   case DDERR_NORASTEROPHW:                 return "DDERR_NORASTEROPHW";
    	   case DDERR_NOROTATIONHW:                 return "DDERR_NOROTATIONHW";
    	   case DDERR_NOSTRETCHHW:                  return "DDERR_NOSTRETCHHW";
    	   case DDERR_NOT4BITCOLOR:                 return "DDERR_NOT4BITCOLOR";
    	   case DDERR_NOT4BITCOLORINDEX:            return "DDERR_NOT4BITCOLORINDEX";
    	   case DDERR_NOT8BITCOLOR:                 return "DDERR_NOT8BITCOLOR";
    	   case DDERR_NOTEXTUREHW:                  return "DDERR_NOTEXTUREHW";
    	   case DDERR_NOVSYNCHW:                    return "DDERR_NOVSYNCHW";
    	   case DDERR_NOZBUFFERHW:                  return "DDERR_NOZBUFFERHW";
    	   case DDERR_NOZOVERLAYHW:                 return "DDERR_NOZOVERLAYHW";
    	   case DDERR_OUTOFCAPS:                    return "DDERR_OUTOFCAPS";
    	   case DDERR_OUTOFMEMORY:                  return "DDERR_OUTOFMEMORY";
    	   case DDERR_OUTOFVIDEOMEMORY:             return "DDERR_OUTOFVIDEOMEMORY";
    	   case DDERR_OVERLAYCANTCLIP:              return "DDERR_OVERLAYCANTCLIP";
    	   case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: return "DDERR_OVERLAYCOLORKEYONLYONEACTIVE";
    	   case DDERR_PALETTEBUSY:                  return "DDERR_PALETTEBUSY";
    	   case DDERR_COLORKEYNOTSET:               return "DDERR_COLORKEYNOTSET";
    	   case DDERR_SURFACEALREADYATTACHED:       return "DDERR_SURFACEALREADYATTACHED";
    	   case DDERR_SURFACEALREADYDEPENDENT:      return "DDERR_SURFACEALREADYDEPENDENT";
    	   case DDERR_SURFACEBUSY:                  return "DDERR_SURFACEBUSY";
    	   case DDERR_CANTLOCKSURFACE:              return "DDERR_CANTLOCKSURFACE";
    	   case DDERR_SURFACEISOBSCURED:            return "DDERR_SURFACEISOBSCURED";
    	   case DDERR_SURFACELOST:                  return "DDERR_SURFACELOST";
    	   case DDERR_SURFACENOTATTACHED:           return "DDERR_SURFACENOTATTACHED";
    	   case DDERR_TOOBIGHEIGHT:                 return "DDERR_TOOBIGHEIGHT";
    	   case DDERR_TOOBIGSIZE:                   return "DDERR_TOOBIGSIZE";
    	   case DDERR_TOOBIGWIDTH:                  return "DDERR_TOOBIGWIDTH";
    	   case DDERR_UNSUPPORTED:                  return "DDERR_UNSUPPORTED";
    	   case DDERR_UNSUPPORTEDFORMAT:            return "DDERR_UNSUPPORTEDFORMAT";
    	   case DDERR_UNSUPPORTEDMASK:              return "DDERR_UNSUPPORTEDMASK";
    	   case DDERR_VERTICALBLANKINPROGRESS:      return "DDERR_VERTICALBLANKINPROGRESS";
    	   case DDERR_WASSTILLDRAWING:              return "DDERR_WASSTILLDRAWING";
    	   case DDERR_XALIGN:                       return "DDERR_XALIGN";
    	   case DDERR_INVALIDDIRECTDRAWGUID:        return "DDERR_INVALIDDIRECTDRAWGUID";
    	   case DDERR_DIRECTDRAWALREADYCREATED:     return "DDERR_DIRECTDRAWALREADYCREATED";
    	   case DDERR_NODIRECTDRAWHW:               return "DDERR_NODIRECTDRAWHW";
    	   case DDERR_PRIMARYSURFACEALREADYEXISTS:  return "DDERR_PRIMARYSURFACEALREADYEXISTS";
    	   case DDERR_NOEMULATION:                  return "DDERR_NOEMULATION";
    	   case DDERR_REGIONTOOSMALL:               return "DDERR_REGIONTOOSMALL";
    	   case DDERR_CLIPPERISUSINGHWND:           return "DDERR_CLIPPERISUSINGHWND";
    	   case DDERR_NOCLIPPERATTACHED:            return "DDERR_NOCLIPPERATTACHED";
    	   case DDERR_NOHWND:                       return "DDERR_NOHWND";
    	   case DDERR_HWNDSUBCLASSED:               return "DDERR_HWNDSUBCLASSED";
    	   case DDERR_HWNDALREADYSET:               return "DDERR_HWNDALREADYSET";
    	   case DDERR_NOPALETTEATTACHED:            return "DDERR_NOPALETTEATTACHED";
    	   case DDERR_NOPALETTEHW:                  return "DDERR_NOPALETTEHW";
    	   case DDERR_BLTFASTCANTCLIP:              return "DDERR_BLTFASTCANTCLIP";
    	   case DDERR_NOBLTHW:                      return "DDERR_NOBLTHW";
    	   case DDERR_NODDROPSHW:                   return "DDERR_NODDROPSHW";
    	   case DDERR_OVERLAYNOTVISIBLE:            return "DDERR_OVERLAYNOTVISIBLE";
    	   case DDERR_NOOVERLAYDEST:                return "DDERR_NOOVERLAYDEST";
    	   case DDERR_INVALIDPOSITION:              return "DDERR_INVALIDPOSITION";
    	   case DDERR_NOTAOVERLAYSURFACE:           return "DDERR_NOTAOVERLAYSURFACE";
    	   case DDERR_EXCLUSIVEMODEALREADYSET:      return "DDERR_EXCLUSIVEMODEALREADYSET";
    	   case DDERR_NOTFLIPPABLE:                 return "DDERR_NOTFLIPPABLE";
    	   case DDERR_CANTDUPLICATE:                return "DDERR_CANTDUPLICATE";
    	   case DDERR_NOTLOCKED:                    return "DDERR_NOTLOCKED";
    	   case DDERR_CANTCREATEDC:                 return "DDERR_CANTCREATEDC";
    	   case DDERR_NODC:                         return "DDERR_NODC";
    	   case DDERR_WRONGMODE:                    return "DDERR_WRONGMODE";
    	   case DDERR_IMPLICITLYCREATED:            return "DDERR_IMPLICITLYCREATED";
    	   case DDERR_NOTPALETTIZED:                return "DDERR_NOTPALETTIZED";
    	   case DDERR_UNSUPPORTEDMODE:              return "DDERR_UNSUPPORTEDMODE";
    	   case DDERR_NOMIPMAPHW:                   return "DDERR_NOMIPMAPHW";
    	   case DDERR_INVALIDSURFACETYPE:           return "DDERR_INVALIDSURFACETYPE";
    	   case DDERR_DCALREADYCREATED:             return "DDERR_DCALREADYCREATED";
    	   case DDERR_CANTPAGELOCK:                 return "DDERR_CANTPAGELOCK";
    	   case DDERR_CANTPAGEUNLOCK:               return "DDERR_CANTPAGEUNLOCK";
    	   case DDERR_NOTPAGELOCKED:                return "DDERR_NOTPAGELOCKED";
    	   case DDERR_NOTINITIALIZED:               return "DDERR_NOTINITIALIZED";
          default:                                 return "DDERR_UNKNOWN";
    	}
    }

    void DDDisplay::CheckDDRVal(char* Method)
    {
       if(DDRVal == DD_OK)
          return;

       if(DDRVal == DDERR_SURFACELOST)
       {
          DDRVal = PrimarySurface->Restore();
          if(DDRVal == DD_OK)
             return;
       }

       char Message[256];

       wsprintf(Message, "Direct Draw Method \"%s\" Failed: %s (%d).\nPress OK to close the program.  Press CANCEL to ignore the error.", Method, DDRValToString(DDRVal), DDRVal);
       int button = MessageBox(hWnd, Message, "ERROR", MB_OKCANCEL | MB_ICONSTOP);

       if(button == IDCANCEL)
          return;
       else
       {
          ReleaseAllObjects();
          exit(EXIT_FAILURE);
       }
    }

    void DDDisplay::ReleaseAllObjects()
    {
       if(DirectDraw)
       {
          if(PrimarySurface)
          {
             PrimarySurface->Release();
             PrimarySurface = NULL;
          }
          DirectDraw->Release();
          DirectDraw = NULL;
       }

    	delete[] DepthBuffer;

       Active = false;
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [DebugLog.cpp] - (2,217 bytes)

    #include "DebugLog.h"
    DebugLog Log(DEBUG_LOG);

    #include <stdarg.h>
    #include <time.h>

    DebugLog::DebugLog(const char *file)
    {
       File = file;
       hFile = NULL;

    	New();
    }

    void DebugLog::New()
    {
    	hFile = fopen(File, "wt");
       fprintf(hFile, "==== Debug Log File ==== \n\n");

       time_t ltime;
       time(<ime);

    	fprintf(hFile, "%s\n\n", ctime(<ime));   // Include date and time

       fclose(hFile);
    }

    void __cdecl DebugLog::printf(const char *Format, ...)
    {
    	char Buffer[256];
       va_list ArgList;

       va_start(ArgList, Format);
       _vsnprintf(Buffer, 256, Format, ArgList);
       va_end(ArgList);

       hFile = fopen(File, "at");
       fprintf(hFile, Buffer);
       fclose(hFile);
    }

    DebugLog &DebugLog::operator<<(char ch)
    {
    	printf("%c", ch);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(unsigned char uch)
    {
    	printf("%c", uch);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(signed char sch)
    {
    	printf("%c", sch);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(const char* psz)
    {
    	printf(psz);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(const unsigned char* pusz)
    {
    	printf((const char*)pusz);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(const signed char* pssz)
    {
    	printf((const char*)pssz);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(short s)
    {
    	printf("%hi", s);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(unsigned short us)
    {
    	printf("%hu", us);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(int n)
    {
    	printf("%i", n);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(unsigned int un)
    {
    	printf("%u", un);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(long l)
    {
    	printf("%li", l);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(unsigned long ul)
    {
    	printf("%lu", ul);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(float f)
    {
    	printf("%g", f);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(double d)
    {
    	printf("%g", d);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(long double ld)
    {
    	printf("%g", ld);

    	return *this;
    }

    DebugLog &DebugLog::operator<<(const void* pv)
    {
    	printf("%p", pv);

    	return *this;
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [DIDevice.cpp] - (477 bytes)

    #include "DIDevice.h"
    DIDevice Input;

    IDirectInput *DIDevice::DirectInput;

    DIDevice::DIDevice()
    {
    	DirectInput = NULL;
    }

    DIDevice::~DIDevice()
    {
    	ReleaseDirectInput();
    }

    void DIDevice::Init(HWND Handle)
    {
    	hWnd = Handle;

    	DirectInputCreate((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), DIRECTINPUT_VERSION, &DirectInput, NULL);
    }

    void DIDevice::ReleaseDirectInput()
    {
    	if(DirectInput)
    	{
    		DirectInput->Release();
    		DirectInput = NULL;
    	}
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [DIKeyboard.cpp] - (750 bytes)

    #include "DIKeyboard.h"
    DIKeyboard Keyboard;

    IDirectInputDevice *DIKeyboard::Keyboard;

    DIKeyboard::DIKeyboard()
    {
    	Keyboard = NULL;
    }

    DIKeyboard::~DIKeyboard()
    {
    	ReleaseKeyboard();
    }

    void DIKeyboard::Init()
    {
    	DirectInput->CreateDevice(GUID_SysKeyboard, &Keyboard, NULL);

    	Keyboard->SetDataFormat(&c_dfDIKeyboard);

       Keyboard->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
    }

    void DIKeyboard::SetAcquire()
    {
    	Keyboard->Acquire();
    }

    void DIKeyboard::Input()
    {
    	Keyboard->GetDeviceState(sizeof(Key), &Key);
    }

    bool DIKeyboard::KeyPressed(int k)
    {
    	return (Key[k] & 0x80) != 0;
    }

    void DIKeyboard::ReleaseKeyboard()
    {
    	if(Keyboard)
    	{
    		Keyboard->Release();
    		Keyboard = NULL;
    	}
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [DIMouse.cpp] - (804 bytes)

    #include "DIMouse.h"
    DIMouse Mouse;

    IDirectInputDevice *DIMouse::Mouse;

    DIMouse::DIMouse()
    {
    	Mouse = NULL;
    }

    DIMouse::~DIMouse()
    {
    	ReleaseMouse();
    }

    void DIMouse::Init()
    {
       DirectInput->CreateDevice(GUID_SysMouse, &Mouse, NULL);

       Mouse->SetDataFormat(&c_dfDIMouse);

       Mouse->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
    }

    void DIMouse::SetAcquire()
    {
    	Mouse->Acquire();
    }

    void DIMouse::Input()
    {
    	DIMOUSESTATE dims;

    	Mouse->GetDeviceState(sizeof(DIMOUSESTATE), &dims);

    	dx = dims.lX;
    	dy = dims.lY;
    	dz = dims.lZ;
       b1 = dims.rgbButtons[0];
       b2 = dims.rgbButtons[1];
       b3 = dims.rgbButtons[2];
       b4 = dims.rgbButtons[3];
    }

    void DIMouse::ReleaseMouse()
    {
    	if(Mouse)
    	{
    		Mouse->Release();
    		Mouse = NULL;
    	}
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [FPSCounter.cpp] - (429 bytes)

    #include "FPSCounter.h"

    #include "Timer.h"

    FPSCounter::FPSCounter()
    {
    	CurrentFPS = 0.0f;
    	FPSFrame = 0;
    	StartTime = Timer::Ticks();
    }

    void FPSCounter::NewFrame()
    {
    	FPSFrame++;

    	double CurrentTime = Timer::Ticks();
    	double ElapsedTime = CurrentTime - StartTime;

    	if(ElapsedTime >= FPS_UPDATE)
    	{
    		CurrentFPS = (float)FPSFrame / (float)ElapsedTime;

    		FPSFrame = 0;
    		StartTime = CurrentTime;
    	}
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Main.cpp] - (2,742 bytes)

    #include "Main.h"

    #include "DDDisplay.h"
    #include "DIKeyboard.h"
    #include "DIMouse.h"
    #include "Render.h"

    #include <windows.h>

    #define IDI_MAIN_ICON 101
    #define IDR_MENU 102
    #define IDM_EXIT 40001

    #define NAME "Real Virtuality"

    long WINAPI WindowProc(HWND hWnd, unsigned int Message, unsigned int wParam, long lParam)
    {
       switch(Message)
       {
          case WM_ACTIVATE:
             // Pause if minimized
             Display.Active = !((BOOL)HIWORD(wParam));
             return 0L;

          case WM_DESTROY:
             // Clean up and close the app
    			PostQuitMessage(0);
             return 0L;

          case WM_KEYDOWN:
             // hWnd any non-accelerated key commands
             switch(wParam)
             {
                case VK_ESCAPE:
                case VK_F12:
                   PostMessage(hWnd, WM_CLOSE, 0, 0);
                   return 0L;
             }
             break;

          case WM_SETCURSOR:
             // Turn off the cursor since this is a full-screen app
             SetCursor(NULL);
             return true;
       }

       return DefWindowProc(hWnd, Message, wParam, lParam);
    }

    HWND InitApp(HINSTANCE hInstance, int nCmdShow)
    {
       HWND hWnd = NULL;
       WNDCLASS WC;

        // Set up and register window class
    	WC.lpfnWndProc = WindowProc;   // Call back function
    	WC.style = CS_HREDRAW | CS_VREDRAW;
    	WC.cbClsExtra = 0;
    	WC.cbWndExtra = 0;
    	WC.hInstance = hInstance;
    	WC.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
    	WC.hCursor = LoadCursor(NULL, IDC_ARROW);
    	WC.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH);
    	WC.lpszMenuName = NAME;
    	WC.lpszClassName = NAME;
    	RegisterClass(&WC);

    	// Create a window
    	hWnd = CreateWindowEx(WS_EX_TOPMOST, NAME, NAME, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);

    	ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
       SetFocus(hWnd);

       return hWnd;
    }

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
       MSG Msg;
       HWND hWnd;

       hPrevInstance;   // Just to avoid compiler warning
       lpCmdLine;   // Just to avoid compiler warning

    	int Width = 1024;
    	int Height = 768;
    	int BPP = 32;

       hWnd = InitApp(hInstance, nCmdShow);

    	Display.Init(hWnd, Width, Height, BPP);
    	Input.Init(hWnd);
    	Keyboard.Init();
    	Keyboard.SetAcquire();
    	Mouse.Init();
    	Mouse.SetAcquire();

       while(true)
       {
          if(PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE))
          {
             if (!GetMessage(&Msg, NULL, 0, 0))
                return Msg.wParam;
             TranslateMessage(&Msg);
             DispatchMessage(&Msg);
          }
          else if(Display.Active)
             Render();
          else
             WaitMessage();
       }
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Matrix.cpp] - (15,865 bytes)

    #include "Matrix.h"

    #include "Vector.h"
    #include "Point.h"
    #include "Quaternion.h"

    #include <math.h>

    Matrix::Matrix()
    {
    }

    Matrix::Matrix(const int i)
    {
    	const float s = (float)i;

    	Matrix &A = *this;

    	A(1, 1) = s;  A(1, 2) = 0;  A(1, 3) = 0;  A(1, 4) = 0;
    	A(2, 1) = 0;  A(2, 2) = s;  A(2, 3) = 0;  A(2, 4) = 0;
    	A(3, 1) = 0;  A(3, 2) = 0;  A(3, 3) = s;  A(3, 4) = 0;
    	A(4, 1) = 0;  A(4, 2) = 0;  A(4, 3) = 0;  A(4, 4) = s;
    }

    Matrix::Matrix(const float a[16])
    {
    	Matrix &A = *this;

    	A(1, 1) = a[0];   A(1, 2) = a[1];   A(1, 3) = a[2];   A(1, 4) = a[3];
    	A(2, 1) = a[4];   A(2, 2) = a[5];   A(2, 3) = a[6];   A(2, 4) = a[7];
    	A(3, 1) = a[8];   A(3, 2) = a[8];   A(3, 3) = a[10];  A(3, 4) = a[11];
    	A(4, 1) = a[12];  A(4, 2) = a[13];  A(4, 3) = a[14];  A(4, 4) = a[15];
    }

    Matrix::Matrix(const float a[4][4])
    {
    	Matrix &A = *this;

    	A[0][0] = a[0][0];  A[0][1] = a[0][1];  A[0][2] = a[0][2];  A[0][3] = a[0][3];
    	A[1][0] = a[1][0];  A[1][1] = a[1][1];  A[1][2] = a[0][2];  A[1][3] = a[0][3];
    	A[2][0] = a[2][0];  A[2][1] = a[2][1];  A[2][2] = a[0][2];  A[2][3] = a[0][3];
    	A[3][0] = a[3][0];  A[3][1] = a[3][1];  A[3][2] = a[0][2];  A[3][3] = a[0][3];
    }

    Matrix::Matrix(float A_11, float A_12, float A_13,
                   float A_21, float A_22, float A_23,
                   float A_31, float A_32, float A_33)
    {
    	Matrix &A = *this;

    	A(1, 1) = A_11;  A(1, 2) = A_12;  A(1, 3) = A_13;  A(1, 4) = 0;
    	A(2, 1) = A_21;  A(2, 2) = A_22;  A(2, 3) = A_23;  A(2, 4) = 0;
    	A(3, 1) = A_31;  A(3, 2) = A_32;  A(3, 3) = A_33;  A(3, 4) = 0;
    	A(4, 1) = 0;     A(4, 2) = 0;     A(4, 3) = 0;     A(4, 4) = 1;
    }

    Matrix::Matrix(float A_11, float A_12, float A_13, float A_14,
                   float A_21, float A_22, float A_23, float A_24,
                   float A_31, float A_32, float A_33, float A_34,
                   float A_41, float A_42, float A_43, float A_44)
    {
    	Matrix &A = *this;

    	A(1, 1) = A_11;  A(1, 2) = A_12;  A(1, 3) = A_13;  A(1, 4) = A_14;
    	A(2, 1) = A_21;  A(2, 2) = A_22;  A(2, 3) = A_23;  A(2, 4) = A_24;
    	A(3, 1) = A_31;  A(3, 2) = A_32;  A(3, 3) = A_33;  A(3, 4) = A_34;
    	A(4, 1) = A_41;  A(4, 2) = A_42;  A(4, 3) = A_43;  A(4, 4) = A_44;
    }

    Matrix::Matrix(const Vector &v1, const Vector &v2, const Vector &v3)
    {
    	Matrix &A = *this;

    	A(1, 1) = v1.x;  A(1, 2) = v2.x;  A(1, 3) = v3.x;  A(1, 4) = 0;
    	A(2, 1) = v1.y;  A(2, 2) = v2.y;  A(2, 3) = v3.y;  A(2, 4) = 0;
    	A(3, 1) = v1.z;  A(3, 2) = v2.z;  A(3, 3) = v3.z;  A(3, 4) = 0;
    	A(4, 1) = 0;     A(4, 2) = 0;     A(4, 3) = 0;     A(4, 4) = 1;
    }

    Matrix &Matrix::operator=(const Matrix &B)
    {
    	Matrix &A = *this;

    	A(1, 1) = B(1, 1);  A(1, 2) = B(1, 2);  A(1, 3) = B(1, 3);  A(1, 4) = B(1, 4);
    	A(2, 1) = B(2, 1);  A(2, 2) = B(2, 2);  A(2, 3) = B(2, 3);  A(2, 4) = B(2, 4);
    	A(3, 1) = B(3, 1);  A(3, 2) = B(3, 2);  A(3, 3) = B(3, 3);  A(3, 4) = B(3, 4);
    	A(4, 1) = B(4, 1);  A(4, 2) = B(4, 2);  A(4, 3) = B(4, 3);  A(4, 4) = B(4, 4);

    	return A;
    }

    Matrix diag(float A_11, float A_22, float A_33, float A_44)
    {
    	Matrix A;

    	A(1, 1) = A_11;  A(1, 2) = 0;     A(1, 3) = 0;     A(1, 4) = 0;
    	A(2, 1) = 0;     A(2, 2) = A_22;  A(2, 3) = 0;     A(2, 4) = 0;
    	A(3, 1) = 0;     A(3, 2) = 0;     A(3, 3) = A_33;  A(3, 4) = 0;
    	A(4, 1) = 0;     A(4, 2) = 0;     A(4, 3) = 0;     A(4, 4) = A_44;

    	return A;
    }

    Matrix::operator float*()
    {
    	return &(*this)(1, 1);
    }

    Matrix Matrix::operator+() const
    {
    	return *this;
    }

    Matrix Matrix::operator-() const
    {
    	const Matrix &A = *this;

    	return Matrix(-A(1, 1), -A(1, 2), -A(1, 3), -A(1, 4),
    	              -A(2, 1), -A(2, 2), -A(2, 3), -A(2, 4),
    	              -A(3, 1), -A(3, 2), -A(3, 3), -A(3, 4),
    	              -A(4, 1), -A(4, 2), -A(4, 3), -A(4, 4));
    }

    Matrix Matrix::operator!() const
    {
    	const Matrix &A = *this;
    	Matrix I;

    	float M3344 = A(3, 3) * A(4, 4) - A(4, 3) * A(3, 4);
    	float M2344 = A(2, 3) * A(4, 4) - A(4, 3) * A(2, 4);
    	float M2334 = A(2, 3) * A(3, 4) - A(3, 3) * A(2, 4);
    	float M3244 = A(3, 2) * A(4, 4) - A(4, 2) * A(3, 4);
    	float M2244 = A(2, 2) * A(4, 4) - A(4, 2) * A(2, 4);
    	float M2234 = A(2, 2) * A(3, 4) - A(3, 2) * A(2, 4);
    	float M3243 = A(3, 2) * A(4, 3) - A(4, 2) * A(3, 3);
    	float M2243 = A(2, 2) * A(4, 3) - A(4, 2) * A(2, 3);
    	float M2233 = A(2, 2) * A(3, 3) - A(3, 2) * A(2, 3);
    	float M1344 = A(1, 3) * A(4, 4) - A(4, 3) * A(1, 4);
    	float M1334 = A(1, 3) * A(3, 4) - A(3, 3) * A(1, 4);
    	float M1244 = A(1, 2) * A(4, 4) - A(4, 2) * A(1, 4);
    	float M1234 = A(1, 2) * A(3, 4) - A(3, 2) * A(1, 4);
    	float M1243 = A(1, 2) * A(4, 3) - A(4, 2) * A(1, 3);
    	float M1233 = A(1, 2) * A(3, 3) - A(3, 2) * A(1, 3);
    	float M1324 = A(1, 3) * A(2, 4) - A(2, 3) * A(1, 4);
    	float M1224 = A(1, 2) * A(2, 4) - A(2, 2) * A(1, 4);
    	float M1223 = A(1, 2) * A(2, 3) - A(2, 2) * A(1, 3);

    	// Adjoint Matrix
    	I(1, 1) =  A(2, 2) * M3344 - A(3, 2) * M2344 + A(4, 2) * M2334;
    	I(2, 1) = -A(2, 1) * M3344 + A(3, 1) * M2344 - A(4, 1) * M2334;
    	I(3, 1) =  A(2, 1) * M3244 - A(3, 1) * M2244 + A(4, 1) * M2234;
    	I(4, 1) = -A(2, 1) * M3243 + A(3, 1) * M2243 - A(4, 1) * M2233;

    	I(1, 2) = -A(1, 2) * M3344 + A(3, 2) * M1344 - A(4, 2) * M1334;
    	I(2, 2) =  A(1, 1) * M3344 - A(3, 1) * M1344 + A(4, 1) * M1334;
    	I(3, 2) = -A(1, 1) * M3244 + A(3, 1) * M1244 - A(4, 1) * M1234;
    	I(4, 2) =  A(1, 1) * M3243 - A(3, 1) * M1243 + A(4, 1) * M1233;

    	I(1, 3) =  A(1, 2) * M2344 - A(2, 2) * M1344 + A(4, 2) * M1324;
    	I(2, 3) = -A(1, 1) * M2344 + A(2, 1) * M1344 - A(4, 1) * M1324;
    	I(3, 3) =  A(1, 1) * M2244 - A(2, 1) * M1244 + A(4, 1) * M1224;
    	I(4, 3) = -A(1, 1) * M2243 + A(2, 1) * M1243 - A(4, 1) * M1223;

    	I(1, 4) = -A(1, 2) * M2334 + A(2, 2) * M1334 - A(3, 2) * M1324;
    	I(2, 4) =  A(1, 1) * M2334 - A(2, 1) * M1334 + A(3, 1) * M1324;
    	I(3, 4) = -A(1, 1) * M2234 + A(2, 1) * M1234 - A(3, 1) * M1224;
    	I(4, 4) =  A(1, 1) * M2233 - A(2, 1) * M1233 + A(3, 1) * M1223;

    	// Divide by determinant
    	I /= A(1, 1) * I(1, 1) +
    	     A(2, 1) * I(1, 2) +
    	     A(3, 1) * I(1, 3) +
    	     A(4, 1) * I(1, 4);

    	return I;
    }

    Matrix Matrix::operator~() const
    {
    	const Matrix &A = *this;

    	return Matrix(A(1, 1), A(2, 1), A(3, 1), A(4, 1),
    	              A(1, 2), A(2, 2), A(3, 2), A(4, 2),
    	              A(1, 3), A(2, 3), A(3, 3), A(4, 3),
    	              A(1, 4), A(2, 4), A(3, 4), A(4, 4));
    }

    Matrix &Matrix::operator+=(const Matrix &B)
    {
    	Matrix &A = *this;

    	A(1, 1) += B(1, 1);  A(1, 2) += B(1, 2);  A(1, 3) += B(1, 3);  A(1, 4) += B(1, 4);
    	A(2, 1) += B(2, 1);  A(2, 2) += B(2, 2);  A(2, 3) += B(2, 3);  A(2, 4) += B(2, 4);
    	A(3, 1) += B(3, 1);  A(3, 2) += B(3, 2);  A(3, 3) += B(3, 3);  A(3, 4) += B(3, 4);
    	A(4, 1) += B(4, 1);  A(4, 2) += B(4, 2);  A(4, 3) += B(4, 3);  A(4, 4) += B(4, 4);

    	return A;
    }

    Matrix &Matrix::operator-=(const Matrix &B)
    {
    	Matrix &A = *this;

    	A(1, 1) -= B(1, 1);  A(1, 2) -= B(1, 2);  A(1, 3) -= B(1, 3);  A(1, 4) -= B(1, 4);
    	A(2, 1) -= B(2, 1);  A(2, 2) -= B(2, 2);  A(2, 3) -= B(2, 3);  A(2, 4) -= B(2, 4);
    	A(3, 1) -= B(3, 1);  A(3, 2) -= B(3, 2);  A(3, 3) -= B(3, 3);  A(3, 4) -= B(3, 4);
    	A(4, 1) -= B(4, 1);  A(4, 2) -= B(4, 2);  A(4, 3) -= B(4, 3);  A(4, 4) -= B(4, 4);

    	return A;
    }

    Matrix &Matrix::operator*=(float s)
    {
    	Matrix &A = *this;

    	A(1, 1) *= s;  A(1, 2) *= s;  A(1, 3) *= s;  A(1, 4) *= s;
    	A(2, 1) *= s;  A(2, 2) *= s;  A(2, 3) *= s;  A(2, 4) *= s;
    	A(3, 1) *= s;  A(3, 2) *= s;  A(3, 3) *= s;  A(3, 4) *= s;
    	A(4, 1) *= s;  A(4, 2) *= s;  A(4, 3) *= s;  A(4, 4) *= s;

    	return A;
    }

    Matrix &Matrix::operator*=(const Matrix &A)
    {
    	return *this = *this * A;
    }

    Matrix &Matrix::operator/=(float s)
    {
    	float r = 1.0f / s;

    	return *this *= r;
    }

    bool operator==(const Matrix &A, const Matrix &B)
    {
    	if(A(1, 1) == B(1, 1) && A(1, 2) == B(1, 2) && A(1, 3) == B(1, 3) && A(1, 4) == B(1, 4) &&
    	   A(2, 1) == B(2, 1) && A(2, 2) == B(2, 2) && A(2, 3) == B(2, 3) && A(2, 4) == B(2, 4) &&
    	   A(3, 1) == B(3, 1) && A(3, 2) == B(3, 2) && A(3, 3) == B(3, 3) && A(3, 4) == B(3, 4) &&
    	   A(4, 1) == B(4, 1) && A(4, 2) == B(4, 2) && A(4, 3) == B(4, 3) && A(4, 4) == B(4, 4))
    		return true;
    	else
    		return false;
    }

    bool operator!=(const Matrix &A, const Matrix &B)
    {
    	if(A(1, 1) != B(1, 1) || A(1, 2) != B(1, 2) || A(1, 3) != B(1, 3) || A(1, 4) != B(1, 4) ||
    	   A(2, 1) != B(2, 1) || A(2, 2) != B(2, 2) || A(2, 3) != B(2, 3) || A(2, 4) != B(2, 4) ||
    	   A(3, 1) != B(3, 1) || A(3, 2) != B(3, 2) || A(3, 3) != B(3, 3) || A(3, 4) != B(3, 4) ||
    	   A(4, 1) != B(4, 1) || A(4, 2) != B(4, 2) || A(4, 3) != B(4, 3) || A(4, 4) != B(4, 4))
    		return true;
    	else
    		return false;
    }

    Matrix operator+(const Matrix &A, const Matrix &B)
    {
    	return Matrix(A(1, 1) + B(1, 1), A(1, 2) + B(1, 2), A(1, 3) + B(1, 3), A(1, 4) + B(1, 4),
    	              A(2, 1) + B(2, 1), A(2, 2) + B(2, 2), A(2, 3) + B(2, 3), A(2, 4) + B(2, 4),
    	              A(3, 1) + B(3, 1), A(3, 2) + B(3, 2), A(3, 3) + B(3, 3), A(3, 4) + B(3, 4),
    	              A(4, 1) + B(4, 1), A(4, 2) + B(4, 2), A(4, 3) + B(4, 3), A(4, 4) + B(4, 4));
    }

    Matrix operator-(const Matrix &A, const Matrix &B)
    {
    	return Matrix(A(1, 1) - B(1, 1), A(1, 2) - B(1, 2), A(1, 3) - B(1, 3), A(1, 4) - B(1, 4),
    	              A(2, 1) - B(2, 1), A(2, 2) - B(2, 2), A(2, 3) - B(2, 3), A(2, 4) - B(2, 4),
    	              A(3, 1) - B(3, 1), A(3, 2) - B(3, 2), A(3, 3) - B(3, 3), A(3, 4) - B(3, 4),
    	              A(4, 1) - B(4, 1), A(4, 2) - B(4, 2), A(4, 3) - B(4, 3), A(4, 4) - B(4, 4));
    }

    Matrix operator*(float s, const Matrix &A)
    {
    	return Matrix(s * A(1, 1), s * A(1, 2), s * A(1, 3), s * A(1, 4),
    	              s * A(2, 1), s * A(2, 2), s * A(2, 3), s * A(2, 4),
    	              s * A(3, 1), s * A(3, 2), s * A(3, 3), s * A(3, 4),
    	              s * A(4, 1), s * A(4, 2), s * A(4, 3), s * A(4, 4));
    }

    Matrix operator*(const Matrix &A, float s)
    {
    	return Matrix(A(1, 1) * s, A(1, 2) * s, A(1, 3) * s, A(1, 4) * s,
    	              A(2, 1) * s, A(2, 2) * s, A(2, 3) * s, A(2, 4) * s,
    	              A(3, 1) * s, A(3, 2) * s, A(3, 3) * s, A(3, 4) * s,
    	              A(4, 1) * s, A(4, 2) * s, A(4, 3) * s, A(4, 4) * s);
    }

    Matrix operator*(const Matrix &A, const Matrix &B)
    {
    	return Matrix(A(1, 1) * B(1, 1) + A(1, 2) * B(2, 1) + A(1, 3) * B(3, 1) + A(1, 4) * B(4, 1), A(1, 1) * B(1, 2) + A(1, 2) * B(2, 2) + A(1, 3) * B(3, 2) + A(1, 4) * B(4, 2), A(1, 1) * B(1, 3) + A(1, 2) * B(2, 3) + A(1, 3) * B(3, 3) + A(1, 4) * B(4, 3), A(1, 1) * B(1, 4) + A(1, 2) * B(2, 4) + A(1, 3) * B(3, 4) + A(1, 4) * B(4, 4),
    	              A(2, 1) * B(1, 1) + A(2, 2) * B(2, 1) + A(2, 3) * B(3, 1) + A(2, 4) * B(4, 1), A(2, 1) * B(1, 2) + A(2, 2) * B(2, 2) + A(2, 3) * B(3, 2) + A(2, 4) * B(4, 2), A(2, 1) * B(1, 3) + A(2, 2) * B(2, 3) + A(2, 3) * B(3, 3) + A(2, 4) * B(4, 3), A(2, 1) * B(1, 4) + A(2, 2) * B(2, 4) + A(2, 3) * B(3, 4) + A(2, 4) * B(4, 4),
    	              A(3, 1) * B(1, 1) + A(3, 2) * B(2, 1) + A(3, 3) * B(3, 1) + A(3, 4) * B(4, 1), A(3, 1) * B(1, 2) + A(3, 2) * B(2, 2) + A(3, 3) * B(3, 2) + A(3, 4) * B(4, 2), A(3, 1) * B(1, 3) + A(3, 2) * B(2, 3) + A(3, 3) * B(3, 3) + A(3, 4) * B(4, 3), A(3, 1) * B(1, 4) + A(3, 2) * B(2, 4) + A(3, 3) * B(3, 4) + A(3, 4) * B(4, 4),
    	              A(4, 1) * B(1, 1) + A(4, 2) * B(2, 1) + A(4, 3) * B(3, 1) + A(4, 4) * B(4, 1), A(4, 1) * B(1, 2) + A(4, 2) * B(2, 2) + A(4, 3) * B(3, 2) + A(4, 4) * B(4, 2), A(4, 1) * B(1, 3) + A(4, 2) * B(2, 3) + A(4, 3) * B(3, 3) + A(4, 4) * B(4, 3), A(4, 1) * B(1, 4) + A(4, 2) * B(2, 4) + A(4, 3) * B(3, 4) + A(4, 4) * B(4, 4));
    }

    Matrix operator/(const Matrix &A, float s)
    {
    	float r = 1.0f / s;

    	return A * s;
    }

    Vector Matrix::operator*(const Vector &v) const
    {
    	const Matrix &A = *this;

    	return Vector(A(1, 1) * v.x + A(1, 2) * v.y + A(1, 3) * v.z,
    	              A(2, 1) * v.x + A(2, 2) * v.y + A(2, 3) * v.z,
    	              A(3, 1) * v.x + A(3, 2) * v.y + A(3, 3) * v.z);
    }

    Point Matrix::operator*(const Point &P) const
    {
    	const Matrix &A = *this;

    	return Point(A(1, 1) * P.x + A(1, 2) * P.y + A(1, 3) * P.z + A(1, 4),
    	             A(2, 1) * P.x + A(2, 2) * P.y + A(2, 3) * P.z + A(2, 4),
    	             A(3, 1) * P.x + A(3, 2) * P.y + A(3, 3) * P.z + A(3, 4));
    }

    Quaternion Matrix::operator*(const Quaternion &Q) const
    {
    	const Matrix &A = *this;

    	return Quaternion(A(1, 1) * Q.x + A(1, 2) * Q.y + A(1, 3) * Q.z + A(1, 4) * Q.w,
    	                  A(2, 1) * Q.x + A(2, 2) * Q.y + A(2, 3) * Q.z + A(2, 4) * Q.w,
    	                  A(3, 1) * Q.x + A(3, 2) * Q.y + A(3, 3) * Q.z + A(3, 4) * Q.w,
    							A(4, 1) * Q.x + A(4, 2) * Q.y + A(4, 3) * Q.z + A(4, 4) * Q.w);
    }

    Vector operator*(const Vector &v, const Matrix &A)
    {
    	return Vector(v.x * A(1, 1) + v.y * A(2, 1) + v.z * A(3, 1) + A(4, 1),
    	              v.x * A(1, 2) + v.y * A(2, 2) + v.z * A(3, 2) + A(4, 2),
    	              v.x * A(1, 3) + v.y * A(2, 3) + v.z * A(3, 3) + A(4, 3));
    }

    Point operator*(const Point &P, const Matrix &A)
    {
    	return Point(P.x * A(1, 1) + P.y * A(2, 1) + P.z * A(3, 1),
    	             P.x * A(1, 2) + P.y * A(2, 2) + P.z * A(3, 2),
    	             P.x * A(1, 3) + P.y * A(2, 3) + P.z * A(3, 3));
    }

    Quaternion operator*(const Quaternion &Q, const Matrix &A)
    {
    	return Quaternion(Q.x * A(1, 1) + Q.y * A(2, 1) + Q.z + A(3, 1) + Q.w * A(4, 1),
    	                  Q.x * A(1, 2) + Q.y * A(2, 2) + Q.z + A(3, 2) + Q.w * A(4, 2),
    	                  Q.x * A(1, 3) + Q.y * A(2, 3) + Q.z + A(3, 3) + Q.w * A(4, 3),
    							Q.x * A(1, 4) + Q.y * A(2, 4) + Q.z + A(3, 4) + Q.w * A(4, 4));
    }

    Vector &operator*=(Vector &v, const Matrix &A)
    {
    	return v = v * A;
    }

    Point &operator*=(Point &P, const Matrix &A)
    {
    	return P = P * A;
    }

    Quaternion &operator*=(Quaternion &Q, const Matrix &A)
    {
    	return Q = Q * A;
    }

    float det(const Matrix &A)
    {
    	float M3344 = A(3, 3) * A(4, 4) - A(4, 3) * A(3, 4);
    	float M2344 = A(2, 3) * A(4, 4) - A(4, 3) * A(2, 4);
    	float M2334 = A(2, 3) * A(3, 4) - A(3, 3) * A(2, 4);
    	float M1344 = A(1, 3) * A(4, 4) - A(4, 3) * A(1, 4);
    	float M1334 = A(1, 3) * A(3, 4) - A(3, 3) * A(1, 4);
    	float M1324 = A(1, 3) * A(2, 4) - A(2, 3) * A(1, 4);

    	return A(1, 1) * (A(2, 2) * M3344 - A(3, 2) * M2344 + A(4, 2) * M2334) -
    	       A(2, 1) * (A(1, 2) * M3344 - A(3, 2) * M1344 + A(4, 2) * M1334) +
    	       A(3, 1) * (A(1, 2) * M2344 - A(2, 2) * M1344 + A(4, 2) * M1324) -
    	       A(4, 1) * (A(1, 2) * M2334 - A(2, 2) * M1334 + A(3, 2) * M1324);
    }

    float det(float A_11)
    {
    	return A_11;
    }

    float det(float A_11, float A_12,
              float A_21, float A_22)
    {
    	return A_11 * A_22 - A_12 * A_21;
    }

    float det(float A_11, float A_12, float A_13,
              float A_21, float A_22, float A_23,
              float A_31, float A_32, float A_33)
    {
    	return A_11 * (A_22 * A_33 - A_32 * A_23) -
    	       A_21 * (A_12 * A_33 - A_32 * A_13) +
    	       A_31 * (A_12 * A_23 - A_22 * A_13);
    }

    float det(float A_11, float A_12, float A_13, float A_14,
              float A_21, float A_22, float A_23, float A_24,
              float A_31, float A_32, float A_33, float A_34,
              float A_41, float A_42, float A_43, float A_44)
    {
    	float M3344 = A_33 * A_44 - A_43 * A_34;
    	float M2344 = A_23 * A_44 - A_43 * A_24;
    	float M2334 = A_23 * A_34 - A_33 * A_24;
    	float M1344 = A_13 * A_44 - A_43 * A_14;
    	float M1334 = A_13 * A_34 - A_33 * A_14;
    	float M1324 = A_13 * A_24 - A_23 * A_14;

    	return A_11 * (A_22 * M3344 - A_32 * M2344 + A_42 * M2334) -
    	       A_21 * (A_12 * M3344 - A_32 * M1344 + A_42 * M1334) +
    	       A_31 * (A_12 * M2344 - A_22 * M1344 + A_42 * M1324) -
    	       A_41 * (A_12 * M2334 - A_22 * M1334 + A_32 * M1324);
    }

    float det(const Vector &v1, const Vector &v2, const Vector &v3)
    {
    	return v1 * (v2 % v3);
    }

    float tr(const Matrix &A)
    {
    	return A(1, 1) + A(2, 2) + A(3, 3) + A(4, 4);
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Point.cpp] - (1,250 bytes)

    #include "Point.h"

    #include "Vector.h"

    Point::Point() : x(Element[0]), y(Element[1]), z(Element[2])
    {
    }

    Point::Point(const Point &P) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	x = P.x;
    	y = P.y;
    	z = P.z;
    }

    Point::Point(const Vector &v) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	x = v.x;
    	y = v.y;
    	z = v.z;
    }

    Point::Point(float P_x, float P_y, float P_z) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	x = P_x;
    	y = P_y;
    	z = P_z;
    }

    Point &Point::operator=(const Point &P)
    {
    	x = P.x;
    	y = P.y;
    	z = P.z;

    	return *this;
    }

    Point &Point::operator+=(const Vector &v)
    {
    	x += v.x;
    	y += v.y;
    	z += v.z;

    	return *this;
    }

    Point &Point::operator-=(const Vector &v)
    {
    	x -= v.x;
    	y -= v.y;
    	z -= v.z;

    	return *this;
    }

    Point operator+(const Point &P, const Vector &v)
    {
    	return Point(P.x + v.x, P.y + v.y, P.z + v.z);
    }

    Point operator-(const Point &P, const Vector &v)
    {
    	return Point(P.x - v.x, P.y - v.y, P.z - v.z);
    }

    Vector operator-(const Point &P, const Point &Q)
    {
    	return Vector(P.x - Q.x, P.y - Q.y, P.z - Q.z);
    }

    float d(const Point &P, const Point &Q)
    {
    	return N(P - Q);
    }

    float d2(const Point &P, const Point &Q)
    {
    	return N2(P - Q);
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Quaternion.cpp] - (4,166 bytes)

    #include "Quaternion.h"

    #include "Point.h"
    #include "Matrix.h"

    #include <math.h>

    Quaternion::Quaternion(const Quaternion &Q)
    {
    	x = Q.x;
    	y = Q.y;
    	z = Q.z;
    	w = Q.w;
    }

    Quaternion::Quaternion(const Quaternion &Q, const Quaternion &R, float t)
    {
    	float a = acosf(Q.x * R.x + Q.y * R.y + Q.z * R.z + Q.w * R.w);   // Angle
    	float s = sinf(a);

    	*this = Q * sinf(a * (1 - t)) / s + R * sinf(a * t) / s;
    }

    Quaternion::Quaternion(float Q_w)
    {
    	v = 0;
    	w = Q_w;
    }

    Quaternion::Quaternion(const Vector &Q_v)
    {
    	v = Q_v;
    	w = 0;
    }

    Quaternion::Quaternion(const Vector &Q_v, float Q_w)
    {
    	v = Q_v;
    	w = Q_w;
    }

    Quaternion::Quaternion(const Point &P, float Q_w)
    {
    	v = P;
    	w = Q_w;
    }

    Quaternion::Quaternion(const Matrix &A)
    {
    	w = 0.5F * sqrtf(tr(A));
    	x = (A(3, 2) - A(2, 3)) / (4 * w);
    	y = (A(1, 3) - A(3, 1)) / (4 * w);
    	z = (A(2, 1) - A(1, 2)) / (4 * w);
    }

    Quaternion::Quaternion(float Q_x, float Q_y, float Q_z, float Q_w)
    {
    	x = Q_x;
    	y = Q_y;
    	z = Q_z;
    	w = Q_w;
    }

    Quaternion &Quaternion::operator=(const Quaternion &Q)
    {
    	x = Q.x;
    	y = Q.y;
    	z = Q.z;
    	w = Q.w;

    	return *this;
    }

    Quaternion::operator float() const
    {
    	return w;
    }

    Quaternion::operator Vector() const
    {
    	return v;
    }

    Quaternion::operator Matrix() const
    {
    	return Matrix(1 - 2 * (y * y + z * z), 2 * (x * y - w * z),     2 * (x * z + w * y),
    	              2 * (x * y + w * z),     1 - 2 * (x * x + z * z), 2 * (y * z - w * x),
    	              2 * (x * z - w * y),     2 * (y * z + w * x),     1 - 2 * (x * x + y * y));
    }

    Quaternion Quaternion::operator+() const
    {
    	return *this;
    }

    Quaternion Quaternion::operator-() const
    {
    	return Quaternion(-x, -y, -z, -w);
    }

    Quaternion Quaternion::operator!() const
    {
    	return ~(*this) / N(*this);
    }

    Quaternion Quaternion::operator~() const
    {
    	return Quaternion(-x, -y, -z, w);
    }

    Quaternion &Quaternion::operator+=(const Quaternion &Q)
    {
    	x += Q.x;
    	y += Q.y;
    	z += Q.z;
    	w += Q.w;

    	return *this;
    }

    Quaternion &Quaternion::operator-=(const Quaternion &Q)
    {
    	x -= Q.x;
    	y -= Q.y;
    	z -= Q.z;
    	w -= Q.w;

    	return *this;
    }

    Quaternion &Quaternion::operator*=(float s)
    {
    	x *= s;
    	y *= s;
    	z *= s;
    	w *= s;

    	return *this;
    }

    Quaternion &Quaternion::operator*=(const Quaternion &Q)
    {
    	float Q_x = w * Q.x + x * Q.w + y * Q.z - z * Q.y;
    	float Q_y = w * Q.y - x * Q.z + y * Q.w + z * Q.x;
    	float Q_z = w * Q.z + x * Q.y - y * Q.x + z * Q.w;
    	float Q_w = w * Q.w - x * Q.x - y * Q.y - z * Q.z;

    	w = Q_w;
    	x = Q_x;
    	y = Q_y;
    	z = Q_z;

    	return (*this);
    }

    Quaternion &Quaternion::operator/=(float s)
    {
    	float r = 1.0f / s;

    	return *this *= r;
    }

    bool operator==(const Quaternion &Q, const Quaternion &R)
    {
    	if(Q.x == R.x && Q.y == R.y && Q.z == R.z && Q.w == R.w)
    		return true;
    	else
    		return false;
    }

    bool operator!=(const Quaternion &Q, const Quaternion &R)
    {
    	if(Q.x != R.x || Q.y != R.y || Q.z != R.z || Q.w != R.w)
    		return true;
    	else
    		return false;
    }

    Quaternion operator+(const Quaternion &Q, const Quaternion &R)
    {
    	return Quaternion(Q.x + R.x, Q.y + R.y, Q.z + R.z, Q.w + R.w);
    }

    Quaternion operator-(const Quaternion &Q, const Quaternion &R)
    {
    	return Quaternion(Q.x - R.x, Q.y - R.y, Q.z - R.z, Q.w - R.w);
    }

    Quaternion operator*(const Quaternion &Q, const Quaternion &R)
    {
    	float x = +Q.x * R.w + Q.y * R.z - Q.z * R.y + Q.w * R.x;
    	float y = -Q.x * R.z + Q.y * R.w + Q.z * R.x + Q.w * R.y;
    	float z = +Q.x * R.y - Q.y * R.x + Q.z * R.w + Q.w * R.z;
    	float w = -Q.x * R.x - Q.y * R.y - Q.z * R.z + Q.w * R.w;

    	return Quaternion(x, y, z, w);
    }

    Quaternion operator*(float s, const Quaternion &Q)
    {
    	return Quaternion(s * Q.x, s * Q.y, s * Q.z, s * Q.w);
    }

    Quaternion operator*(const Quaternion &Q, float s)
    {
    	return Quaternion(Q.x * s, Q.y * s, Q.z * s, Q.w * s);
    }

    Quaternion operator/(const Quaternion &Q, float s)
    {
    	float r = 1.0f / s;

    	return Q * r;
    }

    float N(const Quaternion &Q)
    {
    	return Q.x*Q.x + Q.y*Q.y + Q.z*Q.z + Q.w*Q.w;
    }

    Quaternion &Quaternion::normalize()
    {
    	return *this /= sqrtf(N(*this));
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [RandVec.cpp] - (443 bytes)

    #include "RandVec.h"

    #include "Vector.h"

    #include <stdlib.h>
    #include <math.h>

    const float M_2PIf = 6.283185307179586476925286766559f;

    float rand(float min, float max)
    {
    	return min + (max - min) * rand() / (float)RAND_MAX;
    }

    Vector RandVec()
    {
    	float z = rand(-1.0f, 1.0f);
    	float a = rand(0.0f, M_2PIf);

    	float r = sqrtf(1.0f - z*z);

    	float x = r * cosf(a);
    	float y = r * sinf(a);

    	return Vector(x, y, z);
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Render.cpp] - (1,785 bytes)

    #include "Render.h"

    #include "Vector.h"
    #include "Matrix.h"
    #include "Quaternion.h"
    #include "RandVec.h"
    #include "DDDisplay.h"
    #include "DIKeyboard.h"
    #include "DIMouse.h"
    #include "FPSCounter.h"

    #include <stdlib.h>
    #include <math.h>

    #define NUM_RAND_POINTS 8192

    void Render()
    {
    	static FPSCounter FPSCounter;

    	static Vector *v = NULL;

    	if(v == NULL)
    	{
    		Display.ClearBack();
    		Display.Text(0, 0, " Loading... ");
    		Display.Flip();

    		v = new Vector[NUM_RAND_POINTS];

    		for(unsigned int i = 0; i < NUM_RAND_POINTS; i++)
    			v[i] = RandVec();
    	}

    	static Quaternion View = 1;

    	Matrix M = (Matrix)View;

    	Display.ClearBack();
    	Display.Lock();

    	const float W = 0.5f * Display.Width;
    	const float H = 0.5f * Display.Height;
    	const float D = 0.5f * Display.Width;   // Distance to projection plane, 90 FOV
    	unsigned int *DisplayAddress = (unsigned int*)Display.BackBuffer;

    	for(unsigned int i = 0; i < NUM_RAND_POINTS; i++)
    	{
    		Vector u = M * v[i];

    		if(u.y > 0.01f)   // Not behind view
    		{
    			float Z = 1.0f / u.y;

    			u.x = W + D * u.x * Z;
    			u.y = H - D * u.z * Z;

    			unsigned int X = (unsigned int)u.x;
    			unsigned int Y = (unsigned int)u.y;

    			if(X < Display.Width && Y < Display.Height)
    				*(DisplayAddress + Display.Stride * Y + X) = 0xFFFFFFFF;
    		}
    	}

    	Display.Unlock();
    	Display.Text(0, 0, " %.1f FPS ", FPSCounter.CurrentFPS);
    	Display.Flip();

    	Keyboard.Input();

    	if(Keyboard.KeyPressed(DIK_ESCAPE))
    	{
    		delete[] v;
    		exit(0);
    	}

    	Mouse.Input();

    	float SinPhi = sinf(1e-3f * Mouse.dx);
    	float SinTheta = sinf(1e-3f * Mouse.dy);
    	View = Quaternion(SinTheta, 0, SinPhi, sqrtf(1 - SinPhi*SinPhi - SinTheta*SinTheta)) * View;

    	View.normalize();

    	FPSCounter.NewFrame();
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Timer.cpp] - (406 bytes)

    #include "Timer.h"

    #include <windows.h>

    double Timer::Ticks()
    {
       __int64 CurrentTime;
       __int64 Frequency;

    	QueryPerformanceFrequency((LARGE_INTEGER*)&Frequency);
    	QueryPerformanceCounter((LARGE_INTEGER*)&CurrentTime);

    	return (double)CurrentTime / (double)Frequency;
    }

    void Timer::Pause(double p)
    {
       double StopTime = Timer::Ticks() + p;
       while(Timer::Ticks() < StopTime);
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [Tuple.cpp] - (18 bytes)

    #include "Tuple.h"

Currently browsing [RandVec.zip] (100,350 bytes) - [Vector.cpp] - (3,114 bytes)

    #include "Vector.h"

    #include "Point.h"

    #include <math.h>

    Vector::Vector() : x(Element[0]), y(Element[1]), z(Element[2])
    {
    }

    Vector::Vector(const int i) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	const float s = (float)i;

    	x = s;
    	y = s;
    	z = s;
    }

    Vector::Vector(const Vector &v) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	x = v.x;
    	y = v.y;
    	z = v.z;
    }

    Vector::Vector(const Point &P) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	x = P.x;
    	y = P.y;
    	z = P.z;
    }

    Vector::Vector(float v_x, float v_y, float v_z) : x(Element[0]), y(Element[1]), z(Element[2])
    {
    	x = v_x;
    	y = v_y;
    	z = v_z;
    }

    Vector &Vector::operator=(const Vector &v)
    {
    	x = v.x;
    	y = v.y;
    	z = v.z;

    	return *this;
    }

    Vector Vector::operator+() const
    {
    	return *this;
    }

    Vector Vector::operator-() const
    {
    	return Vector(-x, -y, -z);
    }

    Vector &Vector::operator+=(const Vector &v)
    {
    	x += v.x;
    	y += v.y;
    	z += v.z;

    	return *this;
    }

    Vector &Vector::operator-=(const Vector &v)
    {
    	x -= v.x;
    	y -= v.y;
    	z -= v.z;

    	return *this;
    }

    Vector &Vector::operator*=(float s)
    {
    	x *= s;
    	y *= s;
    	z *= s;

    	return *this;
    }

    Vector &Vector::operator/=(float s)
    {
    	float r = 1.0f / s;

    	return *this *= r;
    }

    bool operator==(const Vector &U, const Vector &v)
    {
    	if(U.x == v.x && U.y == v.y && U.z == v.z)
    		return true;
    	else
    		return false;
    }

    bool operator!=(const Vector &U, const Vector &v)
    {
    	if(U.x != v.x || U.y != v.y || U.z != v.z)
    		return true;
    	else
    		return false;
    }

    bool operator>(const Vector &u, const Vector &v)
    {
    	if((u^2) > (v^2))
    		return true;
    	else
    		return false;
    }

    bool operator<(const Vector &u, const Vector &v)
    {
    	if((u^2) < (v^2))
    		return true;
    	else
    		return false;
    }

    Vector operator+(const Vector &u, const Vector &v)
    {
    	return Vector(u.x + v.x, u.y + v.y, u.z + v.z);
    }

    Vector operator-(const Vector &u, const Vector &v)
    {
    	return Vector(u.x - v.x, u.y - v.y, u.z - v.z);
    }

    float operator*(const Vector &u, const Vector &v)
    {
    	return u.x * v.x + u.y * v.y + u.z * v.z;
    }

    Vector operator*(float s, const Vector &v)
    {
    	return Vector(s * v.x, s * v.y, s * v.z);
    }

    Vector operator*(const Vector &v, float s)
    {
    	return Vector(v.x * s, v.y * s, v.z * s);
    }

    Vector operator/(const Vector &v, float s)
    {
    	float r = 1.0f / s;

    	return Vector(v.x * r, v.y * r, v.z * r);
    }

    float operator^(const Vector &v, const int n)
    {
    	switch(n)
    	{
    		case 2: return v*v;
    		default: return 1.0f;
    	}
    }

    float operator^(const Vector &u, const Vector &v)
    {
    	return acosf((u / u.length()) * (v / v.length()));
    }

    Vector operator%(const Vector &u, const Vector &v)
    {
    	return Vector(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x);
    }

    float Vector::length() const
    {
    	return sqrtf(x*x + y*y + z*z);
    }

    float N(const Vector &v)
    {
    	return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
    }

    float N2(const Vector &v)
    {
    	return v.x*v.x + v.y*v.y + v.z*v.z;
    }

    Vector &Vector::normalize()
    {
    	return *this /= this->length();
    }

Currently browsing [RandVec.zip] (100,350 bytes) - [DDDisplay.h] - (1,356 bytes)

    #ifndef DDDISPLAY_H
    #define DDDISPLAY_H

    #include <ddraw.h>

    class DDDisplay
    {
       HWND hWnd;   // Window handle

       IDirectDraw *DirectDraw;
       IDirectDrawSurface *PrimarySurface;
       IDirectDrawSurface *BackSurface;

       HRESULT DDRVal;   // DirectDraw return value

       char *DDRValToString(HRESULT DDRVal);
       void CheckDDRVal(char *Method = "Undefined");
       void ReleaseAllObjects();

    public:
       bool Active;
       bool Locked;

       unsigned long Width;
       unsigned long Height;
       unsigned long Bitdepth;

    	// TODO: Make 'Buffer' class and derive BackBuffer, DepthBuffer...

       void *BackBuffer;   // Pointer to starting address of backbuffer, Lock() first!
    	void *DepthBuffer;  // Pointer to starting address of z-buffer
       long Pitch;         // Physical width in bytes, use to calculate pixel position
    	long Stride;        // Physical width in pixels;

       DDDisplay();

       ~DDDisplay();

       void Init(HWND, unsigned long, unsigned long, unsigned long);
       void Flip();
       void ClearDepth();              // TODO: Make DepthBuffer class with Clear() method
    	void ClearBack(int fill = 0);   // TODO: Make BackBuffer class with Clear() method
       void Lock();
       void Unlock();
       void __cdecl Text(int x, int y, const char*, ...);   // Simple text output
    };

    extern DDDisplay Display;

    #endif   // DDDISPLAY_H

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.