Files
2024-02-28 12:57:28 -08:00

365 lines
6.9 KiB
C++

#ifndef _JSYSTEM_JGEOMETRY_H
#define _JSYSTEM_JGEOMETRY_H
#include "types.h"
#ifdef __cplusplus
inline f32 fsqrt_step(f32 mag)
{
f32 root = __frsqrte(mag);
return 0.5f * root * (3.0f - mag * (root * root));
}
namespace JGeometry {
template <typename T>
struct TVec2 {
TVec2() { }
TVec2(T v) { set(v); }
TVec2(T x, T y) { set(x, y); }
void set(T v) { y = x = v; }
void set(T x, T y)
{
this->x = x;
this->y = y;
}
void set(const TVec2& other)
{
x = other.x;
y = other.y;
}
void setMin(const TVec2<f32>& min)
{
if (x >= min.x)
x = min.x;
if (y >= min.y)
y = min.y;
}
void setMax(const TVec2<f32>& max)
{
if (x <= max.x)
x = max.x;
if (y <= max.y)
y = max.y;
}
void add(const TVec2<T>& other)
{
x += other.x;
y += other.y;
}
/** @fabricated */
// TVec2<T> adding(const TVec2<T>& other) { return TVec2<T>(x + other.x, y + other.y); }
/** @fabricated */
TVec2<T> adding(T xDelta, T yDelta) { return TVec2<T>(x + xDelta, y + yDelta); }
/** @fabricated */
void add(T xDelta, T yDelta)
{
x += xDelta;
y += yDelta;
}
TVec2<T>& operator+=(const TVec2<T>& other)
{
x += other.x;
y += other.y;
return *this;
}
TVec2<T>& operator*=(const TVec2<T>& other)
{
x *= other.x;
y *= other.y;
return *this;
}
bool isAbove(const TVec2<T>& other) const { return (x >= other.x) && (y >= other.y) ? true : false; }
T x;
T y;
};
template <typename T>
struct TVec3 {
// inline TVec3() { }
// inline TVec3(T value)
// : x(value)
// , y(value)
// , z(value)
// {
// }
// inline TVec3(T inX, T inY, T inZ)
// : x(inX)
// , y(inY)
// , z(inZ) {};
// // TODO: Determine if this could've actually existed, or if I'm just making it up.
// inline TVec3(const TVec3<T>& other)
// {
// x = other.x;
// y = other.y;
// z = other.z;
// }
// TODO: Determine if this could've actually existed, or if I'm just making
// it up.
inline TVec3& operator=(const TVec3& other)
{
x = other.x;
y = other.y;
z = other.z;
return *this;
}
void set(T x, T y, T z)
{
this->x = x;
this->y = y;
this->z = z;
}
void set(const TVec3& other)
{
x = other.x;
y = other.y;
z = other.z;
}
void setMin(const TVec3<f32>& min)
{
if (x >= min.x)
x = min.x;
if (y >= min.y)
y = min.y;
if (z >= min.z)
z = min.z;
}
void setMax(const TVec3<f32>& max)
{
if (x <= max.x)
x = max.x;
if (y <= max.y)
y = max.y;
if (z >= max.z)
z = max.z;
}
// inline operator Vec() const { return *this; }
inline operator Vec() const
{
Vec other;
other.x = x;
other.y = y;
other.z = z;
return other;
}
// inline TVec3(Vec& vec)
// {
// x = vec.x;
// y = vec.y;
// z = vec.z;
// }
void zero() { x = y = z = 0.0f; }
f32 squared() const { return x * x + y * y + z * z; }
void normalize()
{
f32 sq = squared();
if (sq <= FLT_EPSILON * 32.0f) {
return;
}
f32 norm;
if (sq <= 0.0f) {
norm = sq;
} else {
norm = fsqrt_step(sq);
}
x *= norm;
y *= norm;
z *= norm;
}
void normalize(const TVec3<f32>& other)
{
f32 sq = other.squared();
if (sq <= FLT_EPSILON * 32.0f) {
zero();
return;
}
f32 norm;
if (sq <= 0.0f) {
norm = sq;
} else {
norm = fsqrt_step(sq);
}
x = other.x * norm;
y = other.y * norm;
z = other.z * norm;
}
bool isAbove(const TVec3<T>& other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z); }
T x;
T y;
T z;
};
// Size: 0x10
template <class T>
struct TBox {
TBox()
: i()
, f()
{
}
TBox(const TBox& other)
: i(other.f)
, f(other.y)
{
}
T i, f;
};
// clang-format off
template<> struct TBox<TVec2<f32> > {
inline f32 getWidth() const { return f.x - i.x; }
inline f32 getHeight() const { return f.y - i.y; }
bool isValid() const { return f.isAbove(i); }
void addPos(f32 x, f32 y) {
addPos(TVec2<f32>(x, y));
}
void addPos(const TVec2<f32>& pos) {
i.add(pos);
f.add(pos);
}
bool intersect(const TBox<TVec2<f32> >& other) {
i.setMax(other.i);
f.setMin(other.f);
return isValid();
}
TVec2<f32> i, f;
};
template <typename T>
struct TBox2 : TBox<TVec2<T> > {
TBox2() {}
// TBox2(const TBox2& other) { set(other); }
TBox2(const TVec2<T>& i, const TVec2<T> f) { set(i, f); }
// TBox2(const TVec2<T>& i, T x1, T y1) { set(i, x1, y1); }
// TBox2(T x0, T y0, const TVec2<T>& f) { set(x0, y0, f); }
TBox2(f32 x0, f32 y0, f32 x1, f32 y1) { set(x0, y0, x1, y1); }
TBox2(f32 x0, f32 y0, TVec2<f32>& f) { set(x0, y0, x0 + f.x, y0 + f.y); }
TBox2(f32 val)
{
f.y = val;
f.x = val;
i.y = val;
i.x = val;
}
// inline TBox2& operator=(const TBox2& other)
// {
// set(other);
// return *this;
// }
void absolute() {
if (!this->isValid()) {
TBox2<T> box(*this);
this->i.setMin(box.i);
this->i.setMin(box.f);
this->f.setMax(box.i);
this->f.setMax(box.f);
}
}
inline void setX(const T& x) {
this->f.x = this->i.x = x;
}
inline void setY(const T& y) {
this->f.y = this->i.y = y;
}
// /** @fabricated */
// TBox2<T>& addingPos(TBox2<T>& result, const TVec2<T>& pos) {
// return TBox2<T>(i.adding(pos), f.adding(pos));
// }
void set(const TBox2& other) { set(other.i, other.f); }
void set(const TVec2<T>& i, const TVec2<T>& f) { this->i.set(i), this->f.set(f); }
// void set(const TVec2<T>& i, T x1, T y1) { this->i.set(i), this->f.set(x1, y1); }
// void set(T x0, T y0, const TVec2<T>& f) { this->i.set(x0, y0), this->f.set(f); }
void set(T x0, T y0, T x1, T y1) { this->i.set(x0, y0); this->f.set(x1, y1); }
// void setOrigin(const TVec2<T>& other) { this->i.set(other); }
// void setSize(T width, T height) { this->f.x = this->i.x + width; this->f.y = this->i.y + height; }
};
// clang-format on
template <typename T>
struct TBox3 {
// TBox3() {}
// TBox2(const TBox2& other) { set(other); }
// TBox3(const TVec3<T>& i, const TVec3<T> f) { set(i, f); }
// // TBox2(const TVec2<T>& i, T x1, T y1) { set(i, x1, y1); }
// // TBox2(T x0, T y0, const TVec2<T>& f) { set(x0, y0, f); }
// TBox3(T x0, T y0, T z0, T x1, T y1, T z1) { set(x0, y0, z0, x1, y1, z1); }
// TBox3(T x0, T y0, TVec3<T>& f) { set(x0, y0, z0, x0 + f.x, y0 + f.y, z0 + f.z); }
// TBox3(T val)
// {
// f.x = f.y = f.z = val;
// i.x = i.y = i.z = val;
// }
inline bool isValid() { return mMax.isAbove(mMin); }
void absolute()
{
if (!this->isValid()) {
TBox3<T> box(*this);
this->mMin.setMin(box.mMin);
this->mMin.setMin(box.mMax);
this->mMax.setMax(box.mMin);
this->mMax.setMax(box.mMax);
}
}
void set(const TBox3& other) { set(other.mMin, other.mMax); }
void set(const TVec3<T>& i, const TVec3<T>& f) { this->mMin.set(i), this->mMax.set(f); }
void set(T x0, T y0, T z0, T x1, T y1, T z1)
{
this->mMin.set(x0, y0);
this->mMax.set(x1, y1);
}
TVec3<T> mMin; // _00
TVec3<T> mMax; // _0C
};
typedef TVec2<f32> TVec2f;
typedef TVec3<f32> TVec3f;
typedef TBox2<f32> TBox2f;
typedef TBox3<f32> TBox3f;
} // namespace JGeometry
#endif
#endif