2018-10-06 20:39:40 -07:00
|
|
|
#pragma once
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2019-09-01 00:38:45 -07:00
|
|
|
#include <cassert>
|
|
|
|
#include <cfloat>
|
|
|
|
#include <cmath>
|
|
|
|
|
2016-03-04 15:03:26 -08:00
|
|
|
#include "zeus/CVector2f.hpp"
|
2019-09-01 00:38:45 -07:00
|
|
|
#include "zeus/Global.hpp"
|
|
|
|
#include "zeus/Math.hpp"
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
namespace zeus {
|
2017-03-14 00:02:09 -07:00
|
|
|
class CVector3d;
|
2018-12-12 23:36:29 -08:00
|
|
|
class CRelAngle;
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
class CVector3f {
|
2015-04-19 13:39:16 -07:00
|
|
|
public:
|
2018-12-07 17:16:50 -08:00
|
|
|
zeus::simd<float> mSimd;
|
2020-05-01 16:20:31 -07:00
|
|
|
constexpr CVector3f() : mSimd() {}
|
2016-01-16 15:16:30 -08:00
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
template <typename T>
|
2019-02-23 23:15:32 -08:00
|
|
|
constexpr CVector3f(const simd<T>& s) : mSimd(s) {}
|
2016-01-16 15:16:30 -08:00
|
|
|
|
2019-02-23 23:15:32 -08:00
|
|
|
inline CVector3f(const CVector3d& vec);
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2019-02-23 23:15:32 -08:00
|
|
|
explicit constexpr CVector3f(float xyz) : mSimd(xyz) {}
|
2016-02-17 18:40:58 -08:00
|
|
|
|
2020-05-01 16:20:31 -07:00
|
|
|
void assign(float x, float y, float z) { mSimd.set(x, y, z); }
|
2017-01-20 21:57:34 -08:00
|
|
|
|
2019-02-23 23:15:32 -08:00
|
|
|
constexpr CVector3f(float x, float y, float z) : mSimd(x, y, z) {}
|
2015-10-07 17:21:38 -07:00
|
|
|
|
2019-02-23 23:15:32 -08:00
|
|
|
constexpr CVector3f(const float* floats) : mSimd(floats[0], floats[1], floats[2]) {}
|
2016-04-26 03:36:44 -07:00
|
|
|
|
2019-02-10 12:58:27 -08:00
|
|
|
CVector3f(const CVector2f& other, float z = 0.f) {
|
2018-12-07 17:16:50 -08:00
|
|
|
mSimd = other.mSimd;
|
2019-02-10 12:58:27 -08:00
|
|
|
mSimd[2] = z;
|
2018-12-07 17:16:50 -08:00
|
|
|
}
|
2016-04-26 03:36:44 -07:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] CVector2f toVec2f() const { return CVector2f(mSimd); }
|
2016-07-08 11:42:42 -07:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool operator==(const CVector3f& rhs) const {
|
2020-05-01 16:20:31 -07:00
|
|
|
const auto mask = mSimd == rhs.mSimd;
|
|
|
|
return mask[0] && mask[1] && mask[2];
|
2018-12-07 17:16:50 -08:00
|
|
|
}
|
2018-03-03 20:25:21 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool operator!=(const CVector3f& rhs) const { return !(*this == rhs); }
|
2018-03-03 20:25:21 -08:00
|
|
|
|
2020-05-01 16:20:31 -07:00
|
|
|
[[nodiscard]] simd<float>::mask_type operator>(const CVector3f& rhs) const { return mSimd > rhs.mSimd; }
|
|
|
|
[[nodiscard]] simd<float>::mask_type operator>=(const CVector3f& rhs) const { return mSimd >= rhs.mSimd; }
|
|
|
|
[[nodiscard]] simd<float>::mask_type operator<(const CVector3f& rhs) const { return mSimd < rhs.mSimd; }
|
|
|
|
[[nodiscard]] simd<float>::mask_type operator<=(const CVector3f& rhs) const { return mSimd <= rhs.mSimd; }
|
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator+(const CVector3f& rhs) const { return mSimd + rhs.mSimd; }
|
2016-07-08 11:42:42 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator-(const CVector3f& rhs) const { return mSimd - rhs.mSimd; }
|
2016-07-08 11:42:42 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator-() const { return -mSimd; }
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator*(const CVector3f& rhs) const { return mSimd * rhs.mSimd; }
|
2015-08-25 15:04:15 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator/(const CVector3f& rhs) const { return mSimd / rhs.mSimd; }
|
2016-04-26 03:36:44 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator+(float val) const { return mSimd + val; }
|
2015-08-25 15:04:15 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator-(float val) const { return mSimd - val; }
|
2015-08-28 21:49:19 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator*(float val) const { return mSimd * val; }
|
2015-08-25 15:04:15 -07:00
|
|
|
|
2022-05-31 17:17:23 -07:00
|
|
|
[[nodiscard]] CVector3f operator/(float val) const { return mSimd / val; }
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
const CVector3f& operator+=(const CVector3f& rhs) {
|
|
|
|
mSimd += rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2018-12-07 17:16:50 -08:00
|
|
|
const CVector3f& operator-=(const CVector3f& rhs) {
|
|
|
|
mSimd -= rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CVector3f& operator*=(const CVector3f& rhs) {
|
|
|
|
mSimd *= rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CVector3f& operator/=(const CVector3f& rhs) {
|
|
|
|
mSimd /= rhs.mSimd;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void normalize() {
|
|
|
|
float mag = 1.f / magnitude();
|
|
|
|
*this *= CVector3f(mag);
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] CVector3f normalized() const {
|
2018-12-07 17:16:50 -08:00
|
|
|
float mag = 1.f / magnitude();
|
|
|
|
return *this * mag;
|
|
|
|
}
|
2015-08-28 21:49:19 -07:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] CVector3f cross(const CVector3f& rhs) const {
|
2020-05-01 16:20:31 -07:00
|
|
|
return {y() * rhs.z() - z() * rhs.y(), z() * rhs.x() - x() * rhs.z(), x() * rhs.y() - y() * rhs.x()};
|
2018-12-07 17:16:50 -08:00
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] float dot(const CVector3f& rhs) const { return mSimd.dot3(rhs.mSimd); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] float magSquared() const { return mSimd.dot3(mSimd); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] float magnitude() const { return std::sqrt(magSquared()); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool isNotInf() const { return !(std::isinf(x()) || std::isinf(y()) || std::isinf(z())); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool isMagnitudeSafe() const { return isNotInf() && magSquared() >= 9.9999994e-29; }
|
2021-05-16 15:29:06 -07:00
|
|
|
[[nodiscard]] bool isNaN() const { return std::isnan(x()) || std::isnan(y()) || std::isnan(z()); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-05-01 16:20:31 -07:00
|
|
|
void zeroOut() { mSimd.broadcast(0.f); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-05-01 16:20:31 -07:00
|
|
|
void splat(float xyz) { mSimd.broadcast(xyz); }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] static float getAngleDiff(const CVector3f& a, const CVector3f& b);
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] static CVector3f lerp(const CVector3f& a, const CVector3f& b, float t) {
|
2018-12-07 17:16:50 -08:00
|
|
|
return zeus::simd<float>(1.f - t) * a.mSimd + b.mSimd * zeus::simd<float>(t);
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] static CVector3f nlerp(const CVector3f& a, const CVector3f& b, float t) {
|
|
|
|
return lerp(a, b, t).normalized();
|
|
|
|
}
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] static CVector3f slerp(const CVector3f& a, const CVector3f& b, CRelAngle clampAngle);
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool isNormalized() const { return std::fabs(1.f - magSquared()) <= FLT_EPSILON; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool canBeNormalized() const {
|
2018-12-07 17:16:50 -08:00
|
|
|
if (std::isinf(x()) || std::isinf(y()) || std::isinf(z()))
|
|
|
|
return false;
|
2020-03-03 16:47:59 -08:00
|
|
|
return !(std::fabs(x()) < FLT_EPSILON && std::fabs(y()) < FLT_EPSILON && std::fabs(z()) < FLT_EPSILON);
|
2018-12-07 17:16:50 -08:00
|
|
|
}
|
|
|
|
|
2020-09-15 21:41:47 -07:00
|
|
|
[[nodiscard]] bool isZero() const { return mSimd[0] == 0.f && mSimd[1] == 0.f && mSimd[2] == 0.f; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
|
|
|
void scaleToLength(float newLength) {
|
|
|
|
float length = magSquared();
|
|
|
|
if (length < FLT_EPSILON) {
|
|
|
|
mSimd[0] = newLength, mSimd[1] = 0.f, mSimd[2] = 0.f;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
length = std::sqrt(length);
|
|
|
|
float scalar = newLength / length;
|
|
|
|
*this *= CVector3f(scalar);
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] CVector3f scaledToLength(float newLength) const {
|
2018-12-07 17:16:50 -08:00
|
|
|
CVector3f v = *this;
|
|
|
|
v.scaleToLength(newLength);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] bool isEqu(const CVector3f& other, float epsilon = FLT_EPSILON) const {
|
2018-12-07 17:16:50 -08:00
|
|
|
const CVector3f diffVec = other - *this;
|
|
|
|
return (diffVec.x() <= epsilon && diffVec.y() <= epsilon && diffVec.z() <= epsilon);
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] simd<float>::reference operator[](size_t idx) {
|
2018-12-07 17:16:50 -08:00
|
|
|
assert(idx < 3);
|
|
|
|
return mSimd[idx];
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] float operator[](size_t idx) const {
|
2018-12-07 17:16:50 -08:00
|
|
|
assert(idx < 3);
|
|
|
|
return mSimd[idx];
|
|
|
|
}
|
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] float x() const { return mSimd[0]; }
|
|
|
|
[[nodiscard]] float y() const { return mSimd[1]; }
|
|
|
|
[[nodiscard]] float z() const { return mSimd[2]; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] simd<float>::reference x() { return mSimd[0]; }
|
|
|
|
[[nodiscard]] simd<float>::reference y() { return mSimd[1]; }
|
|
|
|
[[nodiscard]] simd<float>::reference z() { return mSimd[2]; }
|
2018-12-07 17:16:50 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] static inline CVector3f radToDeg(const CVector3f& rad);
|
2019-02-23 23:15:32 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] static inline CVector3f degToRad(const CVector3f& deg);
|
2015-04-19 13:39:16 -07:00
|
|
|
};
|
2020-04-19 00:16:34 -07:00
|
|
|
constexpr inline CVector3f skOne3f(1.f);
|
|
|
|
constexpr inline CVector3f skNegOne3f(-1.f);
|
|
|
|
constexpr inline CVector3f skZero3f(0.f);
|
|
|
|
constexpr inline CVector3f skForward(0.f, 1.f, 0.f);
|
|
|
|
constexpr inline CVector3f skBack(0.f, -1.f, 0.f);
|
|
|
|
constexpr inline CVector3f skLeft(-1.f, 0.f, 0.f);
|
|
|
|
constexpr inline CVector3f skRight(1.f, 0.f, 0.f);
|
|
|
|
constexpr inline CVector3f skUp(0.f, 0.f, 1.f);
|
|
|
|
constexpr inline CVector3f skDown(0.f, 0.f, -1.f);
|
|
|
|
constexpr inline CVector3f skRadToDegVec(180.f / M_PIF);
|
|
|
|
constexpr inline CVector3f skDegToRadVec(M_PIF / 180.f);
|
2019-02-23 23:15:32 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] inline CVector3f operator+(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) + rhs.mSimd; }
|
2019-02-23 23:15:32 -08:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] inline CVector3f operator-(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) - rhs.mSimd; }
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] inline CVector3f operator*(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) * rhs.mSimd; }
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2020-02-29 01:33:29 -08:00
|
|
|
[[nodiscard]] inline CVector3f operator/(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) / rhs.mSimd; }
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2019-02-23 23:15:32 -08:00
|
|
|
inline CVector3f CVector3f::radToDeg(const CVector3f& rad) { return rad * skRadToDegVec; }
|
2016-03-04 15:03:26 -08:00
|
|
|
|
2019-02-23 23:15:32 -08:00
|
|
|
inline CVector3f CVector3f::degToRad(const CVector3f& deg) { return deg * skDegToRadVec; }
|
2015-04-19 13:39:16 -07:00
|
|
|
|
2018-12-07 21:23:50 -08:00
|
|
|
} // namespace zeus
|