#ifndef JGEOMETRY_H #define JGEOMETRY_H #include "dolphin/mtx/vec.h" #include "dolphin/types.h" namespace JGeometry { template struct TVec3 { T x; T y; T z; void set(const TVec3& other) { x = other.x; y = other.y; z = other.z; } }; template <> struct TVec3 { s16 x, y, z; TVec3& operator=(const TVec3& b) { // Force copies to use lwz/lha *((s32*)this) = *((s32*)&b); z = b.z; return *this; } }; inline void setTVec3f(const f32* vec_a, f32* vec_b) { const register f32* v_a = vec_a; register f32* v_b = vec_b; register f32 a_x; register f32 b_x; asm { psq_l a_x, 0(v_a), 0, 0 /* qr0 */ lfs b_x, 8(v_a) psq_st a_x, 0(v_b), 0, 0 /* qr0 */ stfs b_x, 8(v_b) }; } template <> struct TVec3 { f32 x; f32 y; f32 z; /* TVec3(const Vec& i_vec) { setTVec3f(&i_vec.x, &x); } */ /* TVec3() {} */ operator Vec*() { return (Vec*)&x; } operator const Vec*() const { return (Vec*)&x; } void set(const TVec3& other) { x = other.x; y = other.y; z = other.z; } void set(f32 x_, f32 y_, f32 z_) { x = x_; y = y_; z = z_; } void zero() { x = y = z = 0.0f; } void mul(const TVec3& a, const TVec3& b) { register f32* dst = &x; const register f32* srca = &a.x; const register f32* srcb = &b.x; register f32 a_x_y; register f32 b_x_y; register f32 x_y; register f32 za; register f32 zb; register f32 z; asm { psq_l a_x_y, 0(srca), 0, 0 psq_l b_x_y, 0(srcb), 0, 0 ps_mul x_y, a_x_y, b_x_y psq_st x_y, 0(dst), 0, 0 lfs za, 8(srca) lfs zb, 8(srcb) fmuls z, za, zb stfs z, 8(dst) }; } inline TVec3& operator=(const TVec3& b) { register f32* dst = &x; const register f32* src = &b.x; register f32 x_y; register f32 z; asm { psq_l x_y, 0(src), 0, 0 psq_st x_y, 0(dst), 0, 0 lfs z, 8(src) stfs z, 8(dst) }; return *this; } }; template struct TVec2 { TVec2() {} TVec2(T x, T y) { set(x, y); } 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; } bool isAbove(const TVec2& other) const { return (x >= other.x) && (y >= other.y) ? true : false; } T x; T y; }; 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 > { f32 getWidth() const { return f.x - i.x; } 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 TVec2& i, const TVec2 f) { set(i, f); } TBox2(f32 x0, f32 y0, f32 x1, f32 y1) { set(x0, y0, x1, y1); } 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); } } 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(f32 x0, f32 y0, f32 x1, f32 y1) { i.set(x0, y0); f.set(x1, y1); } }; // clang-format on } // namespace JGeometry #endif