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 #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.0class 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_Hclass 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_Hclass 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_Hvoid Render();#endif // RENDER_H

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

 #ifndef TIMER_H #define TIMER_Hclass 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_Htemplate 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 inline Tuple::Tuple() { }template inline Tuple::Tuple(Type e[n]) { for(int i = 0; i < n; i++) Element[i] = e[i]; }template inline Tuple &Tuple::operator=(const Tuple &T) { for(int i = 0; i < n; i++) Element[i] = T.Element[i]; return *this; }template inline float &Tuple::operator[](int i) { return Element[i]; }template inline float &Tuple::operator()(int i) { return Element[(i - 1) & 3]; }template inline const float &Tuple::operator[](int i) const { return Element[i]; }template inline const float &Tuple::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)

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

 #include "DebugLog.h" DebugLog Log(DEBUG_LOG);#include #include 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(

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 #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 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 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 #include 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 #include #define NUM_RAND_POINTS 8192void 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 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 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 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.