summaryrefslogtreecommitdiff
path: root/Runtime/Math/Vector3.h
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Math/Vector3.h
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Math/Vector3.h')
-rw-r--r--Runtime/Math/Vector3.h205
1 files changed, 205 insertions, 0 deletions
diff --git a/Runtime/Math/Vector3.h b/Runtime/Math/Vector3.h
new file mode 100644
index 0000000..ea4bbc4
--- /dev/null
+++ b/Runtime/Math/Vector3.h
@@ -0,0 +1,205 @@
+#ifndef VECTOR3_H
+#define VECTOR3_H
+
+#include <algorithm>
+#include "FloatConversion.h"
+#include "Runtime/Serialize/SerializeUtility.h"
+#include "Runtime/Serialize/SerializationMetaFlags.h"
+#include "Runtime/Utilities/LogAssert.h"
+#include "Runtime/Modules/ExportModules.h"
+
+class Vector3f
+{
+ public:
+
+ float x, y, z;
+
+ DEFINE_GET_TYPESTRING_IS_ANIMATION_CHANNEL (Vector3f)
+ template<class TransferFunction> void Transfer (TransferFunction& transfer);
+
+ Vector3f () : x(0.f), y(0.f), z(0.f) {}
+ Vector3f (float inX, float inY, float inZ) { x = inX; y = inY; z = inZ; }
+ explicit Vector3f (const float* array) { x = array[0]; y = array[1]; z = array[2]; }
+ void Set (float inX, float inY, float inZ) { x = inX; y = inY; z = inZ; }
+ void Set (const float* array) { x = array[0]; y = array[1]; z = array[2]; }
+
+ float* GetPtr () { return &x; }
+ const float* GetPtr ()const { return &x; }
+ float& operator[] (int i) { DebugAssertIf (i < 0 || i > 2); return (&x)[i]; }
+ const float& operator[] (int i)const { DebugAssertIf (i < 0 || i > 2); return (&x)[i]; }
+
+ bool operator == (const Vector3f& v)const { return x == v.x && y == v.y && z == v.z; }
+ bool operator != (const Vector3f& v)const { return x != v.x || y != v.y || z != v.z; }
+
+ Vector3f& operator += (const Vector3f& inV) { x += inV.x; y += inV.y; z += inV.z; return *this; }
+ Vector3f& operator -= (const Vector3f& inV) { x -= inV.x; y -= inV.y; z -= inV.z; return *this; }
+ Vector3f& operator *= (float s) { x *= s; y *= s; z *= s; return *this; }
+ Vector3f& operator /= (float s);
+
+ Vector3f operator - () const { return Vector3f (-x, -y, -z); }
+
+ Vector3f& Scale (const Vector3f& inV) { x *= inV.x; y *= inV.y; z *= inV.z; return *this;}
+
+
+ EXPORT_COREMODULE static const float epsilon;
+ EXPORT_COREMODULE static const float infinity;
+ EXPORT_COREMODULE static const Vector3f infinityVec;
+ EXPORT_COREMODULE static const Vector3f zero;
+ EXPORT_COREMODULE static const Vector3f one;
+ EXPORT_COREMODULE static const Vector3f xAxis;
+ EXPORT_COREMODULE static const Vector3f yAxis;
+ EXPORT_COREMODULE static const Vector3f zAxis;
+};
+
+inline Vector3f Scale (const Vector3f& lhs, const Vector3f& rhs) { return Vector3f (lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); }
+
+inline Vector3f operator + (const Vector3f& lhs, const Vector3f& rhs) { return Vector3f (lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); }
+inline Vector3f operator - (const Vector3f& lhs, const Vector3f& rhs) { return Vector3f (lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); }
+inline Vector3f Cross (const Vector3f& lhs, const Vector3f& rhs);
+inline float Dot (const Vector3f& lhs, const Vector3f& rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; }
+
+inline Vector3f operator * (const Vector3f& inV, const float s) { return Vector3f (inV.x * s, inV.y * s, inV.z * s); }
+inline Vector3f operator * (const float s, const Vector3f& inV) { return Vector3f (inV.x * s, inV.y * s, inV.z * s); }
+inline Vector3f operator / (const Vector3f& inV, const float s) { Vector3f temp (inV); temp /= s; return temp; }
+inline Vector3f Inverse (const Vector3f& inVec) { return Vector3f (1.0F / inVec.x, 1.0F / inVec.y, 1.0F / inVec.z); }
+
+inline float SqrMagnitude (const Vector3f& inV) { return Dot (inV, inV); }
+inline float Magnitude (const Vector3f& inV) {return SqrtImpl(Dot (inV, inV));}
+
+// Normalizes a vector, asserts if the vector can be normalized
+inline Vector3f Normalize (const Vector3f& inV) { return inV / Magnitude (inV); }
+// Normalizes a vector, returns default vector if it can't be normalized
+inline Vector3f NormalizeSafe (const Vector3f& inV, const Vector3f& defaultV = Vector3f::zero);
+
+inline Vector3f ReflectVector (const Vector3f& inDirection, const Vector3f& inNormal) { return -2.0F * Dot (inNormal, inDirection) * inNormal + inDirection; }
+
+inline Vector3f Lerp (const Vector3f& from, const Vector3f& to, float t) { return to * t + from * (1.0F - t); }
+Vector3f Slerp (const Vector3f& from, const Vector3f& to, float t);
+
+// Returns a vector with the smaller of every component from v0 and v1
+inline Vector3f min (const Vector3f& lhs, const Vector3f& rhs) { return Vector3f (FloatMin (lhs.x, rhs.x), FloatMin (lhs.y, rhs.y), FloatMin (lhs.z, rhs.z)); }
+// Returns a vector with the larger of every component from v0 and v1
+inline Vector3f max (const Vector3f& lhs, const Vector3f& rhs) { return Vector3f (FloatMax (lhs.x, rhs.x), FloatMax (lhs.y, rhs.y), FloatMax (lhs.z, rhs.z)); }
+
+/// Project one vector onto another.
+inline Vector3f Project (const Vector3f& v1, const Vector3f& v2) { return v2* Dot (v1, v2)/ Dot (v2, v2); }
+
+
+/// Returns the abs of every component of the vector
+inline Vector3f Abs (const Vector3f& v) { return Vector3f (Abs (v.x), Abs (v.y), Abs (v.z)); }
+
+bool CompareApproximately (const Vector3f& inV0, const Vector3f& inV1, const float inMaxDist = Vector3f::epsilon);
+// Orthonormalizes the three vectors, assuming that a orthonormal basis can be formed
+void OrthoNormalizeFast (Vector3f* inU, Vector3f* inV, Vector3f* inW);
+// Orthonormalizes the three vectors, returns false if no orthonormal basis could be formed.
+EXPORT_COREMODULE void OrthoNormalize (Vector3f* inU, Vector3f* inV, Vector3f* inW);
+// Orthonormalizes the two vectors. inV is taken as a hint and will try to be as close as possible to inV.
+EXPORT_COREMODULE void OrthoNormalize (Vector3f* inU, Vector3f* inV);
+
+// Calculates a vector that is orthonormal to n.
+// Assumes that n is normalized
+Vector3f OrthoNormalVectorFast (const Vector3f& n);
+
+// Rotates lhs towards rhs by no more than max Angle
+// Moves the magnitude of lhs towards rhs by no more than maxMagnitude
+Vector3f RotateTowards (const Vector3f& lhs, const Vector3f& rhs, float maxAngle, float maxMagnitude);
+
+// Spherically interpolates the direction of two vectors
+// and interpolates the magnitude of the two vectors
+Vector3f Slerp (const Vector3f& lhs, const Vector3f& rhs, float t);
+
+/// Returns a Vector3 that moves lhs towards rhs by a maximum of clampedDistance
+Vector3f MoveTowards (const Vector3f& lhs, const Vector3f& rhs, float clampedDistance);
+
+inline bool IsNormalized (const Vector3f& vec, float epsilon = Vector3f::epsilon)
+{
+ return CompareApproximately (SqrMagnitude (vec), 1.0F, epsilon);
+}
+
+inline Vector3f Cross (const Vector3f& lhs, const Vector3f& rhs)
+{
+ return Vector3f (
+ lhs.y * rhs.z - lhs.z * rhs.y,
+ lhs.z * rhs.x - lhs.x * rhs.z,
+ lhs.x * rhs.y - lhs.y * rhs.x);
+}
+
+inline Vector3f NormalizeSafe (const Vector3f& inV, const Vector3f& defaultV)
+{
+ float mag = Magnitude (inV);
+ if (mag > Vector3f::epsilon)
+ return inV / Magnitude (inV);
+ else
+ return defaultV;
+}
+
+/// - Handles zero vector correclty
+inline Vector3f NormalizeFast (const Vector3f& inV)
+{
+ float m = SqrMagnitude (inV);
+ // GCC version of __frsqrte:
+ // static inline double __frsqrte (double x) {
+ // double y;
+ // asm ( "frsqrte %0, %1" : /*OUT*/ "=f" (y) : /*IN*/ "f" (x) );
+ // return y;
+ // }
+ return inV * FastInvSqrt (m);
+}
+
+/// - low precision normalize
+/// - nan for zero vector
+inline Vector3f NormalizeFastest (const Vector3f& inV)
+{
+ float m = SqrMagnitude (inV);
+ // GCC version of __frsqrte:
+ // static inline double __frsqrte (double x) {
+ // double y;
+ // asm ( "frsqrte %0, %1" : /*OUT*/ "=f" (y) : /*IN*/ "f" (x) );
+ // return y;
+ // }
+ return inV * FastestInvSqrt (m);
+}
+
+inline bool IsFinite (const Vector3f& f)
+{
+ return IsFinite(f.x) & IsFinite(f.y) & IsFinite(f.z);
+}
+
+
+
+inline bool CompareApproximately (const Vector3f& inV0, const Vector3f& inV1, const float inMaxDist)
+{
+ return SqrMagnitude (inV1 - inV0) < inMaxDist * inMaxDist;
+}
+
+inline Vector3f& Vector3f::operator /= (float s)
+{
+ DebugAssertIf (CompareApproximately (s, 0.0F));
+ x /= s;
+ y /= s;
+ z /= s;
+ return *this;
+}
+
+template<class TransferFunction>
+inline void Vector3f::Transfer (TransferFunction& t)
+{
+ t.AddMetaFlag (kTransferUsingFlowMappingStyle);
+ t.Transfer (x, "x");
+ t.Transfer (y, "y");
+ t.Transfer (z, "z");
+}
+
+// this may be called for vectors `a' with extremely small magnitude, for
+// example the result of a cross product on two nearly perpendicular vectors.
+// we must be robust to these small vectors. to prevent numerical error,
+// first find the component a[i] with the largest magnitude and then scale
+// all the components by 1/a[i]. then we can compute the length of `a' and
+// scale the components by 1/l. this has been verified to work with vectors
+// containing the smallest representable numbers.
+Vector3f NormalizeRobust (const Vector3f& a);
+// This also returns vector's inverse original length, to avoid duplicate
+// invSqrt calculations when needed. If a is a zero vector, invOriginalLength will be 0.
+Vector3f NormalizeRobust (const Vector3f& a, float &invOriginalLength);
+
+#endif