#pragma once
#include <iostream>
namespace Rage {
template <typename T>
class Vector2 {
private:
T _a[2];
public:
static const Vector2<T> Zero;
static const Vector2<T> One;
static const Vector2<T> UnitX;
static const Vector2<T> UnitY;
Vector2(const Vector2<T> & v = Zero) {
_a[0] = v[0];
_a[1] = v[1];
}
Vector2(T x, T y) {
_a[0] = x;
_a[1] = y;
}
T X() const { return _a[0]; }
T Y() const { return _a[1]; }
T & operator [] (int i) { return _v[i]; }
const T & operator [] (int i) const { return _a[i]; }
void Normalize() {
T scale = 1 / GetLength();
_a[0] *= scale;
_a[1] *= scale;
}
T GetLength() const {
return sqrt(GetLengthSquared());
}
T GetLengthSquared() const {
return _a[0] * _a[0] + _a[1] * _a[1];
}
static Vector2<T> Lerp(const Vector2<T> & a, const Vector2<T> & b, T blend) {
Vector2<T> r(a);
r[0] = blend * (b[0] - a[0]) + a[0];
r[1] = blend * (b[1] - a[1]) + a[1];
return r;
}
Vector2<T> operator - () const {
Vector2<T> r;
r[0] = -_a[0];
r[1] = -_a[1];
return r;
}
bool operator == (const Vector2<T> & rhs) const {
bool r = true;
r &= _a[0] == rhs[0];
r &= _a[1] == rhs[1];
return r;
}
bool operator != (const Vector2<T> & rhs) const {
bool r = true;
r &= _a[0] != rhs[0];
r &= _a[1] != rhs[1];
return r;
}
Vector2<T> & operator /= (T rhs) {
if (rhs != 0) {
_a[0] /= rhs;
_a[1] /= rhs;
}
return *this;
}
Vector2<T> & operator /= (const Vector2<T> & rhs) {
if (rhs[0] != 0)
_a[0] /= rhs[0];
if (rhs[1] != 0)
_a[1] /= rhs[1];
return *this;
}
Vector2<T> & operator *= (const T rhs) {
_a[0] *= rhs;
_a[1] *= rhs;
return *this;
}
Vector2<T> & operator *= (const Vector2<T> & rhs) {
_a[0] *= rhs[0];
_a[1] *= rhs[1];
return *this;
}
Vector2<T> & operator += (const T rhs) {
_a[0] += rhs;
_a[1] += rhs;
return *this;
}
Vector2<T> & operator += (const Vector2<T> & rhs) {
_a[0] += rhs[0];
_a[1] += rhs[1];
return *this;
}
Vector2<T> & operator -= (const T rhs) {
_a[0] -= rhs;
_a[1] -= rhs;
return *this;
}
Vector2<T> & operator -= (const Vector2<T> & rhs) {
_a[0] -= rhs[0];
_a[1] -= rhs[1];
return *this;
}
Vector2<T> & operator / (const T rhs) const {
Vector2<T> r(*this);
return r /= rhs;
}
Vector2<T> & operator / (const Vector2<T> & rhs) const {
Vector2<T> r(*this);
return r /= rhs;
}
Vector2<T> & operator * (const T rhs) const {
Vector2<T> r(*this);
return r *= rhs;
}
Vector2<T> & operator * (const Vector2<T> & rhs) const {
Vector2<T> r(*this);
return r *= rhs;
}
Vector2<T> & operator + (const T rhs) const {
Vector2<T> r(*this);
return r *= rhs;
}
Vector2<T> & operator + (const Vector2<T> & rhs) const {
Vector2<T> r(*this);
return r += rhs;
}
Vector2<T> & operator - (const T rhs) const {
Vector2<T> r(*this);
return r -= rhs;
}
Vector2<T> & operator - (const Vector2<T> & rhs) const {
Vector2<T> r(*this);
return r -= rhs;
}
};
template <typename T>
std::ostream & operator << (std::ostream & s, const Vector2<T> & rhs) {
s << '(' << rhs[0] << ", ";
s << rhs[1] << ')';
return s;
}
template <typename T>
std::istream & operator >> (std::istream & s, Vector2<T> & rhs) {
s >> rhs[0];
s >> rhs[1];
return s;
}
template <typename T>
const Vector2<T> Vector2<T>::Zero(T(0), T(0));
template <typename T>
const Vector2<T> Vector2<T>::One(T(1), T(1));
template <typename T>
const Vector2<T> Vector2<T>::UnitX(T(1), T(0));
template <typename T>
const Vector2<T> Vector2<T>::UnitY(T(0), T(1));
typedef Vector2<float> Vector2f;
typedef Vector2<double> Vector2d;
template <typename T>
class Vector3 {
private:
T _a[3];
public:
static const Vector3<T> Zero;
static const Vector3<T> One;
static const Vector3<T> UnitX;
static const Vector3<T> UnitY;
static const Vector3<T> UnitZ;
Vector3(const Vector3<T> & v = Zero) {
_a[0] = v[0];
_a[1] = v[1];
_a[2] = v[2];
}
Vector3(T x, T y, T z) {
_a[0] = x;
_a[1] = y;
_a[2] = z;
}
T X() const { return _a[0]; }
T Y() const { return _a[1]; }
T Z() const { return _a[2]; }
T & operator [] (int i) { return _a[i]; }
const T & operator [] (int i) const { return _a[i]; }
void Normalize() {
T scale = 1 / GetLength();
_a[0] *= scale;
_a[1] *= scale;
_a[2] *= scale;
}
T GetLength() const {
return sqrt(GetLengthSquared());
}
T GetLengthSquared() const {
return _a[0] * _a[0] + _a[1] * _a[1] + _a[2] * _a[2];
}
friend Vector3<T> Cross(const Vector3<T> & lhs, const Vector3<T> & rhs) {
Vector3<T> r(lhs);
r[0] = r[1] * rhs[2] - r[2] * rhs[1];
r[1] = r[2] * rhs[0] - r[0] * rhs[2];
r[2] = r[0] * rhs[1] - r[1] * rhs[0];
return r;
}
static Vector3<T> Lerp(const Vector3<T> & a, const Vector3<T> & b, T blend) {
Vector3<T> r(a);
r[0] = blend * (b[0] - a[0]) + a[0];
r[1] = blend * (b[1] - a[1]) + a[1];
r[2] = blend * (b[2] - a[2]) + a[2];
return r;
}
Vector3<T> operator - () const {
Vector3<T> r;
r[0] = -_a[0];
r[1] = -_a[1];
r[2] = -_a[2];
return r;
}
bool operator == (const Vector3<T> & rhs) const {
bool r = true;
r &= _a[0] == rhs[0];
r &= _a[1] == rhs[1];
r &= _a[2] == rhs[2];
return r;
}
bool operator != (const Vector3<T> & rhs) const {
bool r = true;
r &= _a[0] != rhs[0];
r &= _a[1] != rhs[1];
r &= _a[2] != rhs[2];
return r;
}
Vector3<T> & operator /= (T rhs) {
if (rhs != 0) {
_a[0] /= rhs;
_a[1] /= rhs;
_a[2] /= rhs;
}
return *this;
}
Vector3<T> & operator /= (const Vector3<T> & rhs) {
if (rhs[0] != 0)
_a[0] /= rhs[0];
if (rhs[1] != 0)
_a[1] /= rhs[1];
if (rhs[2] != 0)
_a[2] /= rhs[2];
return *this;
}
Vector3<T> & operator *= (const T rhs) {
_a[0] *= rhs;
_a[1] *= rhs;
_a[2] *= rhs;
return *this;
}
Vector3<T> & operator *= (const Vector3<T> & rhs) {
_a[0] *= rhs[0];
_a[1] *= rhs[1];
_a[2] *= rhs[2];
return *this;
}
Vector3<T> & operator += (const T rhs) {
_a[0] += rhs;
_a[1] += rhs;
_a[2] += rhs;
return *this;
}
Vector3<T> & operator += (const Vector3<T> & rhs) {
_a[0] += rhs[0];
_a[1] += rhs[1];
_a[2] += rhs[2];
return *this;
}
Vector3<T> & operator -= (const T rhs) {
_a[0] -= rhs;
_a[1] -= rhs;
_a[2] -= rhs;
return *this;
}
Vector3<T> & operator -= (const Vector3<T> & rhs) {
_a[0] -= rhs[0];
_a[1] -= rhs[1];
_a[2] -= rhs[2];
return *this;
}
Vector3<T> & operator / (const T rhs) const {
Vector3<T> r(*this);
return r /= rhs;
}
Vector3<T> & operator / (const Vector3<T> & rhs) const {
Vector3<T> r(*this);
return r /= rhs;
}
Vector3<T> & operator * (const T rhs) const {
Vector3<T> r(*this);
return r *= rhs;
}
Vector3<T> & operator * (const Vector3<T> & rhs) const {
Vector3<T> r(*this);
return r *= rhs;
}
Vector3<T> & operator + (const T rhs) const {
Vector3<T> r(*this);
return r *= rhs;
}
Vector3<T> & operator + (const Vector3<T> & rhs) const {
Vector3<T> r(*this);
return r += rhs;
}
Vector3<T> & operator - (const T rhs) const {
Vector3<T> r(*this);
return r -= rhs;
}
Vector3<T> & operator - (const Vector3<T> & rhs) const {
Vector3<T> r(*this);
return r -= rhs;
}
};
template <typename T>
std::ostream & operator << (std::ostream & s, const Vector3<T> & rhs) {
s << '(' << rhs[0] << ", ";
s << rhs[1] << ", ";
s << rhs[2] << ')';
return s;
}
template <typename T>
std::istream & operator >> (std::istream & s, Vector3<T> & rhs) {
s >> rhs[0];
s >> rhs[1];
s >> rhs[2];
return s;
}
template <typename T>
const Vector3<T> Vector3<T>::Zero(T(0), T(0), T(0));
template <typename T>
const Vector3<T> Vector3<T>::One(T(1), T(1), T(1));
template <typename T>
const Vector3<T> Vector3<T>::UnitX(T(1), T(0), T(0));
template <typename T>
const Vector3<T> Vector3<T>::UnitY(T(0), T(1), T(0));
template <typename T>
const Vector3<T> Vector3<T>::UnitZ(T(0), T(0), T(1));
typedef Vector3<float> Vector3f;
typedef Vector3<double> Vector3d;
template <typename T>
class Vector4 {
private:
T _a[4];
public:
static const Vector4<T> Zero;
static const Vector4<T> One;
static const Vector4<T> UnitX;
static const Vector4<T> UnitY;
static const Vector4<T> UnitZ;
static const Vector4<T> UnitW;
Vector4(const Vector4<T> & v = Zero) {
_a[0] = v[0];
_a[1] = v[1];
_a[2] = v[2];
_a[3] = v[3];
}
Vector4(T x, T y, T z, T w) {
_a[0] = x;
_a[1] = y;
_a[2] = z;
_a[3] = w;
}
T X() const { return _a[0]; }
T Y() const { return _a[1]; }
T Z() const { return _a[2]; }
T W() const { return _a[3]; }
T & operator [] (int i) { return _a[i]; }
const T & operator [] (int i) const { return _a[i]; }
void Normalize() {
T scale = 1 / GetLength();
_a[0] *= scale;
_a[1] *= scale;
_a[2] *= scale;
_a[3] *= scale;
}
T GetLength() const {
return sqrt(GetLengthSquared());
}
T GetLengthSquared() const {
return _a[0] * _a[0] + _a[1] * _a[1] + _a[2] * _a[2] + _a[3] * _a[3];
}
static Vector4<T> Lerp(const Vector4<T> & a, const Vector4<T> & b, T blend) {
Vector4<T> r(a);
r[0] = blend * (b[0] - a[0]) + a[0];
r[1] = blend * (b[1] - a[1]) + a[1];
r[2] = blend * (b[2] - a[2]) + a[2];
r[3] = blend * (b[3] - a[3]) + a[3];
return r;
}
Vector4<T> operator - () const {
Vector4<T> r;
r[0] = -_a[0];
r[1] = -_a[1];
r[2] = -_a[2];
r[3] = -_a[3];
return r;
}
bool operator == (const Vector4<T> & rhs) const {
bool r = true;
r &= _a[0] == rhs[0];
r &= _a[1] == rhs[1];
r &= _a[2] == rhs[2];
r &= _a[3] == rhs[3];
return r;
}
bool operator != (const Vector4<T> & rhs) const {
bool r = true;
r &= _a[0] != rhs[0];
r &= _a[1] != rhs[1];
r &= _a[2] != rhs[2];
r &= _a[3] != rhs[3];
return r;
}
Vector4<T> & operator /= (T rhs) {
if (rhs != 0) {
_a[0] /= rhs;
_a[1] /= rhs;
_a[2] /= rhs;
_a[3] /= rhs;
}
return *this;
}
Vector4<T> & operator /= (const Vector4<T> & rhs) {
if (rhs[0] != 0)
_a[0] /= rhs[0];
if (rhs[1] != 0)
_a[1] /= rhs[1];
if (rhs[2] != 0)
_a[2] /= rhs[2];
if (rhs[3] != 0)
_a[3] /= rhs[2];
return *this;
}
Vector4<T> & operator *= (const T rhs) {
_a[0] *= rhs;
_a[1] *= rhs;
_a[2] *= rhs;
_a[3] *= rhs;
return *this;
}
Vector4<T> & operator *= (const Vector4<T> & rhs) {
_a[0] *= rhs[0];
_a[1] *= rhs[1];
_a[2] *= rhs[2];
_a[3] *= rhs[3];
return *this;
}
Vector4<T> & operator += (const T rhs) {
_a[0] += rhs;
_a[1] += rhs;
_a[2] += rhs;
_a[3] += rhs;
return *this;
}
Vector4<T> & operator += (const Vector4<T> & rhs) {
_a[0] += rhs[0];
_a[1] += rhs[1];
_a[2] += rhs[2];
_a[3] += rhs[3];
return *this;
}
Vector4<T> & operator -= (const T rhs) {
_a[0] -= rhs;
_a[1] -= rhs;
_a[2] -= rhs;
_a[3] -= rhs;
return *this;
}
Vector4<T> & operator -= (const Vector4<T> & rhs) {
_a[0] -= rhs[0];
_a[1] -= rhs[1];
_a[2] -= rhs[2];
_a[3] -= rhs[3];
return *this;
}
Vector4<T> & operator / (const T rhs) const {
Vector4<T> r(*this);
return r /= rhs;
}
Vector4<T> & operator / (const Vector4<T> & rhs) const {
Vector4<T> r(*this);
return r /= rhs;
}
Vector4<T> & operator * (const T rhs) const {
Vector4<T> r(*this);
return r *= rhs;
}
Vector4<T> & operator * (const Vector4<T> & rhs) const {
Vector4<T> r(*this);
return r *= rhs;
}
Vector4<T> & operator + (const T rhs) const {
Vector4<T> r(*this);
return r *= rhs;
}
Vector4<T> & operator + (const Vector4<T> & rhs) const {
Vector4<T> r(*this);
return r += rhs;
}
Vector4<T> & operator - (const T rhs) const {
Vector4<T> r(*this);
return r -= rhs;
}
Vector4<T> & operator - (const Vector4<T> & rhs) const {
Vector4<T> r(*this);
return r -= rhs;
}
};
template <typename T>
std::ostream & operator << (std::ostream & s, const Vector4<T> & rhs) {
s << '(' << rhs[0] << ", ";
s << rhs[1] << ", ";
s << rhs[2] << ", ";
s << rhs[3] << ')';
return s;
}
template <typename T>
std::istream & operator >> (std::istream & s, Vector4<T> & rhs) {
s >> rhs[0];
s >> rhs[1];
s >> rhs[2];
s >> rhs[3];
return s;
}
template <typename T>
const Vector4<T> Vector4<T>::Zero(T(0), T(0), T(0), T(0));
template <typename T>
const Vector4<T> Vector4<T>::One(T(1), T(1), T(1), T(1));
template <typename T>
const Vector4<T> Vector4<T>::UnitX(T(1), T(0), T(0), T(0));
template <typename T>
const Vector4<T> Vector4<T>::UnitY(T(0), T(1), T(0), T(0));
template <typename T>
const Vector4<T> Vector4<T>::UnitZ(T(0), T(0), T(1), T(0));
template <typename T>
const Vector4<T> Vector4<T>::UnitW(T(0), T(0), T(0), T(1));
typedef Vector4<float> Vector4f;
typedef Vector4<double> Vector4d;
}
Refactorings
No refactoring yet !
Thomas Salvador
November 14, 2009, November 14, 2009 23:52, permalink
hello.
i suggest you to implement a generic VectorX for arbitary long vectors. most operations would loop over this length l and handle the components. like:
for(i=0;i<l;i++) { _a[i] += rhs[i]; }
then create subclasses of VectorX for the required lengths Vector2 .. Vector4 and just set the length in their constructors. i.e. Vector2 inherits the complete functionality and just configures VectorX to process 2-component vectors.
you could check for compatibility of the parameters by checking their number of components.
regards,
thomas.
Ants
November 17, 2009, November 17, 2009 10:15, permalink
Why are your division operators guarding for division by zero? Don't you want an exception to be thrown if you are dividing by zero and catch the error early, instead of masking it and getting weird results? If you really want to mask the division by zero, then you should also add the same kind of guard in the Normalize() methods.
vodkamilkshake
December 8, 2011, December 08, 2011 23:18, permalink
Why not use Boost.Operators for comparison operators?
vodkamilkshake
December 8, 2011, December 08, 2011 23:25, permalink
Why not use Boost.Operators for comparison operators?
for my 3d game :) still working on Matrix4<T>...