zeus/include/zeus/CVector4f.hpp

190 lines
6.0 KiB
C++
Raw Permalink Normal View History

2018-10-06 20:39:40 -07:00
#pragma once
#include <cassert>
#include <cfloat>
#include <cmath>
2016-03-04 15:03:26 -08:00
#include "zeus/CVector3f.hpp"
#include "zeus/Global.hpp"
2018-12-07 17:16:50 -08:00
#if ZE_ATHENA_TYPES
#include <athena/IStreamReader.hpp>
#endif
2018-12-07 17:16:50 -08:00
namespace zeus {
class CColor;
2018-12-07 17:16:50 -08:00
class CVector4f {
public:
2018-12-07 17:16:50 -08:00
zeus::simd<float> mSimd;
2020-05-01 16:20:31 -07:00
constexpr CVector4f() : mSimd() {}
2018-12-07 17:16:50 -08:00
template <typename T>
2019-02-23 23:15:32 -08:00
constexpr CVector4f(const simd<T>& s) : mSimd(s) {}
2019-02-23 23:15:32 -08:00
explicit constexpr CVector4f(float xyzw) : mSimd(xyzw) {}
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
void assign(float x, float y, float z, float w) { mSimd = simd<float>(x, y, z, w); }
2018-12-07 17:16:50 -08:00
2019-02-23 23:15:32 -08:00
constexpr CVector4f(float x, float y, float z, float w) : mSimd(x, y, z, w) {}
2019-02-23 23:15:32 -08:00
constexpr CVector4f(const CColor& other);
2016-04-26 03:36:44 -07:00
2019-02-24 00:41:50 -08:00
CVector4f(const CVector3f& other, float wIn = 1.f) : mSimd(other.mSimd) { mSimd[3] = wIn; }
2016-04-26 03:36:44 -07:00
[[nodiscard]] static CVector4f ToClip(const zeus::CVector3f& v, float w) { return CVector4f(v * w, w); }
2015-08-25 15:04:15 -07:00
[[nodiscard]] CVector3f toVec3f() const { return CVector3f(mSimd); }
2019-02-23 23:15:32 -08:00
constexpr CVector4f& operator=(const CColor& other);
2018-12-07 17:16:50 -08:00
[[nodiscard]] bool operator==(const CVector4f& rhs) const {
2018-12-07 17:16:50 -08:00
auto eq_mask = mSimd == rhs.mSimd;
return eq_mask[0] && eq_mask[1] && eq_mask[2] && eq_mask[3];
}
[[nodiscard]] bool operator!=(const CVector4f& rhs) const {
2018-12-07 17:16:50 -08:00
auto eq_mask = mSimd != rhs.mSimd;
return eq_mask[0] || eq_mask[1] || eq_mask[2] || eq_mask[3];
}
[[nodiscard]] bool operator<(const CVector4f& rhs) const {
2018-12-07 17:16:50 -08:00
auto eq_mask = mSimd < rhs.mSimd;
return eq_mask[0] && eq_mask[1] && eq_mask[2] && eq_mask[3];
}
[[nodiscard]] bool operator<=(const CVector4f& rhs) const {
2018-12-07 17:16:50 -08:00
auto eq_mask = mSimd <= rhs.mSimd;
return eq_mask[0] && eq_mask[1] && eq_mask[2] && eq_mask[3];
}
[[nodiscard]] bool operator>(const CVector4f& rhs) const {
2018-12-07 17:16:50 -08:00
auto eq_mask = mSimd > rhs.mSimd;
return eq_mask[0] && eq_mask[1] && eq_mask[2] && eq_mask[3];
}
[[nodiscard]] bool operator>=(const CVector4f& rhs) const {
2018-12-07 17:16:50 -08:00
auto eq_mask = mSimd >= rhs.mSimd;
return eq_mask[0] && eq_mask[1] && eq_mask[2] && eq_mask[3];
}
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator+(const CVector4f& rhs) const { return mSimd + rhs.mSimd; }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator-(const CVector4f& rhs) const { return mSimd - rhs.mSimd; }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator-() const { return -mSimd; }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator*(const CVector4f& rhs) const { return mSimd * rhs.mSimd; }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator/(const CVector4f& rhs) const { return mSimd / rhs.mSimd; }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator+(float val) const { return mSimd + zeus::simd<float>(val); }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator-(float val) const { return mSimd - zeus::simd<float>(val); }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator*(float val) const { return mSimd * zeus::simd<float>(val); }
2018-12-07 17:16:50 -08:00
2022-05-31 17:17:23 -07:00
[[nodiscard]] CVector4f operator/(float val) const {
2018-12-07 17:16:50 -08:00
float ooval = 1.f / val;
return mSimd * zeus::simd<float>(ooval);
}
const CVector4f& operator+=(const CVector4f& rhs) {
mSimd += rhs.mSimd;
return *this;
}
const CVector4f& operator-=(const CVector4f& rhs) {
mSimd -= rhs.mSimd;
return *this;
}
const CVector4f& operator*=(const CVector4f& rhs) {
mSimd *= rhs.mSimd;
return *this;
}
const CVector4f& operator/=(const CVector4f& rhs) {
mSimd /= rhs.mSimd;
return *this;
}
void normalize() {
float mag = magnitude();
mag = 1.f / mag;
*this *= CVector4f(mag);
}
[[nodiscard]] CVector4f normalized() const {
2018-12-07 17:16:50 -08:00
float mag = magnitude();
mag = 1.f / mag;
return *this * mag;
}
[[nodiscard]] float dot(const CVector4f& rhs) const { return mSimd.dot4(rhs.mSimd); }
2018-12-07 17:16:50 -08:00
[[nodiscard]] float magSquared() const { return mSimd.dot4(mSimd); }
2018-12-07 17:16:50 -08:00
[[nodiscard]] float magnitude() const { return std::sqrt(magSquared()); }
2018-12-07 17:16:50 -08:00
2019-02-23 23:15:32 -08:00
void zeroOut() { mSimd = zeus::simd<float>(0.f); }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
void splat(float xyzw) { mSimd = zeus::simd<float>(xyzw); }
2018-12-07 17:16:50 -08:00
[[nodiscard]] static CVector4f lerp(const CVector4f& a, const CVector4f& 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);
}
[[nodiscard]] static CVector4f nlerp(const CVector4f& a, const CVector4f& b, float t) {
return lerp(a, b, t).normalized();
}
2018-12-07 17:16:50 -08:00
[[nodiscard]] bool isNormalized() const { return std::fabs(1.f - magSquared()) < 0.01f; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] bool canBeNormalized() const {
2018-12-07 17:16:50 -08:00
if (std::isinf(x()) || std::isinf(y()) || std::isinf(z()) || std::isinf(w()))
return false;
2018-12-07 21:23:50 -08:00
return std::fabs(x()) >= FLT_EPSILON || std::fabs(y()) >= FLT_EPSILON || std::fabs(z()) >= FLT_EPSILON ||
std::fabs(w()) >= FLT_EPSILON;
2018-12-07 17:16:50 -08:00
}
[[nodiscard]] bool isEqu(const CVector4f& other, float epsilon = FLT_EPSILON) const {
2018-12-07 17:16:50 -08:00
const CVector4f diffVec = other - *this;
2018-12-07 21:23:50 -08:00
return (diffVec.x() <= epsilon && diffVec.y() <= epsilon && diffVec.z() <= epsilon && diffVec.w() <= epsilon);
2018-12-07 17:16:50 -08:00
}
[[nodiscard]] simd<float>::reference operator[](size_t idx) {
2018-12-07 17:16:50 -08:00
assert(idx < 4);
return mSimd[idx];
}
[[nodiscard]] float operator[](size_t idx) const {
2018-12-07 17:16:50 -08:00
assert(idx < 4);
return mSimd[idx];
}
[[nodiscard]] float x() const { return mSimd[0]; }
[[nodiscard]] float y() const { return mSimd[1]; }
[[nodiscard]] float z() const { return mSimd[2]; }
[[nodiscard]] float w() const { return mSimd[3]; }
2018-12-07 17:16:50 -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]; }
[[nodiscard]] simd<float>::reference w() { return mSimd[3]; }
};
2019-02-23 23:15:32 -08:00
constexpr CVector4f skOne4f(1.f);
constexpr CVector4f skNegOne4f(-1.f);
constexpr CVector4f skZero4f(0.f);
[[nodiscard]] inline CVector4f operator+(float lhs, const CVector4f& rhs) { return zeus::simd<float>(lhs) + rhs.mSimd; }
[[nodiscard]] inline CVector4f operator-(float lhs, const CVector4f& rhs) { return zeus::simd<float>(lhs) - rhs.mSimd; }
[[nodiscard]] inline CVector4f operator*(float lhs, const CVector4f& rhs) { return zeus::simd<float>(lhs) * rhs.mSimd; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] inline CVector4f operator/(float lhs, const CVector4f& rhs) { return zeus::simd<float>(lhs) / rhs.mSimd; }
2018-12-07 21:23:50 -08:00
} // namespace zeus