bluecore/engine/Math/Vector.h

433 lines
7.8 KiB
C++

//------------------------------------------------------------------------------
// Author: Gero Mueller <gero.mueller@cloo.de>
// Copyright: (c) 2006 Gero Mueller
// License: MIT License
//------------------------------------------------------------------------------
#ifndef BLUECORE_VECTOR_H
#define BLUECORE_VECTOR_H
// system includes
#include <cmath>
#include <ostream>
// project includes
#include "Scalar.h"
namespace BlueCore
{
template <class T>
class Vector3Template
{
public:
T x, y, z;
/**
* Default Contructor
*/
inline Vector3Template()
{
x = static_cast<T>(0);
y = static_cast<T>(0);
z = static_cast<T>(0);
}
/**
* Constructor from three values
*/
template <class S>
inline Vector3Template( S x, S y, S z )
{
this->x = static_cast<T>(x);
this->y = static_cast<T>(y);
this->z = static_cast<T>(z);
}
/**
* copy contructor
*/
template <class S>
inline Vector3Template( Vector3Template<S> &a )
{
x = static_cast<T>(a.x);
y = static_cast<T>(a.y);
z = static_cast<T>(a.z);
}
/**
* add operataor
*/
template <class S>
inline Vector3Template<T> operator + (
const Vector3Template<S> &a ) const
{
return Vector3Template<T>(
x + static_cast<T>(a.x),
y + static_cast<T>(a.y),
z + static_cast<T>(a.z) );
}
/**
* zero the vector
*/
inline void zero()
{
x = static_cast<T>(0);
y = static_cast<T>(0);
z = static_cast<T>(0);
}
/**
* zero the vector
*/
inline bool isZero() const
{
if( x != 0.0 )
return false;
if( y != 0.0 )
return false;
if( z != 0.0 )
return false;
return true;
}
/**
* add-assign operator
*/
template <class S>
inline Vector3Template<T> &operator += (
const Vector3Template<S> &a )
{
x += static_cast<T>(a.x);
y += static_cast<T>(a.y);
z += static_cast<T>(a.z);
return *this;
}
/**
* sub operator
*/
template <class S>
inline Vector3Template<T> operator - (
const Vector3Template<S> &a ) const
{
return Vector3Template<T>(
x - static_cast<T>(a.x),
y - static_cast<T>(a.y),
z - static_cast<T>(a.z)
);
}
/**
* sub-assign operator
*/
template <class S>
inline Vector3Template<T> &operator -= (
const Vector3Template<S> &a )
{
x -= static_cast<T>(a.x);
y -= static_cast<T>(a.y);
z -= static_cast<T>(a.z);
return *this;
}
/**
* multiply by scalar operator
*/
template <class S>
inline Vector3Template<T> operator * ( const S a ) const
{
return Vector3Template<T>(
x * static_cast<T>(a),
y * static_cast<T>(a),
z * static_cast<T>(a)
);
}
/**
* multiply-assign by scalar operator
*/
template <class S>
inline Vector3Template<T> &operator *= ( const S a )
{
x *= static_cast<T>(a);
y *= static_cast<T>(a);
z *= static_cast<T>(a);
return *this;
}
/**
* divide by scalar operator
*/
template <class S>
inline Vector3Template<T> operator / ( const S a ) const
{
return Vector3Template<T>(
x / static_cast<T>(a),
y / static_cast<T>(a),
z / static_cast<T>(a)
);
}
/**
* divide-assign by scalar operator
*/
template <class S>
inline Vector3Template<T> &operator /= ( const S a )
{
x /= static_cast<T>(a);
y /= static_cast<T>(a);
z /= static_cast<T>(a);
return *this;
}
/**
* assign operator
*/
template <class S>
inline Vector3Template<T> operator = (
const Vector3Template<S> &a )
{
x = static_cast<T>(a.x);
y = static_cast<T>(a.y);
z = static_cast<T>(a.z);
return *this;
}
inline Vector3Template<T> operator - (void) const
{
return Vector3Template<T>( -x, -y, -z );
}
/**
* compare operator
*/
template <class S>
inline bool operator == ( const Vector3Template<S> &a )
{
if( x != static_cast<T>(a.x) )
return false;
if( y != static_cast<T>(a.y) )
return false;
if( z != static_cast<T>(a.z) )
return false;
return true;
}
/**
* anti compare operator
*/
template <class S>
inline bool operator != ( const Vector3Template<S> &a )
{
if( x != static_cast<T>(a.x) )
return true;
if( y != static_cast<T>(a.y) )
return true;
if( z != static_cast<T>(a.z) )
return true;
return false;
}
/**
* return the length of the vector
*/
inline T length() const
{
return static_cast<T>( sqrt(x*x + y*y + z*z) );
}
/**
* length squared
*/
inline T length2() const
{
return x*x + y*y + z*z;
}
/**
* calculate the cross product
*/
template <class S>
inline Vector3Template<T> cross(
const Vector3Template<S> &a ) const
{
return Vector3Template<T>(
y * static_cast<T>(a.z) - z * static_cast<T>(a.y),
z * static_cast<T>(a.x) - x * static_cast<T>(a.z),
x * static_cast<T>(a.y) - y * static_cast<T>(a.x)
);
}
/**
* calculate dot product
*/
template <class S>
inline T dot( const Vector3Template<S> &a ) const
{
return (
x * static_cast<T>(a.x) +
y * static_cast<T>(a.y) +
z * static_cast<T>(a.z) );
}
/**
* check if vectors are nearly equal
*/
template <class S>
inline bool nearlyEquals(
const Vector3Template<S> &a,
T epsilon = 0.00001 ) const
{
if( fabs(x-static_cast<T>(a.x)) > epsilon )
return false;
if( fabs(y-static_cast<T>(a.y)) > epsilon )
return false;
if( fabs(z-static_cast<T>(a.z)) > epsilon )
return false;
return true;
}
/**
* normalize the vector to length 1
*/
inline void normalize()
{
T a = length();
if( a == 0 )
return;
x /= a;
y /= a;
z /= a;
}
/**
* get normalized vector
*/
inline Vector3Template<T> normalized() const
{
T a = length();
if( a == 0 )
return Vector3Template<T>( 0.0, 0.0, 1.0 );
return Vector3Template<T>( x / a, y / a, z / a );
}
/**
* check if vectors are parallel
*/
inline bool parallel( const Vector3Template<T> &a ) const
{
return ( (static_cast<T>(a.x) / x) ==
(static_cast<T>(a.y) / y) ==
(static_cast<T>(a.z) / z) );
}
/**
* check if vectors are parallel
*/
template <class S>
inline bool nearlyParallel(
const Vector3Template<S> &a,
T epsilon = 0.00001 ) const
{
T ax = static_cast<T>(a.x) / x;
T ay = static_cast<T>(a.y) / y;
T az = static_cast<T>(a.z) / z;
if( fabs(ax - ay) > epsilon )
return false;
if( fabs(ax - az) > epsilon )
return false;
if( fabs(ay - az) > epsilon )
return false;
return true;
}
/**
* check if vectors are orthogonal
*/
inline bool orthogonal( const Vector3Template<T> &a ) const
{
return ( dot(a) == static_cast<T>(0) );
}
/**
* check if vectors are orthogonal
*/
template <class S>
inline bool nearlyOrthogonal(
const Vector3Template<S> &a,
T epsilon = 0.00001 ) const
{
return ( dot(a) < epsilon );
}
T& operator[] (unsigned int i)
{
if( i == 0 )
return x;
else if( i == 1 )
return y;
else if( i == 2 )
return z;
else
throw "index out of bound";
}
friend std::ostream &operator << ( std::ostream& os, Vector3Template<T> v )
{
os << "( " << v.x << ", " << v.y << ", " << v.z << " )";
return os;
}
};
typedef Vector3Template<float> Vector3Float;
typedef Vector3Template<double> Vector3Double;
typedef Vector3Template<Scalar> Vector3;
}
#endif