From 4890acfe80ce5d1b723febfbb0d2a7a1395cc809 Mon Sep 17 00:00:00 2001 From: robojumper Date: Fri, 21 Mar 2025 00:46:41 +0100 Subject: [PATCH] Some frustum/screen --- config/SOUE01/splits.txt | 7 + config/SOUE01/symbols.txt | 22 +- include/egg/gfx/eggFrustum.h | 142 +++++++++---- include/egg/gfx/eggGXUtility.h | 1 + include/egg/gfx/eggGfxEngine.h | 8 +- include/egg/gfx/eggScreen.h | 84 +++++--- include/egg/gfx/eggStateGX.h | 10 +- src/d/lyt/d2d.cpp | 6 +- src/egg/gfx/eggFrustum.cpp | 239 ++++++++++++++++++++- src/egg/gfx/eggPostEffectBase.cpp | 2 +- src/egg/gfx/eggScreen.cpp | 342 +++++++++++++++++++++++++++++- src/m/m2d.cpp | 6 +- 12 files changed, 773 insertions(+), 96 deletions(-) diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 8d54a2a5..c6b4d2ec 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -2228,6 +2228,9 @@ egg/gfx/eggFogManager.cpp: egg/gfx/eggFrustum.cpp: .text start:0x804A5F60 end:0x804A6854 .ctors start:0x804DB99C end:0x804DB9A0 + .data start:0x8056F030 end:0x8056F048 + .sbss start:0x80576810 end:0x80576820 + .sdata2 start:0x8057F618 end:0x8057F63C egg/gfx/eggG3DUtility.cpp: .text start:0x804A6860 end:0x804A75B0 @@ -2311,6 +2314,10 @@ egg/gfx/eggPostEffectSimple.cpp: egg/gfx/eggScreen.cpp: .text start:0x804B1E60 end:0x804B30B4 .ctors start:0x804DB9A8 end:0x804DB9AC + .data start:0x8056F230 end:0x8056F268 + .sbss start:0x80576870 end:0x80576898 + .sdata2 start:0x8057F818 end:0x8057F840 + .bss start:0x80674F00 end:0x80674F88 egg/gfx/eggScreenEffectBase.cpp: .text start:0x804B30C0 end:0x804B30EC diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 85c66915..1a95fda0 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -26545,7 +26545,7 @@ __ct__Q23EGG7FrustumFQ33EGG7Frustum14ProjectionTypeRCQ34nw4r4math4VEC2ffQ33EGG7F __ct__Q23EGG7FrustumFRCQ23EGG7Frustum = .text:0x804A5FD0; // type:function size:0x3C ResetOrthographic__Q23EGG7FrustumFffffff = .text:0x804A6010; // type:function size:0x104 CopyFromAnother__Q23EGG7FrustumFRCQ23EGG7Frustum = .text:0x804A6120; // type:function size:0x74 -SetFovy__Q23EGG7FrustumFf = .text:0x804A61A0; // type:function size:0x68 +SetFovy__Q23EGG7FrustumFd = .text:0x804A61A0; // type:function size:0x68 ConvertToCanvasLU__Q23EGG7FrustumCFffPfPf = .text:0x804A6210; // type:function size:0x4C GetScreenSizeToViewSize__Q23EGG7FrustumCFff = .text:0x804A6260; // type:function size:0x30 SetProjectionGX__Q23EGG7FrustumCFv = .text:0x804A6290; // type:function size:0x14 @@ -26731,7 +26731,7 @@ CopyToG3D__Q23EGG6ScreenCFQ34nw4r3g3d6Camera = .text:0x804B2390; // type:functio CopyFromAnother__Q23EGG6ScreenFRCQ23EGG6Screen = .text:0x804B24C0; // type:function size:0xD0 Reset__Q23EGG6ScreenFffffQ33EGG7Frustum10CanvasMode = .text:0x804B2590; // type:function size:0x38 SetParent__Q23EGG6ScreenFPCQ23EGG6Screen = .text:0x804B25D0; // type:function size:0x30 -FUN_804b2600 = .text:0x804B2600; // type:function size:0x24 +SetUnkFlag8__Q23EGG6ScreenFv = .text:0x804B2600; // type:function size:0x24 OnDirectEfb__Q23EGG6ScreenFv = .text:0x804B2630; // type:function size:0x4D8 GetDataEfb__Q23EGG6ScreenCFv = .text:0x804B2B10; // type:function size:0x5C IsChangeEfb__Q23EGG6ScreenCFv = .text:0x804B2B70; // type:function size:0x2C @@ -29879,7 +29879,7 @@ __vt__Q23d3d12UnkWithWater = .data:0x805009C0; // type:object size:0x10 __vt__Q23d3d14AnmMdlWrapper2 = .data:0x805009D0; // type:object size:0x50 __vt__Q23d3d13AnmMdlWrapper = .data:0x80500A20; // type:object size:0x50 lbl_80500A70 = .data:0x80500A70; // type:object size:0x2C -lbl_80500A9C = .data:0x80500A9C; // type:object size:0xC +lbl_80500A9C = .data:0x80500A9C; // type:object size:0xB data:string lbl_80500AA8 = .data:0x80500AA8; // type:object size:0x10 data:string __vt__14dScnCallback_c = .data:0x80500AB8; // type:object size:0x20 lbl_80500AD8 = .data:0x80500AD8; // type:object size:0x18 @@ -37366,7 +37366,7 @@ __vt__Q23EGG11DrawPathDOF = .data:0x8056EF28; // type:object size:0x78 lbl_8056EFA0 = .data:0x8056EFA0; // type:object size:0x50 __vt__Q23EGG3Fog = .data:0x8056EFF0; // type:object size:0x20 __vt__Q23EGG10FogManager = .data:0x8056F010; // type:object size:0x1C -EGG__Frustum__vtable = .data:0x8056F030; // type:object size:0x18 +__vt__Q23EGG7Frustum = .data:0x8056F030; // type:object size:0x14 EGG__GfxEnginer__Configuration__vtable = .data:0x8056F048; // type:object size:0x10 __vt__Q23EGG8IScnProc = .data:0x8056F058; // type:object size:0x10 EGG__LightManager__vtable = .data:0x8056F068; // type:object size:0x30 @@ -37383,7 +37383,7 @@ __vt__Q23EGG14PostEffectMask = .data:0x8056F1D0; // type:object size:0x1C lbl_8056F1F0 = .data:0x8056F1F0; // type:object size:0x1C __vt__Q23EGG16PostEffectSimple = .data:0x8056F210; // type:object size:0x1C sTVModeInfo__Q23EGG6Screen = .data:0x8056F230; // type:object size:0x24 data:2byte -EGG__Screen__vtable = .data:0x8056F254; // type:object size:0x14 +__vt__Q23EGG6Screen = .data:0x8056F254; // type:object size:0x14 __vt__Q23EGG16ScreenEffectBase = .data:0x8056F268; // type:object size:0xC __vt__Q23EGG16ScreenEffectBlur = .data:0x8056F278; // type:object size:0x38 __vt__Q23EGG13TextureBuffer = .data:0x8056F2B0; // type:object size:0x10 @@ -41149,8 +41149,8 @@ sInstantHalt__Q23EGG6Assert = .sbss:0x80576804; // type:object size:0x1 data:byt sAssertOccurred__Q23EGG6Assert = .sbss:0x80576805; // type:object size:0x1 data:byte s_flag__Q23EGG6DrawGX = .sbss:0x80576808; // type:object size:0x4 data:4byte sTexMapDefault__Q23EGG6DrawGX = .sbss:0x8057680C; // type:object size:0x4 data:4byte -EGG__Frustum__sGlobalScale = .sbss:0x80576810; // type:object size:0x4 data:float -EGG__Frustum__sGlobalOffset = .sbss:0x80576818; // type:object size:0x4 data:float +sGlobalScale__Q23EGG7Frustum = .sbss:0x80576810; // type:object size:0x8 data:float +sGlobalOffset__Q23EGG7Frustum = .sbss:0x80576818; // type:object size:0x8 data:float lbl_80576820 = .sbss:0x80576820; // type:object size:0x1 data:byte sAllocator__Q23EGG10G3DUtility = .sbss:0x80576824; // type:object size:0x4 data:4byte lbl_80576828 = .sbss:0x80576828; // type:object size:0x4 data:4byte @@ -41173,15 +41173,15 @@ lbl_80576860 = .sbss:0x80576860; // type:object size:0x1 data:byte lbl_80576861 = .sbss:0x80576861; // type:object size:0x7 data:byte lbl_80576868 = .sbss:0x80576868; // type:object size:0x8 data:float sTVMode__Q23EGG6Screen = .sbss:0x80576870; // type:object size:0x4 data:4byte -lbl_80576874 = .sbss:0x80576874; // type:object size:0x4 data:4byte +spRoot__Q23EGG6Screen = .sbss:0x80576874; // type:object size:0x4 data:4byte lbl_80576878 = .sbss:0x80576878; // type:object size:0x4 data:4byte lbl_8057687C = .sbss:0x8057687C; // type:object size:0x4 data:4byte lbl_80576880 = .sbss:0x80576880; // type:object size:0x4 data:float lbl_80576888 = .sbss:0x80576888; // type:object size:0x4 data:float lbl_80576890 = .sbss:0x80576890; // type:object size:0x8 data:byte lbl_80576898 = .sbss:0x80576898; // type:object size:0x8 data:4byte -lbl_805768A0 = .sbss:0x805768A0; // type:object size:0x2 data:2byte -lbl_805768A2 = .sbss:0x805768A2; // type:object size:0x2 data:2byte +s_widthEfb__Q23EGG7StateGX = .sbss:0x805768A0; // type:object size:0x2 data:2byte +s_heightEfb__Q23EGG7StateGX = .sbss:0x805768A2; // type:object size:0x2 data:2byte lbl_805768A4 = .sbss:0x805768A4; // type:object size:0x4 data:4byte lbl_805768A8 = .sbss:0x805768A8; // type:object size:0x4 data:4byte sDefaultTexColor__Q23EGG7StateGX = .sbss:0x805768AC; // type:object size:0x1 data:byte @@ -49804,7 +49804,7 @@ sMtx__Q23EGG15GlobalDrawState = .bss:0x80674E48; // type:object size:0x30 CPU_TEX_ARR = .bss:0x80674E78; // type:object size:0x48 data:4byte sMtx__3EGG = .bss:0x80674EC0; // type:object size:0x30 data:float lbl_80674EF0 = .bss:0x80674EF0; // type:object size:0xC data:float -lbl_80674F00 = .bss:0x80674F00; // type:object size:0x88 data:4byte +@LOCAL@Initialize__Q23EGG6ScreenFPCUsPCUsPQ23EGG6Screen@defaultRoot = .bss:0x80674F00; // type:object size:0x88 data:4byte sScreen__Q23EGG16ScreenEffectBase = .bss:0x80674F88; // type:object size:0x88 lbl_80675010 = .bss:0x80675010; // type:object size:0x30 lbl_80675040 = .bss:0x80675040; // type:object size:0x18 data:float diff --git a/include/egg/gfx/eggFrustum.h b/include/egg/gfx/eggFrustum.h index f3dd56d3..5adbc40e 100644 --- a/include/egg/gfx/eggFrustum.h +++ b/include/egg/gfx/eggFrustum.h @@ -1,52 +1,54 @@ #ifndef EGG_FRUSTUM_H #define EGG_FRUSTUM_H -#include "common.h" #include "nw4r/g3d/g3d_camera.h" namespace EGG { - -// TODO: Fill out more class Frustum { public: - enum CanvasMode { - CANVAS_0, - CANVAS_1, + enum Flag { + FLAG_DIRTY = (1 << 0), + FLAG_0x40 = (1 << 6), }; + enum ProjectionType { PROJ_ORTHO, PROJ_PERSP }; - enum Flag { - FLAG_DIRTY = (1 << 0), - FLAG_0x40 = 0x40, + enum CanvasMode { + CANVASMODE_0, + CANVASMODE_1, }; -private: - /* 0x00 */ ProjectionType mProjType; - /* 0x04 */ CanvasMode mCanvasMode; - /* 0x08 */ nw4r::math::VEC2 mSize; - /* 0x10 */ f32 mFovY; - /* 0x14 */ f32 mTanFovY; - /* 0x18 */ f32 mNearZ; - /* 0x1C */ f32 mFarZ; - /* 0x20 */ nw4r::math::VEC2 mOffset; - /* 0x28 */ nw4r::math::VEC3 mScale; - /* 0x34 */ mutable u16 mFlags; +protected: + ProjectionType mProjType; // at 0x0 + CanvasMode mCanvasMode; // at 0x4 + nw4r::math::VEC2 mSize; // at 0x8 + f32 mFovY; // at 0x10 + f32 mTanFovY; // at 0x14 + f32 mNearZ; // at 0x18 + f32 mFarZ; // at 0x1C + nw4r::math::VEC2 mOffset; // at 0x20 + nw4r::math::VEC3 mScale; // at 0x28 + mutable u16 mFlags; // at 0x34 public: - // vt at 0x38 - virtual ~Frustum() {} - virtual void SetProjectionGX() const; - virtual void CopyToG3D(nw4r::g3d::Camera) const; + Frustum(ProjectionType, const nw4r::math::VEC2 &, f32, f32, CanvasMode); + Frustum(const Frustum &); - ProjectionType GetProjectionType() const { - return mProjType; - } - void SetProjectionType(ProjectionType type) { - mProjType = type; - } + virtual ~Frustum() {} // at 0x8 + virtual void SetProjectionGX() const; // at 0xC + virtual void CopyToG3D(nw4r::g3d::Camera) const; // at 0x10 + void ResetOrthographic(f32, f32, f32, f32, f32, f32); + void CopyFromAnother(const Frustum &); + void SetFovy(f32); + void ConvertToCanvasLU(f32, f32, f32 *, f32 *) const; + + static void SetGlobalScaleOffset(f32, f32, f32, f32); + static void GetGlobalScaleOffset(f32 *, f32 *, f32 *, f32 *); + + f32 GetScreenSizeToViewSize(f32, f32) const; void SetDirty(bool dirty) const { if (dirty) { @@ -56,27 +58,75 @@ public: } } - void SetFlag(Flag f) const { - mFlags |= f; + ProjectionType GetProjectionType() const { + return mProjType; + } + void SetProjectionType(ProjectionType type) { + mProjType = type; } CanvasMode GetCanvasMode() const { return mCanvasMode; } void SetCanvasMode(CanvasMode mode) { - if (mCanvasMode != mode) { + if (mode != mCanvasMode) { SetDirty(true); mCanvasMode = mode; } } + const nw4r::math::VEC2 &GetSize() const { + return mSize; + } + + u16 GetWidth() const { + return mSize.x; + } + f32 GetSizeX() const { + return mSize.x; + } + void SetSizeX(f32 sizeX) { + SetDirty(true); + mSize.x = sizeX; + } + + u16 GetHeight() const { + return mSize.y; + } + f32 GetSizeY() const { + return mSize.y; + } + void SetSizeY(f32 sizeY) { + SetDirty(true); + mSize.y = sizeY; + } + + void SetSize(const nw4r::math::VEC2 &size) { + // ??? + mSize.x = size.x; + SetDirty(true); + mSize.y = size.y; + } + + void SetNearZ(f32 nearZ) { + mNearZ = nearZ; + } + f32 GetNearZ() const { + return mNearZ; + } + + void SetFarZ(f32 farZ) { + mFarZ = farZ; + } + f32 GetFarZ() const { + return mFarZ; + } + void SetNearFar(f32 near, f32 far) { mNearZ = near; mFarZ = far; } - void ResetOrthographic(f32, f32, f32, f32, f32, f32); - void SetScale(const nw4r::math::VEC3 &scale) { mScale = scale; } @@ -84,11 +134,27 @@ public: mOffset = offset; } - const nw4r::math::VEC2 &GetSize() { - return mSize; + void SetFlag(u32 flag) { + mFlags |= flag; } -}; +private: + void SetProjectionPerspectiveGX_() const; + void SetProjectionOrthographicGX_() const; + + void CopyToG3D_Perspective_(nw4r::g3d::Camera) const; + void CopyToG3D_Orthographic_(nw4r::g3d::Camera) const; + + void CalcMtxPerspective_(nw4r::math::MTX44 *) const; + + void GetOrthographicParam_(f32 *) const; + void GetPerspectiveParam_(f32 *) const; + void GetOrthographicParam_(f32 *, f32 *, f32 *, f32 *) const; + +private: + static nw4r::math::VEC2 sGlobalScale; + static nw4r::math::VEC2 sGlobalOffset; +}; } // namespace EGG #endif diff --git a/include/egg/gfx/eggGXUtility.h b/include/egg/gfx/eggGXUtility.h index d3ac74b7..cba929e6 100644 --- a/include/egg/gfx/eggGXUtility.h +++ b/include/egg/gfx/eggGXUtility.h @@ -16,6 +16,7 @@ public: static void getTexObj(GXTexObj *, nw4r::g3d::ResTex, GXTexWrapMode, GXTexWrapMode, GXTexFilter, GXTexFilter); static void getNormalColor(GXColor &outColor, const Vector3f &vec); + static void setScaleOffsetPerspective(f32*, f32, f32, f32, f32); }; } // namespace EGG diff --git a/include/egg/gfx/eggGfxEngine.h b/include/egg/gfx/eggGfxEngine.h index 56e8d67b..20b6729b 100644 --- a/include/egg/gfx/eggGfxEngine.h +++ b/include/egg/gfx/eggGfxEngine.h @@ -2,12 +2,12 @@ #define EGG_GFXENGINE_H #include "common.h" -#include "rvl/GX.h" +#include "rvl/GX/GXTypes.h" namespace EGG { -namespace GfxEngine { - +class GfxEngine { +public: struct Configuration { /* 0x00 */ u16 efbWidth; /* 0x02 */ u16 efbHeight; @@ -23,7 +23,7 @@ struct Configuration { virtual ~Configuration() {} }; -} // namespace GfxEngine +}; } // namespace EGG diff --git a/include/egg/gfx/eggScreen.h b/include/egg/gfx/eggScreen.h index 699df321..df63bf81 100644 --- a/include/egg/gfx/eggScreen.h +++ b/include/egg/gfx/eggScreen.h @@ -1,41 +1,20 @@ #ifndef EGG_SCREEN_H #define EGG_SCREEN_H -#include "common.h" +#include "egg/egg_types.h" #include "egg/gfx/eggFrustum.h" namespace EGG { -// TODO: Fill out more class Screen : public Frustum { public: - Screen(); - Screen(const Screen &other); - Screen(f32, f32, f32, f32, Screen *, CanvasMode); + enum TVMode { TV_MODE_4_3, TV_MODE_16_9, TV_MODE_UNK_3, TV_MODE_MAX }; - virtual ~Screen() {} - virtual void SetProjectionGX() const override; - virtual void CopyToG3D(nw4r::g3d::Camera) const override; + typedef void (*ChangeTVModeFunc)(void *); - static void Initialize(const u16 *, const u16 *, Screen *); - static void SetTVModeDefault(); - - u8 TODO_0x3C[0x88 - 0x3C]; - - enum TVMode { - TV_MODE_1, - TV_MODE_2, - TV_MODE_3, - TV_MODE_4, - TV_MODE_MAX - }; - - struct TVModeInfo { - TVModeInfo() {} - u16 width; - u16 height; - f32 w_ratio; - f32 h_ratio; + struct UnkStruct { + UNKWORD field_0x00; + UNKWORD field_0x04; }; struct DataEfb { @@ -49,10 +28,26 @@ public: f32 z2; // at 0x14 } vp; - s32 sc_ox; // at 0x18 - s32 sc_oy; // at 0x1C + u32 sc_x; + u32 sc_y; + u32 sc_w; + u32 sc_h; + + s32 sc_ox; // at 0x28 + s32 sc_oy; // at 0x2C }; + struct TVModeInfo { + u16 width; + u16 height; + nw4r::math::VEC2 ratios; + }; + +public: + static void Initialize(const u16 *, const u16 *, Screen *); + static void SetTVMode(TVMode); + static void SetTVModeDefault(); + static u16 GetSizeXMax(TVMode mode) { return sTVModeInfo[mode].width; } @@ -74,11 +69,40 @@ public: return sTVMode; } + Screen(); + Screen(f32, f32, f32, f32, const Screen *, CanvasMode); + Screen(const Screen &); + + virtual ~Screen() {} // at 0x8 + virtual void SetProjectionGX() const; // at 0xC + virtual void CopyToG3D(nw4r::g3d::Camera) const; // at 0x10 + + const Screen *GetParent() const { + return mParent; + } + void SetParent(const Screen *parent); + void SetUnkFlag8(); + + void CopyFromAnother(const Screen &other); + void Reset(f32, f32, f32, f32, CanvasMode); + void GetPosSizeInEfb() const; + const DataEfb &GetDataEfb() const; + bool IsChangeEfb() const; + void CalcMatrixForDrawQuad(nw4r::math::MTX34 *, f32, f32, f32, f32) const; + void FillBufferGX(u32, GXColor, u32) const; + void GetGlobalPos(f32 *, f32 *) const; + +private: + const Screen *mParent; // at 0x3C + nw4r::math::VEC2 mPosition; // at 0x40 + nw4r::math::VEC2 field_0x44; + nw4r::math::VEC2 field_0x48; + mutable DataEfb mDataEfb; // at 0x58 + static TVMode sTVMode; static Screen *spRoot; - typedef void (*ChangeTVModeFunc)(void *); static ChangeTVModeFunc sChangeTVModeFunc; static void *spChangeTVModeFuncInfo; static TVModeInfo sTVModeInfo[Screen::TV_MODE_MAX]; diff --git a/include/egg/gfx/eggStateGX.h b/include/egg/gfx/eggStateGX.h index e575dcc8..bcc4e9f8 100644 --- a/include/egg/gfx/eggStateGX.h +++ b/include/egg/gfx/eggStateGX.h @@ -88,14 +88,16 @@ public: static bool GXSetDstAlpha(); // Unk func here static void GXSetProjection(Mtx44, int); - static void GXSetProjectionv(const f32 *); - static void GXSetViewport(f32, f32, f32, f32, f32, f32); - static void GZSetScissor(u32, u32, u32, u32); - static void GZSetScissorBoxOffset(s32, s32); + static void GXSetProjectionv_(const f32 *); + static void GXSetViewport_(f32, f32, f32, f32, f32, f32); + static void GXSetScissor_(u32, u32, u32, u32); + static void GXSetScissorBoxOffset_(s32, s32); static u16 s_commandFlag; static u16 s_flag; + static u16 s_widthEfb; + static u16 s_heightEfb; static GXColor sDefaultTexColor; }; diff --git a/src/d/lyt/d2d.cpp b/src/d/lyt/d2d.cpp index c69bada8..d33c741e 100644 --- a/src/d/lyt/d2d.cpp +++ b/src/d/lyt/d2d.cpp @@ -164,7 +164,7 @@ nw4r::lyt::AnimTransform *Layout_c::CreateAnimTransform(const void *animResBuf, Multi_c::Multi_c() : Base_c(0x80), mLayout(), mDrawInfo(), mpResAcc(nullptr), mFlags(0) { mDrawInfo.SetLocationAdjustScale(nw4r::math::VEC2( - (f32)EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_1) / (f32)EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_2), + (f32)EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_4_3) / (f32)EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_16_9), 1.0f )); mDrawInfo.SetLocationAdjust(true); @@ -207,8 +207,8 @@ void Multi_c::draw() { f32 far = 500.0f; EGG::Screen s; bool needsAdjust = NeedsScreenAdjustment(); - f32 f1 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_2); - f32 f2 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_1); + f32 f1 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_UNK_3); + f32 f2 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_16_9); f32 left = needsAdjust ? f1 * r.left / f2 : r.left; f32 right = needsAdjust ? f1 * r.right / f2 : r.right; diff --git a/src/egg/gfx/eggFrustum.cpp b/src/egg/gfx/eggFrustum.cpp index c060e519..d7c9e039 100644 --- a/src/egg/gfx/eggFrustum.cpp +++ b/src/egg/gfx/eggFrustum.cpp @@ -1,3 +1,240 @@ #include "egg/gfx/eggFrustum.h" -namespace EGG {} // namespace EGG +#include "egg/gfx/eggGXUtility.h" +#include "egg/gfx/eggStateGX.h" +#include "nw4r/math/math_arithmetic.h" + + +void eggFrustum_float_ordering() { + 1.0f; +} + +namespace EGG { +using namespace nw4r; + +Frustum::Frustum(ProjectionType proj, const math::VEC2 &size, f32 nearZ, f32 farZ, CanvasMode canvas) + : mProjType(proj), + mCanvasMode(canvas), + mSize(size), + mFovY(45.0f), + mTanFovY(2.4142134f), + mNearZ(nearZ), + mFarZ(farZ), + mOffset(0.0f, 0.0f), + mScale(1.0f, 1.0f, 1.0f), + mFlags(FLAG_DIRTY) {} + +Frustum::Frustum(const Frustum &other) { + CopyFromAnother(other); +} + +void Frustum::ResetOrthographic(f32 t, f32 b, f32 l, f32 r, f32 near, f32 far) { + 0.5f; + 2.0f; + + mProjType = PROJ_ORTHO; + mScale.z = 1.0f; + mScale.y = 1.0f; + mScale.x = 1.0f; + mSize.x = r - l; + if (mSize.x < 0.0f) { + mScale.x = -1.0f; + mSize.x *= -1.0f; + } + + mSize.y = t - b; + if (mSize.y >= 0.0f) { + SetCanvasMode(CANVASMODE_0); + mOffset = math::VEC2(0.5f * (r + l), 0.5f * (t + b)); + } else { + SetCanvasMode(CANVASMODE_1); + mOffset = math::VEC2(0.0f, t); + mSize.y *= -1.0f; + } + mNearZ = near; + mFarZ = far; + SetFlag(1); +} + +void Frustum::CopyFromAnother(const Frustum &other) { + mProjType = other.mProjType; + mCanvasMode = other.mCanvasMode; + mSize = other.mSize; + mFovY = other.mFovY; + mTanFovY = other.mTanFovY; + mNearZ = other.mNearZ; + mFarZ = other.mFarZ; + mOffset = other.mOffset; + mScale = other.mScale; + mFlags = other.mFlags; +} + +void Frustum::SetFovy(f32 fov) { + if (mFovY != fov) { + mFovY = fov; + f32 sin, cos; + + math::SinCosDeg(&sin, &cos, (f32)(f64)fov / 2.0f); + mTanFovY = cos / sin; + } +} + +void Frustum::ConvertToCanvasLU(f32 ix, f32 iy, f32 *ox, f32 *oy) const { + if (mCanvasMode == CANVASMODE_1) { + *ox = ix; + *oy = iy; + } else if (mCanvasMode == CANVASMODE_0) { + *ox = ix + (mSize.x * 0.5f); + *oy = -(iy - (mSize.y * 0.5f)); + } +} + +f32 Frustum::GetScreenSizeToViewSize(f32 p1, f32 p2) const { + if (mProjType != PROJ_PERSP) { + return p1; + } + return p1 * math::FAbs(p2) / (mSize.y * 0.5f * mTanFovY); +} + +void Frustum::SetProjectionGX() const { + if (mProjType == PROJ_ORTHO) { + SetProjectionOrthographicGX_(); + } else { + SetProjectionPerspectiveGX_(); + } +} + +void Frustum::CopyToG3D(g3d::Camera cam) const { + if (mProjType == PROJ_ORTHO) { + CopyToG3D_Orthographic_(cam); + } else { + CopyToG3D_Perspective_(cam); + } +} + +void Frustum::SetGlobalScaleOffset(f32 sx, f32 sy, f32 ox, f32 oy) { + sGlobalScale.x = sx; + sGlobalScale.y = sy; + sGlobalOffset.x = ox; + sGlobalOffset.y = oy; +} + +void Frustum::GetGlobalScaleOffset(f32 *sx, f32 *sy, f32 *ox, f32 *oy) { + *sx = sGlobalScale.x; + *sy = sGlobalScale.y; + *ox = sGlobalOffset.x; + *oy = sGlobalOffset.y; +} + +void Frustum::SetProjectionPerspectiveGX_() const { + f32 params[7]; + GetPerspectiveParam_(params); + StateGX::GXSetProjectionv_(params); +} + +void Frustum::SetProjectionOrthographicGX_() const { + f32 v[8]; + GetOrthographicParam_(v); + StateGX::GXSetProjectionv_(v); +} + +void Frustum::CopyToG3D_Perspective_(g3d::Camera cam) const { + math::MTX44 mtx; + f32 ratio = mSize.x / mSize.y; + cam.SetPerspective(mFovY, ratio, mNearZ, mFarZ); + CalcMtxPerspective_(&mtx); + cam.SetProjectionMtxDirectly(&mtx); +} + +void Frustum::CopyToG3D_Orthographic_(g3d::Camera cam) const { + f32 t, b, l, r; + GetOrthographicParam_(&t, &b, &l, &r); + cam.SetOrtho(t, b, l, r, mNearZ, mFarZ); +} + +void Frustum::CalcMtxPerspective_(math::MTX44 *out) const { + f32 params[7]; + GetPerspectiveParam_(params); + + out->m[0][3] = 0.0f; + out->m[0][1] = 0.0f; + out->m[0][0] = params[1]; + out->m[0][2] = params[2]; + + out->m[1][3] = 0.0f; + out->m[1][0] = 0.0f; + out->m[1][1] = params[3]; + out->m[1][2] = params[4]; + + out->m[2][1] = 0.0f; + out->m[2][0] = 0.0f; + out->m[2][2] = params[5]; + out->m[2][3] = params[6]; + + out->m[3][3] = 0.0f; + out->m[3][1] = 0.0f; + out->m[3][0] = 0.0f; + out->m[3][2] = -1.0f; +} + +void Frustum::GetPerspectiveParam_(f32 *p) const { + // NONMATCHING - FPR regswaps + f32 f1 = 1.0f / (mSize.x * 0.5f); + f32 f2 = 1.0f / (mSize.y * 0.5f); + p[0] = 0.0f; + p[1] = (mTanFovY / (mScale.x * (mSize.x / mSize.y))); + p[2] = mOffset.x * f1; + p[3] = mTanFovY / mScale.y; + p[4] = mOffset.y * f2; + + f32 z = -mNearZ / (mFarZ - mNearZ); + p[5] = z; + p[6] = mFarZ * z; + + GXUtility::setScaleOffsetPerspective(p, sGlobalScale.x, sGlobalScale.y, sGlobalOffset.x * f1, sGlobalOffset.y * f2); +} + +void Frustum::GetOrthographicParam_(f32 *p) const { + f32 t, b, l, r; + GetOrthographicParam_(&t, &b, &l, &r); + + f32 invHor = 1.0f / (r - l); + f32 invVert = 1.0f / (t - b); + f32 invZ = 1.0f / (mFarZ - mNearZ); + + p[0] = 1.0f; + p[1] = invHor * 2.0f; + p[3] = invVert * 2.0f; + + p[2] = invHor * -(r + l); + p[4] = invVert * -(t + b); + p[5] = -1.0f * invZ; + p[6] = -mFarZ * invZ; +} + +void Frustum::GetOrthographicParam_(f32 *pT, f32 *pB, f32 *pL, f32 *pR) const { + f32 adjOffsetX = mOffset.x + sGlobalOffset.x; + f32 adjOffsetY = mOffset.y + sGlobalOffset.y; + + if (mCanvasMode == CANVASMODE_0) { + const math::VEC2 adjScale(mScale.x * sGlobalScale.x, mScale.y * sGlobalScale.y); + + *pT = adjScale.y * ((0.5f * mSize.y) + adjOffsetY); + *pB = adjScale.y * ((-0.5f * mSize.y) + adjOffsetY); + *pL = adjScale.x * ((-0.5f * mSize.x) + adjOffsetX); + *pR = adjScale.x * ((0.5f * mSize.x) + adjOffsetX); + } else if (mCanvasMode == CANVASMODE_1) { + f32 adjScaleX = -(sGlobalScale.x - 1.0f) * mSize.x / 2.0f; + f32 adjScaleY = -(sGlobalScale.y - 1.0f) * mSize.y / 2.0f; + + *pT = adjScaleY + -sGlobalScale.y * adjOffsetY; + *pB = adjScaleY + -sGlobalScale.y * (adjOffsetY + mSize.y * -1.0f * mScale.y); + *pL = adjScaleX + sGlobalScale.x * adjOffsetX; + *pR = adjScaleX + sGlobalScale.x * (adjOffsetX + mSize.x * mScale.x); + } +} + +math::VEC2 Frustum::sGlobalScale(1.0f, 1.0f); +math::VEC2 Frustum::sGlobalOffset(0.0f, 0.0f); + +} // namespace EGG diff --git a/src/egg/gfx/eggPostEffectBase.cpp b/src/egg/gfx/eggPostEffectBase.cpp index 9ecead4a..bf824907 100644 --- a/src/egg/gfx/eggPostEffectBase.cpp +++ b/src/egg/gfx/eggPostEffectBase.cpp @@ -153,7 +153,7 @@ void PostEffectBase::setProjection(const Screen &screen) { Screen screenCpy(screen); screenCpy.SetFlag(Screen::FLAG_0x40); - screenCpy.SetCanvasMode(Screen::CANVAS_1); + screenCpy.SetCanvasMode(Screen::CANVASMODE_1); screenCpy.SetProjectionType(Screen::PROJ_ORTHO); screenCpy.SetNearFar(0.0f, 1.0f); screenCpy.SetScale(sScale); diff --git a/src/egg/gfx/eggScreen.cpp b/src/egg/gfx/eggScreen.cpp index 66b80c4e..af26dc25 100644 --- a/src/egg/gfx/eggScreen.cpp +++ b/src/egg/gfx/eggScreen.cpp @@ -1,3 +1,343 @@ #include "egg/gfx/eggScreen.h" -namespace EGG {} // namespace EGG +#include "common.h" +#include "egg/gfx/eggDrawGX.h" +#include "egg/gfx/eggStateGX.h" +#include "rvl/SC/scapi.h" + + +// ported from OGWS, though this class has evolved a fair bit + +using namespace nw4r; + +namespace EGG { + +Screen::TVMode Screen::sTVMode; +Screen::TVModeInfo Screen::sTVModeInfo[TV_MODE_MAX] = { + { + 608, 456, + nw4r::math::VEC2(1.0526316f, 1.0f), + }, + { + 812, 456, + nw4r::math::VEC2(0.7881773, 1.0f), + }, + { + 640, 456, + nw4r::math::VEC2(1.0f, 1.0f), + } +}; + +Screen *Screen::spRoot = nullptr; + +Screen::ChangeTVModeFunc Screen::sChangeTVModeFunc = nullptr; +void *Screen::spChangeTVModeFuncInfo = nullptr; + +math::VEC2 Screen::sCanvasScale(1.0f, 1.0f); +math::VEC2 Screen::sCanvasOffset(0.0f, 0.0f); + +void Screen::Initialize(const u16 *maxX, const u16 *maxY, Screen *userRoot) { + + sTVModeInfo[TV_MODE_4_3].width = maxX[0]; + sTVModeInfo[TV_MODE_4_3].height = maxY[0]; + + sTVModeInfo[TV_MODE_4_3].ratios.x = (f32)StateGX::s_widthEfb / (f32)sTVModeInfo[TV_MODE_4_3].width; + sTVModeInfo[TV_MODE_4_3].ratios.y = (f32)StateGX::s_heightEfb / (f32)sTVModeInfo[TV_MODE_4_3].height; + + sTVModeInfo[TV_MODE_16_9].width = maxX[1]; + sTVModeInfo[TV_MODE_16_9].height = maxY[1]; + + sTVModeInfo[TV_MODE_16_9].ratios.x = (f32)StateGX::s_widthEfb / (f32)sTVModeInfo[TV_MODE_16_9].width; + sTVModeInfo[TV_MODE_16_9].ratios.y = (f32)StateGX::s_heightEfb / (f32)sTVModeInfo[TV_MODE_16_9].height; + + sTVModeInfo[TV_MODE_UNK_3].width = StateGX::s_widthEfb; + sTVModeInfo[TV_MODE_UNK_3].height = StateGX::s_heightEfb; + + sTVModeInfo[TV_MODE_UNK_3].ratios.x = 1.0f; + sTVModeInfo[TV_MODE_UNK_3].ratios.y = 1.0f; + + static Screen defaultRoot; + defaultRoot.SetProjectionType(PROJ_ORTHO); + defaultRoot.SetCanvasMode(CANVASMODE_1); + defaultRoot.SetNearZ(0.0f); + defaultRoot.SetFarZ(1.0f); + defaultRoot.SetSize(math::VEC2(sTVModeInfo[sTVMode].width, sTVModeInfo[sTVMode].height)); + + userRoot = (userRoot == nullptr) ? &defaultRoot : userRoot; + spRoot = userRoot; + userRoot->mParent = nullptr; + SetTVMode(sTVMode); +} + +Screen::Screen() + : Frustum( + PROJ_PERSP, math::VEC2(sTVModeInfo[sTVMode].width, sTVModeInfo[sTVMode].height), 10.0f, 100000.0f, + CANVASMODE_1 + ) { + mParent = nullptr; + mPosition.x = 0.0f; + mPosition.y = 0.0f; + field_0x44.x = 0.0f; + field_0x44.y = 0.0f; + field_0x48.x = 0.0f; + field_0x48.y = 0.0f; + SetParent(nullptr); +} + +Screen::Screen(f32 x, f32 y, f32 w, f32 h, const Screen *userRoot, CanvasMode canvasMode) + : Frustum(PROJ_PERSP, math::VEC2(w, h), 10.0f, 100000.0f, canvasMode) { + mParent = nullptr; + mPosition.x = x; + mPosition.y = y; + field_0x44.x = 0.0f; + field_0x44.y = 0.0f; + field_0x48.x = 0.0f; + field_0x48.y = 0.0f; + SetParent(userRoot); +} + +Screen::Screen(const Screen &other) + : Frustum(other), + mPosition(other.mPosition), + mDataEfb(other.mDataEfb), + field_0x44(other.field_0x44), + field_0x48(other.field_0x48) { + SetParent(other.mParent); +} + +void Screen::SetProjectionGX() const { + if (!(mFlags & 0x40)) { + f32 sx, sy, ox, oy; + GetGlobalScaleOffset(&sx, &sy, &ox, &oy); + + SetGlobalScaleOffset(sCanvasScale.x, sCanvasScale.y, sCanvasOffset.x, sCanvasOffset.y); + Frustum::SetProjectionGX(); + + SetGlobalScaleOffset(sx, sy, ox, oy); + } else { + Frustum::SetProjectionGX(); + } + + const DataEfb &efb = GetDataEfb(); + + StateGX::GXSetViewport_(efb.vp.x1, efb.vp.y1, efb.vp.x2, efb.vp.y2, efb.vp.z1, efb.vp.z2); + StateGX::GXSetScissor_(efb.sc_x, efb.sc_y, efb.sc_w, efb.sc_h); + StateGX::GXSetScissorBoxOffset_(efb.sc_ox, efb.sc_oy); +} + +void Screen::CopyToG3D(g3d::Camera cam) const { + if (!(mFlags & 0x40)) { + f32 sx, sy, ox, oy; + GetGlobalScaleOffset(&sx, &sy, &ox, &oy); + + SetGlobalScaleOffset(sCanvasScale.x, sCanvasScale.y, sCanvasOffset.x, sCanvasOffset.y); + Frustum::CopyToG3D(cam); + + SetGlobalScaleOffset(sx, sy, ox, oy); + } else { + Frustum::CopyToG3D(cam); + } + + const DataEfb &efb = GetDataEfb(); + + f32 x1, x2, y1, y2; + f32 z1, z2; + + y2 = efb.vp.y2; + x2 = efb.vp.x2; + + y1 = efb.vp.y1; + x1 = efb.vp.x1; + + z2 = efb.vp.z2; + z1 = efb.vp.z1; + + cam.SetViewport(x1, y1, x2, y2); + cam.SetViewportZRange(z1, z2); + cam.SetScissor(efb.sc_x, efb.sc_y, efb.sc_w, efb.sc_h); + cam.SetScissorBoxOffset(efb.sc_ox, efb.sc_oy); +} + +void Screen::CopyFromAnother(const Screen &other) { + Frustum::CopyFromAnother(other); + + mPosition = other.mPosition; + field_0x44 = other.field_0x44; + field_0x48 = other.field_0x48; + mDataEfb = other.mDataEfb; + mParent = other.mParent; +} + +void Screen::Reset(f32 x, f32 y, f32 w, f32 h, CanvasMode mode) { + mPosition.x = x; + mPosition.y = y; + mSize.x = w; + SetDirty(true); + mSize.y = h; + SetCanvasMode(mode); +} + +void Screen::SetParent(const Screen *parent) { + const Screen *newParent = parent != nullptr ? parent : spRoot; + + if (mParent != newParent) { + SetDirty(true); + mParent = newParent; + } +} + +void Screen::SetUnkFlag8() { + if ((mFlags & 0x8) == 0) { + SetDirty(true); + } + mFlags |= 0x8; +} + +void Screen::GetPosSizeInEfb() const { + // TODO + const TVMode tvMode = (!(mFlags & 0x20)) ? sTVMode : TV_MODE_4_3; + const TVModeInfo &tvRatio = sTVModeInfo[tvMode]; + + f32 *px = &mDataEfb.vp.x1; + f32 *py = &mDataEfb.vp.y1; + GetGlobalPos(px, py); + + *px = sCanvasScale.x * *px; + *py = sCanvasScale.y * *py; + + *px *= tvRatio.ratios.x; + *py *= tvRatio.ratios.y; + + mDataEfb.sc_oy = 0; + mDataEfb.sc_ox = 0; + + const f32 x = *px; + if (x < 0.0f) { + *px = 0.0f; + + const s32 lx = static_cast(-x); + mDataEfb.sc_ox = lx - (lx & 0x1); + } + + const f32 y = *py; + if (y < 0.0f) { + *py = 0.0f; + + const s32 ly = static_cast(-y); + mDataEfb.sc_oy = ly - (ly & 0x1); + } + + if (mFlags & 0x2) { + *px -= static_cast(*px) & 0x1; + *py -= static_cast(*py) & 0x1; + } + + *px = static_cast(*px); + *py = static_cast(*py); + + mDataEfb.vp.x2 = mSize.x; + mDataEfb.vp.y2 = mSize.y; + + if (!(mFlags & 0x8)) { + mDataEfb.vp.x2 = mSize.x * tvRatio.ratios.x; + mDataEfb.vp.y2 = mSize.y * tvRatio.ratios.y; + } + + if (mFlags & 0x4) { + mDataEfb.vp.x2 -= static_cast(mDataEfb.vp.x2) & 0x3; + mDataEfb.vp.y2 -= static_cast(mDataEfb.vp.y2) & 0x3; + } + + mDataEfb.vp.x2 = (mDataEfb.vp.x2 >= 0.0f) ? mDataEfb.vp.x2 : 0.0f; + mDataEfb.vp.y2 = (mDataEfb.vp.y2 >= 0.0f) ? mDataEfb.vp.y2 : 0.0f; + + mDataEfb.vp.x2 = static_cast(mDataEfb.vp.x2); + mDataEfb.vp.y2 = static_cast(mDataEfb.vp.y2); +} + +const Screen::DataEfb &Screen::GetDataEfb() const { + if (IsChangeEfb()) { + GetPosSizeInEfb(); + mDataEfb.vp.z1 = 0.0f; + mDataEfb.vp.z2 = 1.0f; + SetDirty(false); + } + + return mDataEfb; +} + +bool Screen::IsChangeEfb() const { + if (mFlags & FLAG_DIRTY) { + return true; + } + + if (mParent != nullptr) { + return mParent->IsChangeEfb(); + } + + return false; +} + +void Screen::CalcMatrixForDrawQuad(math::MTX34 *mtx, f32 x, f32 y, f32 sx, f32 sy) const { + PSMTXScale(*mtx, sx, sy, 1.0f); + + mtx->m[0][3] = x; + mtx->m[1][3] = mCanvasMode == CANVASMODE_0 ? y - sy : y; + mtx->m[2][3] = 0.0f; +} + +void Screen::FillBufferGX(u32 flags, GXColor color, u32 r6) const { + if (flags != 0) { + math::MTX34 drawMtx; + Screen clone(mPosition.x, mPosition.y, mSize.x, mSize.y, mParent, CANVASMODE_1); + + if ((mFlags & 0x8) != 0) { + clone.SetUnkFlag8(); + } + + clone.SetNearZ(0.0f); + clone.SetFarZ(1.0f); + clone.SetFlag(0x40); + clone.SetProjectionType(PROJ_ORTHO); + + clone.SetProjectionGX(); + clone.CalcMatrixForDrawQuad(&drawMtx, 0.0f, 0.0f, mSize.x, mSize.y); + // Ugh + DrawGX::ClearEfb(drawMtx, (flags & 1) != 0, (flags & 2) != 0, (flags & 4) != 0, color, true); + } +} + +void Screen::GetGlobalPos(f32 *ox, f32 *oy) const { + f32 px, py; + const Screen *parent = GetParent(); + + if (parent != nullptr) { + parent->GetGlobalPos(&px, &py); + parent->ConvertToCanvasLU(mPosition.x, mPosition.y, ox, oy); + + *ox += px; + *oy += py; + } else { + + *ox = mPosition.x; + *oy = mPosition.y; + } +} + +void Screen::SetTVMode(TVMode tvMode) { + sTVMode = tvMode; + if (spRoot != nullptr) { + spRoot->SetSizeX(GetSizeXMax()); + spRoot->SetSizeY(GetSizeYMax()); + } + + if (sChangeTVModeFunc != nullptr) { + sChangeTVModeFunc(spChangeTVModeFuncInfo); + } +} + +void Screen::SetTVModeDefault() { + SetTVMode(SCGetAspectRatio() == SC_ASPECT_STD ? TV_MODE_4_3 : TV_MODE_16_9); +} + +} // namespace EGG diff --git a/src/m/m2d.cpp b/src/m/m2d.cpp index 9f591a69..3f2ec24d 100644 --- a/src/m/m2d.cpp +++ b/src/m/m2d.cpp @@ -295,9 +295,9 @@ void Simple_c::draw() { f32 near = 0.0f; f32 far = 500.0f; EGG::Screen s; - bool needsAdjust = EGG::Screen::GetTVMode() == EGG::Screen::TV_MODE_2; - f32 f1 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_2); - f32 f2 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_1); + bool needsAdjust = EGG::Screen::GetTVMode() == EGG::Screen::TV_MODE_16_9; + f32 f1 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_16_9); + f32 f2 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_4_3); f32 left = needsAdjust ? f1 * r.left / f2 : r.left; f32 right = needsAdjust ? f1 * r.right / f2 : r.right;