#include "ge_math.h" // place before #ifdef #ifndef __GELVECTOR_H #define __GELVECTOR_H struct Vector64 { Float64 x, y, z; Vector64() : x(0.0), y(0.0), z(0.0) { } explicit Vector64(Float64 ix, Float64 iy, Float64 iz) : x(ix), y(iy), z(iz) { } explicit Vector64(_DONTCONSTRUCT v) { } explicit Vector64(const Vector32& v) : x(v.x), y(v.y), z(v.z) { } #ifndef __LEGACY_API explicit Vector64(Float64 in) : x(in), y(in), z(in) { } #else Vector64(Float64 in) : x(in), y(in), z(in) { } Float64 Dot(const Vector32& v) const { return x * Float64(v.x) + y* Float64(v.y) + z* Float64(v.z); } Float64 Dot(const Vector64& v2) const { return x * v2.x + y * v2.y + z * v2.z; } Vector64 Cross(const Vector64& v2) const { return Vector64(y * v2.z - z * v2.y, z * v2.x - x * v2.z, x * v2.y - y * v2.x); } inline const Vector32 ToSV() const { return Vector32((Float32)x, (Float32)y, (Float32)z); } inline const Vector64& ToLV() const { return *this; } inline const Vector64& ToRV() const { return *this; } friend Float64 operator * (const Vector64& v1, const Vector64& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } friend const Vector64 operator % (const Vector64& v1, const Vector64& v2) { return Vector64(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } inline const Vector64& operator *= (const Matrix64& m); inline const Vector64& operator ^= (const Matrix64& m); const Vector64& operator ^= (const Vector64& v) { x *= v.x; y *= v.y; z *= v.z; return *this; } friend const Vector64 operator ^ (const Vector64& v1, const Vector64& v2) { return Vector64(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } #endif /// Checks if each component is zero. Bool IsZero() const { return (x == 0.0) && (y == 0.0) && (z == 0.0); } /// Checks if one of the components is not zero. Bool IsNotZero() const { return (x != 0.0) || (y != 0.0) || (z != 0.0); } /// Sets all components to zero. void SetZero() { x = 0.0; y = 0.0; z = 0.0; } /// Tests component-wise if the difference is no bigger than 'epsilon' Bool IsEqual(const Vector64& v2, const Float64& epsilon = 0.01) const { return Abs(x - v2.x) < epsilon && Abs(y - v2.y) < epsilon && Abs(z - v2.z) < epsilon; } /// Calculates the average value of 'x', 'y' and 'z' Float64 GetAverage() const { return (x + y + z) * (1.0 / 3.0); } /// Calculates the sum of 'x', 'y' and 'z' Float64 GetSum() const { return x + y + z; } /// Returns the minimum of 'x', 'y' and 'z' Float64 GetMin() const { if (x < y) { return (z < x) ? z : x; } else { return (z < y) ? z : y; } } /// Returns the maximum of 'x', 'y' and 'z' Float64 GetMax() const { if (x > y) { return (z > x) ? z : x; } else { return (z > y) ? z : y; } } /// Returns a vector that is clamped to the range [0.0 .. 1.0] Vector64 Clamp01() const { return Vector64(::Clamp01(x), ::Clamp01(y), ::Clamp01(z)); } /// Calculates angle (in radians) between v1 and v2 friend Float64 GetAngle(const Vector64& v1, const Vector64& v2) { Float64 il = Inverse(v1.GetSquaredLength() * v2.GetSquaredLength()); return ACos((v1.x * v2.x + v1.y * v2.y + v1.z * v2.z) * Sqrt(il)); } /// Calculates dot product of v1 and v2 friend Float64 Dot(const Vector64& v1, const Vector64& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } /// Calculates cross product of v1 and v2 friend Vector64 Cross(const Vector64& v1, const Vector64& v2) { return Vector64(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } /// Returns the length of the vector Float64 GetLength(void) const { return Sqrt(x * x + y * y + z * z); } /// Returns the squared length of the vector Float64 GetSquaredLength(void) const { return x * x + y * y + z * z; } /// Returns a normalized vector, so that GetLength(vector)==1.0 Vector64 GetNormalized(void) const { Float64 l = GetLength(); if (l == 0.0) return Vector64(0.0, 0.0, 0.0); l = 1.0 / l; return Vector64(x * l, y * l, z * l); } /// Normalizes this vector, so that GetLength()==1.0 void Normalize(void) { Float64 l = Sqrt(x * x + y * y + z * z); if (l != 0.0) { l = 1.0 / l; x *= l; y *= l; z *= l; } } const Vector64& operator += (Float64 s) { x += s; y += s; z += s; return *this; } const Vector64& operator += (const Vector64& v) { x += v.x; y += v.y; z += v.z; return *this; } const Vector64& operator -= (Float64 s) { x -= s; y -= s; z -= s; return *this; } const Vector64& operator -= (const Vector64& v) { x -= v.x; y -= v.y; z -= v.z; return *this; } // multiply each vector component by a scalar const Vector64& operator *= (Float64 s) { x *= s; y *= s; z *= s; return *this; } // divide each vector component by a scalar const Vector64& operator /= (Float64 s) { if (s) { s = 1.0 / s; x *= s; y *= s; z *= s; } else { x = y = z = 0.0; } return *this; } #ifndef __LEGACY_API // multiply vectors componentwise const Vector64& operator *= (const Vector64& v) { x *= v.x; y *= v.y; z *= v.z; return *this; } #endif // GetLength() friend Float64 Len(const Vector64& v) { return Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } // normalized operator (GetNormalized) friend const Vector64 operator ! (const Vector64& v) { Float64 l = Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); if (l == 0.0) return Vector64(0.0); l = 1.0 / l; return Vector64(v.x * l, v.y * l, v.z * l); } // multiply each vector component by a scalar friend const Vector64 operator * (Float64 s, const Vector64& v) { return Vector64(v.x * s, v.y * s, v.z * s); } // multiply each vector component by a scalar friend const Vector64 operator * (const Vector64& v, Float64 s) { return Vector64(v.x * s, v.y * s, v.z * s); } // divide each vector component by a scalar friend const Vector64 operator / (const Vector64& v, Float64 s) { if (s) { s = 1.0 / s; return Vector64(v.x * s, v.y * s, v.z * s); } return Vector64(0.0); } #ifndef __LEGACY_API // multiply vectors componentwise friend const Vector64 operator * (const Vector64& v1, const Vector64& v2) { return Vector64(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } #endif friend const Vector64 operator + (Float64 s, const Vector64& v) { return Vector64(v.x + s, v.y + s, v.z + s); } friend const Vector64 operator + (const Vector64& v, Float64 s) { return Vector64(v.x + s, v.y + s, v.z + s); } friend const Vector64 operator + (const Vector64& v1, const Vector64& v2) { return Vector64(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } friend const Vector64 operator - (Float64 s, const Vector64& v) { return Vector64(s - v.x, s - v.y, s - v.z); } friend const Vector64 operator - (const Vector64& v, Float64 s) { return Vector64(v.x - s, v.y - s, v.z - s); } friend const Vector64 operator - (const Vector64& v1, const Vector64& v2) { return Vector64(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); } friend const Vector64 operator - (const Vector64& v) { return Vector64(-v.x, -v.y, -v.z); } friend Bool operator == (const Vector64& v1, const Vector64& v2) { return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z); } friend Bool operator == (const Vector64& v1, Float64 r) { return (v1.x == r) && (v1.y == r) && (v1.z == r); } friend Bool operator != (const Vector64& v1, Float64 r) { return (v1.x != r) || (v1.y != r) || (v1.z != r); } friend Bool operator != (const Vector64& v1, const Vector64& v2) { return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z); } /// access vector component: index 0 is 'x', index 1 is 'y', index 2 is 'z'. All other values must not be used and will crash Float64& operator [](Int l) { return (&x)[l]; } /// access vector component: index 0 is 'x', index 1 is 'y', index 2 is 'z'. All other values must not be used and will crash const Float64& operator [](Int l) const { return (&x)[l]; } }; #ifdef __LEGACY_API inline const Vector64 Vector32::ToLV() const { return Vector64((Float64)x, (Float64)y, (Float64)z); } inline const Vector64 Vector32::ToRV() const { return Vector64((Float64)x, (Float64)y, (Float64)z); } #endif #endif