From 0f0084ed40ad27f1da91bfa31d22ccf15865a75f Mon Sep 17 00:00:00 2001 From: Henrique Gemignani Passos Lima Date: Mon, 7 Aug 2023 20:40:09 +0300 Subject: [PATCH] Add CVector3f --- config/G2ME01/splits.txt | 5 ++ config/G2ME01/symbols.txt | 50 +++++------ configure.py | 1 + include/Kyoto/Math/CRelAngle.hpp | 52 +++++++++++ include/Kyoto/Math/CVector3f.hpp | 20 +++-- include/Kyoto/Math/CloseEnough.hpp | 29 ++++++ include/Kyoto/Streams/COutputStream.hpp | 86 ++++++++++++++++++ src/Kyoto/Math/CVector3f.cpp | 114 ++++++++++++++++++++++++ 8 files changed, 323 insertions(+), 34 deletions(-) create mode 100644 include/Kyoto/Math/CRelAngle.hpp create mode 100644 include/Kyoto/Math/CloseEnough.hpp create mode 100644 include/Kyoto/Streams/COutputStream.hpp create mode 100644 src/Kyoto/Math/CVector3f.cpp diff --git a/config/G2ME01/splits.txt b/config/G2ME01/splits.txt index d0bf96b..599d2ee 100644 --- a/config/G2ME01/splits.txt +++ b/config/G2ME01/splits.txt @@ -32,6 +32,11 @@ Kyoto/Math/CVector3d.cpp: .ctors start:0x803A5608 end:0x803A560C .sdata2 start:0x8041E5F8 end:0x8041E610 +Kyoto/Math/CVector3f.cpp: + .text start:0x802CAB00 end:0x802CB124 + .ctors start:0x803A560C end:0x803A5610 + .sdata2 start:0x8041E610 end:0x8041E624 + Runtime/__init_cpp_exceptions.cpp: .text start:0x80345C34 end:0x80345CA4 .ctors start:0x803A54A0 end:0x803A54A4 diff --git a/config/G2ME01/symbols.txt b/config/G2ME01/symbols.txt index daf1be3..d71082e 100644 --- a/config/G2ME01/symbols.txt +++ b/config/G2ME01/symbols.txt @@ -471,7 +471,7 @@ fn_8001935C = .text:0x8001935C; // type:function size:0x4 align:0x4 fn_80019360 = .text:0x80019360; // type:function size:0x28 fn_80019388 = .text:0x80019388; // type:function size:0x1D4 fn_8001955C = .text:0x8001955C; // type:function size:0x3F0 -fn_8001994C = .text:0x8001994C; // type:function size:0x40 +Cross__9CVector3fFRC9CVector3fRC9CVector3f = .text:0x8001994C; // type:function size:0x40 fn_8001998C = .text:0x8001998C; // type:function size:0x27C align:0x4 fn_80019C08 = .text:0x80019C08; // type:function size:0x6C fn_80019C74 = .text:0x80019C74; // type:function size:0x154 @@ -12924,18 +12924,18 @@ Magnitude__9CVector3dCFv = .text:0x802CA910; // type:function size:0x40 scope:gl __ct__9CVector3dFRC9CVector3f = .text:0x802CA950; // type:function size:0x1C scope:global __ct__9CVector3dFddd = .text:0x802CA96C; // type:function size:0x10 scope:global __sinit_CVector3d_cpp = .text:0x802CA97C; // type:function size:0x184 scope:local align:0x4 -fn_802CAB00 = .text:0x802CAB00; // type:function size:0x80 align:0x4 -fn_802CAB80 = .text:0x802CAB80; // type:function size:0xCC align:0x4 -fn_802CAC4C = .text:0x802CAC4C; // type:function size:0x94 -fn_802CACE0 = .text:0x802CACE0; // type:function size:0x78 align:0x4 -fn_802CAD58 = .text:0x802CAD58; // type:function size:0x4C -fn_802CADA4 = .text:0x802CADA4; // type:function size:0x68 -fn_802CAE0C = .text:0x802CAE0C; // type:function size:0x40 -fn_802CAE4C = .text:0x802CAE4C; // type:function size:0x5C -fn_802CAEA8 = .text:0x802CAEA8; // type:function size:0x11C align:0x4 -fn_802CAFC4 = .text:0x802CAFC4; // type:function size:0x94 align:0x4 -fn_802CB058 = .text:0x802CB058; // type:function size:0x3C -fn_802CB094 = .text:0x802CB094; // type:function size:0x90 align:0x4 +IsEqu__9CVector3fCFRC9CVector3ff = .text:0x802CAB00; // type:function size:0x80 scope:global align:0x4 +GetAngleDiff__9CVector3fFRC9CVector3fRC9CVector3f = .text:0x802CAB80; // type:function size:0xCC scope:global align:0x4 +CanBeNormalized__9CVector3fCFv = .text:0x802CAC4C; // type:function size:0x94 scope:global +IsMagnitudeSafe__9CVector3fCFv = .text:0x802CACE0; // type:function size:0x78 scope:global align:0x4 +IsNotInf__9CVector3fCFv = .text:0x802CAD58; // type:function size:0x4C scope:global +AsNormalized__9CVector3fCFv = .text:0x802CADA4; // type:function size:0x68 scope:global +Magnitude__9CVector3fCFv = .text:0x802CAE0C; // type:function size:0x40 scope:global +Normalize__9CVector3fFv = .text:0x802CAE4C; // type:function size:0x5C scope:global +Slerp__9CVector3fFRC9CVector3fRC9CVector3fRC9CRelAngle = .text:0x802CAEA8; // type:function size:0x11C scope:global align:0x4 +PutTo__9CVector3fCFR13COutputStream = .text:0x802CAFC4; // type:function size:0x94 scope:global align:0x4 +__ct__9CVector3fFR12CInputStream = .text:0x802CB058; // type:function size:0x3C scope:global +__sinit_CVector3f_cpp = .text:0x802CB094; // type:function size:0x90 scope:local align:0x4 fn_802CB124 = .text:0x802CB124; // type:function size:0x40 align:0x4 fn_802CB164 = .text:0x802CB164; // type:function size:0x10 fn_802CB174 = .text:0x802CB174; // type:function size:0x1BC align:0x4 @@ -13879,7 +13879,7 @@ fn_802FFF84 = .text:0x802FFF84; // type:function size:0x70 align:0x4 fn_802FFFF4 = .text:0x802FFFF4; // type:function size:0x7C fn_80300070 = .text:0x80300070; // type:function size:0x80 fn_803000F0 = .text:0x803000F0; // type:function size:0x50 -fn_80300140 = .text:0x80300140; // type:function size:0xE8 +DoPut__13COutputStreamFPCvUl = .text:0x80300140; // type:function size:0xE8 scope:global fn_80300228 = .text:0x80300228; // type:function size:0x6C fn_80300294 = .text:0x80300294; // type:function size:0xA4 fn_80300338 = .text:0x80300338; // type:function size:0x6C align:0x4 @@ -15411,7 +15411,7 @@ fn_80342F6C = .text:0x80342F6C; // type:function size:0x24 fn_80342F90 = .text:0x80342F90; // type:function size:0x1C fn_80342FAC = .text:0x80342FAC; // type:function size:0x8C fn_80343038 = .text:0x80343038; // type:function size:0x14 -fn_8034304C = .text:0x8034304C; // type:function size:0x4C +Get__12CInputStreamFPvUl = .text:0x8034304C; // type:function size:0x4C scope:global fn_80343098 = .text:0x80343098; // type:function size:0x6C fn_80343104 = .text:0x80343104; // type:function size:0x2C fn_80343130 = .text:0x80343130; // type:function size:0x24 @@ -15659,12 +15659,12 @@ fn_80352084 = .text:0x80352084; // type:function size:0xA0 fn_80352124 = .text:0x80352124; // type:function size:0x214 fn_80352338 = .text:0x80352338; // type:function size:0x218 align:0x4 fn_80352550 = .text:0x80352550; // type:function size:0x28 -fn_80352578 = .text:0x80352578; // type:function size:0xD4 +cos = .text:0x80352578; // type:function size:0xD4 scope:global fn_8035264C = .text:0x8035264C; // type:function size:0x148 fn_80352794 = .text:0x80352794; // type:function size:0x8C fn_80352820 = .text:0x80352820; // type:function size:0x1C4 fn_803529E4 = .text:0x803529E4; // type:function size:0xFC -fn_80352AE0 = .text:0x80352AE0; // type:function size:0xD8 +sin = .text:0x80352AE0; // type:function size:0xD8 scope:global fn_80352BB8 = .text:0x80352BB8; // type:function size:0x78 fn_80352C30 = .text:0x80352C30; // type:function size:0x20 fn_80352C50 = .text:0x80352C50; // type:function size:0x20 align:0x4 @@ -19103,14 +19103,14 @@ sLeftVector__9CVector3d = .bss:0x80417450; // type:object size:0x18 data:double sRightVector__9CVector3d = .bss:0x80417468; // type:object size:0x18 data:double sForwardVector__9CVector3d = .bss:0x80417480; // type:object size:0x18 data:double sBackVector__9CVector3d = .bss:0x80417498; // type:object size:0x18 data:double -lbl_804174B0 = .bss:0x804174B0; // type:object size:0xC data:float -lbl_804174BC = .bss:0x804174BC; // type:object size:0xC data:float -lbl_804174C8 = .bss:0x804174C8; // type:object size:0xC data:float -lbl_804174D4 = .bss:0x804174D4; // type:object size:0xC data:float -lbl_804174E0 = .bss:0x804174E0; // type:object size:0xC data:float -lbl_804174EC = .bss:0x804174EC; // type:object size:0xC data:float -lbl_804174F8 = .bss:0x804174F8; // type:object size:0xC data:float -lbl_80417504 = .bss:0x80417504; // type:object size:0xC data:float +sZeroVector__9CVector3f = .bss:0x804174B0; // type:object size:0xC data:float +sUpVector__9CVector3f = .bss:0x804174BC; // type:object size:0xC data:float +sDownVector__9CVector3f = .bss:0x804174C8; // type:object size:0xC data:float +sLeftVector__9CVector3f = .bss:0x804174D4; // type:object size:0xC data:float +sRightVector__9CVector3f = .bss:0x804174E0; // type:object size:0xC data:float +sForwardVector__9CVector3f = .bss:0x804174EC; // type:object size:0xC data:float +sBackVector__9CVector3f = .bss:0x804174F8; // type:object size:0xC data:float +sOneVector__9CVector3f = .bss:0x80417504; // type:object size:0xC data:float lbl_80417510 = .bss:0x80417510; // type:object size:0xC data:4byte lbl_8041751C = .bss:0x8041751C; // type:object size:0xC data:4byte lbl_80417528 = .bss:0x80417528; // type:object size:0xC data:4byte diff --git a/configure.py b/configure.py index 74191b1..d5b09b3 100644 --- a/configure.py +++ b/configure.py @@ -35,6 +35,7 @@ LIBS = [ ["Kyoto/Math/CVector2f.cpp", False], ["Kyoto/Math/CVector2i.cpp", True], ["Kyoto/Math/CVector3d.cpp", False], + ["Kyoto/Math/CVector3f.cpp", False], ] } ] diff --git a/include/Kyoto/Math/CRelAngle.hpp b/include/Kyoto/Math/CRelAngle.hpp new file mode 100644 index 0000000..bdb86f1 --- /dev/null +++ b/include/Kyoto/Math/CRelAngle.hpp @@ -0,0 +1,52 @@ +#ifndef _CRELANGLE +#define _CRELANGLE + +#include "types.h" + +#include "Kyoto/Math/CMath.hpp" + +class CRelAngle { +public: + float AsDegrees() const { return x0_angle * (180.f / M_PIF); } + float AsRadians() const { return x0_angle; } + // ArcCosine__9CRelAngleFf weak + + CRelAngle& operator+=(const CRelAngle& v) { + x0_angle += v.x0_angle; + return *this; + } + CRelAngle& operator-=(const CRelAngle& v) { + x0_angle -= v.x0_angle; + return *this; + } + CRelAngle& operator*=(float v) { + x0_angle *= v; + return *this; + } + CRelAngle& operator/=(float v) { + x0_angle /= v; + return *this; + } + + // __lt__9CRelAngleCFRC9CRelAngle + + static CRelAngle FromDegrees(float deg) { return CRelAngle(deg * (M_PIF / 180.f)); } + static CRelAngle FromRadians(float rad) { return CRelAngle(rad); } + +private: + CRelAngle(float rad) : x0_angle(rad) {} + + float x0_angle; +}; +CHECK_SIZEOF(CRelAngle, 0x4) + +// __mi__FRC9CRelAngleRC9CRelAngle +// __pl__FRC9CRelAngleRC9CRelAngle +// __dv__FRC9CRelAnglef +// static inline CRelAngle operator/(const CRelAngle& ang, float f) { +// return CRelAngle::FromRadians(ang.AsRadians() / f); +// } +static inline float sine(const CRelAngle& angle) { return sin(angle.AsRadians()); } +static inline float cosine(const CRelAngle& angle) { return cos(angle.AsRadians()); } + +#endif // _CRELANGLE diff --git a/include/Kyoto/Math/CVector3f.hpp b/include/Kyoto/Math/CVector3f.hpp index e056377..c356063 100644 --- a/include/Kyoto/Math/CVector3f.hpp +++ b/include/Kyoto/Math/CVector3f.hpp @@ -54,12 +54,7 @@ public: return CVector3f(x, y, z); } inline float MagSquared() const { return GetX() * GetX() + GetY() * GetY() + GetZ() * GetZ(); } - static CVector3f Cross(const CVector3f& lhs, const CVector3f& rhs) { - const float x = (lhs.GetY() * rhs.GetZ()) - (rhs.GetY() * lhs.GetZ()); - const float y = (lhs.GetZ() * rhs.GetX()) - (rhs.GetZ() * lhs.GetX()); - const float z = (lhs.GetX() * rhs.GetY()) - (rhs.GetX() * lhs.GetY()); - return CVector3f(x, y, z); - } + static CVector3f Cross(const CVector3f& lhs, const CVector3f& rhs); float& operator[](EDimX dim) { return mX; } float& operator[](EDimY dim) { return mY; } @@ -99,9 +94,7 @@ public: return *this; } - CVector2f ToVec2f() const { - return CVector2f(mX, mY); - } + CVector2f ToVec2f() const { return CVector2f(mX, mY); } static float Dot(const CVector3f& a, const CVector3f& b) { return (a.GetX() * b.GetX()) + (a.GetY() * b.GetY()) + (a.GetZ() * b.GetZ()); @@ -121,6 +114,7 @@ protected: float mZ; static CVector3f sZeroVector; + static CVector3f sOneVector; static CVector3f sUpVector; static CVector3f sDownVector; static CVector3f sLeftVector; @@ -134,6 +128,14 @@ CHECK_SIZEOF(CVector3f, 0xc) // TGetType<9CVector3f>__FRC9CVector3f // close_enough__FRC9CVector3fRC9CVector3ff in CloseEnough.cpp +CVector3f CVector3f::Cross(const CVector3f& lhs, const CVector3f& rhs) +{ + const float x = (lhs.GetY() * rhs.GetZ()) - (rhs.GetY() * lhs.GetZ()); + const float y = (lhs.GetZ() * rhs.GetX()) - (rhs.GetZ() * lhs.GetX()); + const float z = (lhs.GetX() * rhs.GetY()) - (rhs.GetX() * lhs.GetY()); + return CVector3f(x, y, z); +} + inline bool operator==(const CVector3f& lhs, const CVector3f& rhs) { return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY() && lhs.GetZ() == rhs.GetZ(); } diff --git a/include/Kyoto/Math/CloseEnough.hpp b/include/Kyoto/Math/CloseEnough.hpp new file mode 100644 index 0000000..11dd195 --- /dev/null +++ b/include/Kyoto/Math/CloseEnough.hpp @@ -0,0 +1,29 @@ +#ifndef _CLOSEENOUGH +#define _CLOSEENOUGH + +#include "types.h" + +#include "Kyoto/Math/CVector2f.hpp" +#include "Kyoto/Math/CVector3f.hpp" + +#include "math.h" + +struct Real32 { + static inline float Epsilon() { return 1.e-5f; } +}; +struct Double { + static inline double Epsilon() { return 1.e-5; } // TODO check +}; +static inline float vector3_epsilon() { return 1.e-4f; } +static inline float vector2_epsilon() { return 1.e-4f; } + +bool close_enough(const CVector2f& a, const CVector2f& b, float epsilon = vector2_epsilon()); +bool close_enough(const CVector3f& a, const CVector3f& b, float epsilon = vector3_epsilon()); +inline bool close_enough(float a, float b, float epsilon = Real32::Epsilon()) { + return fabs(a - b) < epsilon; +} +inline bool close_enough(double a, double b, double epsilon = Double::Epsilon()) { + return fabs(a - b) < epsilon; +} + +#endif // _CLOSEENOUGH diff --git a/include/Kyoto/Streams/COutputStream.hpp b/include/Kyoto/Streams/COutputStream.hpp new file mode 100644 index 0000000..b63d0ff --- /dev/null +++ b/include/Kyoto/Streams/COutputStream.hpp @@ -0,0 +1,86 @@ +#ifndef _COUTPUTSTREAM +#define _COUTPUTSTREAM + +#include "types.h" + +#include "stddef.h" + +class COutputStream; + +template < typename T > +void coutput_stream_helper(const T& t, COutputStream& out); + +class COutputStream { +public: + COutputStream(int len); + virtual ~COutputStream(); + virtual void Write(const void* ptr, size_t len) = 0; + void WriteBits(uint val, uint bitCount); + + void DoPut(const void* ptr, size_t len); + void DoFlush(); + void Flush(); + void FlushShiftRegister(); + void Put(const void* ptr, size_t len) { + // FlushShiftRegister(); + DoPut(ptr, len); + } + + template < typename T > + void Put(const T& t) { + coutput_stream_helper(t, *this); + } + + void WriteReal32(float t) { Put(t); } + + void WriteUint32(uint t) { Put(t); } + void WriteInt32(int t) { Put(t); } + + void WriteLong(int t) { Put(&t, sizeof(int)); } + + void WriteChar(u8 c) { + FlushShiftRegister(); + if (mUnwrittenLen >= mBufLen) { + DoFlush(); + } + ++mNumWrites; + *(reinterpret_cast< u8* >(mBufPtr) + mUnwrittenLen++) = c; + } + +private: + uint mUnwrittenLen; + uint mBufLen; + void* mBufPtr; + uint mNumWrites; + uint mShiftRegister; + volatile uint mShiftRegisterOffset; + uchar mScratch[96]; +}; + +template < typename T > +inline void coutput_stream_helper(const T& t, COutputStream& out) { + t.PutTo(out); +} + +template <> +inline void coutput_stream_helper(const float& t, COutputStream& out) { + int tmp = *(int*)&t; + out.Put(&tmp, sizeof(float)); +} + +template <> +inline void coutput_stream_helper(const int& t, COutputStream& out) { + out.WriteLong(t); +} + +template <> +inline void coutput_stream_helper(const uint& t, COutputStream& out) { + out.WriteLong(t); +} + +template <> +inline void coutput_stream_helper(const bool& t, COutputStream& out) { + out.WriteChar(static_cast< u8 >(t)); +} + +#endif // _COUTPUTSTREAM diff --git a/src/Kyoto/Math/CVector3f.cpp b/src/Kyoto/Math/CVector3f.cpp new file mode 100644 index 0000000..7a360bb --- /dev/null +++ b/src/Kyoto/Math/CVector3f.cpp @@ -0,0 +1,114 @@ +#include "Kyoto/Math/CVector3f.hpp" + +#include "Kyoto/Math/CMath.hpp" +#include "Kyoto/Math/CRelAngle.hpp" +#include "Kyoto/Math/CloseEnough.hpp" +#include "Kyoto/Streams/CInputStream.hpp" +#include "Kyoto/Streams/COutputStream.hpp" +#include "types.h" + +#ifndef __MWERKS__ +// TODO +#define __HI(x) (*(int*)&x) +#endif + +CVector3f CVector3f::sZeroVector(0.f, 0.f, 0.f); +CVector3f CVector3f::sUpVector(0.f, 0.f, 1.f); +CVector3f CVector3f::sDownVector(0.f, 0.f, -1.f); +CVector3f CVector3f::sLeftVector(-1.f, 0.f, 0.f); +CVector3f CVector3f::sRightVector(1.f, 0.f, 0.f); +CVector3f CVector3f::sForwardVector(0.f, 1.f, 0.f); +CVector3f CVector3f::sBackVector(0.f, -1.f, 0.f); +CVector3f CVector3f::sOneVector(1.f, 1.f, 1.f); + +CVector3f::CVector3f(CInputStream& in) { in.Get(this, sizeof(CVector3f)); } + +void CVector3f::PutTo(COutputStream& out) const { + out.WriteReal32(mX); + out.WriteReal32(mY); + out.WriteReal32(mZ); +} + +CVector3f CVector3f::Slerp(const CVector3f& a, const CVector3f& b, const CRelAngle& angle) { + CVector3f axb = CVector3f::Cross(a, b).AsNormalized(); + CVector3f crs = CVector3f::Cross(axb, a); + float asin = sine(angle); + float acos = cosine(angle); + return acos * a + asin * crs; +} + +CVector3f& CVector3f::Normalize() { + float mag = 1.f / Magnitude(); + mX *= mag; + mY *= mag; + mZ *= mag; + return *this; +} + +float CVector3f::Magnitude() const { + float mag = mX * mX; + mag += mY * mY; + mag += mZ * mZ; + return CMath::SqrtF(mag); +} + +CVector3f CVector3f::AsNormalized() const { + float mag = 1.f / Magnitude(); + float x = mX * mag; + float y = mY * mag; + float z = mZ * mag; + return CVector3f(x, y, z); +} + +bool CVector3f::IsNotInf() const { + int x = __HI(mX); + int y = __HI(mY); + int z = __HI(mZ); + if ((x & 0x7f800000) == 0x7f800000 || (y & 0x7f800000) == 0x7f800000 || + (z & 0x7f800000) == 0x7f800000) { + return false; + } + + return true; +} + +bool CVector3f::IsMagnitudeSafe() const { return IsNotInf() && MagSquared() >= 9.999999e-29f; } + +bool CVector3f::CanBeNormalized() const { + int x = __HI(mX); + int y = __HI(mY); + int z = __HI(mZ); + if ((x & 0x7f800000) == 0x7f800000 || (y & 0x7f800000) == 0x7f800000 || + (z & 0x7f800000) == 0x7f800000) { + return false; + } + + if (CMath::AbsF(mX) < FLT_EPSILON && CMath::AbsF(mY) < FLT_EPSILON && + CMath::AbsF(mZ) < FLT_EPSILON) { + return false; + } + + return true; +} + +float CVector3f::GetAngleDiff(const CVector3f& a, const CVector3f& b) { + float mag1 = a.Magnitude(); + float mag2 = b.Magnitude(); + + float ret = 0.f; + if (mag1 > FLT_EPSILON && mag2 > FLT_EPSILON) { + float dist = CVector3f::Dot(a, b) / (mag1 * mag2); + if (dist < -1.f) { + dist = -1.f; + } else if (dist > 1.f) { + dist = 1.f; + } + ret = CMath::ArcCosineR(dist); + } + return ret; +} + +bool CVector3f::IsEqu(const CVector3f& vec, float epsilon) const { + return CMath::AbsF(mX - vec.mX) <= epsilon && CMath::AbsF(mY - vec.mY) <= epsilon && + CMath::AbsF(mZ - vec.mZ) <= epsilon; +}