2021-12-05 17:54:36 +00:00
|
|
|
#include "NiPoint3.h"
|
|
|
|
#include "NiQuaternion.h"
|
|
|
|
|
|
|
|
// C++
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
// Static Variables
|
|
|
|
const NiPoint3 NiPoint3::ZERO(0.0f, 0.0f, 0.0f);
|
|
|
|
const NiPoint3 NiPoint3::UNIT_X(1.0f, 0.0f, 0.0f);
|
|
|
|
const NiPoint3 NiPoint3::UNIT_Y(0.0f, 1.0f, 0.0f);
|
|
|
|
const NiPoint3 NiPoint3::UNIT_Z(0.0f, 0.0f, 1.0f);
|
|
|
|
const NiPoint3 NiPoint3::UNIT_ALL(1.0f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
//! Initializer
|
|
|
|
NiPoint3::NiPoint3(void) {
|
2022-07-28 13:39:57 +00:00
|
|
|
this->x = 0;
|
|
|
|
this->y = 0;
|
|
|
|
this->z = 0;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Initializer
|
|
|
|
NiPoint3::NiPoint3(float x, float y, float z) {
|
2022-07-28 13:39:57 +00:00
|
|
|
this->x = x;
|
|
|
|
this->y = y;
|
|
|
|
this->z = z;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Copy Constructor
|
|
|
|
NiPoint3::NiPoint3(const NiPoint3& point) {
|
2022-07-28 13:39:57 +00:00
|
|
|
this->x = point.x;
|
|
|
|
this->y = point.y;
|
|
|
|
this->z = point.z;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Destructor
|
|
|
|
NiPoint3::~NiPoint3(void) {}
|
|
|
|
|
|
|
|
// MARK: Getters / Setters
|
|
|
|
|
|
|
|
//! Gets the X coordinate
|
|
|
|
float NiPoint3::GetX(void) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return this->x;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Sets the X coordinate
|
|
|
|
void NiPoint3::SetX(float x) {
|
2022-07-28 13:39:57 +00:00
|
|
|
this->x = x;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Gets the Y coordinate
|
|
|
|
float NiPoint3::GetY(void) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return this->y;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Sets the Y coordinate
|
|
|
|
void NiPoint3::SetY(float y) {
|
2022-07-28 13:39:57 +00:00
|
|
|
this->y = y;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Gets the Z coordinate
|
|
|
|
float NiPoint3::GetZ(void) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return this->z;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Sets the Z coordinate
|
|
|
|
void NiPoint3::SetZ(float z) {
|
2022-07-28 13:39:57 +00:00
|
|
|
this->z = z;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Functions
|
|
|
|
|
|
|
|
//! Gets the length of the vector
|
|
|
|
float NiPoint3::Length(void) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return sqrt(x * x + y * y + z * z);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Gets the squared length of a vector
|
|
|
|
float NiPoint3::SquaredLength(void) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return (x * x + y * y + z * z);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns the dot product of the vector dotted with another vector
|
|
|
|
float NiPoint3::DotProduct(const Vector3& vec) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns the cross product of the vector crossed with another vector
|
|
|
|
Vector3 NiPoint3::CrossProduct(const Vector3& vec) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
|
|
|
|
((this->z * vec.x) - (this->x * vec.z)),
|
|
|
|
((this->x * vec.y) - (this->y * vec.x)));
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Unitize the vector
|
|
|
|
NiPoint3 NiPoint3::Unitize(void) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
float length = this->Length();
|
|
|
|
|
|
|
|
return length != 0 ? *this / length : NiPoint3::ZERO;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: Operators
|
|
|
|
|
|
|
|
//! Operator to check for equality
|
|
|
|
bool NiPoint3::operator==(const NiPoint3& point) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return point.x == this->x && point.y == this->y && point.z == this->z;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator to check for inequality
|
|
|
|
bool NiPoint3::operator!=(const NiPoint3& point) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return !(*this == point);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for subscripting
|
|
|
|
float& NiPoint3::operator[](int i) {
|
2022-07-28 13:39:57 +00:00
|
|
|
float* base = &x;
|
2023-12-28 04:18:20 +00:00
|
|
|
return base[i];
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for subscripting
|
|
|
|
const float& NiPoint3::operator[](int i) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
const float* base = &x;
|
2023-12-28 04:18:20 +00:00
|
|
|
return base[i];
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for addition of vectors
|
|
|
|
NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-03-25 10:26:39 +00:00
|
|
|
//! Operator for addition of vectors
|
2023-07-31 07:22:56 +00:00
|
|
|
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
|
|
|
|
this->x += point.x;
|
|
|
|
this->y += point.y;
|
|
|
|
this->z += point.z;
|
|
|
|
return *this;
|
2023-03-25 10:26:39 +00:00
|
|
|
}
|
|
|
|
|
2023-08-10 05:13:20 +00:00
|
|
|
NiPoint3& NiPoint3::operator*=(const float scalar) {
|
|
|
|
this->x *= scalar;
|
|
|
|
this->y *= scalar;
|
|
|
|
this->z *= scalar;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
//! Operator for subtraction of vectors
|
|
|
|
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for addition of a scalar on all vector components
|
|
|
|
NiPoint3 NiPoint3::operator+(float fScalar) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for subtraction of a scalar on all vector components
|
|
|
|
NiPoint3 NiPoint3::operator-(float fScalar) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for scalar multiplication of a vector
|
|
|
|
NiPoint3 NiPoint3::operator*(float fScalar) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Operator for scalar division of a vector
|
|
|
|
NiPoint3 NiPoint3::operator/(float fScalar) const {
|
2022-07-28 13:39:57 +00:00
|
|
|
float retX = this->x != 0 ? this->x / fScalar : 0;
|
|
|
|
float retY = this->y != 0 ? this->y / fScalar : 0;
|
|
|
|
float retZ = this->z != 0 ? this->z / fScalar : 0;
|
|
|
|
return NiPoint3(retX, retY, retZ);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: Helper Functions
|
|
|
|
|
|
|
|
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
|
|
|
|
bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) {
|
2022-07-28 13:39:57 +00:00
|
|
|
if (this->x < minPoint.x) return false;
|
|
|
|
if (this->x > maxPoint.x) return false;
|
|
|
|
if (this->y < minPoint.y) return false;
|
|
|
|
if (this->y > maxPoint.y) return false;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-12-28 04:18:20 +00:00
|
|
|
return (this->z < maxPoint.z && this->z > minPoint.z);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Checks to see if the point (or vector) is within a sphere
|
|
|
|
bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
|
2022-07-28 13:39:57 +00:00
|
|
|
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
|
|
|
|
return (diffVec.SquaredLength() <= (radius * radius));
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
|
|
|
|
if (a == b) return a;
|
|
|
|
|
|
|
|
const auto pa = p - a;
|
|
|
|
const auto ab = b - a;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (t <= 0.0f) return a;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
if (t >= 1.0f) return b;
|
|
|
|
|
|
|
|
return a + ab * t;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
|
|
|
|
const auto dot = a.DotProduct(b);
|
|
|
|
const auto lenA = a.SquaredLength();
|
|
|
|
const auto lenB = a.SquaredLength();
|
|
|
|
return acos(dot / sqrt(lenA * lenB));
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
|
|
|
|
const auto dx = a.x - b.x;
|
|
|
|
const auto dy = a.y - b.y;
|
|
|
|
const auto dz = a.z - b.z;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
return std::sqrt(dx * dx + dy * dy + dz * dz);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) {
|
|
|
|
const auto dx = a.x - b.x;
|
|
|
|
const auto dy = a.y - b.y;
|
|
|
|
const auto dz = a.z - b.z;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
return dx * dx + dy * dy + dz * dz;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
|
|
|
|
float dx = target.x - current.x;
|
|
|
|
float dy = target.y - current.y;
|
|
|
|
float dz = target.z - current.z;
|
2023-12-28 04:18:20 +00:00
|
|
|
|
|
|
|
float lengthSquared = static_cast<float>(
|
|
|
|
static_cast<double>(dx) * static_cast<double>(dx) +
|
|
|
|
static_cast<double>(dy) * static_cast<double>(dy) +
|
|
|
|
static_cast<double>(dz) * static_cast<double>(dz)
|
|
|
|
);
|
|
|
|
|
|
|
|
if (static_cast<double>(lengthSquared) == 0.0
|
|
|
|
|| static_cast<double>(maxDistanceDelta) >= 0.0
|
|
|
|
&& static_cast<double>(lengthSquared)
|
|
|
|
<= static_cast<double>(maxDistanceDelta) * static_cast<double>(maxDistanceDelta)) {
|
2022-07-28 13:39:57 +00:00
|
|
|
return target;
|
2023-12-28 04:18:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float length = std::sqrt(lengthSquared);
|
2022-07-28 13:39:57 +00:00
|
|
|
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
|
|
|
|
NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) {
|
2022-07-28 13:39:57 +00:00
|
|
|
Vector3 vector;
|
|
|
|
float num12 = rotation.x + rotation.x;
|
|
|
|
float num2 = rotation.y + rotation.y;
|
|
|
|
float num = rotation.z + rotation.z;
|
|
|
|
float num11 = rotation.w * num12;
|
|
|
|
float num10 = rotation.w * num2;
|
|
|
|
float num9 = rotation.w * num;
|
|
|
|
float num8 = rotation.x * num12;
|
|
|
|
float num7 = rotation.x * num2;
|
|
|
|
float num6 = rotation.x * num;
|
|
|
|
float num5 = rotation.y * num2;
|
|
|
|
float num4 = rotation.y * num;
|
|
|
|
float num3 = rotation.z * num;
|
|
|
|
|
|
|
|
NiPoint3 value = *this;
|
|
|
|
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
|
|
|
|
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
|
|
|
|
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
|
|
|
|
vector.x = num15;
|
|
|
|
vector.y = num14;
|
|
|
|
vector.z = num13;
|
|
|
|
return vector;
|
|
|
|
}
|