Initial implementation Vector3Of
This commit is contained in:
parent
9886f98f6b
commit
4cf2511a8b
177
Vector3.cpp
177
Vector3.cpp
@ -5,6 +5,7 @@
|
|||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
#include "Angle.h"
|
#include "Angle.h"
|
||||||
#include "Spherical.h"
|
#include "Spherical.h"
|
||||||
|
//#include "TypeTraits.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
@ -160,8 +161,7 @@ float Vector3::Distance(const Vector3& v1, const Vector3& v2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) {
|
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) {
|
||||||
return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z,
|
return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);
|
||||||
v1.x * v2.y - v1.y * v2.x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::Project(const Vector3& v, const Vector3& n) {
|
Vector3 Vector3::Project(const Vector3& v, const Vector3& n) {
|
||||||
@ -194,17 +194,14 @@ AngleOf<float> Vector3::Angle(const Vector3& v1, const Vector3& v2) {
|
|||||||
float dot = Vector3::Dot(v1, v2);
|
float dot = Vector3::Dot(v1, v2);
|
||||||
float fraction = dot / denominator;
|
float fraction = dot / denominator;
|
||||||
if (isnan(fraction))
|
if (isnan(fraction))
|
||||||
return AngleOf<float>::Degrees(
|
return AngleOf<float>::Degrees(fraction); // short cut to returning NaN universally
|
||||||
fraction); // short cut to returning NaN universally
|
|
||||||
|
|
||||||
float cdot = clamp(fraction, -1.0, 1.0);
|
float cdot = clamp(fraction, -1.0, 1.0);
|
||||||
float r = ((float)acos(cdot));
|
float r = ((float)acos(cdot));
|
||||||
return AngleOf<float>::Radians(r);
|
return AngleOf<float>::Radians(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
AngleOf<float> Vector3::SignedAngle(const Vector3& v1,
|
AngleOf<float> Vector3::SignedAngle(const Vector3& v1, const Vector3& v2, const Vector3& axis) {
|
||||||
const Vector3& v2,
|
|
||||||
const Vector3& axis) {
|
|
||||||
// angle in [0,180]
|
// angle in [0,180]
|
||||||
AngleOf<float> angle = Vector3::Angle(v1, v2);
|
AngleOf<float> angle = Vector3::Angle(v1, v2);
|
||||||
|
|
||||||
@ -222,3 +219,169 @@ Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) {
|
|||||||
Vector3 v = v1 + (v2 - v1) * f;
|
Vector3 v = v1 + (v2 - v1) * f;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma region Vector3Of
|
||||||
|
|
||||||
|
namespace LinearAlgebra {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T>::Vector3Of() {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T>::Vector3Of(T horizontal, T vertical, T depth)
|
||||||
|
: horizontal(horizontal), vertical(vertical), depth(depth) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T>::Vector3Of(Vector2Of<T> v) : horizontal(v.horizontal), vertical(v.vertical) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T>::Vector3Of(SphericalOf<T> v) {
|
||||||
|
float cosVertical = Angle::Cos(v.direction.vertical);
|
||||||
|
float sinVertical = Angle::Sin(v.direction.vertical);
|
||||||
|
float cosHorizontal = Angle::Cos(v.direction.horizontal);
|
||||||
|
float sinHorizontal = Angle::Sin(v.direction.horizontal);
|
||||||
|
|
||||||
|
horizontal = v.distance * sinVertical * sinHorizontal;
|
||||||
|
vertical = v.distance * cosVertical;
|
||||||
|
depth = v.distance * sinVertical * cosHorizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T>::Vector3Of(Vector3 v) : horizontal(v.x), vertical(v.y), depth(v.z) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3 Vector3Of<T>::ToVector3() {
|
||||||
|
return Vector3(this->horizontal, this->vertical, this->depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T>::~Vector3Of() {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const Vector3Of<T> Vector3Of<T>::zero = Vector3Of(T{}, T{}, T{});
|
||||||
|
|
||||||
|
template <>
|
||||||
|
const Vector3Of<int> Vector3Of<int>::unit = Vector3Of<int>(1, 1, 1);
|
||||||
|
template <>
|
||||||
|
const Vector3Of<float> Vector3Of<float>::unit = Vector3Of<float>(1.0f, 1.0f, 1.0f);
|
||||||
|
template <>
|
||||||
|
const Vector3Of<double> Vector3Of<double>::unit = Vector3Of<double>(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// const Vector3Of<T> Vector3Of<T>::unit =
|
||||||
|
// Vector3Of(TypeTraits<T>::unit(), TypeTraits<T>::unit(), TypeTraits<T>::unit());
|
||||||
|
// const Vector3Of Vector3Of::right = Vector3Of(1, 0, 0);
|
||||||
|
// const Vector3Of Vector3Of::left = Vector3Of(-1, 0, 0);
|
||||||
|
// const Vector3Of Vector3Of::up = Vector3Of(0, 1, 0);
|
||||||
|
// const Vector3Of Vector3Of::down = Vector3Of(0, -1, 0);
|
||||||
|
// const Vector3Of Vector3Of::forward = Vector3Of(0, 0, 1);
|
||||||
|
// const Vector3Of Vector3Of::back = Vector3Of(0, 0, -1);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T Vector3Of<T>::MagnitudeOf(const Vector3Of& v) {
|
||||||
|
return sqrtf(v.horizontal * v.horizontal + v.vertical * v.vertical + v.depth * v.depth);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
T Vector3Of<T>::Magnitude() const {
|
||||||
|
return (T)sqrtf(this->horizontal * this->horizontal + this->vertical * this->vertical +
|
||||||
|
this->depth * this->depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
float Vector3Of<T>::SqrMagnitudeOf(const Vector3Of& v) {
|
||||||
|
return v.horizontal * v.horizontal + v.vertical * v.vertical + v.depth * v.depth;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
float Vector3Of<T>::SqrMagnitude() const {
|
||||||
|
return (horizontal * horizontal + vertical * vertical + depth * depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::Normalize(const Vector3Of& v) {
|
||||||
|
float num = Vector3Of<T>::MagnitudeOf(v);
|
||||||
|
Vector3Of<T> result = Vector3Of<T>::zero;
|
||||||
|
if (num > epsilon) {
|
||||||
|
result = v / num;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::Normalized() const {
|
||||||
|
float num = this->Magnitude();
|
||||||
|
Vector3Of<T> result = Vector3Of<T>::zero;
|
||||||
|
if (num > epsilon) {
|
||||||
|
result = ((Vector3Of<T>) * this) / num;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::operator-(const Vector3Of& v) const {
|
||||||
|
return Vector3(this->horizontal - v.horizontal, this->vertical - v.vertical,
|
||||||
|
this->depth - v.depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::operator-=(const Vector3Of& v) {
|
||||||
|
this->horizontal -= v.horizontal;
|
||||||
|
this->vertical -= v.vertical;
|
||||||
|
this->depth -= v.depth;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::operator+(const Vector3Of& v) const {
|
||||||
|
return Vector3(this->horizontal + v.horizontal, this->vertical + v.vertical,
|
||||||
|
this->depth + v.depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::operator+=(const Vector3Of& v) {
|
||||||
|
this->horizontal += v.horizontal;
|
||||||
|
this->vertical += v.vertical;
|
||||||
|
this->depth += v.depth;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::operator*=(float f) {
|
||||||
|
this->horizontal *= f;
|
||||||
|
this->vertical *= f;
|
||||||
|
this->depth *= f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Vector3Of<T> Vector3Of<T>::operator/=(float f) {
|
||||||
|
this->horizontal /= f;
|
||||||
|
this->vertical /= f;
|
||||||
|
this->depth /= f;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
float Vector3Of<T>::Dot(const Vector3Of& v1, const Vector3Of& v2) {
|
||||||
|
return v1.horizontal * v2.horizontal + v1.vertical * v2.vertical + v1.depth * v2.depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
AngleOf<float> Vector3Of<T>::Angle(const Vector3Of& v1, const Vector3Of& v2) {
|
||||||
|
float denominator = sqrtf(v1.SqrMagnitude() * v2.SqrMagnitude());
|
||||||
|
if (denominator < epsilon)
|
||||||
|
return AngleOf<float>();
|
||||||
|
|
||||||
|
float dot = Vector3Of::Dot(v1, v2);
|
||||||
|
float fraction = dot / denominator;
|
||||||
|
if (isnan(fraction))
|
||||||
|
return AngleOf<float>::Degrees(fraction); // short cut to returning NaN universally
|
||||||
|
|
||||||
|
float cdot = clamp(fraction, -1.0, 1.0);
|
||||||
|
float r = ((float)acos(cdot));
|
||||||
|
return AngleOf<float>::Radians(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template class Vector3Of<float>;
|
||||||
|
|
||||||
|
} // namespace LinearAlgebra
|
||||||
|
|
||||||
|
#pragma endregion Vector3Of
|
||||||
145
Vector3.h
145
Vector3.h
@ -146,9 +146,7 @@ struct Vector3 : Vec3 {
|
|||||||
/// @return The scaled vector
|
/// @return The scaled vector
|
||||||
/// @remark Each component of the vector will be multipled with the same
|
/// @remark Each component of the vector will be multipled with the same
|
||||||
/// factor f.
|
/// factor f.
|
||||||
friend Vector3 operator*(const Vector3& v, float f) {
|
friend Vector3 operator*(const Vector3& v, float f) { return Vector3(v.x * f, v.y * f, v.z * f); }
|
||||||
return Vector3(v.x * f, v.y * f, v.z * f);
|
|
||||||
}
|
|
||||||
friend Vector3 operator*(float f, const Vector3& v) {
|
friend Vector3 operator*(float f, const Vector3& v) {
|
||||||
// return Vector3(f * v.x, f * v.y, f * v.z);
|
// return Vector3(f * v.x, f * v.y, f * v.z);
|
||||||
return Vector3(v.x * f, v.y * f, v.z * f);
|
return Vector3(v.x * f, v.y * f, v.z * f);
|
||||||
@ -158,9 +156,7 @@ struct Vector3 : Vec3 {
|
|||||||
/// @param f The scaling factor
|
/// @param f The scaling factor
|
||||||
/// @return The scaled vector
|
/// @return The scaled vector
|
||||||
/// @remark Each componet of the vector will be divided by the same factor.
|
/// @remark Each componet of the vector will be divided by the same factor.
|
||||||
friend Vector3 operator/(const Vector3& v, float f) {
|
friend Vector3 operator/(const Vector3& v, float f) { return Vector3(v.x / f, v.y / f, v.z / f); }
|
||||||
return Vector3(v.x / f, v.y / f, v.z / f);
|
|
||||||
}
|
|
||||||
friend Vector3 operator/(float f, const Vector3& v) {
|
friend Vector3 operator/(float f, const Vector3& v) {
|
||||||
// return Vector3(f / v.x, f / v.y, f / v.z);
|
// return Vector3(f / v.x, f / v.y, f / v.z);
|
||||||
return Vector3(v.x / f, v.y / f, v.z / f);
|
return Vector3(v.x / f, v.y / f, v.z / f);
|
||||||
@ -210,9 +206,7 @@ struct Vector3 : Vec3 {
|
|||||||
/// @param v2 The ending vector
|
/// @param v2 The ending vector
|
||||||
/// @param axis The axis to rotate around
|
/// @param axis The axis to rotate around
|
||||||
/// @return The signed angle between the two vectors
|
/// @return The signed angle between the two vectors
|
||||||
static AngleOf<float> SignedAngle(const Vector3& v1,
|
static AngleOf<float> SignedAngle(const Vector3& v1, const Vector3& v2, const Vector3& axis);
|
||||||
const Vector3& v2,
|
|
||||||
const Vector3& axis);
|
|
||||||
|
|
||||||
/// @brief Lerp (linear interpolation) between two vectors
|
/// @brief Lerp (linear interpolation) between two vectors
|
||||||
/// @param v1 The starting vector
|
/// @param v1 The starting vector
|
||||||
@ -225,8 +219,139 @@ struct Vector3 : Vec3 {
|
|||||||
static Vector3 Lerp(const Vector3& v1, const Vector3& v2, float f);
|
static Vector3 Lerp(const Vector3& v1, const Vector3& v2, float f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief A 3-dimensional vector
|
||||||
|
/// @remark This uses a right-handed carthesian coordinate system.
|
||||||
|
/// @remark No default unit (for instance, meters) is specified
|
||||||
|
/// @note This implementation intentionally avoids the use of x, y and z values.
|
||||||
|
/// @tparam T The type of the paramters used to measure distance. Typical values are float and int
|
||||||
|
template <typename T>
|
||||||
|
class Vector3Of {
|
||||||
|
public:
|
||||||
|
/// @brief The distance in the horizontal direction, left = negative, right = positive
|
||||||
|
T horizontal = T{};
|
||||||
|
/// @brief The distance in the vertical direction, down = negative, up = positive
|
||||||
|
T vertical = T{};
|
||||||
|
/// @brief The distance in the depth direction, backward = negative, forward = positive
|
||||||
|
T depth = T{};
|
||||||
|
|
||||||
|
/// @brief A new 3-dimensional zero vector
|
||||||
|
Vector3Of();
|
||||||
|
/// @brief A new 3-dimensional vector
|
||||||
|
/// @param horizontal The distance in the horizontal direction, left = negative, right =
|
||||||
|
/// positive
|
||||||
|
/// @param vertical The distance in the vertical direction, down = negative, up =
|
||||||
|
/// positive
|
||||||
|
/// @param depth The distance in the depth direction, backward = negative, forward =
|
||||||
|
/// positive
|
||||||
|
Vector3Of(T horizontal, T vertical, T depth);
|
||||||
|
Vector3Of(Vector2Of<T> v);
|
||||||
|
Vector3Of(SphericalOf<T> v);
|
||||||
|
Vector3Of(Vector3 v);
|
||||||
|
|
||||||
|
Vector3 ToVector3();
|
||||||
|
|
||||||
|
/// @brief Vector3 destructor
|
||||||
|
~Vector3Of();
|
||||||
|
|
||||||
|
/// @brief A vector with zero for all axis
|
||||||
|
const static Vector3Of zero;
|
||||||
|
/// @brief A vector with unit for all axis
|
||||||
|
const static Vector3Of unit;
|
||||||
|
// const Vector3Of<int> Vector3Of<int>::unit(1, 1, 1); // Hardcoded unit vector for int
|
||||||
|
// const Vector3Of<float> Vector3Of<float>::unit(1.0f, 1.0f, 1.0f); // Hardcoded unit vector for
|
||||||
|
// float
|
||||||
|
|
||||||
|
/// @brief The vector length
|
||||||
|
/// @param v The vector for which you need the length
|
||||||
|
/// @return The vector length
|
||||||
|
static T MagnitudeOf(const Vector3Of& v);
|
||||||
|
|
||||||
|
/// @brief The vector length
|
||||||
|
/// @return The vector length
|
||||||
|
T Magnitude() const;
|
||||||
|
|
||||||
|
/// @brief The squared vector length
|
||||||
|
/// @param v The vector for which you need the length
|
||||||
|
/// @return The squared vector length
|
||||||
|
/// @remark The squared length is computationally simpler than the real
|
||||||
|
/// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the
|
||||||
|
/// calculation of the squared root of C.
|
||||||
|
static float SqrMagnitudeOf(const Vector3Of& v);
|
||||||
|
/// @brief The squared vector length
|
||||||
|
/// @return The squared vector length
|
||||||
|
/// @remark The squared length is computationally simpler than the real
|
||||||
|
/// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the
|
||||||
|
/// calculation of the squared root of C.
|
||||||
|
float SqrMagnitude() const;
|
||||||
|
|
||||||
|
/// @brief Convert the vector to a length of 1
|
||||||
|
/// @param v The vector to convert
|
||||||
|
/// @return The vector normalized to a length of 1
|
||||||
|
static Vector3Of<T> Normalize(const Vector3Of& v);
|
||||||
|
/// @brief Convert the vector to a length of 1
|
||||||
|
/// @return The vector normalized to a length of 1
|
||||||
|
Vector3Of<T> Normalized() const;
|
||||||
|
|
||||||
|
/// @brief Subtract a vector from this vector
|
||||||
|
/// @param v The vector to subtract from this vector
|
||||||
|
/// @return The result of this subtraction
|
||||||
|
Vector3Of<T> operator-(const Vector3Of& v) const;
|
||||||
|
Vector3Of<T> operator-=(const Vector3Of& v);
|
||||||
|
|
||||||
|
/// @brief Add a vector to this vector
|
||||||
|
/// @param v The vector to add to this vector
|
||||||
|
/// @return The result of the addition
|
||||||
|
Vector3Of<T> operator+(const Vector3Of& v) const;
|
||||||
|
Vector3Of<T> operator+=(const Vector3Of& v);
|
||||||
|
|
||||||
|
/// @brief Scale the vector uniformly up
|
||||||
|
/// @param f The scaling factor
|
||||||
|
/// @return The scaled vector
|
||||||
|
/// @remark Each component of the vector will be multipled with the same
|
||||||
|
/// factor f.
|
||||||
|
friend Vector3Of<T> operator*(const Vector3Of& v, float f) {
|
||||||
|
return Vector3Of<T>(v.horizontal * f, v.vertical * f, v.depth * f);
|
||||||
|
}
|
||||||
|
friend Vector3Of<T> operator*(float f, const Vector3Of& v) {
|
||||||
|
return Vector3Of<T>(f * v.horizontal, f * v.vertical, f * v.depth);
|
||||||
|
// return Vector3Of<T>(v.horizontal * f, v.vertical * f, v.depth * f);
|
||||||
|
}
|
||||||
|
Vector3Of<T> operator*=(float f);
|
||||||
|
|
||||||
|
/// @brief Scale the vector uniformly down
|
||||||
|
/// @param f The scaling factor
|
||||||
|
/// @return The scaled vector
|
||||||
|
/// @remark Each componet of the vector will be divided by the same factor.
|
||||||
|
friend Vector3Of<T> operator/(const Vector3Of& v, float f) {
|
||||||
|
return Vector3Of<T>(v.horizontal / f, v.vertical / f, v.depth / f);
|
||||||
|
}
|
||||||
|
friend Vector3Of<T> operator/(float f, const Vector3Of& v) {
|
||||||
|
return Vector3Of<T>(f / v.horizontal, f / v.vertical, f / v.depth);
|
||||||
|
// return Vector3Of<T>(v.horizontal / f, v.vertical / f, v.depth / f);
|
||||||
|
}
|
||||||
|
Vector3Of<T> operator/=(float f);
|
||||||
|
|
||||||
|
/// @brief The dot product of two vectors
|
||||||
|
/// @param v1 The first vector
|
||||||
|
/// @param v2 The second vector
|
||||||
|
/// @return The dot product of the two vectors
|
||||||
|
static float Dot(const Vector3Of& v1, const Vector3Of& v2);
|
||||||
|
|
||||||
|
/// @brief The angle between two vectors
|
||||||
|
/// @param v1 The first vector
|
||||||
|
/// @param v2 The second vector
|
||||||
|
/// @return The angle between the two vectors
|
||||||
|
/// @remark This reterns an unsigned angle which is the shortest distance
|
||||||
|
/// between the two vectors. Use Vector3::SignedAngle if a signed angle is
|
||||||
|
/// needed.
|
||||||
|
static AngleOf<float> Angle(const Vector3Of& v1, const Vector3Of& v2);
|
||||||
|
};
|
||||||
|
|
||||||
|
using Vector3Int = Vector3Of<int>;
|
||||||
|
using Vector3Float = Vector3Of<float>;
|
||||||
|
|
||||||
} // namespace LinearAlgebra
|
} // namespace LinearAlgebra
|
||||||
using namespace LinearAlgebra;
|
// using namespace LinearAlgebra;
|
||||||
|
|
||||||
#include "Spherical.h"
|
#include "Spherical.h"
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user