|
|
@@ -25,8 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
THE SOFTWARE.
|
|
|
-----------------------------------------------------------------------------
|
|
|
*/
|
|
|
-#ifndef __Vector3_H__
|
|
|
-#define __Vector3_H__
|
|
|
+#pragma once
|
|
|
|
|
|
#include "CmPrerequisitesUtil.h"
|
|
|
#include "CmMath.h"
|
|
|
@@ -34,596 +33,343 @@ THE SOFTWARE.
|
|
|
|
|
|
namespace CamelotFramework
|
|
|
{
|
|
|
- /** \addtogroup Core
|
|
|
- * @{
|
|
|
- */
|
|
|
- /** \addtogroup Math
|
|
|
- * @{
|
|
|
- */
|
|
|
- /** Standard 3-dimensional vector.
|
|
|
- @remarks
|
|
|
- A direction in 3D space represented as distances along the 3
|
|
|
- orthogonal axes (x, y, z). Note that positions, directions and
|
|
|
- scaling factors can be represented by a vector, depending on how
|
|
|
- you interpret the values.
|
|
|
- */
|
|
|
class CM_UTILITY_EXPORT Vector3
|
|
|
{
|
|
|
public:
|
|
|
float x, y, z;
|
|
|
|
|
|
public:
|
|
|
- inline Vector3()
|
|
|
- {
|
|
|
- }
|
|
|
+ Vector3()
|
|
|
+ { }
|
|
|
|
|
|
- inline Vector3( const float fX, const float fY, const float fZ )
|
|
|
- : x( fX ), y( fY ), z( fZ )
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- inline explicit Vector3( const float afCoordinate[3] )
|
|
|
- : x( afCoordinate[0] ),
|
|
|
- y( afCoordinate[1] ),
|
|
|
- z( afCoordinate[2] )
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- inline explicit Vector3( const int afCoordinate[3] )
|
|
|
- {
|
|
|
- x = (float)afCoordinate[0];
|
|
|
- y = (float)afCoordinate[1];
|
|
|
- z = (float)afCoordinate[2];
|
|
|
- }
|
|
|
-
|
|
|
- inline explicit Vector3( float* const r )
|
|
|
- : x( r[0] ), y( r[1] ), z( r[2] )
|
|
|
- {
|
|
|
- }
|
|
|
+ Vector3(float x, float y, float z)
|
|
|
+ : x(x), y(y), z(z)
|
|
|
+ { }
|
|
|
|
|
|
- inline explicit Vector3( const float scaler )
|
|
|
- : x( scaler )
|
|
|
- , y( scaler )
|
|
|
- , z( scaler )
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /** Exchange the contents of this vector with another.
|
|
|
- */
|
|
|
- inline void swap(Vector3& other)
|
|
|
+ /**
|
|
|
+ * @brief Exchange the contents of this vector with another.
|
|
|
+ */
|
|
|
+ void swap(Vector3& other)
|
|
|
{
|
|
|
std::swap(x, other.x);
|
|
|
std::swap(y, other.y);
|
|
|
std::swap(z, other.z);
|
|
|
}
|
|
|
|
|
|
- inline float operator [] ( const size_t i ) const
|
|
|
+ float operator[] (size_t i) const
|
|
|
{
|
|
|
- assert( i < 3 );
|
|
|
+ assert(i < 3);
|
|
|
|
|
|
return *(&x+i);
|
|
|
}
|
|
|
|
|
|
- inline float& operator [] ( const size_t i )
|
|
|
+ float& operator[] (size_t i)
|
|
|
{
|
|
|
- assert( i < 3 );
|
|
|
+ assert(i < 3);
|
|
|
|
|
|
return *(&x+i);
|
|
|
}
|
|
|
- /// Pointer accessor for direct copying
|
|
|
- inline float* ptr()
|
|
|
+
|
|
|
+ float* ptr()
|
|
|
{
|
|
|
return &x;
|
|
|
}
|
|
|
- /// Pointer accessor for direct copying
|
|
|
- inline const float* ptr() const
|
|
|
+
|
|
|
+ const float* ptr() const
|
|
|
{
|
|
|
return &x;
|
|
|
}
|
|
|
|
|
|
- /** Assigns the value of the other vector.
|
|
|
- @param
|
|
|
- rkVector The other vector
|
|
|
- */
|
|
|
- inline Vector3& operator = ( const Vector3& rkVector )
|
|
|
+ Vector3& operator= (const Vector3& rhs)
|
|
|
{
|
|
|
- x = rkVector.x;
|
|
|
- y = rkVector.y;
|
|
|
- z = rkVector.z;
|
|
|
+ x = rhs.x;
|
|
|
+ y = rhs.y;
|
|
|
+ z = rhs.z;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator = ( const float fScaler )
|
|
|
+ Vector3& operator= (float rhs)
|
|
|
{
|
|
|
- x = fScaler;
|
|
|
- y = fScaler;
|
|
|
- z = fScaler;
|
|
|
+ x = rhs;
|
|
|
+ y = rhs;
|
|
|
+ z = rhs;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline bool operator == ( const Vector3& rkVector ) const
|
|
|
+ bool operator== (const Vector3& rhs) const
|
|
|
{
|
|
|
- return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
|
|
|
+ return (x == rhs.x && y == rhs.y && z == rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline bool operator != ( const Vector3& rkVector ) const
|
|
|
+ bool operator!= (const Vector3& rhs) const
|
|
|
{
|
|
|
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
|
|
|
+ return (x != rhs.x || y != rhs.y || z != rhs.z);
|
|
|
}
|
|
|
|
|
|
- // arithmetic operations
|
|
|
- inline Vector3 operator + ( const Vector3& rkVector ) const
|
|
|
+ Vector3 operator+ (const Vector3& rhs) const
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- x + rkVector.x,
|
|
|
- y + rkVector.y,
|
|
|
- z + rkVector.z);
|
|
|
+ return Vector3(x + rhs.x, y + rhs.y, z + rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline Vector3 operator - ( const Vector3& rkVector ) const
|
|
|
+ Vector3 operator- (const Vector3& rhs) const
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- x - rkVector.x,
|
|
|
- y - rkVector.y,
|
|
|
- z - rkVector.z);
|
|
|
+ return Vector3(x - rhs.x, y - rhs.y, z - rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline Vector3 operator * ( const float fScalar ) const
|
|
|
+ Vector3 operator* (float rhs) const
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- x * fScalar,
|
|
|
- y * fScalar,
|
|
|
- z * fScalar);
|
|
|
+ return Vector3(x * rhs, y * rhs, z * rhs);
|
|
|
}
|
|
|
|
|
|
- inline Vector3 operator * ( const Vector3& rhs) const
|
|
|
+ Vector3 operator* (const Vector3& rhs) const
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- x * rhs.x,
|
|
|
- y * rhs.y,
|
|
|
- z * rhs.z);
|
|
|
+ return Vector3(x * rhs.x, y * rhs.y, z * rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline Vector3 operator / ( const float fScalar ) const
|
|
|
+ Vector3 operator/ (float val) const
|
|
|
{
|
|
|
- assert( fScalar != 0.0 );
|
|
|
-
|
|
|
- float fInv = 1.0f / fScalar;
|
|
|
+ assert(val != 0.0);
|
|
|
|
|
|
- return Vector3(
|
|
|
- x * fInv,
|
|
|
- y * fInv,
|
|
|
- z * fInv);
|
|
|
+ float fInv = 1.0f / val;
|
|
|
+ return Vector3(x * fInv, y * fInv, z * fInv);
|
|
|
}
|
|
|
|
|
|
- inline Vector3 operator / ( const Vector3& rhs) const
|
|
|
+ Vector3 operator/ (const Vector3& rhs) const
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- x / rhs.x,
|
|
|
- y / rhs.y,
|
|
|
- z / rhs.z);
|
|
|
+ return Vector3(x / rhs.x, y / rhs.y, z / rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline const Vector3& operator + () const
|
|
|
+ const Vector3& operator+ () const
|
|
|
{
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3 operator - () const
|
|
|
+ Vector3 operator- () const
|
|
|
{
|
|
|
return Vector3(-x, -y, -z);
|
|
|
}
|
|
|
|
|
|
- // overloaded operators to help Vector3
|
|
|
- inline friend Vector3 operator * ( const float fScalar, const Vector3& rkVector )
|
|
|
+ friend Vector3 operator* (float lhs, const Vector3& rhs)
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- fScalar * rkVector.x,
|
|
|
- fScalar * rkVector.y,
|
|
|
- fScalar * rkVector.z);
|
|
|
+ return Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline friend Vector3 operator / ( const float fScalar, const Vector3& rkVector )
|
|
|
+ friend Vector3 operator/ (float lhs, const Vector3& rhs)
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- fScalar / rkVector.x,
|
|
|
- fScalar / rkVector.y,
|
|
|
- fScalar / rkVector.z);
|
|
|
+ return Vector3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline friend Vector3 operator + (const Vector3& lhs, const float rhs)
|
|
|
+ friend Vector3 operator+ (const Vector3& lhs, float rhs)
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- lhs.x + rhs,
|
|
|
- lhs.y + rhs,
|
|
|
- lhs.z + rhs);
|
|
|
+ return Vector3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs);
|
|
|
}
|
|
|
|
|
|
- inline friend Vector3 operator + (const float lhs, const Vector3& rhs)
|
|
|
+ friend Vector3 operator+ (float lhs, const Vector3& rhs)
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- lhs + rhs.x,
|
|
|
- lhs + rhs.y,
|
|
|
- lhs + rhs.z);
|
|
|
+ return Vector3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z);
|
|
|
}
|
|
|
|
|
|
- inline friend Vector3 operator - (const Vector3& lhs, const float rhs)
|
|
|
+ friend Vector3 operator- (const Vector3& lhs, float rhs)
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- lhs.x - rhs,
|
|
|
- lhs.y - rhs,
|
|
|
- lhs.z - rhs);
|
|
|
+ return Vector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs);
|
|
|
}
|
|
|
|
|
|
- inline friend Vector3 operator - (const float lhs, const Vector3& rhs)
|
|
|
+ friend Vector3 operator- (float lhs, const Vector3& rhs)
|
|
|
{
|
|
|
- return Vector3(
|
|
|
- lhs - rhs.x,
|
|
|
- lhs - rhs.y,
|
|
|
- lhs - rhs.z);
|
|
|
+ return Vector3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z);
|
|
|
}
|
|
|
|
|
|
- // arithmetic updates
|
|
|
- inline Vector3& operator += ( const Vector3& rkVector )
|
|
|
+ Vector3& operator+= (const Vector3& rhs)
|
|
|
{
|
|
|
- x += rkVector.x;
|
|
|
- y += rkVector.y;
|
|
|
- z += rkVector.z;
|
|
|
+ x += rhs.x;
|
|
|
+ y += rhs.y;
|
|
|
+ z += rhs.z;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator += ( const float fScalar )
|
|
|
+ Vector3& operator+= (float rhs)
|
|
|
{
|
|
|
- x += fScalar;
|
|
|
- y += fScalar;
|
|
|
- z += fScalar;
|
|
|
+ x += rhs;
|
|
|
+ y += rhs;
|
|
|
+ z += rhs;
|
|
|
+
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator -= ( const Vector3& rkVector )
|
|
|
+ Vector3& operator-= (const Vector3& rhs)
|
|
|
{
|
|
|
- x -= rkVector.x;
|
|
|
- y -= rkVector.y;
|
|
|
- z -= rkVector.z;
|
|
|
+ x -= rhs.x;
|
|
|
+ y -= rhs.y;
|
|
|
+ z -= rhs.z;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator -= ( const float fScalar )
|
|
|
+ Vector3& operator-= (float rhs)
|
|
|
{
|
|
|
- x -= fScalar;
|
|
|
- y -= fScalar;
|
|
|
- z -= fScalar;
|
|
|
+ x -= rhs;
|
|
|
+ y -= rhs;
|
|
|
+ z -= rhs;
|
|
|
+
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator *= ( const float fScalar )
|
|
|
+ Vector3& operator*= (float rhs)
|
|
|
{
|
|
|
- x *= fScalar;
|
|
|
- y *= fScalar;
|
|
|
- z *= fScalar;
|
|
|
+ x *= rhs;
|
|
|
+ y *= rhs;
|
|
|
+ z *= rhs;
|
|
|
+
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator *= ( const Vector3& rkVector )
|
|
|
+ Vector3& operator*= (const Vector3& rhs)
|
|
|
{
|
|
|
- x *= rkVector.x;
|
|
|
- y *= rkVector.y;
|
|
|
- z *= rkVector.z;
|
|
|
+ x *= rhs.x;
|
|
|
+ y *= rhs.y;
|
|
|
+ z *= rhs.z;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator /= ( const float fScalar )
|
|
|
+ Vector3& operator/= (float rhs)
|
|
|
{
|
|
|
- assert( fScalar != 0.0 );
|
|
|
+ assert(rhs != 0.0f);
|
|
|
|
|
|
- float fInv = 1.0f / fScalar;
|
|
|
+ float inv = 1.0f / rhs;
|
|
|
|
|
|
- x *= fInv;
|
|
|
- y *= fInv;
|
|
|
- z *= fInv;
|
|
|
+ x *= inv;
|
|
|
+ y *= inv;
|
|
|
+ z *= inv;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- inline Vector3& operator /= ( const Vector3& rkVector )
|
|
|
+ Vector3& operator/= (const Vector3& rhs)
|
|
|
{
|
|
|
- x /= rkVector.x;
|
|
|
- y /= rkVector.y;
|
|
|
- z /= rkVector.z;
|
|
|
+ x /= rhs.x;
|
|
|
+ y /= rhs.y;
|
|
|
+ z /= rhs.z;
|
|
|
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- /** Returns the length (magnitude) of the vector.
|
|
|
- @warning
|
|
|
- This operation requires a square root and is expensive in
|
|
|
- terms of CPU operations. If you don't need to know the exact
|
|
|
- length (e.g. for just comparing lengths) use squaredLength()
|
|
|
- instead.
|
|
|
- */
|
|
|
- inline float length () const
|
|
|
+ /**
|
|
|
+ * @brief Returns the length (magnitude) of the vector.
|
|
|
+ */
|
|
|
+ float length() const
|
|
|
{
|
|
|
- return Math::Sqrt( x * x + y * y + z * z );
|
|
|
+ return Math::Sqrt(x * x + y * y + z * z);
|
|
|
}
|
|
|
|
|
|
- /** Returns the square of the length(magnitude) of the vector.
|
|
|
- @remarks
|
|
|
- This method is for efficiency - calculating the actual
|
|
|
- length of a vector requires a square root, which is expensive
|
|
|
- in terms of the operations required. This method returns the
|
|
|
- square of the length of the vector, i.e. the same as the
|
|
|
- length but before the square root is taken. Use this if you
|
|
|
- want to find the longest / shortest vector without incurring
|
|
|
- the square root.
|
|
|
- */
|
|
|
- inline float squaredLength () const
|
|
|
+ /**
|
|
|
+ * @brief Returns the square of the length(magnitude) of the vector.
|
|
|
+ */
|
|
|
+ float squaredLength() const
|
|
|
{
|
|
|
return x * x + y * y + z * z;
|
|
|
}
|
|
|
|
|
|
- /** Returns the distance to another vector.
|
|
|
- @warning
|
|
|
- This operation requires a square root and is expensive in
|
|
|
- terms of CPU operations. If you don't need to know the exact
|
|
|
- distance (e.g. for just comparing distances) use squaredDistance()
|
|
|
- instead.
|
|
|
- */
|
|
|
- inline float distance(const Vector3& rhs) const
|
|
|
+ /**
|
|
|
+ * @brief Returns the distance to another vector.
|
|
|
+ */
|
|
|
+ float distance(const Vector3& rhs) const
|
|
|
{
|
|
|
return (*this - rhs).length();
|
|
|
}
|
|
|
|
|
|
- /** Returns the square of the distance to another vector.
|
|
|
- @remarks
|
|
|
- This method is for efficiency - calculating the actual
|
|
|
- distance to another vector requires a square root, which is
|
|
|
- expensive in terms of the operations required. This method
|
|
|
- returns the square of the distance to another vector, i.e.
|
|
|
- the same as the distance but before the square root is taken.
|
|
|
- Use this if you want to find the longest / shortest distance
|
|
|
- without incurring the square root.
|
|
|
- */
|
|
|
- inline float squaredDistance(const Vector3& rhs) const
|
|
|
+ /**
|
|
|
+ * @brief Returns the square of the distance to another vector.
|
|
|
+ */
|
|
|
+ float squaredDistance(const Vector3& rhs) const
|
|
|
{
|
|
|
return (*this - rhs).squaredLength();
|
|
|
}
|
|
|
|
|
|
- /** Calculates the dot (scalar) product of this vector with another.
|
|
|
- @remarks
|
|
|
- The dot product can be used to calculate the angle between 2
|
|
|
- vectors. If both are unit vectors, the dot product is the
|
|
|
- cosine of the angle; otherwise the dot product must be
|
|
|
- divided by the product of the lengths of both vectors to get
|
|
|
- the cosine of the angle. This result can further be used to
|
|
|
- calculate the distance of a point from a plane.
|
|
|
- @param
|
|
|
- vec Vector with which to calculate the dot product (together
|
|
|
- with this one).
|
|
|
- @returns
|
|
|
- A float representing the dot product value.
|
|
|
- */
|
|
|
- inline float dotProduct(const Vector3& vec) const
|
|
|
+ /**
|
|
|
+ * @brief Calculates the dot (scalar) product of this vector with another
|
|
|
+ */
|
|
|
+ float dot(const Vector3& vec) const
|
|
|
{
|
|
|
return x * vec.x + y * vec.y + z * vec.z;
|
|
|
}
|
|
|
|
|
|
- /** Calculates the absolute dot (scalar) product of this vector with another.
|
|
|
- @remarks
|
|
|
- This function work similar dotProduct, except it use absolute value
|
|
|
- of each component of the vector to computing.
|
|
|
- @param
|
|
|
- vec Vector with which to calculate the absolute dot product (together
|
|
|
- with this one).
|
|
|
- @returns
|
|
|
- A float representing the absolute dot product value.
|
|
|
- */
|
|
|
- inline float absDotProduct(const Vector3& vec) const
|
|
|
- {
|
|
|
- return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
|
|
|
- }
|
|
|
-
|
|
|
- /** Normalises the vector.
|
|
|
- @remarks
|
|
|
- This method normalises the vector such that it's
|
|
|
- length / magnitude is 1. The result is called a unit vector.
|
|
|
- @note
|
|
|
- This function will not crash for zero-sized vectors, but there
|
|
|
- will be no changes made to their components.
|
|
|
- @returns The previous length of the vector.
|
|
|
- */
|
|
|
- inline float normalize()
|
|
|
+ /**
|
|
|
+ * @brief Normalizes the vector.
|
|
|
+ */
|
|
|
+ float normalize()
|
|
|
{
|
|
|
- float fLength = Math::Sqrt( x * x + y * y + z * z );
|
|
|
+ float len = Math::Sqrt(x * x + y * y + z * z);
|
|
|
|
|
|
// Will also work for zero-sized vectors, but will change nothing
|
|
|
- if ( fLength > 1e-08 )
|
|
|
+ if (len > 1e-08)
|
|
|
{
|
|
|
- float fInvLength = 1.0f / fLength;
|
|
|
- x *= fInvLength;
|
|
|
- y *= fInvLength;
|
|
|
- z *= fInvLength;
|
|
|
+ float invLen = 1.0f / len;
|
|
|
+ x *= invLen;
|
|
|
+ y *= invLen;
|
|
|
+ z *= invLen;
|
|
|
}
|
|
|
|
|
|
- return fLength;
|
|
|
- }
|
|
|
-
|
|
|
- /** Calculates the cross-product of 2 vectors, i.e. the vector that
|
|
|
- lies perpendicular to them both.
|
|
|
- @remarks
|
|
|
- The cross-product is normally used to calculate the normal
|
|
|
- vector of a plane, by calculating the cross-product of 2
|
|
|
- non-equivalent vectors which lie on the plane (e.g. 2 edges
|
|
|
- of a triangle).
|
|
|
- @param
|
|
|
- vec Vector which, together with this one, will be used to
|
|
|
- calculate the cross-product.
|
|
|
- @returns
|
|
|
- A vector which is the result of the cross-product. This
|
|
|
- vector will <b>NOT</b> be normalised, to maximise efficiency
|
|
|
- - call Vector3::normalise on the result if you wish this to
|
|
|
- be done. As for which side the resultant vector will be on, the
|
|
|
- returned vector will be on the side from which the arc from 'this'
|
|
|
- to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
|
|
|
- = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
|
|
|
- This is because engine uses a right-handed coordinate system.
|
|
|
- @par
|
|
|
- For a clearer explanation, look a the left and the bottom edges
|
|
|
- of your monitor's screen. Assume that the first vector is the
|
|
|
- left edge and the second vector is the bottom edge, both of
|
|
|
- them starting from the lower-left corner of the screen. The
|
|
|
- resulting vector is going to be perpendicular to both of them
|
|
|
- and will go <i>inside</i> the screen, towards the cathode tube
|
|
|
- (assuming you're using a CRT monitor, of course).
|
|
|
- */
|
|
|
- inline Vector3 crossProduct( const Vector3& rkVector ) const
|
|
|
- {
|
|
|
- return Vector3(
|
|
|
- y * rkVector.z - z * rkVector.y,
|
|
|
- z * rkVector.x - x * rkVector.z,
|
|
|
- x * rkVector.y - y * rkVector.x);
|
|
|
+ return len;
|
|
|
}
|
|
|
|
|
|
- /** Returns a vector at a point half way between this and the passed
|
|
|
- in vector.
|
|
|
- */
|
|
|
- inline Vector3 midPoint( const Vector3& vec ) const
|
|
|
+ /**
|
|
|
+ * @brief Calculates the cross-product of 2 vectors, i.e. the vector that
|
|
|
+ * lies perpendicular to them both.
|
|
|
+ */
|
|
|
+ Vector3 cross(const Vector3& other) const
|
|
|
{
|
|
|
return Vector3(
|
|
|
- ( x + vec.x ) * 0.5f,
|
|
|
- ( y + vec.y ) * 0.5f,
|
|
|
- ( z + vec.z ) * 0.5f );
|
|
|
+ y * other.z - z * other.y,
|
|
|
+ z * other.x - x * other.z,
|
|
|
+ x * other.y - y * other.x);
|
|
|
}
|
|
|
|
|
|
- /** Returns true if the vector's scalar components are all greater
|
|
|
- that the ones of the vector it is compared against.
|
|
|
- */
|
|
|
- inline bool operator < ( const Vector3& rhs ) const
|
|
|
+ /**
|
|
|
+ * @brief Sets this vector's components to the minimum of its own and the
|
|
|
+ * ones of the passed in vector.
|
|
|
+ */
|
|
|
+ void floor(const Vector3& cmp)
|
|
|
{
|
|
|
- if( x < rhs.x && y < rhs.y && z < rhs.z )
|
|
|
- return true;
|
|
|
- return false;
|
|
|
+ if(cmp.x < x) x = cmp.x;
|
|
|
+ if(cmp.y < y) y = cmp.y;
|
|
|
+ if(cmp.z < z) z = cmp.z;
|
|
|
}
|
|
|
|
|
|
- /** Returns true if the vector's scalar components are all smaller
|
|
|
- that the ones of the vector it is compared against.
|
|
|
- */
|
|
|
- inline bool operator > ( const Vector3& rhs ) const
|
|
|
+ /**
|
|
|
+ * @brief Sets this vector's components to the maximum of its own and the
|
|
|
+ * ones of the passed in vector.
|
|
|
+ */
|
|
|
+ void ceil(const Vector3& cmp)
|
|
|
{
|
|
|
- if( x > rhs.x && y > rhs.y && z > rhs.z )
|
|
|
- return true;
|
|
|
- return false;
|
|
|
+ if(cmp.x > x) x = cmp.x;
|
|
|
+ if(cmp.y > y) y = cmp.y;
|
|
|
+ if(cmp.z > z) z = cmp.z;
|
|
|
}
|
|
|
|
|
|
- /** Sets this vector's components to the minimum of its own and the
|
|
|
- ones of the passed in vector.
|
|
|
- @remarks
|
|
|
- 'Minimum' in this case means the combination of the lowest
|
|
|
- value of x, y and z from both vectors. Lowest is taken just
|
|
|
- numerically, not magnitude, so -1 < 0.
|
|
|
+ /**
|
|
|
+ * @brief Generates a vector perpendicular to this vector.
|
|
|
*/
|
|
|
- inline void makeFloor( const Vector3& cmp )
|
|
|
+ Vector3 perpendicular() const
|
|
|
{
|
|
|
- if( cmp.x < x ) x = cmp.x;
|
|
|
- if( cmp.y < y ) y = cmp.y;
|
|
|
- if( cmp.z < z ) z = cmp.z;
|
|
|
- }
|
|
|
+ static const float squareZero = (float)(1e-06 * 1e-06);
|
|
|
|
|
|
- /** Sets this vector's components to the maximum of its own and the
|
|
|
- ones of the passed in vector.
|
|
|
- @remarks
|
|
|
- 'Maximum' in this case means the combination of the highest
|
|
|
- value of x, y and z from both vectors. Highest is taken just
|
|
|
- numerically, not magnitude, so 1 > -3.
|
|
|
- */
|
|
|
- inline void makeCeil( const Vector3& cmp )
|
|
|
- {
|
|
|
- if( cmp.x > x ) x = cmp.x;
|
|
|
- if( cmp.y > y ) y = cmp.y;
|
|
|
- if( cmp.z > z ) z = cmp.z;
|
|
|
- }
|
|
|
+ Vector3 perp = this->cross(Vector3::UNIT_X);
|
|
|
|
|
|
- /** Generates a vector perpendicular to this vector (eg an 'up' vector).
|
|
|
- @remarks
|
|
|
- This method will return a vector which is perpendicular to this
|
|
|
- vector. There are an infinite number of possibilities but this
|
|
|
- method will guarantee to generate one of them. If you need more
|
|
|
- control you should use the Quaternion class.
|
|
|
- */
|
|
|
- inline Vector3 perpendicular(void) const
|
|
|
- {
|
|
|
- static const float fSquareZero = (float)(1e-06 * 1e-06);
|
|
|
-
|
|
|
- Vector3 perp = this->crossProduct( Vector3::UNIT_X );
|
|
|
+ if(perp.squaredLength() < squareZero)
|
|
|
+ perp = this->cross(Vector3::UNIT_Y);
|
|
|
|
|
|
- // Check length
|
|
|
- if( perp.squaredLength() < fSquareZero )
|
|
|
- {
|
|
|
- /* This vector is the Y axis multiplied by a scalar, so we have
|
|
|
- to use another axis.
|
|
|
- */
|
|
|
- perp = this->crossProduct( Vector3::UNIT_Y );
|
|
|
- }
|
|
|
perp.normalize();
|
|
|
-
|
|
|
return perp;
|
|
|
}
|
|
|
- /** Generates a new random vector which deviates from this vector by a
|
|
|
- given angle in a random direction.
|
|
|
- @remarks
|
|
|
- This method assumes that the random number generator has already
|
|
|
- been seeded appropriately.
|
|
|
- @param
|
|
|
- angle The angle at which to deviate
|
|
|
- @param
|
|
|
- up Any vector perpendicular to this one (which could generated
|
|
|
- by cross-product of this vector and any other non-colinear
|
|
|
- vector). If you choose not to provide this the function will
|
|
|
- derive one on it's own, however if you provide one yourself the
|
|
|
- function will be faster (this allows you to reuse up vectors if
|
|
|
- you call this method more than once)
|
|
|
- @returns
|
|
|
- A random vector which deviates from this vector by angle. This
|
|
|
- vector will not be normalised, normalise it if you wish
|
|
|
- afterwards.
|
|
|
- */
|
|
|
- inline Vector3 randomDeviant(
|
|
|
- const Radian& angle,
|
|
|
- const Vector3& up = Vector3::ZERO ) const
|
|
|
- {
|
|
|
- Vector3 newUp;
|
|
|
-
|
|
|
- if (up == Vector3::ZERO)
|
|
|
- {
|
|
|
- // Generate an up vector
|
|
|
- newUp = this->perpendicular();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- newUp = up;
|
|
|
- }
|
|
|
-
|
|
|
- // Rotate up vector by random amount around this
|
|
|
- Quaternion q;
|
|
|
- q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
|
|
|
- newUp = q * newUp;
|
|
|
|
|
|
- // Finally rotate this by given angle around randomised up
|
|
|
- q.FromAngleAxis( angle, newUp );
|
|
|
- return q * (*this);
|
|
|
- }
|
|
|
-
|
|
|
- /** Gets the angle between 2 vectors.
|
|
|
- @remarks
|
|
|
- Vectors do not have to be unit-length but must represent directions.
|
|
|
- */
|
|
|
- inline Radian angleBetween(const Vector3& dest)
|
|
|
+ /**
|
|
|
+ * @brief Gets the angle between 2 vectors.
|
|
|
+ */
|
|
|
+ Radian angleBetween(const Vector3& dest)
|
|
|
{
|
|
|
float lenProduct = length() * dest.length();
|
|
|
|
|
|
@@ -631,50 +377,46 @@ namespace CamelotFramework
|
|
|
if(lenProduct < 1e-6f)
|
|
|
lenProduct = 1e-6f;
|
|
|
|
|
|
- float f = dotProduct(dest) / lenProduct;
|
|
|
+ float f = dot(dest) / lenProduct;
|
|
|
|
|
|
- f = Math::Clamp(f, (float)-1.0, (float)1.0);
|
|
|
+ f = Math::Clamp(f, -1.0f, 1.0f);
|
|
|
return Math::ACos(f);
|
|
|
|
|
|
}
|
|
|
- /** Gets the shortest arc quaternion to rotate this vector to the destination
|
|
|
- vector.
|
|
|
- @remarks
|
|
|
- If you call this with a dest vector that is close to the inverse
|
|
|
- of this vector, we will rotate 180 degrees around the 'fallbackAxis'
|
|
|
- (if specified, or a generated axis if not) since in this case
|
|
|
- ANY axis of rotation is valid.
|
|
|
- */
|
|
|
- Quaternion getRotationTo(const Vector3& dest,
|
|
|
- const Vector3& fallbackAxis = Vector3::ZERO) const
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Gets the shortest arc quaternion to rotate this vector to the destination
|
|
|
+ * vector.
|
|
|
+ */
|
|
|
+ Quaternion getRotationTo(const Vector3& dest, const Vector3& fallbackAxis = Vector3::ZERO) const
|
|
|
{
|
|
|
// Based on Stan Melax's article in Game Programming Gems
|
|
|
Quaternion q;
|
|
|
- // Copy, since cannot modify local
|
|
|
+
|
|
|
Vector3 v0 = *this;
|
|
|
Vector3 v1 = dest;
|
|
|
v0.normalize();
|
|
|
v1.normalize();
|
|
|
|
|
|
- float d = v0.dotProduct(v1);
|
|
|
+ float d = v0.dot(v1);
|
|
|
+
|
|
|
// If dot == 1, vectors are the same
|
|
|
if (d >= 1.0f)
|
|
|
- {
|
|
|
return Quaternion::IDENTITY;
|
|
|
- }
|
|
|
+
|
|
|
if (d < (1e-6f - 1.0f))
|
|
|
{
|
|
|
if (fallbackAxis != Vector3::ZERO)
|
|
|
{
|
|
|
- // rotate 180 degrees about the fallback axis
|
|
|
+ // Rotate 180 degrees about the fallback axis
|
|
|
q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// Generate an axis
|
|
|
- Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
|
|
|
- if (axis.isZeroLength()) // pick another if colinear
|
|
|
- axis = Vector3::UNIT_Y.crossProduct(*this);
|
|
|
+ Vector3 axis = Vector3::UNIT_X.cross(*this);
|
|
|
+ if (axis.isZeroLength()) // Pick another if colinear
|
|
|
+ axis = Vector3::UNIT_Y.cross(*this);
|
|
|
axis.normalize();
|
|
|
q.FromAngleAxis(Radian(Math::PI), axis);
|
|
|
}
|
|
|
@@ -684,7 +426,7 @@ namespace CamelotFramework
|
|
|
float s = Math::Sqrt( (1+d)*2 );
|
|
|
float invs = 1 / s;
|
|
|
|
|
|
- Vector3 c = v0.crossProduct(v1);
|
|
|
+ Vector3 c = v0.cross(v1);
|
|
|
|
|
|
q.x = c.x * invs;
|
|
|
q.y = c.y * invs;
|
|
|
@@ -692,79 +434,48 @@ namespace CamelotFramework
|
|
|
q.w = s * 0.5f;
|
|
|
q.normalize();
|
|
|
}
|
|
|
+
|
|
|
return q;
|
|
|
}
|
|
|
|
|
|
- /** Returns true if this vector is zero length. */
|
|
|
- inline bool isZeroLength(void) const
|
|
|
+ /**
|
|
|
+ * @brief Returns true if this vector is zero length.
|
|
|
+ */
|
|
|
+ bool isZeroLength() const
|
|
|
{
|
|
|
float sqlen = (x * x) + (y * y) + (z * z);
|
|
|
return (sqlen < (1e-06 * 1e-06));
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /** As normalise, except that this vector is unaffected and the
|
|
|
- normalised vector is returned as a copy. */
|
|
|
- inline Vector3 normalizedCopy(void) const
|
|
|
- {
|
|
|
- Vector3 ret = *this;
|
|
|
- ret.normalize();
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
- /** Calculates a reflection vector to the plane with the given normal .
|
|
|
- @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
|
|
|
- */
|
|
|
- inline Vector3 reflect(const Vector3& normal) const
|
|
|
+ /**
|
|
|
+ * @brief Calculates a reflection vector to the plane with the given normal.
|
|
|
+ */
|
|
|
+ Vector3 reflect(const Vector3& normal) const
|
|
|
{
|
|
|
- return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
|
|
|
+ return Vector3(*this - (2 * this->dot(normal) * normal));
|
|
|
}
|
|
|
|
|
|
- /** Returns whether this vector is within a positional tolerance
|
|
|
- of another vector.
|
|
|
- @param rhs The vector to compare with
|
|
|
- @param tolerance The amount that each element of the vector may vary by
|
|
|
- and still be considered equal
|
|
|
- */
|
|
|
- inline bool positionEquals(const Vector3& rhs, float tolerance = 1e-03) const
|
|
|
+ static Vector3 normalize(const Vector3& val)
|
|
|
{
|
|
|
- return Math::RealEqual(x, rhs.x, tolerance) &&
|
|
|
- Math::RealEqual(y, rhs.y, tolerance) &&
|
|
|
- Math::RealEqual(z, rhs.z, tolerance);
|
|
|
+ float len = Math::Sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- /** Returns whether this vector is within a positional tolerance
|
|
|
- of another vector, also take scale of the vectors into account.
|
|
|
- @param rhs The vector to compare with
|
|
|
- @param tolerance The amount (related to the scale of vectors) that distance
|
|
|
- of the vector may vary by and still be considered close
|
|
|
- */
|
|
|
- inline bool positionCloses(const Vector3& rhs, float tolerance = 1e-03f) const
|
|
|
- {
|
|
|
- return squaredDistance(rhs) <=
|
|
|
- (squaredLength() + rhs.squaredLength()) * tolerance;
|
|
|
- }
|
|
|
-
|
|
|
- /** Returns whether this vector is within a directional tolerance
|
|
|
- of another vector.
|
|
|
- @param rhs The vector to compare with
|
|
|
- @param tolerance The maximum angle by which the vectors may vary and
|
|
|
- still be considered equal
|
|
|
- @note Both vectors should be normalised.
|
|
|
- */
|
|
|
- inline bool directionEquals(const Vector3& rhs,
|
|
|
- const Radian& tolerance) const
|
|
|
- {
|
|
|
- float dot = dotProduct(rhs);
|
|
|
- Radian angle = Math::ACos(dot);
|
|
|
+ // Will also work for zero-sized vectors, but will change nothing
|
|
|
+ if (len > 1e-08)
|
|
|
+ {
|
|
|
+ float invLen = 1.0f / len;
|
|
|
|
|
|
- return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
|
|
|
+ Vector3 normalizedVec;
|
|
|
+ normalizedVec.x = val.x * invLen;
|
|
|
+ normalizedVec.y = val.y * invLen;
|
|
|
+ normalizedVec.z = val.z * invLen;
|
|
|
|
|
|
+ return normalizedVec;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return val;
|
|
|
}
|
|
|
|
|
|
- /// Check whether this vector contains valid values
|
|
|
- inline bool isNaN() const
|
|
|
+ bool isNaN() const
|
|
|
{
|
|
|
return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
|
|
|
}
|
|
|
@@ -779,31 +490,12 @@ namespace CamelotFramework
|
|
|
return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
|
|
|
}
|
|
|
|
|
|
- // special points
|
|
|
static const Vector3 ZERO;
|
|
|
+ static const Vector3 ONE;
|
|
|
static const Vector3 UNIT_X;
|
|
|
static const Vector3 UNIT_Y;
|
|
|
static const Vector3 UNIT_Z;
|
|
|
- static const Vector3 RIGHT;
|
|
|
- static const Vector3 UP;
|
|
|
- static const Vector3 FORWARD;
|
|
|
- static const Vector3 NEGATIVE_UNIT_X;
|
|
|
- static const Vector3 NEGATIVE_UNIT_Y;
|
|
|
- static const Vector3 NEGATIVE_UNIT_Z;
|
|
|
- static const Vector3 UNIT_SCALE;
|
|
|
-
|
|
|
- /** Function for writing to a stream.
|
|
|
- */
|
|
|
- inline CM_UTILITY_EXPORT friend std::ostream& operator <<
|
|
|
- ( std::ostream& o, const Vector3& v )
|
|
|
- {
|
|
|
- o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
|
|
|
- return o;
|
|
|
- }
|
|
|
};
|
|
|
- /** @} */
|
|
|
- /** @} */
|
|
|
|
|
|
CM_ALLOW_MEMCPY_SERIALIZATION(Vector3);
|
|
|
}
|
|
|
-#endif
|