## Tuesday, November 8, 2011

### Using Vector Mathematics, Complete Vector3 Class

After a large series of vector mathematics blog posts, here is a full Vector3 class that I wrote, it's fairly efficient and should be enough to suit your needs if you would like to use it. There are other 3rd-party math libraries out there if you'd like to browse your options.

```#pragma once // Most compilers are compatible, remove if yours isn't
#ifndef VECTOR_3
#define VECTOR_3

#include <math.h>
#include <ostream>

class Vector3
{
public:
Vector3(void);
explicit Vector3(const float x, const float y, const float z);

// Copy constructor
Vector3(const Vector3& rhs);

~Vector3(void);

bool operator==(const Vector3& rhs) const { return ( (x == rhs.x)
&& (y == rhs.y)
&& (z == rhs.z));}
bool operator!=(const Vector3& rhs) const { return ( (x != rhs.x)
|| (y != rhs.y)
|| (z != rhs.z));}
Vector3 operator+(const Vector3& rhs) const;
void operator+=(const Vector3& rhs);
Vector3 operator-(const Vector3& rhs) const;
Vector3 operator-(void) const;
void operator-=(const Vector3& rhs);
void operator*=(const int scalar);
void operator*=(const float scalar);

// Non-member operators get a friend declaration
friend Vector3 operator*(const Vector3& vector, const int scalar);
friend Vector3 operator*(const Vector3& vector, float scalar);
friend Vector3 operator*(const int scalar, const Vector3& vector);
friend Vector3 operator*(const float scalar, const Vector3& vector);
friend std::ostream& operator<<(std::ostream& ofs,const Vector3& rhs);

inline void Flip(void) { x = -x; y = -y; z = -z; }

inline float Dot(const Vector3& rhs) const { return (x * rhs.x
+ y * rhs.y
+ z * rhs.z); }

Vector3 Cross(const Vector3& rhs) const;

float Length(void) const { return sqrtf( LengthSqr() ); }

inline float LengthSqr(void) const { return (x * x + y * y + z * z); }

float Unitize(void);

void Reflect( const Vector3& rhs );

static Vector3 Reflect( const Vector3& first, const Vector3& second );
static Vector3 GetLongest(const Vector3& first, const Vector3& second);

static const Vector3 Left;
static const Vector3 Right;
static const Vector3 Up;
static const Vector3 Down;
static const Vector3 Forward;
static const Vector3 Backward;

static const Vector3 UnitX;
static const Vector3 UnitY;
static const Vector3 UnitZ;

static const Vector3 Zero;

float x;
float y;
float z;
};

#endif //VECTOR_3
```
Implementation File, Vector3.cpp:
```#include "Vector3.h"

#include <sstream>

const Vector3 Vector3::Right(1.f, 0.f, 0.f);
const Vector3 Vector3::Up(0.f, 1.f, 0.f);
const Vector3 Vector3::Forward(0.f, 0.f, 1.f);
const Vector3 Vector3::Left(-1.f, 0.f, 0.f);
const Vector3 Vector3::Down(0.f, -1.f, 0.f);
const Vector3 Vector3::Backward(0.f, 0.f, -1.f);

const Vector3 Vector3::UnitX(1.f, 0.f, 0.f);
const Vector3 Vector3::UnitY(0.f, 1.f, 0.f);
const Vector3 Vector3::UnitZ(0.f, 0.f, 1.f);
const Vector3 Vector3::Zero(0.0f, 0.0f, 0.0f);

Vector3::Vector3(void) : x(0.0f), y(0.0f), z(0.0f)
{
}

Vector3::Vector3(const float x, const float y, const float z)
{
this->x = x;
this->y = y;
this->z = z;
}

// Copy constructor
Vector3::Vector3(const Vector3& rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}

Vector3::~Vector3(void)
{
}
Vector3 Vector3::operator+(const Vector3& rhs) const
{
Vector3 newVector;
newVector.x = x + rhs.x;
newVector.y = y + rhs.y;
newVector.z = z + rhs.z;
return newVector;
}

void Vector3::operator+=(const Vector3& rhs)
{
x += rhs.x;
y += rhs.y;
z += rhs.z;
}

Vector3  Vector3::operator-(const Vector3& rhs) const
{
Vector3  newVector;
newVector.x = x - rhs.x;
newVector.y = y - rhs.y;
newVector.z = z - rhs.z;
return newVector;
}

Vector3 Vector3::operator-(void) const
{
Vector3  newVector(-x, -y, -z);
return newVector;
}

void Vector3::operator-=(const Vector3& rhs)
{
x -= rhs.x;
y -= rhs.y;
z -= rhs.z;
}

void Vector3::operator*=(const int scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
}

void Vector3::operator*=(const float scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
}

Vector3 operator*(const Vector3& vector, const int scalar)
{
return Vector3(vector.x * scalar, vector.y * scalar, vector.z * scalar);
}

Vector3 operator*(const Vector3& vector, const float scalar)
{
return Vector3(vector.x * scalar, vector.y * scalar, vector.z * scalar);
}

Vector3 operator*(const int scalar, const Vector3& vector)
{
return Vector3(vector.x * scalar, vector.y * scalar, vector.z * scalar);
}

Vector3 operator*(const float scalar, const Vector3& vector)
{
return Vector3(vector.x * scalar, vector.y * scalar, vector.z * scalar);
}
std::ostream& operator<< (std::ostream& os, const Vector3& vector)
{
std::stringstream stream;
stream << "X: " << vector.x << ", Y: " << vector.y << ", Z: " << vector.z;
os.write(const_cast<char*>(stream.str().c_str()),
static_cast<std::streamsize>(stream.str().size() *
sizeof(char)) );
return os;
}

Vector3 Vector3::Cross(const Vector3& rhs) const
{
return Vector3( (y * rhs.z) - (z * rhs.y),
(z * rhs.x) - (x * rhs.z),
(x * rhs.y) - (y * rhs.x) );
}

float Vector3::Unitize(void)
{
const float length = Length();
const float inverseLength = 1.0f / length;
x *= inverseLength;
y *= inverseLength;
z *= inverseLength;
return length;
}

void Vector3::Reflect( const Vector3& normal )
{
const float dotProductTimesTwo = Dot(normal) * 2.0f;
x -= dotProductTimesTwo * normal.x;
y -= dotProductTimesTwo * normal.y;
z -= dotProductTimesTwo * normal.z;
}

Vector3 Vector3::Reflect(const Vector3& vector, const Vector3& normal)
{
Vector3  newVector;
const float dotProductTimesTwo = vector.Dot(normal) * 2.0f;
newVector.x = vector.x - (dotProductTimesTwo * normal.x);
newVector.y = vector.y - (dotProductTimesTwo * normal.y);
newVector.z = vector.z - (dotProductTimesTwo * normal.z);
return newVector;
}

Vector3 Vector3::GetLongest(const Vector3& first, const Vector3& second)
{
if ( first.LengthSqr() > second.LengthSqr() )
return first;

return second;
}
```