zeus/include/zeus/CVector3f.hpp

227 lines
6.4 KiB
C++
Raw Normal View History

2018-10-06 20:39:40 -07:00
#pragma once
2015-04-19 13:39:16 -07:00
#include "Global.hpp"
2016-03-04 15:03:26 -08:00
#include "zeus/Math.hpp"
#include "zeus/CVector2f.hpp"
2018-12-07 17:16:50 -08:00
#if ZE_ATHENA_TYPES
2018-12-07 17:16:50 -08:00
#include "athena/IStreamReader.hpp"
#endif
2018-12-07 17:16:50 -08:00
namespace zeus {
2017-03-14 00:02:09 -07:00
class CVector3d;
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;
CVector3f() : mSimd(0.f) {}
2018-12-07 17:16:50 -08:00
template <typename T>
CVector3f(const simd<T>& s) : mSimd(s) {}
2015-07-29 14:59:03 -07:00
#if ZE_ATHENA_TYPES
2018-12-07 17:16:50 -08:00
CVector3f(const atVec3f& vec) : mSimd(vec.simd) {}
2018-12-07 21:23:50 -08:00
operator atVec3f&() { return *reinterpret_cast<atVec3f*>(this); }
2016-04-24 22:03:05 -07:00
2018-12-07 21:23:50 -08:00
operator const atVec3f&() const { return *reinterpret_cast<const atVec3f*>(this); }
2018-12-07 17:16:50 -08:00
void readBig(athena::io::IStreamReader& input) {
simd_floats f;
f[0] = input.readFloatBig();
f[1] = input.readFloatBig();
f[2] = input.readFloatBig();
f[3] = 0.0f;
mSimd.copy_from(f);
}
static CVector3f ReadBig(athena::io::IStreamReader& input) {
CVector3f ret;
ret.readBig(input);
return ret;
}
2018-05-10 00:22:37 -07:00
#endif
2018-12-07 17:16:50 -08:00
CVector3f(const CVector3d& vec);
2015-04-19 13:39:16 -07:00
2018-12-07 17:16:50 -08:00
explicit CVector3f(float xyz) : mSimd(xyz) {}
2016-02-17 18:40:58 -08:00
2018-12-07 21:23:50 -08:00
void assign(float x, float y, float z) { mSimd = zeus::simd<float>(x, y, z); }
2017-01-20 21:57:34 -08:00
2018-12-07 17:16:50 -08:00
CVector3f(float x, float y, float z) : mSimd(x, y, z) {}
2018-12-07 17:16:50 -08:00
CVector3f(const float* floats) : mSimd(floats[0], floats[1], floats[2]) {}
2016-04-26 03:36:44 -07:00
2018-12-07 17:16:50 -08:00
CVector3f(const CVector2f& other) {
mSimd = other.mSimd;
mSimd[2] = 0.0f;
mSimd[3] = 0.0f;
}
2016-04-26 03:36:44 -07:00
2018-12-07 21:23:50 -08:00
CVector2f toVec2f() const { return CVector2f(mSimd); }
2016-07-08 11:42:42 -07:00
2018-12-07 17:16:50 -08:00
bool operator==(const CVector3f& rhs) const {
return mSimd[0] == rhs.mSimd[0] && mSimd[1] == rhs.mSimd[1] && mSimd[2] == rhs.mSimd[2];
}
2018-03-03 20:25:21 -08:00
2018-12-07 17:16:50 -08:00
bool operator!=(const CVector3f& rhs) const { return !(*this == rhs); }
2018-03-03 20:25:21 -08:00
2018-12-07 21:23:50 -08:00
CVector3f operator+(const CVector3f& rhs) const { return mSimd + rhs.mSimd; }
2016-07-08 11:42:42 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator-(const CVector3f& rhs) const { return mSimd - rhs.mSimd; }
2016-07-08 11:42:42 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator-() const { return -mSimd; }
2015-04-19 13:39:16 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator*(const CVector3f& rhs) const { return mSimd * rhs.mSimd; }
2015-08-25 15:04:15 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator/(const CVector3f& rhs) const { return mSimd / rhs.mSimd; }
2016-04-26 03:36:44 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator+(float val) const { return mSimd + zeus::simd<float>(val); }
2015-08-25 15:04:15 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator-(float val) const { return mSimd - zeus::simd<float>(val); }
2015-08-28 21:49:19 -07:00
2018-12-07 21:23:50 -08:00
CVector3f operator*(float val) const { return mSimd * zeus::simd<float>(val); }
2015-08-25 15:04:15 -07:00
2018-12-07 17:16:50 -08:00
CVector3f operator/(float val) const {
float ooval = 1.f / val;
return mSimd * zeus::simd<float>(ooval);
}
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);
}
CVector3f normalized() const {
float mag = 1.f / magnitude();
return *this * mag;
}
2015-08-28 21:49:19 -07:00
2018-12-07 17:16:50 -08:00
CVector3f cross(const CVector3f& rhs) const {
2018-12-07 21:23:50 -08:00
return CVector3f(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
}
2018-12-07 21:23:50 -08:00
float dot(const CVector3f& rhs) const { return mSimd.dot3(rhs.mSimd); }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
float magSquared() const { return mSimd.dot3(mSimd); }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
float magnitude() const { return std::sqrt(magSquared()); }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
bool isNotInf() const { return !(std::isinf(x()) || std::isinf(y()) || std::isinf(z())); }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
bool isMagnitudeSafe() const { return isNotInf() && magSquared() >= 9.9999994e-29; }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
void zeroOut() { *this = CVector3f::skZero; }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
void splat(float xyz) { mSimd = zeus::simd<float>(xyz); }
2018-12-07 17:16:50 -08:00
static float getAngleDiff(const CVector3f& a, const CVector3f& b);
static CVector3f lerp(const CVector3f& a, const CVector3f& b, float t) {
return zeus::simd<float>(1.f - t) * a.mSimd + b.mSimd * zeus::simd<float>(t);
}
2018-12-07 21:23:50 -08:00
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
static CVector3f slerp(const CVector3f& a, const CVector3f& b, float t);
2018-12-07 21:23:50 -08:00
bool isNormalized() const { return std::fabs(1.f - magSquared()) < 0.01f; }
2018-12-07 17:16:50 -08:00
bool canBeNormalized() const {
if (std::isinf(x()) || std::isinf(y()) || std::isinf(z()))
return false;
return std::fabs(x()) >= FLT_EPSILON || std::fabs(y()) >= FLT_EPSILON || std::fabs(z()) >= FLT_EPSILON;
}
2018-12-07 21:23:50 -08:00
bool isZero() const { return magSquared() <= FLT_EPSILON; }
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);
}
CVector3f scaledToLength(float newLength) const {
CVector3f v = *this;
v.scaleToLength(newLength);
return v;
}
bool isEqu(const CVector3f& other, float epsilon = FLT_EPSILON) {
const CVector3f diffVec = other - *this;
return (diffVec.x() <= epsilon && diffVec.y() <= epsilon && diffVec.z() <= epsilon);
}
zeus::simd<float>::reference operator[](size_t idx) {
assert(idx < 3);
return mSimd[idx];
}
float operator[](size_t idx) const {
assert(idx < 3);
return mSimd[idx];
}
float x() const { return mSimd[0]; }
float y() const { return mSimd[1]; }
float z() const { return mSimd[2]; }
simd<float>::reference x() { return mSimd[0]; }
simd<float>::reference y() { return mSimd[1]; }
simd<float>::reference z() { return mSimd[2]; }
static const CVector3f skOne;
static const CVector3f skNegOne;
static const CVector3f skZero;
static const CVector3f skForward;
static const CVector3f skBack;
static const CVector3f skLeft;
static const CVector3f skRight;
static const CVector3f skUp;
static const CVector3f skDown;
static const CVector3f skRadToDegVec;
static const CVector3f skDegToRadVec;
static CVector3f radToDeg(const CVector3f& rad) { return rad * skRadToDegVec; }
static CVector3f degToRad(const CVector3f& deg) { return deg * skDegToRadVec; }
2015-04-19 13:39:16 -07:00
};
2018-12-07 21:23:50 -08:00
static inline CVector3f operator+(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) + rhs.mSimd; }
2015-04-19 13:39:16 -07:00
2018-12-07 21:23:50 -08:00
static inline CVector3f operator-(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) - rhs.mSimd; }
2015-04-19 13:39:16 -07:00
2018-12-07 21:23:50 -08:00
static inline CVector3f operator*(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) * rhs.mSimd; }
2016-03-04 15:03:26 -08:00
2018-12-07 21:23:50 -08:00
static inline CVector3f operator/(float lhs, const CVector3f& rhs) { return zeus::simd<float>(lhs) / rhs.mSimd; }
2015-04-19 13:39:16 -07:00
2018-12-07 21:23:50 -08:00
} // namespace zeus