302 lines
12 KiB
C++
302 lines
12 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#ifndef __NVECTOR__
|
|
#define __NVECTOR__
|
|
|
|
|
|
#include "math/nmath.h"
|
|
#include "alloc/ialloc.h"
|
|
|
|
|
|
namespace GS {
|
|
class Matrix3;
|
|
class Matrix4;
|
|
|
|
namespace NML {
|
|
class File;
|
|
class Tag;
|
|
}
|
|
|
|
/*!
|
|
@short Vector 2d template class.
|
|
@author Emmanuel Julien (ejulien@gsworks.fr)
|
|
*/
|
|
template <class T> struct tVector2
|
|
{
|
|
NPLACEMENT_NEW(Vector)
|
|
|
|
T x, y;
|
|
|
|
inline bool operator == (const tVector2 <T> &b) const { return (x == b.x) && (y == b.y); }
|
|
inline bool operator != (const tVector2 <T> &b) const { return (x != b.x) || (y != b.y); }
|
|
|
|
inline void operator += (const tVector2 <T> &b) { x += b.x; y += b.y; }
|
|
inline void operator += (const float k) { x += k; y += k; }
|
|
inline void operator -= (const tVector2 <T> &b) { x -= b.x; y -= b.y; }
|
|
inline void operator -= (const float k) { x -= k; y -= k; }
|
|
inline void operator *= (const tVector2 <T> &b) { x *= b.x; y *= b.y; }
|
|
inline void operator *= (const float k) { x *= k; y *= k; }
|
|
inline void operator /= (const tVector2 <T> &b) { x /= b.x; y /= b.y; }
|
|
inline void operator /= (const float k) { x /= k; y /= k; }
|
|
|
|
inline tVector2 <T> operator + (const tVector2 <T> &b) const { return tVector2 <T> (x + b.x, y + b.y); }
|
|
inline tVector2 <T> operator + (const T v) const { return tVector2 <T> (x + v, y + v); }
|
|
inline tVector2 <T> operator - (const tVector2 <T> &b) const { return tVector2 <T> (x - b.x, y - b.y); }
|
|
inline tVector2 <T> operator - (const T v) const { return tVector2 <T> (x - v, y - v); }
|
|
inline tVector2 <T> operator * (const tVector2 <T> &b) const { return tVector2 <T> (x * b.x, y * b.y); }
|
|
inline tVector2 <T> operator * (const T v) const { return tVector2 <T> (x * v, y * v); }
|
|
inline tVector2 <T> operator / (const tVector2 <T> &b) const { return tVector2 <T> (x / b.x, y / b.y); }
|
|
inline tVector2 <T> operator / (const T v) const { return tVector2 <T> (x / v, y / v); }
|
|
|
|
tVector2 <T> operator * (const Matrix3 &m) const;
|
|
|
|
/// Squared vector length.
|
|
inline float Len2() const { return (float)(x * x + y * y); }
|
|
/// Vector length.
|
|
inline float Len() const { return Math::Sqrt((float)(x * x + y * y)); }
|
|
|
|
/// Normalize this vector.
|
|
inline void Normalize() { float l = Len(); if (l) { float k = 1.f / l; x *= k; y *= k; } }
|
|
/// Normalize vector.
|
|
inline tVector2 <T> Normalized() const
|
|
{
|
|
float k = 1.f / Len();
|
|
return tVector2 <T>(x * k, y * k);
|
|
}
|
|
|
|
/// Reversed vector.
|
|
inline tVector2 <T> Reversed() const
|
|
{ return tVector2 <T> (-x, -y); }
|
|
|
|
/// Vector squared distance.
|
|
static float Dist2(const tVector2 &a, const tVector2 &b)
|
|
{ return ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y)); }
|
|
/// Vector distance.
|
|
static float Dist(const tVector2 &a, const tVector2 &b)
|
|
{ return Math::Sqrt((float)((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y))); }
|
|
|
|
/// Set vector 2D components.
|
|
inline void Set(const T a, const T b) { x = a; y = b; }
|
|
|
|
tVector2 <T> (T a, T b) { Set(a, b); }
|
|
tVector2 <T> () { Set(0, 0); }
|
|
};
|
|
|
|
typedef tVector2 <float> Vector2;
|
|
|
|
/*!
|
|
@short 4-Component vector
|
|
@author Emmanuel Julien (ejulien@gsworks.fr)
|
|
*/
|
|
struct Vector4
|
|
{
|
|
NPLACEMENT_NEW(Vector)
|
|
|
|
float x, y, z, w;
|
|
|
|
inline bool operator == (const Vector4 &b) const { return Math::TestEqual(x, b.x) && Math::TestEqual(y, b.y) && Math::TestEqual(z, b.z); }
|
|
inline bool operator != (const Vector4 &b) const { return !Math::TestEqual(x, b.x) || !Math::TestEqual(y, b.y) || !Math::TestEqual(z, b.z); }
|
|
|
|
inline void operator += (const Vector4 &b) { x += b.x; y += b.y; z += b.z; };
|
|
inline void operator += (const float k) { x += k; y += k; z += k; };
|
|
inline void operator -= (const Vector4 &b) { x -= b.x; y -= b.y; z -= b.z; };
|
|
inline void operator -= (const float k) { x -= k; y -= k; z -= k; };
|
|
inline void operator *= (const Vector4 &b) { x *= b.x; y *= b.y; z *= b.z; };
|
|
inline void operator *= (const float k) { x *= k; y *= k; z *= k; };
|
|
inline void operator /= (const Vector4 &b) { x /= b.x; y /= b.y; z /= b.z; };
|
|
inline void operator /= (const float k) { float k_ = k ? 1 / k : 0; x *= k_; y *= k_; z *= k_; };
|
|
|
|
inline Vector4 operator + (const Vector4 &b) const { return Vector4(x + b.x, y + b.y, z + b.z); }
|
|
inline Vector4 operator + (const float v) const { return Vector4(x + v, y + v, z + v); }
|
|
inline Vector4 operator - (const Vector4 &b) const { return Vector4(x - b.x, y - b.y, z - b.z); }
|
|
inline Vector4 operator - (const float v) const { return Vector4(x - v, y - v, z - v); }
|
|
inline Vector4 operator * (const Vector4 &b) const { return Vector4(x * b.x, y * b.y, z * b.z); }
|
|
inline Vector4 operator * (const float v) const { return Vector4(x * v, y * v, z * v); }
|
|
inline Vector4 operator / (const Vector4 &b) const { return Vector4(x / b.x, y / b.y, z / b.z); }
|
|
inline Vector4 operator / (const float v) const { float i = v ? 1 / v : 0; return Vector4(x * i, y * i, z * i); }
|
|
|
|
inline float operator [] (size_t n) const { return (&x)[n]; }
|
|
inline float &operator [] (size_t n) { return (&x)[n]; }
|
|
|
|
inline Vector4 SafeDivided(const Vector4 &b) const
|
|
{ return Vector4(b.x ? x / b.x : 0, b.y ? y / b.y : 0, b.z ? z / b.z : 0); }
|
|
|
|
/// Set vector components.
|
|
inline void Set(float x_, float y_, float z_, float w_)
|
|
{ x = x_; y = y_; z = z_; w = w_; }
|
|
inline void Set(float x_ = 0.f, float y_ = 0.f, float z_ = 0.f) // Used to provide script overload.
|
|
{ x = x_; y = y_; z = z_; w = 1.0f; }
|
|
inline void Set(Vector4 &v)
|
|
{ x = v.x; y = v.y; z = v.z; w = v.w; }
|
|
|
|
/// Dot product.
|
|
inline float Dot(const Vector4 &b) const
|
|
{ return x * b.x + y * b.y + z * b.z; }
|
|
/// Cross product.
|
|
inline Vector4 Cross(const Vector4 &b) const
|
|
{ return Vector4(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); }
|
|
|
|
void operator *= (const Matrix4 &);
|
|
Vector4 operator * (const Matrix4 &) const;
|
|
void operator *= (const Matrix3 &);
|
|
Vector4 operator * (const Matrix3 &) const;
|
|
|
|
/// Reverse this vector.
|
|
inline void Reverse() { x = -x; y = -y; z = -z; }
|
|
/// Inverse vector.
|
|
inline void Inverse() { x = x ? 1.f / x : 0; y = y ? 1.f / y : 0; z = z ? 1.f / z : 0; }
|
|
|
|
/// Normalize this vector.
|
|
inline void Normalize() { float l = Len(); if (l) { float k = 1.f / l; x *= k; y *= k; z *= k; } }
|
|
/// Normalize vector.
|
|
inline Vector4 Normalized() const
|
|
{
|
|
float l = Len();
|
|
float k = l ? 1.f / l : 1.f;
|
|
return Vector4(x * k, y * k, z * k);
|
|
}
|
|
|
|
/// Clamp vector components to [min;max].
|
|
Vector4 Clamped(float min, float max) const;
|
|
/// Clamp vector components to [min;max].
|
|
Vector4 Clamped(const Vector4 &min, const Vector4 &max) const;
|
|
/// Clamp vector magnitude to [min;max].
|
|
Vector4 ClampedMagnitude(float min, float max) const;
|
|
|
|
/// Return the opposite vector to this vector.
|
|
inline Vector4 Reversed() const
|
|
{ return Vector4(-x, -y, -z); }
|
|
/// Return the inverse vector to this vector.
|
|
inline Vector4 Inversed() const
|
|
{ return Vector4(1.f / x, 1.f / y, 1.f / z); }
|
|
/// Absolute vector.
|
|
Vector4 Abs() const;
|
|
/// Sign vector.
|
|
inline Vector4 Sign() const
|
|
{ return Vector4(x < 0.f ? -1.f : 1.f, y < 0.f ? -1.f : 1.f, z < 0.f ? -1.f : 1.f); }
|
|
|
|
/// Maximum of two vectors.
|
|
static Vector4 Maximum(const Vector4 &a, const Vector4 &b)
|
|
{ return Vector4(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z); }
|
|
/// Minimum of two vectors.
|
|
static Vector4 Minimum(const Vector4 &a, const Vector4 &b)
|
|
{ return Vector4(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z); }
|
|
|
|
/*!
|
|
@short Reflect vector.
|
|
@note Vector must be normalized.
|
|
*/
|
|
inline Vector4 Reflected(const Vector4 &n) const
|
|
{
|
|
Vector4 rv = Reversed();
|
|
return n * (2.f * rv.Dot(n)) - rv;
|
|
}
|
|
/*!
|
|
@short Refract vector.
|
|
@note Vector must be normalized.
|
|
*/
|
|
inline Vector4 Refracted(const Vector4 &n, float kin = 1, float kout = 1) const
|
|
{
|
|
const float k = kin / kout;
|
|
return (*this) * k + n * (k - 1.f);
|
|
}
|
|
|
|
/// Squared vector length.
|
|
inline float Len2() const { return (float)(x * x + y * y + z * z); }
|
|
/// Vector length.
|
|
inline float Len() const { return Math::Sqrt((float)(x * x + y * y + z * z)); }
|
|
/// Hash vector.
|
|
int Hash() const;
|
|
|
|
Vector4 Floor() const;
|
|
Vector4 Ceil() const;
|
|
|
|
/*!
|
|
@short Return a random vector.
|
|
@note w component is not randomized but set to 1.
|
|
*/
|
|
static Vector4 Random(float min = -1, float max = 1);
|
|
/// Vector squared distance.
|
|
static float Dist2(const Vector4 &a, const Vector4 &b)
|
|
{ return ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z)); }
|
|
/// Vector distance.
|
|
static float Dist(const Vector4 &a, const Vector4 &b)
|
|
{ return Math::Sqrt((float)((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z))); }
|
|
/*!
|
|
@short Vector base to Euler.
|
|
@note base convention u = {0,0,1}, v = {1,0,0}, second axis is optional.
|
|
*/
|
|
static void BaseToEuler(Vector4 &euler, Vector4 &u, Vector4 *v = NULL);
|
|
|
|
/*!
|
|
@short Return a vector which is facing a given direction.
|
|
|
|
Returns a copy of this vector if it is already facing the given
|
|
direction or the opposite of this vector otherwise.
|
|
*/
|
|
Vector4 FaceForward(Vector4 &dir);
|
|
|
|
NML::Tag *AsMetaTag(const char *id, bool full_dump = false) const;
|
|
bool FromMetaTag(NML::Tag &tag);
|
|
|
|
Vector4(float a, float b, float c, float d = 1) : x(a), y(b), z(c), w(d) {}
|
|
Vector4(const tVector2 <float> &v2) : x(v2.x), y(v2.y), z(1), w(1) {}
|
|
Vector4(const tVector2 <int> &v2) : x(float(v2.x)), y(float(v2.y)), z(1), w(1) {}
|
|
Vector4() {}
|
|
};
|
|
|
|
} // GS
|
|
|
|
|
|
#define Vec3Set(v, a, b, c) { (v).x = a; (v).y = b; (v).z = c; }
|
|
|
|
#define Vec3Len2(v) ((v).x * (v).x + (v).y * (v).y + (v).z * (v).z)
|
|
#define Vec3Len(v) Math::Sqrt((float)Vec3Len2(v))
|
|
|
|
#define Vec3Add(r, a, b) { (r).x = (a).x + (b).x; (r).y = (a).y + (b).y; (r).z = (a).z + (b).z; }
|
|
#define Vec3AddConst(r, a, k) { (r).x = (a).x + k; (r).y = (a).y + k; (r).z = (a).z + k; }
|
|
#define Vec3Sub(r, a, b) { (r).x = (a).x - (b).x; (r).y = (a).y - (b).y; (r).z = (a).z - (b).z; }
|
|
#define Vec3SubConst(r, a, k) { (r).x = (a).x - k; (r).y = (a).y - k; (r).z = (a).z - k; }
|
|
#define Vec3Mul(r, a, b) { (r).x = (a).x * (b).x; (r).y = (a).y * (b).y; (r).z = (a).z * (b).z; }
|
|
#define Vec3MulConst(r, a, k) { float _k = k; (r).x = (a).x * _k; (r).y = (a).y * _k; (r).z = (a).z * _k; }
|
|
#define Vec3Div(r, a, b) { (r).x = (a).x / (b).x; (r).y = (a).y / (b).y; (r).z = (a).z / (b).z; }
|
|
#define Vec3DivConst(r, a, k) { float ik = 1.f / k; (r).x = (a).x * ik; (r).y = (a).y * ik; (r).z = (a).z * ik; }
|
|
|
|
#define Vec3Inc(r, a) { (r).x += (a).x; (r).y += (a).y; (r).z += (a).z; }
|
|
#define Vec3IncConst(r, k) { (r).x += k; (r).y += k; (r).z += k; }
|
|
#define Vec3Dec(r, a) { (r).x -= (a).x; (r).y -= (a).y; (r).z -= (a).z; }
|
|
#define Vec3DecConst(r, k) { (r).x -= k; (r).y -= k; (r).z -= k; }
|
|
#define Vec3Scale(r, a) { (r).x *= (a).x; (r).y *= (a).y; (r).z *= (a).z; }
|
|
#define Vec3ScaleConst(r, k) { float _k = k; (r).x *= _k; (r).y *= _k; (r).z *= _k; }
|
|
#define Vec3Shrink(r, a) { (r).x /= (a).x; (r).y /= (a).y; (r).z /= (a).z; }
|
|
#define Vec3ShrinkConst(r, k) { float ik = 1.f / k; (r).x *= ik; (r).y *= ik; (r).z *= ik; }
|
|
|
|
#define Vec3Dot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z)
|
|
#define Vec3Cross(r, a, b) {\
|
|
(r).x = (a).y * (b).z - (a).z * (b).y;\
|
|
(r).y = (a).z * (b).x - (a).x * (b).z;\
|
|
(r).z = (a).x * (b).y - (a).y * (b).x;\
|
|
}
|
|
|
|
#define Vec3Clamp(v, a, b) {\
|
|
if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\
|
|
if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\
|
|
if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\
|
|
}
|
|
#define Vec3ClampMag(v, m) {\
|
|
const float m2 = (m) * (m);\
|
|
const float l2 = Vec3Len2(v);\
|
|
if (l2 > m2)\
|
|
{\
|
|
const float k = Math::Sqrt((float)(m2 / l2));\
|
|
Vec3ScaleConst(v, k);\
|
|
}\
|
|
}
|
|
|
|
|
|
#endif // __NVECTOR__
|