#ifndef _JSYSTEM_JGEOMETRY_H #define _JSYSTEM_JGEOMETRY_H #include #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 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& min) { if (x >= min.x) x = min.x; if (y >= min.y) y = min.y; } void setMax(const TVec2& max) { if (x <= max.x) x = max.x; if (y <= max.y) y = max.y; } void add(const TVec2& other) { x += other.x; y += other.y; } /** @fabricated */ // TVec2 adding(const TVec2& other) { return TVec2(x + other.x, y + other.y); } /** @fabricated */ TVec2 adding(T xDelta, T yDelta) { return TVec2(x + xDelta, y + yDelta); } /** @fabricated */ void add(T xDelta, T yDelta) { x += xDelta; y += yDelta; } TVec2& operator+=(const TVec2& other) { x += other.x; y += other.y; return *this; } TVec2& operator*=(const TVec2& other) { x *= other.x; y *= other.y; return *this; } bool isAbove(const TVec2& other) const { return (x >= other.x) && (y >= other.y) ? true : false; } T x; T y; }; template 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& 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& 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& 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& 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& other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z); } T x; T y; T z; }; // Size: 0x10 template struct TBox { TBox() : i(), f() { } TBox(const TBox& other) : i(other.f), f(other.y) { } T i, f; }; // clang-format off template<> struct TBox > { 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(x, y)); } void addPos(const TVec2& pos) { i.add(pos); f.add(pos); } bool intersect(const TBox >& other) { i.setMax(other.i); f.setMin(other.f); return isValid(); } TVec2 i, f; }; template struct TBox2 : TBox > { TBox2() {} // TBox2(const TBox2& other) { set(other); } TBox2(const TVec2& i, const TVec2 f) { set(i, f); } // TBox2(const TVec2& i, T x1, T y1) { set(i, x1, y1); } // TBox2(T x0, T y0, const TVec2& 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& 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 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& addingPos(TBox2& result, const TVec2& pos) { // return TBox2(i.adding(pos), f.adding(pos)); // } void set(const TBox2& other) { set(other.i, other.f); } void set(const TVec2& i, const TVec2& f) { this->i.set(i), this->f.set(f); } // void set(const TVec2& i, T x1, T y1) { this->i.set(i), this->f.set(x1, y1); } // void set(T x0, T y0, const TVec2& 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& 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 struct TBox3 { // TBox3() {} // TBox2(const TBox2& other) { set(other); } // TBox3(const TVec3& i, const TVec3 f) { set(i, f); } // // TBox2(const TVec2& i, T x1, T y1) { set(i, x1, y1); } // // TBox2(T x0, T y0, const TVec2& 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& 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 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& i, const TVec3& 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 mMin; // _00 TVec3 mMax; // _0C }; typedef TVec2 TVec2f; typedef TVec3 TVec3f; typedef TBox2 TBox2f; typedef TBox3 TBox3f; } // namespace JGeometry #endif #endif