From 24fba690ca93bf9d98d8bf350b271ebf7a46f280 Mon Sep 17 00:00:00 2001 From: Esras Date: Sun, 27 Jul 2025 17:55:47 -0700 Subject: [PATCH 01/12] Fix the header declaration of the Matrix44::setRow function. --- include/math/seadMatrix.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/math/seadMatrix.hpp b/include/math/seadMatrix.hpp index 858f1555..fd3dfa07 100644 --- a/include/math/seadMatrix.hpp +++ b/include/math/seadMatrix.hpp @@ -801,7 +801,7 @@ inline void Matrix44::setCol(s32 axis, const Vec4& v) template inline void Matrix44::setRow(s32 row, const Vec4& v) { - Matrix44CalcCommon::setRow(*this, row, v); + Matrix44CalcCommon::setRow(*this, v, row); } template From 84902870320db296b4ac38df56a9fb2c2be86632 Mon Sep 17 00:00:00 2001 From: Esras Date: Sun, 27 Jul 2025 18:36:30 -0700 Subject: [PATCH 02/12] Try 2 at the Projection libraries. Copying over from the prior PR (#129) and organizing. --- CMakeLists.txt | 6 + include/gfx/nin/seadGraphicsNvn.h | 2 +- include/gfx/seadGraphics.h | 249 +++++++++++- include/gfx/seadGraphicsContext.h | 272 +++++++++++++ include/gfx/seadProjection.h | 231 +++++++---- include/gfx/seadViewport.h | 24 +- modules/src/gfx/seadGraphics.cpp | 44 +++ modules/src/gfx/seadGraphicsContext.cpp | 193 ++++++++++ modules/src/gfx/seadProjection.cpp | 491 +++++++++++++++++++++++- modules/src/gfx/seadViewport.cpp | 181 +++++++++ 10 files changed, 1590 insertions(+), 103 deletions(-) create mode 100644 include/gfx/seadGraphicsContext.h create mode 100644 modules/src/gfx/seadGraphics.cpp create mode 100644 modules/src/gfx/seadGraphicsContext.cpp create mode 100644 modules/src/gfx/seadViewport.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a535892e..a2fb62d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,9 @@ add_library(sead OBJECT include/gfx/seadDrawContext.h include/gfx/seadDrawLockContext.h include/gfx/seadFrameBuffer.h + include/gfx/seadGraphics.h + include/gfx/seadGraphicsContext.h + include/gfx/seadViewport.h include/gfx/seadPrimitiveRenderer.h include/gfx/seadPrimitiveRendererUtil.h include/gfx/seadProjection.h @@ -112,6 +115,9 @@ add_library(sead OBJECT modules/src/gfx/seadColor.cpp modules/src/gfx/seadDrawLockContext.cpp modules/src/gfx/seadFrameBuffer.cpp + modules/src/gfx/seadGraphics.cpp + modules/src/gfx/seadGraphicsContext.cpp + modules/src/gfx/seadViewport.cpp # modules/src/gfx/seadPrimitiveRenderer.cpp # modules/src/gfx/seadPrimitiveRendererUtil.cpp modules/src/gfx/seadProjection.cpp diff --git a/include/gfx/nin/seadGraphicsNvn.h b/include/gfx/nin/seadGraphicsNvn.h index e8686564..2de26703 100644 --- a/include/gfx/nin/seadGraphicsNvn.h +++ b/include/gfx/nin/seadGraphicsNvn.h @@ -65,4 +65,4 @@ class GraphicsNvn : public Graphics }; static_assert(sizeof(GraphicsNvn) == 0x208); -} // namespace sead \ No newline at end of file +} // namespace sead diff --git a/include/gfx/seadGraphics.h b/include/gfx/seadGraphics.h index 1beb2c34..2e127c3c 100644 --- a/include/gfx/seadGraphics.h +++ b/include/gfx/seadGraphics.h @@ -2,15 +2,20 @@ #include #include +#include + +#ifdef cafe +#include +#endif // cafe namespace sead { -// no content yet, just for the enum -class Graphics : public IDisposer -{ - using UnknownCallback = void (*)(int); - static Graphics* sInstance; +class Color4f; +class Thread; + +class Graphics : public sead::IDisposer +{ public: enum DevicePosture { @@ -21,19 +26,239 @@ class Graphics : public IDisposer cDevicePosture_FlipX = 4, cDevicePosture_FlipY = 5, cDevicePosture_FlipXY = 3, - cDevicePosture_Invalid = 4, + cDevicePosture_Invalid = 4 }; - void lockDrawContext(); - void unlockDrawContext(); - void initHostIO(); - void initializeDrawLockContext(Heap*); + static const u32 cRenderTarget_Num = 8; + + static DevicePosture getDefaultDevicePosture() { return sDefaultDevicePosture; } + static f32 getDefaultDeviceZScale() { return sDefaultDeviceZScale; } + static f32 getDefaultDeviceZOffset() { return sDefaultDeviceZOffset; } + + // The value for each enumerator in the following enums has been confirmed to be + // platform-specific when comparing sead between several platforms (3DS, Wii U, Switch) + + enum DepthFunc + { +#ifdef cafe + cDepthFunc_Never = GX2_COMPARE_NEVER, + cDepthFunc_Less = GX2_COMPARE_LESS, + cDepthFunc_Equal = GX2_COMPARE_EQUAL, + cDepthFunc_LessEqual = GX2_COMPARE_LEQUAL, + cDepthFunc_Greater = GX2_COMPARE_GREATER, + cDepthFunc_NotEqual = GX2_COMPARE_NOTEQUAL, + cDepthFunc_GreaterEqual = GX2_COMPARE_GEQUAL, + cDepthFunc_Always = GX2_COMPARE_ALWAYS +#endif // cafe + }; + + enum CullingMode + { +#ifdef cafe + cCullingMode_Front = 0, + cCullingMode_Back = 1, + cCullingMode_None = 2, + cCullingMode_All = 3 +#endif // cafe + }; + + enum BlendFactor + { +#ifdef cafe + cBlendFactor_Zero = GX2_BLEND_ZERO, + cBlendFactor_One = GX2_BLEND_ONE, + cBlendFactor_SrcColor = GX2_BLEND_SRC_COLOR, + cBlendFactor_InvSrcColor = GX2_BLEND_ONE_MINUS_SRC_COLOR, + cBlendFactor_SrcAlpha = GX2_BLEND_SRC_ALPHA, + cBlendFactor_InvSrcAlpha = GX2_BLEND_ONE_MINUS_SRC_ALPHA, + cBlendFactor_DstAlpha = GX2_BLEND_DST_ALPHA, + cBlendFactor_InvDstAlpha = GX2_BLEND_ONE_MINUS_DST_ALPHA, + cBlendFactor_DstColor = GX2_BLEND_DST_COLOR, + cBlendFactor_InvDstColor = GX2_BLEND_ONE_MINUS_DST_COLOR, + cBlendFactor_SrcAlphaSaturate = GX2_BLEND_SRC_ALPHA_SATURATE, + cBlendFactor_ConstantColor = GX2_BLEND_CONSTANT_COLOR, + cBlendFactor_InvConstantColor = GX2_BLEND_ONE_MINUS_CONSTANT_COLOR, + cBlendFactor_ConstantAlpha = GX2_BLEND_CONSTANT_ALPHA, + cBlendFactor_InvConstantAlpha = GX2_BLEND_ONE_MINUS_CONSTANT_ALPHA +#endif // cafe + }; + + enum BlendEquation + { +#ifdef cafe + cBlendEquation_Add = GX2_BLEND_COMBINE_ADD, + cBlendEquation_Sub = GX2_BLEND_COMBINE_SRC_MINUS_DST, + cBlendEquation_Min = GX2_BLEND_COMBINE_MIN, + cBlendEquation_Max = GX2_BLEND_COMBINE_MAX, + cBlendEquation_ReverseSub = GX2_BLEND_COMBINE_DST_MINUS_SRC +#endif // cafe + }; + + enum AlphaFunc + { +#ifdef cafe + cAlphaFunc_Never = GX2_COMPARE_NEVER, + cAlphaFunc_Less = GX2_COMPARE_LESS, + cAlphaFunc_Equal = GX2_COMPARE_EQUAL, + cAlphaFunc_LessEqual = GX2_COMPARE_LEQUAL, + cAlphaFunc_Greater = GX2_COMPARE_GREATER, + cAlphaFunc_NotEqual = GX2_COMPARE_NOTEQUAL, + cAlphaFunc_GreaterEqual = GX2_COMPARE_GEQUAL, + cAlphaFunc_Always = GX2_COMPARE_ALWAYS +#endif // cafe + }; + + enum StencilFunc + { +#ifdef cafe + cStencilFunc_Never = GX2_COMPARE_NEVER, + cStencilFunc_Less = GX2_COMPARE_LESS, + cStencilFunc_Equal = GX2_COMPARE_EQUAL, + cStencilFunc_LessEqual = GX2_COMPARE_LEQUAL, + cStencilFunc_Greater = GX2_COMPARE_GREATER, + cStencilFunc_NotEqual = GX2_COMPARE_NOTEQUAL, + cStencilFunc_GreaterEqual = GX2_COMPARE_GEQUAL, + cStencilFunc_Always = GX2_COMPARE_ALWAYS +#endif // cafe + }; + + enum StencilOp + { +#ifdef cafe + cStencilOp_Keep = GX2_STENCIL_KEEP, + cStencilOp_Zero = GX2_STENCIL_ZERO, + cStencilOp_Replace = GX2_STENCIL_REPLACE, + cStencilOp_Increment = GX2_STENCIL_INCR, + cStencilOp_Decrement = GX2_STENCIL_DECR, + cStencilOp_Invert = GX2_STENCIL_INVERT, + cStencilOp_IncrementWrap = GX2_STENCIL_INCR_WRAP, + cStencilOp_DecrementWrap = GX2_STENCIL_DECR_WRAP +#endif // cafe + }; + + enum PolygonMode + { +#ifdef cafe + cPolygonMode_Point = GX2_POLYGON_MODE_POINT, + cPolygonMode_Line = GX2_POLYGON_MODE_LINE, + cPolygonMode_Fill = GX2_POLYGON_MODE_TRIANGLE +#endif // cafe + }; static Graphics* instance() { return sInstance; } + static void setInstance(Graphics* impl) { sInstance = impl; } + + Graphics(); + ~Graphics() override; private: - UnknownCallback _20; - DrawLockContext* mDrawLockContext; + Graphics(const Graphics&); + const Graphics& operator=(const Graphics&); + +protected: + virtual void initializeImpl(); + virtual void setViewportImpl(f32 x, f32 y, f32 w, f32 h); + virtual void setScissorImpl(f32 x, f32 y, f32 w, f32 h); + virtual void setDepthTestEnableImpl(bool enable); + virtual void setDepthWriteEnableImpl(bool enable); + virtual void setDepthFuncImpl(DepthFunc func); + virtual bool setVBlankWaitIntervalImpl(u32 interval); + virtual void setCullingModeImpl(CullingMode mode); + virtual void setBlendEnableImpl(bool enable); + virtual void setBlendEnableMRTImpl(u32 target, bool enable); + virtual void setBlendFactorImpl(BlendFactor src_factor_rgb, BlendFactor dst_factor_rgb, + BlendFactor src_factor_a, BlendFactor dst_factor_a); + virtual void setBlendFactorMRTImpl(u32 target, BlendFactor src_factor_rgb, + BlendFactor dst_factor_rgb, BlendFactor src_factor_a, + BlendFactor dst_factor_a); + virtual void setBlendEquationImpl(BlendEquation equation_rgb, BlendEquation equation_a); + virtual void setBlendEquationMRTImpl(u32 target, BlendEquation equation_rgb, + BlendEquation equation_a); + virtual void setBlendConstantColorImpl(const Color4f& color); + virtual void lockDrawContextImpl(); + virtual void unlockDrawContextImpl(); + virtual void waitForVBlankImpl(); + virtual void setColorMaskImpl(bool r, bool g, bool b, bool a); + virtual void setColorMaskMRTImpl(u32 target, bool r, bool g, bool b, bool a); + virtual void setAlphaTestEnableImpl(bool enable); + virtual void setAlphaTestFuncImpl(AlphaFunc func, f32 ref); + virtual void setStencilTestEnableImpl(bool enable); + virtual void setStencilTestFuncImpl(StencilFunc func, s32 ref, u32 mask); + virtual void setStencilTestOpImpl(StencilOp fail, StencilOp zfail, StencilOp zpass); + virtual void setPolygonModeImpl(PolygonMode front, PolygonMode back); + virtual void setPolygonOffsetEnableImpl(bool fill_front_enable, bool fill_back_enable, + bool point_line_enable); + +public: + void setViewportRealPosition(f32 x, f32 y, f32 w, f32 h) { setViewportImpl(x, y, w, h); } + + void setScissorRealPosition(f32 x, f32 y, f32 w, f32 h) { setScissorImpl(x, y, w, h); } + + void setDepthEnable(bool test_enable, bool write_enable) + { + setDepthTestEnableImpl(test_enable); + setDepthWriteEnableImpl(write_enable); + } + + void setBlendEnable(bool enable) { setBlendEnableImpl(enable); } + + void setBlendFactor(BlendFactor src_factor, BlendFactor dst_factor) + { + setBlendFactorImpl(src_factor, dst_factor, src_factor, dst_factor); + } + + void setBlendFactorSeparate(BlendFactor src_factor_rgb, BlendFactor dst_factor_rgb, + BlendFactor src_factor_a, BlendFactor dst_factor_a) + { + setBlendFactorImpl(src_factor_rgb, dst_factor_rgb, src_factor_a, dst_factor_a); + } + + void setBlendFactorMRT(u32 target, BlendFactor src_factor, BlendFactor dst_factor) + { + setBlendFactorMRTImpl(target, src_factor, dst_factor, src_factor, dst_factor); + } + + void setBlendFactorSeparateMRT(u32 target, BlendFactor src_factor_rgb, + BlendFactor dst_factor_rgb, BlendFactor src_factor_a, + BlendFactor dst_factor_a) + { + setBlendFactorMRTImpl(target, src_factor_rgb, dst_factor_rgb, src_factor_a, dst_factor_a); + } + + void setBlendEquation(BlendEquation equation) { setBlendEquationImpl(equation, equation); } + + void setBlendEquationSeparate(BlendEquation equation_rgb, BlendEquation equation_a) + { + setBlendEquationImpl(equation_rgb, equation_a); + } + + void setBlendEquationMRT(u32 target, BlendEquation equation) + { + setBlendEquationMRTImpl(target, equation, equation); + } + + void setBlendEquationSeparateMRT(u32 target, BlendEquation equation_rgb, + BlendEquation equation_a) + { + setBlendEquationMRTImpl(target, equation_rgb, equation_a); + } + + void lockDrawContext(); + void unlockDrawContext(); + +protected: + Thread* mContextHolderThread; + s32 mContextRefCounter; + CriticalSection mContextCriticalSection; + + static Graphics* sInstance; + + static DevicePosture sDefaultDevicePosture; + static f32 sDefaultDeviceZScale; + static f32 sDefaultDeviceZOffset; }; +#ifdef cafe +static_assert(sizeof(Graphics) == 0x54, "sead::Graphics size mismatch"); +#endif // cafe } // namespace sead diff --git a/include/gfx/seadGraphicsContext.h b/include/gfx/seadGraphicsContext.h new file mode 100644 index 00000000..705674a1 --- /dev/null +++ b/include/gfx/seadGraphicsContext.h @@ -0,0 +1,272 @@ +#pragma once + +#include +#include + +namespace sead +{ + +class GraphicsContext +{ +public: + GraphicsContext(); + virtual ~GraphicsContext() {} + + void apply() const; + void applyAlphaTest() const; + void applyDepthAndStencilTest() const; + void applyColorMask() const; + void applyBlendAndFastZ() const; + void applyBlendConstantColor() const; + void applyCullingAndPolygonModeAndPolygonOffset() const; + + void setDepthEnable(bool test_enable, bool write_enable) + { + setDepthTestEnable(test_enable); + setDepthWriteEnable(write_enable); + } + + void setDepthTestEnable(bool test_enable) { mDepthTestEnable = test_enable; } + + void setDepthWriteEnable(bool write_enable) { mDepthWriteEnable = write_enable; } + + void setDepthFunc(Graphics::DepthFunc func) { mDepthFunc = func; } + + void setCullingMode(Graphics::CullingMode mode) { mCullingMode = mode; } + + void setBlendEnable(bool blend) { mBlendEnable = blend; } + + void setBlendFactor(Graphics::BlendFactor src_factor, Graphics::BlendFactor dst_factor) + { + setBlendFactorSrc(src_factor); + setBlendFactorDst(dst_factor); + } + + void setBlendFactorSeparate(Graphics::BlendFactor src_factor_rgb, + Graphics::BlendFactor dst_factor_rgb, + Graphics::BlendFactor src_factor_a, + Graphics::BlendFactor dst_factor_a) + { + setBlendFactorSrcRGB(src_factor_rgb); + setBlendFactorDstRGB(dst_factor_rgb); + setBlendFactorSrcAlpha(src_factor_a); + setBlendFactorDstAlpha(dst_factor_a); + } + + void setBlendFactorSrc(Graphics::BlendFactor factor) + { + setBlendFactorSrcRGB(factor); + setBlendFactorSrcAlpha(factor); + } + + void setBlendFactorDst(Graphics::BlendFactor factor) + { + setBlendFactorDstRGB(factor); + setBlendFactorDstAlpha(factor); + } + + void setBlendFactorSrcRGB(Graphics::BlendFactor factor) { mBlendFactorSrcRGB = factor; } + + void setBlendFactorSrcAlpha(Graphics::BlendFactor factor) { mBlendFactorSrcA = factor; } + + void setBlendFactorDstRGB(Graphics::BlendFactor factor) { mBlendFactorDstRGB = factor; } + + void setBlendFactorDstAlpha(Graphics::BlendFactor factor) { mBlendFactorDstA = factor; } + + void setBlendEquation(Graphics::BlendEquation equation) + { + setBlendEquationRGB(equation); + setBlendEquationAlpha(equation); + } + + void setBlendEquationSeparate(Graphics::BlendEquation equation_rgb, + Graphics::BlendEquation equation_a) + { + setBlendEquationRGB(equation_rgb); + setBlendEquationAlpha(equation_a); + } + + void setBlendEquationRGB(Graphics::BlendEquation equation) { mBlendEquationRGB = equation; } + + void setBlendEquationAlpha(Graphics::BlendEquation equation) { mBlendEquationA = equation; } + + void setBlendConstantColor(const Color4f& color) { mBlendConstantColor = color; } + + void setAlphaTestEnable(bool enable) { mAlphaTestEnable = enable; } + + void setAlphaTestFunc(Graphics::AlphaFunc func, f32 ref) + { + mAlphaTestFunc = func; + mAlphaTestRef = ref; + } + + void setColorMask(bool r, bool g, bool b, bool a) + { + mColorMaskR = r; + mColorMaskG = g; + mColorMaskB = b; + mColorMaskA = a; + } + + void setStencilTestEnable(bool enable) { mStencilTestEnable = enable; } + + void setStencilTestFunc(Graphics::StencilFunc func, s32 ref, u32 mask) + { + mStencilTestFunc = func; + mStencilTestRef = ref; + mStencilTestMask = mask; + } + + void setStencilTestOp(Graphics::StencilOp fail, Graphics::StencilOp zfail, + Graphics::StencilOp zpass) + { + mStencilOpFail = fail; + mStencilOpZFail = zfail; + mStencilOpZPass = zpass; + } + + void setPolygonMode(Graphics::PolygonMode front, Graphics::PolygonMode back) + { +#ifdef cafe + mPolygonModeFront = front; + mPolygonModeBack = back; +#endif // cafe + } + + void setPolygonOffsetEnable(bool fill_front_enable, bool fill_back_enable, + bool point_line_enable) + { +#ifdef cafe + mPolygonOffsetFrontEnable = fill_front_enable; + mPolygonOffsetBackEnable = fill_back_enable; + mPolygonOffsetPointLineEnable = point_line_enable; +#endif // cafe + } + + bool getDepthTestEnable() const { return mDepthTestEnable; } + + bool getDepthWriteEnable() const { return mDepthWriteEnable; } + + Graphics::DepthFunc getDepthFunc() const { return mDepthFunc; } + + Graphics::CullingMode getCullingMode() const { return mCullingMode; } + + bool getBlendEnable() const { return mBlendEnable; } + + Graphics::BlendFactor getBlendFactorSrcRGB() const { return mBlendFactorSrcRGB; } + + Graphics::BlendFactor getBlendFactorSrcAlpha() const { return mBlendFactorSrcA; } + + Graphics::BlendFactor getBlendFactorDstRGB() const { return mBlendFactorDstRGB; } + + Graphics::BlendFactor getBlendFactorDstAlpha() const { return mBlendFactorDstA; } + + Graphics::BlendEquation getBlendEquationRGB() const { return mBlendEquationRGB; } + + Graphics::BlendEquation getBlendEquationAlpha() const { return mBlendEquationA; } + + const Color4f& getBlendConstantColor() const { return mBlendConstantColor; } + + bool getAlphaTestEnable() const { return mAlphaTestEnable; } + + Graphics::AlphaFunc getAlphaTestFunc() const { return mAlphaTestFunc; } + + f32 getAlphaTestRef() const { return mAlphaTestRef; } + + bool getColorMaskR() const { return mColorMaskR; } + + bool getColorMaskG() const { return mColorMaskG; } + + bool getColorMaskB() const { return mColorMaskB; } + + bool getColorMaskA() const { return mColorMaskA; } + + bool getStencilTestEnable() const { return mStencilTestEnable; } + + Graphics::StencilFunc getStencilTestFunc() const { return mStencilTestFunc; } + + s32 getStencilTestRef() const { return mStencilTestRef; } + + u32 getStencilTestMask() const { return mStencilTestMask; } + + Graphics::StencilOp getStencilTestOpFail() const { return mStencilOpFail; } + + Graphics::StencilOp getStencilTestOpZFail() const { return mStencilOpZFail; } + + Graphics::StencilOp getStencilTestOpZPass() const { return mStencilOpZPass; } + + Graphics::PolygonMode getPolygonModeFront() const + { +#ifdef cafe + return mPolygonModeFront; +#endif // cafe + } + + Graphics::PolygonMode getPolygonModeBack() const + { +#ifdef cafe + return mPolygonModeBack; +#endif // cafe + } + + bool getPolygonOffsetFrontEnable() const + { +#ifdef cafe + return mPolygonOffsetFrontEnable; +#endif // cafe + } + + bool getPolygonOffsetBackEnable() const + { +#ifdef cafe + return mPolygonOffsetBackEnable; +#endif // cafe + } + + bool getPolygonOffsetPointLineEnable() const + { +#ifdef cafe + return mPolygonOffsetPointLineEnable; +#endif // cafe + } + +private: + bool mDepthTestEnable; + bool mDepthWriteEnable; + Graphics::DepthFunc mDepthFunc; + Graphics::CullingMode mCullingMode; + bool mBlendEnable; + Graphics::BlendFactor mBlendFactorSrcRGB; + Graphics::BlendFactor mBlendFactorSrcA; + Graphics::BlendFactor mBlendFactorDstRGB; + Graphics::BlendFactor mBlendFactorDstA; + Graphics::BlendEquation mBlendEquationRGB; + Graphics::BlendEquation mBlendEquationA; + Color4f mBlendConstantColor; + bool mAlphaTestEnable; + Graphics::AlphaFunc mAlphaTestFunc; + f32 mAlphaTestRef; + bool mColorMaskR; + bool mColorMaskG; + bool mColorMaskB; + bool mColorMaskA; + bool mStencilTestEnable; + Graphics::StencilFunc mStencilTestFunc; + s32 mStencilTestRef; + u32 mStencilTestMask; + Graphics::StencilOp mStencilOpFail; + Graphics::StencilOp mStencilOpZFail; + Graphics::StencilOp mStencilOpZPass; +#ifdef cafe + Graphics::PolygonMode mPolygonModeFront; + Graphics::PolygonMode mPolygonModeBack; + bool mPolygonOffsetFrontEnable; + bool mPolygonOffsetBackEnable; + bool mPolygonOffsetPointLineEnable; +#endif // cafe +}; +#ifdef cafe +static_assert(sizeof(GraphicsContext) == 0x74, "sead::GraphicsContext size mismatch"); +#endif // cafe + +} // namespace sead diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 4f70db7d..60f0403b 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -1,5 +1,4 @@ -#ifndef SEAD_PROJECTION_H_ -#define SEAD_PROJECTION_H_ +#pragma once #include #include @@ -11,11 +10,24 @@ namespace sead { + +class Camera; +class Viewport; + +template +class Ray; + class Projection { SEAD_RTTI_BASE(Projection) public: + enum Type + { + cType_Perspective = 0, + cType_Ortho = 1, + cType_Undefined = 2 + }; Projection(); virtual ~Projection(); @@ -25,13 +37,23 @@ class Projection virtual f32 getAspect() const = 0; virtual void getOffset(Vector2f* offset) const = 0; virtual void updateAttributesForDirectProjection(); - virtual u32 getProjectionType() const = 0; + + virtual Type getProjectionType() const = 0; virtual void doUpdateMatrix(Matrix44f* mtx) const = 0; + virtual void doUpdateDeviceMatrix(Matrix44f*, const Matrix44f&, Graphics::DevicePosture) const; + const Matrix44f& getDeviceProjectionMatrix() const; + const Matrix44f& getProjectionMatrix() const; + Matrix44f& getProjectionMatrixMutable(); + virtual void doScreenPosToCameraPosTo(Vector3f*, const Vector3f&) const = 0; + void cameraPosToScreenPos(Vector3f* dst, const Vector3f& camera_pos) const; + void screenPosToCameraPos(Vector3f* dst, const Vector3f& screen_pos) const; + void screenPosToCameraPos(Vector3f* dst, const Vector2f& screen_pos) const; - void updateMatrixImpl_() const; - const Matrix44f& getDeviceProjectionMatrix() const; + void project(Vector2f* dst, const Vector3f& camera_pos, const Viewport& viewport) const; + void unproject(Vector3f* dst, const Vector3f& screen_pos, const Camera& camera) const; + void unprojectRay(Ray* dst, const Vector3f& screen_pos, const Camera& camera) const; void setDirty() { mDirty = true; } void setDeviceDirty() { mDeviceDirty = true; } @@ -43,6 +65,8 @@ class Projection } private: + void updateMatrixImpl_() const; + mutable bool mDirty; mutable bool mDeviceDirty; Matrix44f mMatrix; @@ -59,25 +83,9 @@ class PerspectiveProjection : public Projection public: PerspectiveProjection(); PerspectiveProjection(f32 near, f32 far, f32 fovy_rad, f32 aspect); - ~PerspectiveProjection() override; + ~PerspectiveProjection() override = default; - f32 getNear() const override; - f32 getFar() const override; - f32 getFovy() const override; - f32 getAspect() const override; - void getOffset(Vector2f* offset) const override; - void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; - u32 getProjectionType() const override; - - void set(f32 near, f32 far, f32 fovy_rad, f32 aspect); - void doUpdateMatrix(Matrix44f* mtx) const override; - void setFovx(f32); - void createDividedProjection(PerspectiveProjection* projection, s32, s32, s32, s32); - f32 getTop() const; - f32 getBottom() const; - f32 getLeft() const; - f32 getRight() const; - void setTBLR(f32 top, f32 bottom, f32 left, f32 right); + void set(f32 _near, f32 _far, f32 fovy_rad, f32 aspect); void setNear(f32 near) { @@ -89,6 +97,8 @@ class PerspectiveProjection : public Projection mFar = far; setDirty(); } + void setFovx(f32 fovx); + void setFovy(f32 fovy) { setFovy_(fovy); } void setAspect(f32 aspect) { mAspect = aspect; @@ -100,41 +110,82 @@ class PerspectiveProjection : public Projection setDirty(); } + void createDividedProjection(PerspectiveProjection* dst, s32 partno_x, s32 partno_y, + s32 divnum_x, s32 divnum_y) const; + + f32 getNear() const override { return mNear; } + f32 getFar() const override { return mFar; } + f32 getFovy() const override { return mAngle; } + f32 getAspect() const override { return mAspect; } + void getOffset(Vector2f* offset) const override { offset->set(mOffset); } + + f32 getTop() const; + f32 getBottom() const; + f32 getLeft() const; + f32 getRight() const; + + void setTBLR(f32 top, f32 bottom, f32 left, f32 right); + + Type getProjectionType() const override { return Projection::cType_Perspective; } + void doUpdateMatrix(Matrix44f* dst) const override; + void doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const override; + private: - f32 mNear; - f32 mFar; - f32 mFovyRad; + void setFovy_(f32 fovy); + + f32 calcNearClipHeight_() const { return mNear * 2 * mFovyTan; } + f32 calcNearClipWidth_() const { return calcNearClipHeight_() * mAspect; } + + f32 mNear = 1.0f; + f32 mFar = 10000.0f; + f32 mAngle = numbers::pi / 2.0f; f32 mFovySin; f32 mFovyCos; f32 mFovyTan; - f32 mAspect; - Vector2f mOffset; + f32 mAspect = 1.333333f; + Vector2f mOffset = Vector2f::zero; }; +#ifdef cafe +static_assert(sizeof(PerspectiveProjection) == 0xB8, "sead::PerspectiveProjection size mismatch"); +#endif // cafe class OrthoProjection : public Projection { - SEAD_RTTI_OVERRIDE(OrthoProjection, Projection); + SEAD_RTTI_OVERRIDE(OrthoProjection, Projection) public: OrthoProjection(); - OrthoProjection(f32 near, f32 far, f32 top, f32 bottom, f32 left, f32 right); - OrthoProjection(f32 near, f32 far, const BoundBox2f& boundBox); - OrthoProjection(f32 near, f32 far, const Viewport& viewport); - ~OrthoProjection() override; + OrthoProjection(f32 _near, f32 _far, f32 top, f32 bottom, f32 left, f32 right); + OrthoProjection(f32 _near, f32 _far, const BoundBox2f& box); + OrthoProjection(f32 _near, f32 _far, const Viewport& vp); + ~OrthoProjection() override = default; - f32 getNear() const override; - f32 getFar() const override; - f32 getFovy() const override; + void setNear(f32 near); + void setFar(f32 far); + void setTop(f32 top); + void setBottom(f32 bottom); + void setLeft(f32 left); + void setRight(f32 right); + void setTBLR(f32 top, f32 bottom, f32 left, f32 right); + void setByViewport(const Viewport& vp); + void setBoundBox(const BoundBox2f& box); + + void createDividedProjection(OrthoProjection* dst, s32 partno_x, s32 partno_y, s32 divnum_x, + s32 divnum_y) const; + + f32 getNear() const override { return mNear; } + f32 getFar() const override { return mFar; } + f32 getFovy() const override { return 0; } + f32 getTop() const { return mTop; } + f32 getBottom() const { return mBottom; } + f32 getLeft() const { return mLeft; } + f32 getRight() const { return mRight; } f32 getAspect() const override; void getOffset(Vector2f* offset) const override; - u32 getProjectionType() const override; - void doUpdateMatrix(Matrix44f* mtx) const override; - void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; - void createDividedProjection(OrthoProjection*, s32, s32, s32, s32) const; - void setBoundBox(const BoundBox2f& boundBox); - void setByViewport(const Viewport& viewport); - void setTBLR(f32 top, f32 bottom, f32 left, f32 right); + Type getProjectionType() const override { return Projection::cType_Ortho; } + void doUpdateMatrix(Matrix44f* dst) const override; + void doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const override; private: f32 mNear; @@ -143,32 +194,51 @@ class OrthoProjection : public Projection f32 mBottom; f32 mLeft; f32 mRight; + Vector2f mOffset; }; +#ifdef cafe +static_assert(sizeof(OrthoProjection) == 0xAC, "sead::OrthoProjection size mismatch"); +#endif // cafe class FrustumProjection : public Projection { SEAD_RTTI_OVERRIDE(FrustumProjection, Projection) public: - FrustumProjection(); - FrustumProjection(f32 near, f32 far, f32 top, f32 bottom, f32 left, f32 right); - FrustumProjection(f32 near, f32 far, const BoundBox2f& boundBox); - ~FrustumProjection() override; + FrustumProjection() = default; + FrustumProjection(f32 _near, f32 _far, f32 top, f32 bottom, f32 left, f32 right); + FrustumProjection(f32 _near, f32 _far, const BoundBox2f& box); + ~FrustumProjection() override = default; + + Type getProjectionType() const override { return Projection::cType_Perspective; } + void doUpdateMatrix(Matrix44f* dst) const override; + void doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const override; + + void setNear(f32 near); + void setFar(f32 far); + void setTop(f32 top); + void setBottom(f32 bottom); + void setLeft(f32 left); + void setRight(f32 right); + + void setTBLR(f32 top, f32 bottom, f32 left, f32 right); + + void setBoundBox(const BoundBox2f& box); + + void createDividedProjection(FrustumProjection* dst, s32 partno_x, s32 partno_y, s32 divnum_x, + s32 divnum_y) const; + + f32 getNear() const override { return mNear; } + f32 getFar() const override { return mFar; } + f32 getTop() const { return mTop; } + f32 getBottom() const { return mBottom; } + f32 getLeft() const { return mLeft; } + f32 getRight() const { return mRight; } - f32 getNear() const override; - f32 getFar() const override; f32 getFovy() const override; f32 getAspect() const override; - void getOffset(Vector2f* offset) const override; - f32 getOffsetX() const; - f32 getOffsetY() const; - u32 getProjectionType() const override; + void getOffset(Vector2f* dst) const override; - void doUpdateMatrix(Matrix44f* mtx) const override; - void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; - void setTBLR(f32 top, f32 bottom, f32 left, f32 right); - void setBoundBox(BoundBox2f& boundBox); - void createDividedProjection(FrustumProjection* out, s32, s32, s32, s32) const; void setFovyAspectOffset(f32 fovy, f32 aspect, const Vector2f& offset); private: @@ -186,30 +256,35 @@ class DirectProjection : public Projection public: DirectProjection(); - DirectProjection(const Matrix44f& mtx, Graphics::DevicePosture posture); - ~DirectProjection() override; + DirectProjection(const Matrix44f* mtx, Graphics::DevicePosture posture); + ~DirectProjection() override = default; - void setProjectionMatrix(const Matrix44f& mtx, Graphics::DevicePosture posture); - f32 getNear() const override; - f32 getFar() const override; - f32 getFovy() const override; - f32 getAspect() const override; - void getOffset(Vector2f* offset) const override; void updateAttributesForDirectProjection() override; - void doUpdateMatrix(Matrix44f* mtx) const override; - void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; - u32 getProjectionType() const override; + Type getProjectionType() const override { return cType_Undefined; } + void doUpdateMatrix(Matrix44f* dst) const override; + + void setDirectProjectionMatrix(const Matrix44f* mtx, Graphics::DevicePosture posture); + + f32 getNear() const override { return mNear; } + f32 getFar() const override { return mFar; } + f32 getFovy() const override { return mFovy; } + + f32 getAspect() const override { return mAspect; } + void getOffset(Vector2f* offset) const override { *offset = mOffset; } + + void doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const override; private: - Matrix44f mProjectionMatrix; - f32 mNear; - f32 mFar; - f32 mFovy; - f32 mAspect; - Vector2f mOffset; - bool _f0; + Matrix44f mDirectMatrix = Matrix44f::ident; + f32 mNear = 0.0; + f32 mFar = 0.0; + f32 mFovy = 0.0; + f32 mAspect = 0.0; + Vector2f mOffset = Vector2f::zero; + bool someBool = true; }; +#ifdef cafe +static_assert(sizeof(FrustumProjection) == 0xAC, "sead::FrustumProjection size mismatch"); +#endif // cafe } // namespace sead - -#endif // SEAD_PROJECTION_H_ diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index 566aaf7c..10de3d9f 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -1,20 +1,20 @@ #pragma once +#include #include -#include -#include +#include namespace sead { +class Camera; +class Projection; + template class Ray; -class DrawContext; -class LogicalFrameBuffer; -class Projection; -class Camera; class Viewport : public BoundBox2f { + SEAD_RTTI_BASE(Viewport) public: Viewport(); Viewport(float left, float top, float right, float bottom); @@ -23,17 +23,25 @@ class Viewport : public BoundBox2f virtual ~Viewport() = default; void setByFrameBuffer(const LogicalFrameBuffer& buffer); - void apply(DrawContext*, const LogicalFrameBuffer& buffer) const; + void getOnFrameBufferPos(Vector2f* out, const LogicalFrameBuffer& buffer) const; void getOnFrameBufferSize(Vector2f* out, const LogicalFrameBuffer& buffer) const; + + void apply(DrawContext*, const LogicalFrameBuffer& buffer) const; void applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const; void applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const; + void project(Vector2f*, const Vector3f&) const; void project(Vector2f*, const Vector2f&) const; void unproject(Vector3f*, const Vector2f&, const Projection&, const Camera&) const; void unproject(Ray*, const Vector2f&, const Projection&, const Camera&) const; private: - Graphics::DevicePosture mDevicePosture; + Graphics::DevicePosture mDevicePosture = Graphics::getDefaultDevicePosture(); + Vector2f mDepthBounds = Vector2f(0.0f, 1.0f); }; +#ifdef cafe +static_assert(sizeof(Viewport) == 0x18, "sead::Viewport size mismatch"); +#endif // cafe + } // namespace sead diff --git a/modules/src/gfx/seadGraphics.cpp b/modules/src/gfx/seadGraphics.cpp new file mode 100644 index 00000000..f49405f6 --- /dev/null +++ b/modules/src/gfx/seadGraphics.cpp @@ -0,0 +1,44 @@ +#include +#include + +namespace sead +{ + +Graphics* Graphics::sInstance = nullptr; + +Graphics::DevicePosture Graphics::sDefaultDevicePosture = Graphics::cDevicePosture_Same; +f32 Graphics::sDefaultDeviceZScale = 1.0f; +f32 Graphics::sDefaultDeviceZOffset = 0.0f; + +void Graphics::lockDrawContext() +{ + sead::Thread* current = ThreadMgr::instance()->getCurrentThread(); + if (current == mContextHolderThread && mContextRefCounter > 0) + { + mContextRefCounter++; + } + else + { + mContextCriticalSection.lock(); + // SEAD_ASSERT(mContextHolderThread == nullptr); + // SEAD_ASSERT(mContextRefCounter == 0); + lockDrawContextImpl(); + mContextHolderThread = current; + mContextRefCounter = 1; + } +} + +void Graphics::unlockDrawContext() +{ + sead::Thread* current = ThreadMgr::instance()->getCurrentThread(); + // SEAD_ASSERT(mContextHolderThread == current); + // SEAD_ASSERT(mContextRefCounter > 0); + if (--mContextRefCounter == 0) + { + mContextHolderThread = nullptr; + unlockDrawContextImpl(); + mContextCriticalSection.unlock(); + } +} + +} // namespace sead diff --git a/modules/src/gfx/seadGraphicsContext.cpp b/modules/src/gfx/seadGraphicsContext.cpp new file mode 100644 index 00000000..745a15fb --- /dev/null +++ b/modules/src/gfx/seadGraphicsContext.cpp @@ -0,0 +1,193 @@ +#include + +namespace sead +{ + +GraphicsContext::GraphicsContext() +#ifdef cafe + + : + + mDepthTestEnable(true), mDepthWriteEnable(true), mDepthFunc(Graphics::cDepthFunc_LessEqual), + mCullingMode(Graphics::cCullingMode_Back) + + , + mBlendEnable(true), mBlendFactorSrcRGB(Graphics::cBlendFactor_SrcAlpha), + mBlendFactorSrcA(Graphics::cBlendFactor_SrcAlpha), + mBlendFactorDstRGB(Graphics::cBlendFactor_InvSrcAlpha), + mBlendFactorDstA(Graphics::cBlendFactor_InvSrcAlpha), + mBlendEquationRGB(Graphics::cBlendEquation_Add), + mBlendEquationA(Graphics::cBlendEquation_Add), mBlendConstantColor(1.0f, 1.0f, 1.0f, 1.0f) + + , + mAlphaTestEnable(false), mAlphaTestFunc(Graphics::cAlphaFunc_Greater), mAlphaTestRef(0.0f) + + , + mColorMaskR(true), mColorMaskG(true), mColorMaskB(true), mColorMaskA(true) + + , + mStencilTestEnable(false), mStencilTestFunc(Graphics::cStencilFunc_Never), mStencilTestRef(0), + mStencilTestMask(0xFFFFFFFF), mStencilOpFail(Graphics::cStencilOp_Keep), + mStencilOpZFail(Graphics::cStencilOp_Keep), mStencilOpZPass(Graphics::cStencilOp_Keep) + + , + mPolygonModeFront(Graphics::cPolygonMode_Fill), mPolygonModeBack(Graphics::cPolygonMode_Fill), + mPolygonOffsetFrontEnable(false), mPolygonOffsetBackEnable(false), + mPolygonOffsetPointLineEnable(false) +#endif // cafe +{ +} + +void GraphicsContext::apply() const +{ +#ifdef cafe + GX2SetDepthStencilControl( + static_cast(mDepthTestEnable), static_cast(mDepthWriteEnable), + static_cast(mDepthFunc), static_cast(mStencilTestEnable), + static_cast(mStencilTestEnable), + static_cast(mStencilTestFunc), + static_cast(mStencilOpZPass), + static_cast(mStencilOpZFail), + static_cast(mStencilOpFail), + static_cast(mStencilTestFunc), + static_cast(mStencilOpZPass), + static_cast(mStencilOpZFail), + static_cast(mStencilOpFail)); + + GX2SetStencilMask(mStencilTestMask, mStencilTestRef, + mStencilTestRef, // Bug: ref in place of write mask + mStencilTestMask, mStencilTestRef, mStencilTestRef); // ^^^ + + { + static const GX2Boolean cCullSettings[4][2] = {{GX2_ENABLE, GX2_DISABLE}, + {GX2_DISABLE, GX2_ENABLE}, + {GX2_DISABLE, GX2_DISABLE}, + {GX2_ENABLE, GX2_ENABLE}}; + const GX2Boolean* const& settings = cCullSettings[mCullingMode]; + + GX2SetPolygonControl( + GX2_FRONT_FACE_CCW, settings[0], settings[1], + static_cast(mPolygonModeFront != Graphics::cPolygonMode_Fill || + mPolygonModeBack != Graphics::cPolygonMode_Fill), + static_cast(mPolygonModeFront), + static_cast(mPolygonModeBack), + static_cast(mPolygonOffsetFrontEnable), + static_cast(mPolygonOffsetBackEnable), + static_cast(mPolygonOffsetPointLineEnable)); + } + + GX2SetColorControl( + GX2_LOGIC_OP_NONE, mBlendEnable ? 0xFF : 0, GX2_DISABLE, + static_cast(mColorMaskR || mColorMaskG || mColorMaskB || mColorMaskA)); + + GX2SetBlendControl(GX2_RENDER_TARGET_0, static_cast(mBlendFactorSrcRGB), + static_cast(mBlendFactorDstRGB), + static_cast(mBlendEquationRGB), GX2_ENABLE, + static_cast(mBlendFactorSrcA), + static_cast(mBlendFactorDstA), + static_cast(mBlendEquationA)); + + GX2SetBlendConstantColor(mBlendConstantColor.r, mBlendConstantColor.g, mBlendConstantColor.b, + mBlendConstantColor.a); + + GX2SetAlphaTest(static_cast(mAlphaTestEnable), + static_cast(mAlphaTestFunc), mAlphaTestRef); + + GX2SetTargetChannelMasks( + static_cast( + mColorMaskR * GX2_CHANNEL_MASK_R + mColorMaskG * GX2_CHANNEL_MASK_G + + mColorMaskB * GX2_CHANNEL_MASK_B + mColorMaskA * GX2_CHANNEL_MASK_A), + GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, + GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE); + + GX2SetAlphaToMask(GX2_DISABLE, GX2_ALPHA_TO_MASK_0); +#endif // cafe +} + +void GraphicsContext::applyAlphaTest() const +{ +#ifdef cafe + GX2SetAlphaTest(static_cast(mAlphaTestEnable), + static_cast(mAlphaTestFunc), mAlphaTestRef); +#endif // cafe +} + +void GraphicsContext::applyDepthAndStencilTest() const +{ +#ifdef cafe + GX2SetDepthStencilControl( + static_cast(mDepthTestEnable), static_cast(mDepthWriteEnable), + static_cast(mDepthFunc), static_cast(mStencilTestEnable), + static_cast(mStencilTestEnable), + static_cast(mStencilTestFunc), + static_cast(mStencilOpZPass), + static_cast(mStencilOpZFail), + static_cast(mStencilOpFail), + static_cast(mStencilTestFunc), + static_cast(mStencilOpZPass), + static_cast(mStencilOpZFail), + static_cast(mStencilOpFail)); + + GX2SetStencilMask(mStencilTestMask, mStencilTestRef, + mStencilTestRef, // Bug: ref in place of write mask + mStencilTestMask, mStencilTestRef, mStencilTestRef); // ^^^ +#endif // cafe +} + +void GraphicsContext::applyColorMask() const +{ +#ifdef cafe + GX2SetTargetChannelMasks( + static_cast( + mColorMaskR * GX2_CHANNEL_MASK_R + mColorMaskG * GX2_CHANNEL_MASK_G + + mColorMaskB * GX2_CHANNEL_MASK_B + mColorMaskA * GX2_CHANNEL_MASK_A), + GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, + GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE, GX2_CHANNEL_MASK_NONE); +#endif // cafe +} + +void GraphicsContext::applyBlendAndFastZ() const +{ +#ifdef cafe + GX2SetColorControl( + GX2_LOGIC_OP_NONE, mBlendEnable ? 0xFF : 0, GX2_DISABLE, + static_cast(mColorMaskR || mColorMaskG || mColorMaskB || mColorMaskA)); + + GX2SetBlendControl(GX2_RENDER_TARGET_0, static_cast(mBlendFactorSrcRGB), + static_cast(mBlendFactorDstRGB), + static_cast(mBlendEquationRGB), GX2_ENABLE, + static_cast(mBlendFactorSrcA), + static_cast(mBlendFactorDstA), + static_cast(mBlendEquationA)); +#endif // cafe +} + +void GraphicsContext::applyBlendConstantColor() const +{ +#ifdef cafe + GX2SetBlendConstantColor(mBlendConstantColor.r, mBlendConstantColor.g, mBlendConstantColor.b, + mBlendConstantColor.a); +#endif // cafe +} + +void GraphicsContext::applyCullingAndPolygonModeAndPolygonOffset() const +{ +#ifdef cafe + static const GX2Boolean cCullSettings[4][2] = {{GX2_ENABLE, GX2_DISABLE}, + {GX2_DISABLE, GX2_ENABLE}, + {GX2_DISABLE, GX2_DISABLE}, + {GX2_ENABLE, GX2_ENABLE}}; + const GX2Boolean* const& settings = cCullSettings[mCullingMode]; + + GX2SetPolygonControl(GX2_FRONT_FACE_CCW, settings[0], settings[1], + static_cast(mPolygonModeFront != Graphics::cPolygonMode_Fill || + mPolygonModeBack != Graphics::cPolygonMode_Fill), + static_cast(mPolygonModeFront), + static_cast(mPolygonModeBack), + static_cast(mPolygonOffsetFrontEnable), + static_cast(mPolygonOffsetBackEnable), + static_cast(mPolygonOffsetPointLineEnable)); +#endif // cafe +} + +} // namespace sead diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 4179f1e9..1d7038e0 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -1,30 +1,513 @@ +#include #include +#include namespace sead { +Projection::Projection() + : mDirty(true), mDeviceDirty(true), mDevicePosture(Graphics::getDefaultDevicePosture()), + mDeviceZScale(Graphics::getDefaultDeviceZScale()), + mDeviceZOffset(Graphics::getDefaultDeviceZOffset()) +{ +} + void Projection::updateMatrixImpl_() const { if (mDirty) { doUpdateMatrix(const_cast(&mMatrix)); mDirty = false; - mDeviceDirty = true; - doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); - mDeviceDirty = false; } - else if (mDeviceDirty) + if (mDeviceDirty) { doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); mDeviceDirty = false; } } +const Matrix44f& Projection::getProjectionMatrix() const +{ + updateMatrixImpl_(); + return mMatrix; +} + const Matrix44f& Projection::getDeviceProjectionMatrix() const { updateMatrixImpl_(); return mDeviceMatrix; } +void Projection::project(Vector2f* dst, const Vector3f& camera_pos, const Viewport& viewport) const +{ + Vector3f temp; + doScreenPosToCameraPosTo(&temp, camera_pos); + viewport.project(dst, temp); +} + +void Projection::unproject(Vector3f* dst, const Vector3f& screen_pos, const Camera& camera) const +{ + doScreenPosToCameraPosTo(dst, screen_pos); + camera.cameraPosToWorldPosByMatrix(dst, screen_pos); +} + +void Projection::unprojectRay(Ray* dst, const Vector3f& screen_pos, + const Camera& camera) const +{ + // doScreenPosToCameraPosTo(dst, screen_pos); + // camera.cameraPosToWorldPosByMatrix(dst, screen_pos); +} + +void Projection::updateAttributesForDirectProjection() {} + +void Projection::doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const +{ + updateMatrixImpl_(); + + f32 scale = 1.0f / (mMatrix(3, 3) + screen_pos.x * mMatrix(3, 0) + + screen_pos.y * mMatrix(3, 1) + screen_pos.z * mMatrix(3, 2)); + dst->x = scale * (mMatrix(3, 3) + screen_pos.x * mMatrix(0, 0) + screen_pos.y * mMatrix(1, 0) + + screen_pos.z * mMatrix(2, 0)); + dst->y = scale * (mMatrix(1, 3) + screen_pos.x * mMatrix(1, 0) + screen_pos.y * mMatrix(1, 1) + + screen_pos.z * mMatrix(1, 2)); + dst->z = scale * (mMatrix(2, 3) + screen_pos.x * mMatrix(2, 0) + screen_pos.y * mMatrix(2, 1) + + screen_pos.z * mMatrix(2, 2)); +} + +namespace +{ + +void swapMatrixXY(Matrix44f* tgt) +{ + Vector4f x; + Vector4f y; + tgt->getRow(x, 0); + tgt->getRow(y, 1); + tgt->setRow(0, y); + tgt->setRow(1, x); +} + +} // namespace + +void Projection::doUpdateDeviceMatrix(Matrix44f* dst, const Matrix44f& src, + Graphics::DevicePosture pose) const +{ + *dst = src; + + switch (pose) + { + case Graphics::cDevicePosture_Same: + break; + case Graphics::cDevicePosture_RotateRight: + (*dst)(0, 0) *= -1; + (*dst)(0, 1) *= -1; + (*dst)(0, 2) *= -1; + (*dst)(0, 3) *= -1; + swapMatrixXY(dst); + break; + case Graphics::cDevicePosture_RotateLeft: + (*dst)(1, 0) *= -1; + (*dst)(1, 1) *= -1; + (*dst)(1, 2) *= -1; + (*dst)(1, 3) *= -1; + swapMatrixXY(dst); + break; + case Graphics::cDevicePosture_RotateHalfAround: + (*dst)(0, 0) *= -1; + (*dst)(0, 1) *= -1; + (*dst)(0, 2) *= -1; + (*dst)(0, 3) *= -1; + (*dst)(1, 0) *= -1; + (*dst)(1, 1) *= -1; + (*dst)(1, 2) *= -1; + (*dst)(1, 3) *= -1; + break; + case Graphics::cDevicePosture_FlipX: + (*dst)(0, 0) *= -1; + (*dst)(0, 1) *= -1; + (*dst)(0, 2) *= -1; + (*dst)(0, 3) *= -1; + break; + case Graphics::cDevicePosture_FlipY: + (*dst)(1, 0) *= -1; + (*dst)(1, 1) *= -1; + (*dst)(1, 2) *= -1; + (*dst)(1, 3) *= -1; + break; + default:; + // SEAD_ASSERTMSG(false, "Invalid DevicePosture(%d).", s32(pose)); + } + + (*dst)(2, 0) = (*dst)(2, 0) * mDeviceZScale; + (*dst)(2, 1) = (*dst)(2, 1) * mDeviceZScale; + + (*dst)(2, 2) = ((*dst)(2, 2) + (*dst)(3, 2) * mDeviceZOffset) * mDeviceZScale; + (*dst)(2, 3) = (*dst)(2, 3) * mDeviceZScale + (*dst)(3, 3) * mDeviceZOffset; +} + +PerspectiveProjection::PerspectiveProjection() +{ + setFovy_(mAngle); // 45 degrees +} + +PerspectiveProjection::PerspectiveProjection(f32 near, f32 far, f32 fovy_rad, f32 aspect) + : mNear(near), mFar(far), mAspect(aspect), mOffset(Vector2f::zero) +{ + setFovy_(fovy_rad); + setDirty(); +} + +void PerspectiveProjection::set(f32 _near, f32 _far, f32 fovy_rad, f32 aspect) +{ + setNear(_near); + setFar(_far); + setFovy_(fovy_rad); + setAspect(aspect); +} + +void PerspectiveProjection::setFovy_(f32 fovy) +{ + mAngle = fovy; + + fovy *= 0.5f; + mFovySin = Mathf::sin(fovy); + mFovyCos = Mathf::cos(fovy); + mFovyTan = Mathf::tan(fovy); + + setDirty(); +} + +f32 PerspectiveProjection::getTop() const +{ + f32 clip_height = calcNearClipHeight_(); + f32 center_y = mOffset.y * clip_height; + return clip_height * 0.5f + center_y; +} + +f32 PerspectiveProjection::getBottom() const +{ + f32 clip_height = calcNearClipHeight_(); + f32 center_y = mOffset.y * clip_height; + return -clip_height * 0.5f + center_y; +} + +f32 PerspectiveProjection::getLeft() const +{ + f32 clip_width = calcNearClipWidth_(); + f32 center_x = mOffset.x * clip_width; + return -clip_width * 0.5f + center_x; +} + +f32 PerspectiveProjection::getRight() const +{ + f32 clip_width = calcNearClipWidth_(); + f32 center_x = mOffset.x * clip_width; + return clip_width * 0.5f + center_x; +} + +void PerspectiveProjection::doUpdateMatrix(Matrix44f* dst) const +{ + f32 clip_height = calcNearClipHeight_(); + f32 clip_width = calcNearClipWidth_(); + + f32 center_x = clip_width * mOffset.x; + f32 center_y = clip_height * mOffset.y; + + clip_height *= 0.5f; + clip_width *= 0.5f; + + f32 top = clip_height + center_y; + f32 bottom = -clip_height + center_y; + + f32 left = -clip_width + center_x; + f32 right = clip_width + center_x; + + f32 inv_size = 1.0f / (right - left); + + (*dst)(0, 0) = mNear * 2 * inv_size; + (*dst)(0, 1) = 0.0f; + (*dst)(0, 2) = (right + left) * inv_size; + (*dst)(0, 3) = 0.0f; + + inv_size = 1.0f / (top - bottom); + + (*dst)(1, 0) = 0.0f; + (*dst)(1, 1) = mNear * 2 * inv_size; + (*dst)(1, 2) = (top + bottom) * inv_size; + (*dst)(1, 3) = 0.0f; + + inv_size = 1.0f / (mFar - mNear); + + (*dst)(2, 0) = 0.0f; + (*dst)(2, 1) = 0.0f; + (*dst)(2, 2) = -(mFar + mNear) * inv_size; + (*dst)(2, 3) = -(mFar * 2 * mNear) * inv_size; + + (*dst)(3, 0) = 0.0f; + (*dst)(3, 1) = 0.0f; + (*dst)(3, 2) = -1.0f; + (*dst)(3, 3) = 0.0f; +} + +void PerspectiveProjection::doScreenPosToCameraPosTo(Vector3f* dst, + const Vector3f& screen_pos) const +{ + dst->set(0.0f, 0.0f, -mNear); + + dst->y = (calcNearClipHeight_() / 2) * (screen_pos.y + mOffset.y * 2); + dst->x = (calcNearClipWidth_() / 2) * (screen_pos.x + mOffset.x * 2); +} + +OrthoProjection::OrthoProjection() + : mNear(0.0), mFar(1.0), mTop(0.5), mBottom(-0.5), mLeft(-0.5), mRight(0.5) +{ +} + +OrthoProjection::OrthoProjection(f32 _near, f32 _far, f32 top, f32 bottom, f32 left, f32 right) + : mNear(_near), mFar(_far), mTop(top), mBottom(bottom), mLeft(left), mRight(right) +{ + setDirty(); +} + +OrthoProjection::OrthoProjection(f32 _near, f32 _far, const Viewport& vp) : mNear(_near), mFar(_far) +{ + setByViewport(vp); + setDirty(); +} + +f32 OrthoProjection::getAspect() const +{ + return (mRight - mLeft) / (mTop - mBottom); +} + +void OrthoProjection::getOffset(Vector2f* offset) const +{ + offset->x = ((float)0.5 * (this->mLeft + this->mRight)) / (this->mRight - this->mLeft); + offset->y = ((float)0.5 * (this->mTop + this->mBottom)) / (this->mTop - this->mBottom); +} + +void OrthoProjection::setNear(f32 near) +{ + mNear = near; + setDirty(); +} + +void OrthoProjection::setFar(f32 far) +{ + mFar = far; + setDirty(); +} + +void OrthoProjection::setTop(f32 top) +{ + mTop = top; + setDirty(); +} + +void OrthoProjection::setBottom(f32 bottom) +{ + mBottom = bottom; + setDirty(); +} + +void OrthoProjection::setLeft(f32 left) +{ + mLeft = left; + setDirty(); +} + +void OrthoProjection::setRight(f32 right) +{ + mRight = right; + setDirty(); +} + +void OrthoProjection::setTBLR(float top, float bottom, float left, float right) +{ + mTop = top; + mBottom = bottom; + mLeft = left; + mRight = right; + setDirty(); + // this->projectionType = ProjectionType::cOrthoProjection; +} + +void OrthoProjection::doUpdateMatrix(Matrix44f* dst) const +{ + f32 inv_size = (mRight - mLeft) * 0.5f; + + (*dst)(0, 0) = 1.0f / inv_size; + (*dst)(0, 1) = 0.0f; + (*dst)(0, 2) = 0.0f; + (*dst)(0, 3) = -0.5f * (mLeft + mRight) / inv_size; + + inv_size = 0.5f * (mTop - mBottom); + + (*dst)(1, 0) = 0; + (*dst)(1, 1) = 1.0f / inv_size; + (*dst)(1, 2) = 0; + (*dst)(1, 3) = -0.5f * (mTop + mBottom) / inv_size; + + inv_size = 0.5f * (mFar - mNear); + + (*dst)(2, 0) = 0; + (*dst)(2, 1) = 0; + (*dst)(2, 2) = -1.0f / inv_size; + (*dst)(2, 3) = -0.5f * (mNear * mFar) / inv_size; + + (*dst)(3, 0) = 0; + (*dst)(3, 1) = 0; + (*dst)(3, 2) = 0; + (*dst)(3, 3) = -1.0f; +} + +// NON-MATCHING: Adds an additional register for a multiplication +void OrthoProjection::setByViewport(const Viewport& vp) +{ + f32 halfY = vp.getHalfSizeY(); + f32 halfX = vp.getHalfSizeX(); + mTop = halfY; + mBottom = -halfY; + mLeft = -halfX; + mRight = halfX; + setDirty(); +} + +FrustumProjection::FrustumProjection(f32 _near, f32 _far, f32 top, f32 bottom, f32 left, f32 right) + : mNear(_near), mFar(_far), mTop(top), mBottom(bottom), mLeft(left), mRight(right) +{ + setDirty(); +} + +FrustumProjection::FrustumProjection(f32 _near, f32 _far, const BoundBox2f& box) + : mNear(_near), mFar(_far) +{ +} + +void FrustumProjection::doUpdateMatrix(Matrix44f* dst) const +{ + f32 inv_size = 1.0f / (mRight - mLeft); + + (*dst)(0, 0) = mNear * 2 * inv_size; + (*dst)(0, 1) = 0.0f; + (*dst)(0, 2) = (mLeft + mRight) * inv_size; + (*dst)(0, 3) = 0.0f; + + inv_size = 1.0f / (mTop - mBottom); + + (*dst)(1, 0) = 0.0f; + (*dst)(1, 1) = mNear * 2 * inv_size; + (*dst)(1, 2) = (mTop + mBottom) * inv_size; + (*dst)(1, 3) = 0.0f; + + inv_size = 1.0f / (mFar - mNear); + + (*dst)(2, 0) = 0.0f; + (*dst)(2, 1) = 0.0f; + (*dst)(2, 2) = -(mFar + mNear) * inv_size; + (*dst)(2, 3) = -(mFar * 2 * mNear) * inv_size; + + (*dst)(3, 0) = 0.0f; + (*dst)(3, 1) = 0.0f; + (*dst)(3, 2) = -1.0f; + (*dst)(3, 3) = 0.0f; +} + +void FrustumProjection::setNear(f32 near) +{ + mNear = near; + setDirty(); +} + +void FrustumProjection::setFar(f32 far) +{ + mFar = far; + setDirty(); +} + +void FrustumProjection::setTop(f32 top) +{ + mTop = top; + setDirty(); +} + +void FrustumProjection::setBottom(f32 bottom) +{ + mBottom = bottom; + setDirty(); +} + +void FrustumProjection::setLeft(f32 left) +{ + mLeft = left; + setDirty(); +} + +void FrustumProjection::setRight(f32 right) +{ + mRight = right; + setDirty(); +} + +f32 FrustumProjection::getFovy() const +{ + return 2 * Mathf::atan2(0.5f * (mTop - mBottom), getNear()); +} + +f32 FrustumProjection::getAspect() const +{ + return (mRight - mLeft) / (mTop - mBottom); +} + +void FrustumProjection::getOffset(Vector2f* dst) const +{ + float denom = mRight - mLeft; + dst->x = (float)0.5 * (mRight + mLeft) / denom; + + denom = mTop - mBottom; + dst->y = (float)0.5 * (mTop + mBottom) / denom; +} + +DirectProjection::DirectProjection() +{ + setDirty(); +} + +DirectProjection::DirectProjection(const Matrix44f* mtx, Graphics::DevicePosture posture) +{ + setDirectProjectionMatrix(mtx, posture); +} + +void DirectProjection::updateAttributesForDirectProjection() +{ + Matrix44f newMatrix; + newMatrix.setInverse(mDirectMatrix); +} + +void DirectProjection::doUpdateMatrix(Matrix44f* dst) const +{ + *dst = mDirectMatrix; +} + +void DirectProjection::setDirectProjectionMatrix(const Matrix44f* mtx, + Graphics::DevicePosture posture) +{ + mDirectMatrix = (*mtx); +} + +void DirectProjection::doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const +{ + Matrix44f inverseDirect; + inverseDirect.setInverse(mDirectMatrix); + f32 scale = 1.0f / (inverseDirect(3, 3) + screen_pos.x * inverseDirect(3, 0) + + screen_pos.y * inverseDirect(3, 1) + screen_pos.z * inverseDirect(3, 2)); + dst->x = scale * (inverseDirect(0, 3) + screen_pos.x * inverseDirect(0, 0) + + screen_pos.y * inverseDirect(0, 1) + screen_pos.z * inverseDirect(0, 2)); + dst->y = scale * (inverseDirect(1, 3) + screen_pos.x * inverseDirect(1, 0) + + screen_pos.y * inverseDirect(1, 1) + screen_pos.z * inverseDirect(1, 2)); + dst->z = scale * (inverseDirect(2, 3) + screen_pos.x * inverseDirect(2, 0) + + screen_pos.y * inverseDirect(2, 1) + screen_pos.z * inverseDirect(2, 2)); +} + } // namespace sead diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp new file mode 100644 index 00000000..c8d047b8 --- /dev/null +++ b/modules/src/gfx/seadViewport.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include "math/seadBoundBox.h" +#include "math/seadMathCalcCommon.h" + +namespace sead +{ + +Viewport::Viewport() +{ + setUndef(); +} + +Viewport::Viewport(f32 left, f32 top, f32 sizeX, f32 sizeY) + : BoundBox2f(left, top, left + sizeX, top + sizeY) +{ +} +Viewport::Viewport(const LogicalFrameBuffer& frame_buffer) +{ + setByFrameBuffer(frame_buffer); +} + +void Viewport::setByFrameBuffer(const LogicalFrameBuffer& frame_buffer) +{ + switch (mDevicePosture) + { + case Graphics::cDevicePosture_Same: + case Graphics::cDevicePosture_FlipX: + case Graphics::cDevicePosture_FlipY: + case Graphics::cDevicePosture_FlipXY: + set(0.0f, 0.0f, frame_buffer.getVirtualSize().x, frame_buffer.getVirtualSize().y); + break; + case Graphics::cDevicePosture_RotateRight: + case Graphics::cDevicePosture_RotateLeft: + set(0.0f, 0.0f, frame_buffer.getVirtualSize().y, frame_buffer.getVirtualSize().x); + break; + default:; + // SEAD_ASSERT_MSG(false, "Undefined DevicePosture(%d)", s32(mDevicePos)); + } +} + +void Viewport::getOnFrameBufferPos(Vector2f* dst, const LogicalFrameBuffer& fb) const +{ + *dst = getMin(); + + switch (mDevicePosture) + { + case Graphics::cDevicePosture_Same: + break; + case Graphics::cDevicePosture_RotateRight: + { + f32 y = (fb.getVirtualSize().y - getSizeX()) - dst->x; + dst->set(dst->y, y); + } + break; + case Graphics::cDevicePosture_RotateLeft: + { + f32 x = (fb.getVirtualSize().x - getSizeY()) - dst->y; + dst->set(x, dst->x); + } + break; + case Graphics::cDevicePosture_FlipXY: + { + f32 x = (fb.getVirtualSize().x - getSizeX()) - dst->x; + f32 y = (fb.getVirtualSize().y - getSizeY()) - dst->y; + dst->set(x, y); + } + break; + case Graphics::cDevicePosture_FlipX: + { + f32 x = (fb.getVirtualSize().x - getSizeX()) - dst->x; + dst->set(x, dst->y); + } + break; + case Graphics::cDevicePosture_FlipY: + { + f32 y = (fb.getVirtualSize().y - getSizeY()) - dst->y; + dst->set(dst->x, y); + } + break; + default:; + // SEAD_ASSERT_MSG(false, "Undefined DevicePosture(%d)", s32(mDevicePos)); + } + + dst->x /= fb.getVirtualSize().x; + dst->y /= fb.getVirtualSize().y; + dst->x *= fb.getPhysicalArea().getSizeX(); + dst->y *= fb.getPhysicalArea().getSizeY(); + dst->x = dst->x + fb.getPhysicalArea().getMin().x; + dst->y = dst->y + fb.getPhysicalArea().getMin().y; +} + +void Viewport::getOnFrameBufferSize(Vector2f* dst, const LogicalFrameBuffer& fb) const +{ + dst->set(getSizeX(), getSizeY()); + + switch (mDevicePosture) + { + case Graphics::cDevicePosture_Same: + case Graphics::cDevicePosture_FlipX: + case Graphics::cDevicePosture_FlipY: + case Graphics::cDevicePosture_FlipXY: + break; + case Graphics::cDevicePosture_RotateRight: + case Graphics::cDevicePosture_RotateLeft: + dst->set(dst->y, dst->x); + break; + default:; + // SEAD_ASSERT_MSG(false, "Undefined DevicePosture(%d)", s32(mDevicePos)); + } + + dst->x /= fb.getVirtualSize().x; + dst->y /= fb.getVirtualSize().y; + dst->x *= fb.getPhysicalArea().getSizeX(); + dst->y *= fb.getPhysicalArea().getSizeY(); +} + +void Viewport::apply(DrawContext* context, const LogicalFrameBuffer& frame_buffer) const +{ + sead::Vector2f real_pos; + getOnFrameBufferPos(&real_pos, frame_buffer); + + sead::Vector2f real_size; + getOnFrameBufferSize(&real_size, frame_buffer); + + SEAD_ASSERT(frame_buffer.getPhysicalArea().isInside(real_pos) && + frame_buffer.getPhysicalArea().isInside(real_pos + real_size)); + + real_pos.y = (frame_buffer.getPhysicalArea().getSizeY() - real_size.y) - real_pos.y; + + // context->getCommandBuffer()->SetScissor(real_pos.x, real_pos.y, real_size.x, real_size.y); + sead::Graphics::instance()->setViewportRealPosition(real_pos.x, real_pos.y, real_size.x, + real_size.y); + sead::Graphics::instance()->setScissorRealPosition(real_pos.x, real_pos.y, real_size.x, + real_size.y); + context->getCommandBuffer()->SetDepthBounds(mDepthBounds.x, mDepthBounds.y); +} + +// void Viewport::applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const +// { +// Vector2f temp; +// getOnFrameBufferPos(&temp, buffer); +// context->someFunction(); +// // apply(buffer); +// } + +void Viewport::applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const {} + +void Viewport::project(Vector2f* aVec, const Vector3f& bVec) const +{ + aVec->x = getHalfSizeX() * bVec.x; + aVec->y = getHalfSizeY() * bVec.y; +} + +void Viewport::project(Vector2f* aVec, const Vector2f& bVec) const +{ + aVec->x = getHalfSizeX() * bVec.x; + aVec->y = getHalfSizeY() * bVec.y; +} + +void Viewport::unproject(Vector3f* some3Vec, const Vector2f& some2Vec, const Projection& projection, + const Camera& camera) const +{ + Vector3f tempVec; + tempVec.x = some2Vec.x / getHalfSizeX(); + tempVec.y = some2Vec.y / getHalfSizeY(); + tempVec.z = 0.0f; + projection.unproject(some3Vec, tempVec, camera); +} + +// void Viewport::unproject(Ray* ray, const Vector2f& someVec, const Projection& +// projection, +// const Camera& camera) const +// { +// float some_value; +// some_value = someVec.x / (getHalfSizeX()); +// // projection.unproject(ray, some_value, camera); +// } + +} // namespace sead From b928260af30d3120af6a60c70e76979032a688da Mon Sep 17 00:00:00 2001 From: Esras Date: Sun, 27 Jul 2025 20:33:55 -0700 Subject: [PATCH 03/12] Minor tweak to a deconstructor and removal of a superfluous line. --- include/gfx/seadProjection.h | 2 +- modules/src/gfx/seadProjection.cpp | 1 - modules/src/gfx/seadViewport.cpp | 14 +++++++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 60f0403b..2dda80a3 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -29,7 +29,7 @@ class Projection cType_Undefined = 2 }; Projection(); - virtual ~Projection(); + virtual ~Projection() = default; virtual f32 getNear() const = 0; virtual f32 getFar() const = 0; diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 1d7038e0..4ee93f54 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -155,7 +155,6 @@ PerspectiveProjection::PerspectiveProjection(f32 near, f32 far, f32 fovy_rad, f3 : mNear(near), mFar(far), mAspect(aspect), mOffset(Vector2f::zero) { setFovy_(fovy_rad); - setDirty(); } void PerspectiveProjection::set(f32 _near, f32 _far, f32 fovy_rad, f32 aspect) diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp index c8d047b8..bc5dba0a 100644 --- a/modules/src/gfx/seadViewport.cpp +++ b/modules/src/gfx/seadViewport.cpp @@ -137,13 +137,13 @@ void Viewport::apply(DrawContext* context, const LogicalFrameBuffer& frame_buffe context->getCommandBuffer()->SetDepthBounds(mDepthBounds.x, mDepthBounds.y); } -// void Viewport::applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const -// { -// Vector2f temp; -// getOnFrameBufferPos(&temp, buffer); -// context->someFunction(); -// // apply(buffer); -// } +void Viewport::applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const +{ + Vector2f temp; + getOnFrameBufferPos(&temp, buffer); + // context->someFunction(); + apply(context, buffer); +} void Viewport::applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const {} From 6aedabffa33486e353e5ea1be7ddb8babb8b320e Mon Sep 17 00:00:00 2001 From: Esras Date: Thu, 7 Aug 2025 14:55:39 -0700 Subject: [PATCH 04/12] WIP, sort of. Add more functions, but a few do not match, looking for feedback. --- CMakeLists.txt | 1 + include/gfx/seadCamera.h | 12 ++-- include/gfx/seadDrawContext.h | 2 +- include/gfx/seadProjection.h | 4 +- include/gfx/seadViewport.h | 2 +- modules/src/gfx/seadCamera.cpp | 101 ++++++++++++++++++++++++++++- modules/src/gfx/seadProjection.cpp | 31 +++++---- modules/src/gfx/seadViewport.cpp | 78 ++++++++++++++-------- 8 files changed, 183 insertions(+), 48 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a2fb62d7..46911d9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ add_library(sead OBJECT modules/src/gfx/nvn/seadDebugFontMgrNvn.cpp modules/src/gfx/seadCamera.cpp modules/src/gfx/seadColor.cpp + modules/src/gfx/seadDrawContext.cpp modules/src/gfx/seadDrawLockContext.cpp modules/src/gfx/seadFrameBuffer.cpp modules/src/gfx/seadGraphics.cpp diff --git a/include/gfx/seadCamera.h b/include/gfx/seadCamera.h index f0823f0e..b11bf936 100644 --- a/include/gfx/seadCamera.h +++ b/include/gfx/seadCamera.h @@ -10,14 +10,16 @@ class OrthoProjection; class Projection; class Viewport; template -class Ray; +class Ray : public T +{ +}; class Camera { SEAD_RTTI_BASE(Camera) public: - Camera() = default; + Camera(); virtual ~Camera(); virtual void doUpdateMatrix(Matrix34f* dst) const = 0; @@ -79,19 +81,21 @@ class DirectCamera : public Camera { SEAD_RTTI_OVERRIDE(DirectCamera, Camera) public: + DirectCamera(); ~DirectCamera() override; void doUpdateMatrix(Matrix34f* dst) const override; private: - Matrix34f mDirectMatrix = Matrix34f::ident; + Matrix34f mDirectMatrix = Matrix34f::ident; // I don't think this is right, the Matrix has 0, 2 + // and 1, 3 populated as 1.0f }; class OrthoCamera : public LookAtCamera { SEAD_RTTI_OVERRIDE(OrthoCamera, LookAtCamera) public: - OrthoCamera(); + OrthoCamera() = default; OrthoCamera(const Vector2f&, float); OrthoCamera(const OrthoProjection&); ~OrthoCamera() override; diff --git a/include/gfx/seadDrawContext.h b/include/gfx/seadDrawContext.h index d5dc3215..35b1323b 100644 --- a/include/gfx/seadDrawContext.h +++ b/include/gfx/seadDrawContext.h @@ -12,7 +12,7 @@ class DrawContext SEAD_RTTI_BASE(DrawContext) public: DrawContext(); - virtual ~DrawContext(); + virtual ~DrawContext() = default; nn::gfx::CommandBuffer* getCommandBuffer() { return &mCommandBuffer; } diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 2dda80a3..9f02003e 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -52,8 +52,8 @@ class Projection void screenPosToCameraPos(Vector3f* dst, const Vector2f& screen_pos) const; void project(Vector2f* dst, const Vector3f& camera_pos, const Viewport& viewport) const; - void unproject(Vector3f* dst, const Vector3f& screen_pos, const Camera& camera) const; - void unprojectRay(Ray* dst, const Vector3f& screen_pos, const Camera& camera) const; + void unproject(Vector3f* dst, const Vector3f& screenPos, const Camera& camera) const; + void unprojectRay(Ray* dst, const Vector3f& screenPos, const Camera& camera) const; void setDirty() { mDirty = true; } void setDeviceDirty() { mDeviceDirty = true; } diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index 10de3d9f..2083ff47 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -34,7 +34,7 @@ class Viewport : public BoundBox2f void project(Vector2f*, const Vector3f&) const; void project(Vector2f*, const Vector2f&) const; void unproject(Vector3f*, const Vector2f&, const Projection&, const Camera&) const; - void unproject(Ray*, const Vector2f&, const Projection&, const Camera&) const; + void unprojectRay(Ray*, const Vector2f&, const Projection&, const Camera&) const; private: Graphics::DevicePosture mDevicePosture = Graphics::getDefaultDevicePosture(); diff --git a/modules/src/gfx/seadCamera.cpp b/modules/src/gfx/seadCamera.cpp index ae58e851..41fcb16b 100644 --- a/modules/src/gfx/seadCamera.cpp +++ b/modules/src/gfx/seadCamera.cpp @@ -1,10 +1,105 @@ #include "gfx/seadCamera.h" +#include +#include +#include #include "basis/seadRawPrint.h" namespace sead { Camera::~Camera() = default; +void Camera::getWorldPosByMatrix(Vector3f* dst) const +{ + // Currently not matching the function, but this _should_ be the math. + dst->x = -(mMatrix(0, 0) * mMatrix(0, 3)) - mMatrix(1, 0) * mMatrix(1, 3) - + mMatrix(2, 0) * mMatrix(2, 3); + dst->y = -(mMatrix(0, 1) * mMatrix(0, 3)) - mMatrix(1, 1) * mMatrix(1, 3) - + mMatrix(2, 1) * mMatrix(2, 3); + dst->z = -(mMatrix(0, 2) * mMatrix(0, 3)) - mMatrix(1, 2) * mMatrix(1, 3) - + mMatrix(2, 2) * mMatrix(2, 3); +} + +void Camera::getLookVectorByMatrix(Vector3f* dst) const +{ + // Also known as the forward vector + dst->x = mMatrix(2, 0); + dst->y = mMatrix(2, 1); + dst->z = mMatrix(2, 2); +}; + +void Camera::getRightVectorByMatrix(Vector3f* dst) const +{ + dst->x = mMatrix(0, 0); + dst->y = mMatrix(0, 1); + dst->z = mMatrix(0, 2); +} + +void Camera::getUpVectorByMatrix(Vector3f* dst) const +{ + dst->x = mMatrix(1, 0); + dst->y = mMatrix(1, 1); + dst->z = mMatrix(1, 2); +}; + +void Camera::worldPosToCameraPosByMatrix(Vector3f* dst, const Vector3f& world_pos) const +{ + *dst = mMatrix * world_pos; + *dst = mMatrix.getBase(3); + // *dst += mMatrix.getBase(3); + // dst->x = mMatrix(0, 3) + world_pos.x * mMatrix(0, 0) + world_pos.y * mMatrix(0, 1) + + // world_pos.z * mMatrix(0, 2); + // dst->y = mMatrix(1, 3) + world_pos.x * mMatrix(1, 0) + world_pos.y * mMatrix(1, 1) + + // world_pos.z * mMatrix(1, 2); + // dst->z = mMatrix(2, 3) + world_pos.x * mMatrix(2, 0) + world_pos.y * mMatrix(2, 1) + + // world_pos.z * mMatrix(2, 2); +} + +void Camera::cameraPosToWorldPosByMatrix(Vector3f* dst, const Vector3f& camera_pos) const +{ + dst->x = mMatrix(0, 0) * camera_pos.x + mMatrix(1, 0) * camera_pos.y + + ((-(mMatrix(0, 3) * mMatrix(0, 0)) - mMatrix(1, 3) * mMatrix(1, 1)) - + mMatrix(2, 3) * mMatrix(2, 0)); + dst->y = mMatrix(0, 1) * camera_pos.x + mMatrix(1, 1) * camera_pos.y + + ((-(mMatrix(0, 3) * mMatrix(0, 1)) - mMatrix(1, 3) * mMatrix(1, 2)) - + mMatrix(2, 3) * mMatrix(2, 1)); + dst->z = mMatrix(0, 2) * camera_pos.x + mMatrix(1, 2) * camera_pos.y + + ((-(mMatrix(0, 3) * mMatrix(0, 2)) - mMatrix(1, 3) * mMatrix(1, 3)) - + mMatrix(2, 3) * mMatrix(2, 2)); +} + +void Camera::projectByMatrix(Vector2f* dst, const Vector3f& world_pos, const Projection& projection, + const Viewport& viewport) const +{ + auto temp = mMatrix * world_pos; + temp += mMatrix.getBase(3); + projection.project(dst, temp, viewport); +} + +void Camera::unprojectRayByMatrix(Ray* dst, const Vector3f& camera_pos) const +{ + auto col_0 = mMatrix.getBase(0).dot(camera_pos); + auto col_1 = mMatrix.getBase(1).dot(camera_pos); + auto col_2 = mMatrix.getBase(2).dot(camera_pos); + auto length = sqrt(col_0 * col_0 + col_1 * col_1 + col_2 * col_2); + if (sead::MathCalcCommon::isNan(length)) + { + length = sqrtf(length); + }; + if (length < 0.0f) + { + auto scale = 1.0f / length; + col_0 *= scale; + col_1 *= scale; + col_2 *= scale; + } + dst->x = ((-mMatrix(0, 0) * mMatrix(0, 3)) - mMatrix(1, 0) * mMatrix(1, 3)) - + mMatrix(2, 0) * mMatrix(2, 3); + dst->y = ((-mMatrix(0, 1) * mMatrix(0, 3)) - mMatrix(1, 1) * mMatrix(1, 3)) - + mMatrix(2, 1) * mMatrix(2, 3); + dst->z = ((-mMatrix(0, 2) * mMatrix(0, 3)) - mMatrix(1, 2) * mMatrix(1, 3)) - + mMatrix(2, 2) * mMatrix(2, 3); +} + LookAtCamera::~LookAtCamera() = default; LookAtCamera::LookAtCamera(const Vector3f& pos, const Vector3f& at, const Vector3f& up) @@ -14,8 +109,12 @@ LookAtCamera::LookAtCamera(const Vector3f& pos, const Vector3f& at, const Vector mUp.normalize(); } -OrthoCamera::~OrthoCamera() = default; +void LookAtCamera::doUpdateMatrix(Matrix34f* dst) const {} + +DirectCamera::DirectCamera() {} DirectCamera::~DirectCamera() = default; +OrthoCamera::~OrthoCamera() = default; + } // namespace sead diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 4ee93f54..df9d9751 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -1,6 +1,8 @@ #include #include #include +#include "math/seadMatrixCalcCommon.h" +#include "math/seadVectorCalcCommon.h" namespace sead { @@ -46,17 +48,18 @@ void Projection::project(Vector2f* dst, const Vector3f& camera_pos, const Viewpo viewport.project(dst, temp); } -void Projection::unproject(Vector3f* dst, const Vector3f& screen_pos, const Camera& camera) const +void Projection::unproject(Vector3f* dst, const Vector3f& screenPos, const Camera& camera) const { - doScreenPosToCameraPosTo(dst, screen_pos); - camera.cameraPosToWorldPosByMatrix(dst, screen_pos); + doScreenPosToCameraPosTo(dst, screenPos); + camera.cameraPosToWorldPosByMatrix(dst, screenPos); } -void Projection::unprojectRay(Ray* dst, const Vector3f& screen_pos, +void Projection::unprojectRay(Ray* dst, const Vector3f& screenPos, const Camera& camera) const { - // doScreenPosToCameraPosTo(dst, screen_pos); - // camera.cameraPosToWorldPosByMatrix(dst, screen_pos); + Vector3f newVec; + doScreenPosToCameraPosTo(dst, screenPos); + camera.unprojectRayByMatrix(dst, newVec); } void Projection::updateAttributesForDirectProjection() {} @@ -64,15 +67,10 @@ void Projection::updateAttributesForDirectProjection() {} void Projection::doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const { updateMatrixImpl_(); - f32 scale = 1.0f / (mMatrix(3, 3) + screen_pos.x * mMatrix(3, 0) + screen_pos.y * mMatrix(3, 1) + screen_pos.z * mMatrix(3, 2)); - dst->x = scale * (mMatrix(3, 3) + screen_pos.x * mMatrix(0, 0) + screen_pos.y * mMatrix(1, 0) + - screen_pos.z * mMatrix(2, 0)); - dst->y = scale * (mMatrix(1, 3) + screen_pos.x * mMatrix(1, 0) + screen_pos.y * mMatrix(1, 1) + - screen_pos.z * mMatrix(1, 2)); - dst->z = scale * (mMatrix(2, 3) + screen_pos.x * mMatrix(2, 0) + screen_pos.y * mMatrix(2, 1) + - screen_pos.z * mMatrix(2, 2)); + *dst = static_cast(mMatrix) * screen_pos; + *dst *= scale; } namespace @@ -373,6 +371,13 @@ void OrthoProjection::setByViewport(const Viewport& vp) setDirty(); } +void OrthoProjection::doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const +{ + dst->x = 0.5f * ((mRight + mLeft) + screen_pos.x * (mRight - mLeft)); + dst->y = 0.5f * ((mTop + mBottom) + (screen_pos.y * (mTop - mBottom))); + dst->z = mNear; +} + FrustumProjection::FrustumProjection(f32 _near, f32 _far, f32 top, f32 bottom, f32 left, f32 right) : mNear(_near), mFar(_far), mTop(top), mBottom(bottom), mLeft(left), mRight(right) { diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp index bc5dba0a..8bfe1508 100644 --- a/modules/src/gfx/seadViewport.cpp +++ b/modules/src/gfx/seadViewport.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -116,20 +117,19 @@ void Viewport::getOnFrameBufferSize(Vector2f* dst, const LogicalFrameBuffer& fb) dst->y *= fb.getPhysicalArea().getSizeY(); } -void Viewport::apply(DrawContext* context, const LogicalFrameBuffer& frame_buffer) const +void Viewport::apply(DrawContext* context, const LogicalFrameBuffer& buffer) const { sead::Vector2f real_pos; - getOnFrameBufferPos(&real_pos, frame_buffer); + getOnFrameBufferPos(&real_pos, buffer); sead::Vector2f real_size; - getOnFrameBufferSize(&real_size, frame_buffer); + getOnFrameBufferSize(&real_size, buffer); - SEAD_ASSERT(frame_buffer.getPhysicalArea().isInside(real_pos) && - frame_buffer.getPhysicalArea().isInside(real_pos + real_size)); + SEAD_ASSERT(buffer.getPhysicalArea().isInside(real_pos) && + buffer.getPhysicalArea().isInside(real_pos + real_size)); - real_pos.y = (frame_buffer.getPhysicalArea().getSizeY() - real_size.y) - real_pos.y; + real_pos.y = (buffer.getPhysicalArea().getSizeY() - real_size.y) - real_pos.y; - // context->getCommandBuffer()->SetScissor(real_pos.x, real_pos.y, real_size.x, real_size.y); sead::Graphics::instance()->setViewportRealPosition(real_pos.x, real_pos.y, real_size.x, real_size.y); sead::Graphics::instance()->setScissorRealPosition(real_pos.x, real_pos.y, real_size.x, @@ -139,13 +139,38 @@ void Viewport::apply(DrawContext* context, const LogicalFrameBuffer& frame_buffe void Viewport::applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const { - Vector2f temp; - getOnFrameBufferPos(&temp, buffer); - // context->someFunction(); - apply(context, buffer); + sead::Vector2f real_pos; + getOnFrameBufferPos(&real_pos, buffer); + + sead::Vector2f real_size; + getOnFrameBufferSize(&real_size, buffer); + + SEAD_ASSERT(buffer.getPhysicalArea().isInside(real_pos) && + buffer.getPhysicalArea().isInside(real_pos + real_size)); + + real_pos.y = (buffer.getPhysicalArea().getSizeY() - real_size.y) - real_pos.y; + // real_pos.x = (buffer.getPhysicalArea().getSizeX() - real_size.x) - real_pos.x; + + sead::Graphics::instance()->setViewportRealPosition(real_pos.x, real_pos.y, real_size.x, + real_size.y); } -void Viewport::applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const {} +void Viewport::applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const +{ + sead::Vector2f real_pos; + getOnFrameBufferPos(&real_pos, buffer); + + sead::Vector2f real_size; + getOnFrameBufferSize(&real_size, buffer); + + SEAD_ASSERT(buffer.getPhysicalArea().isInside(real_pos) && + buffer.getPhysicalArea().isInside(real_pos + real_size)); + + real_pos.y = (buffer.getPhysicalArea().getSizeY() - real_size.y) - real_pos.y; + + sead::Graphics::instance()->setScissorRealPosition(real_pos.x, real_pos.y, real_size.x, + real_size.y); +} void Viewport::project(Vector2f* aVec, const Vector3f& bVec) const { @@ -159,23 +184,24 @@ void Viewport::project(Vector2f* aVec, const Vector2f& bVec) const aVec->y = getHalfSizeY() * bVec.y; } -void Viewport::unproject(Vector3f* some3Vec, const Vector2f& some2Vec, const Projection& projection, +void Viewport::unproject(Vector3f* dst, const Vector2f& some2Vec, const Projection& projection, const Camera& camera) const { - Vector3f tempVec; - tempVec.x = some2Vec.x / getHalfSizeX(); - tempVec.y = some2Vec.y / getHalfSizeY(); - tempVec.z = 0.0f; - projection.unproject(some3Vec, tempVec, camera); + Vector3f screenPos; + screenPos.x = some2Vec.x / getHalfSizeX(); + screenPos.y = some2Vec.y / getHalfSizeY(); + screenPos.z = 0.0f; + projection.unproject(dst, screenPos, camera); } -// void Viewport::unproject(Ray* ray, const Vector2f& someVec, const Projection& -// projection, -// const Camera& camera) const -// { -// float some_value; -// some_value = someVec.x / (getHalfSizeX()); -// // projection.unproject(ray, some_value, camera); -// } +void Viewport::unprojectRay(Ray* dst, const Vector2f& some2Vec, + const Projection& projection, const Camera& camera) const +{ + Vector3f screenPos; + screenPos.x = some2Vec.x / getHalfSizeX(); + screenPos.y = some2Vec.y / getHalfSizeY(); + screenPos.z = 0.0f; + projection.unprojectRay(dst, screenPos, camera); +} } // namespace sead From fb3934bb340bceee4b42dcbf304962cc3c4e1408 Mon Sep 17 00:00:00 2001 From: Esras Date: Thu, 7 Aug 2025 15:20:30 -0700 Subject: [PATCH 05/12] Fix the three get vector functions for the Camera. --- modules/src/gfx/seadCamera.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/modules/src/gfx/seadCamera.cpp b/modules/src/gfx/seadCamera.cpp index 41fcb16b..c1413516 100644 --- a/modules/src/gfx/seadCamera.cpp +++ b/modules/src/gfx/seadCamera.cpp @@ -22,23 +22,20 @@ void Camera::getWorldPosByMatrix(Vector3f* dst) const void Camera::getLookVectorByMatrix(Vector3f* dst) const { // Also known as the forward vector - dst->x = mMatrix(2, 0); - dst->y = mMatrix(2, 1); - dst->z = mMatrix(2, 2); + auto vec = mMatrix.getRow(2); + dst->set(vec.x, vec.y, vec.z); }; void Camera::getRightVectorByMatrix(Vector3f* dst) const { - dst->x = mMatrix(0, 0); - dst->y = mMatrix(0, 1); - dst->z = mMatrix(0, 2); + auto vec = mMatrix.getRow(0); + dst->set(vec.x, vec.y, vec.z); } void Camera::getUpVectorByMatrix(Vector3f* dst) const { - dst->x = mMatrix(1, 0); - dst->y = mMatrix(1, 1); - dst->z = mMatrix(1, 2); + auto vec = mMatrix.getRow(1); + dst->set(vec.x, vec.y, vec.z); }; void Camera::worldPosToCameraPosByMatrix(Vector3f* dst, const Vector3f& world_pos) const From 42435cf3d33923de87786bbb369dd370fe462892 Mon Sep 17 00:00:00 2001 From: Esras Date: Fri, 8 Aug 2025 16:24:09 -0700 Subject: [PATCH 06/12] Simplify some of the matrix math using CalcCommon functions. --- CMakeLists.txt | 2 ++ include/gfx/seadCamera.h | 5 +-- include/gfx/seadProjection.h | 2 +- include/gfx/seadViewport.h | 2 +- include/math/seadGeometry.h | 26 +++++++++++++++ modules/src/gfx/seadCamera.cpp | 53 +++++++++--------------------- modules/src/gfx/seadProjection.cpp | 2 +- modules/src/gfx/seadViewport.cpp | 2 +- modules/src/math/seadGeometry.cpp | 25 ++++++++++++++ 9 files changed, 74 insertions(+), 45 deletions(-) create mode 100644 include/math/seadGeometry.h create mode 100644 modules/src/math/seadGeometry.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 46911d9c..d78b8083 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,6 +138,7 @@ add_library(sead OBJECT include/math/seadBoundBox.h include/math/seadBoundBox.hpp + include/math/seadGeometry.h include/math/seadMathBase.h include/math/seadMathCalcCommon.h include/math/seadMathCalcCommon.hpp @@ -157,6 +158,7 @@ add_library(sead OBJECT include/math/seadVectorCalcCommon.hpp include/math/seadVectorFwd.h modules/src/math/seadBoundBox.cpp + modules/src/math/seadGeometry.cpp modules/src/math/seadMathCalcCommon.cpp modules/src/math/seadMatrix.cpp modules/src/math/seadQuat.cpp diff --git a/include/gfx/seadCamera.h b/include/gfx/seadCamera.h index b11bf936..bc4bda29 100644 --- a/include/gfx/seadCamera.h +++ b/include/gfx/seadCamera.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,10 +10,6 @@ namespace sead class OrthoProjection; class Projection; class Viewport; -template -class Ray : public T -{ -}; class Camera { diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 9f02003e..b51e3f47 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -15,7 +15,7 @@ class Camera; class Viewport; template -class Ray; +struct Ray; class Projection { diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index 2083ff47..b8156ced 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -10,7 +10,7 @@ class Camera; class Projection; template -class Ray; +struct Ray; class Viewport : public BoundBox2f { diff --git a/include/math/seadGeometry.h b/include/math/seadGeometry.h new file mode 100644 index 00000000..4053293c --- /dev/null +++ b/include/math/seadGeometry.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace sead +{ +template +struct Ray +{ + Ray(); + + T position; + T direction; +}; +namespace Geometry +{ +float calcSquaredDistancePointToRay(Vector2* point, Ray>* ray, float* scalar); +// float calcSquaredDistancePointToLine(Vector2* const, Line>* const, +// float*); float calcSquaredDistancePointToSegment(Vector3* const, Segment>* +// const, float*); float calcSquaredDistancePointToSegment(); +// float calcSquaredDistanceSegmentToSegment(Segment>* const, +// Segment>* const, float*, float*); +// float calcSquaredDistanceRayToSegment(Ray> const&, Segment>* const, +// float*, float*); +} // namespace Geometry +} // namespace sead diff --git a/modules/src/gfx/seadCamera.cpp b/modules/src/gfx/seadCamera.cpp index c1413516..2ea69a06 100644 --- a/modules/src/gfx/seadCamera.cpp +++ b/modules/src/gfx/seadCamera.cpp @@ -1,5 +1,4 @@ #include "gfx/seadCamera.h" -#include #include #include #include "basis/seadRawPrint.h" @@ -10,13 +9,10 @@ Camera::~Camera() = default; void Camera::getWorldPosByMatrix(Vector3f* dst) const { - // Currently not matching the function, but this _should_ be the math. - dst->x = -(mMatrix(0, 0) * mMatrix(0, 3)) - mMatrix(1, 0) * mMatrix(1, 3) - - mMatrix(2, 0) * mMatrix(2, 3); - dst->y = -(mMatrix(0, 1) * mMatrix(0, 3)) - mMatrix(1, 1) * mMatrix(1, 3) - - mMatrix(2, 1) * mMatrix(2, 3); - dst->z = -(mMatrix(0, 2) * mMatrix(0, 3)) - mMatrix(1, 2) * mMatrix(1, 3) - - mMatrix(2, 2) * mMatrix(2, 3); + dst->x = mMatrix.getBase(3).dot(mMatrix.getBase(0)); + dst->x = mMatrix.getBase(3).dot(mMatrix.getBase(1)); + dst->x = mMatrix.getBase(3).dot(mMatrix.getBase(2)); + *dst *= -1.0f; } void Camera::getLookVectorByMatrix(Vector3f* dst) const @@ -41,14 +37,6 @@ void Camera::getUpVectorByMatrix(Vector3f* dst) const void Camera::worldPosToCameraPosByMatrix(Vector3f* dst, const Vector3f& world_pos) const { *dst = mMatrix * world_pos; - *dst = mMatrix.getBase(3); - // *dst += mMatrix.getBase(3); - // dst->x = mMatrix(0, 3) + world_pos.x * mMatrix(0, 0) + world_pos.y * mMatrix(0, 1) + - // world_pos.z * mMatrix(0, 2); - // dst->y = mMatrix(1, 3) + world_pos.x * mMatrix(1, 0) + world_pos.y * mMatrix(1, 1) + - // world_pos.z * mMatrix(1, 2); - // dst->z = mMatrix(2, 3) + world_pos.x * mMatrix(2, 0) + world_pos.y * mMatrix(2, 1) + - // world_pos.z * mMatrix(2, 2); } void Camera::cameraPosToWorldPosByMatrix(Vector3f* dst, const Vector3f& camera_pos) const @@ -74,27 +62,18 @@ void Camera::projectByMatrix(Vector2f* dst, const Vector3f& world_pos, const Pro void Camera::unprojectRayByMatrix(Ray* dst, const Vector3f& camera_pos) const { - auto col_0 = mMatrix.getBase(0).dot(camera_pos); - auto col_1 = mMatrix.getBase(1).dot(camera_pos); - auto col_2 = mMatrix.getBase(2).dot(camera_pos); - auto length = sqrt(col_0 * col_0 + col_1 * col_1 + col_2 * col_2); - if (sead::MathCalcCommon::isNan(length)) - { - length = sqrtf(length); - }; - if (length < 0.0f) - { - auto scale = 1.0f / length; - col_0 *= scale; - col_1 *= scale; - col_2 *= scale; - } - dst->x = ((-mMatrix(0, 0) * mMatrix(0, 3)) - mMatrix(1, 0) * mMatrix(1, 3)) - - mMatrix(2, 0) * mMatrix(2, 3); - dst->y = ((-mMatrix(0, 1) * mMatrix(0, 3)) - mMatrix(1, 1) * mMatrix(1, 3)) - - mMatrix(2, 1) * mMatrix(2, 3); - dst->z = ((-mMatrix(0, 2) * mMatrix(0, 3)) - mMatrix(1, 2) * mMatrix(1, 3)) - - mMatrix(2, 2) * mMatrix(2, 3); + dst->direction.x = mMatrix.getBase(0).dot(camera_pos); + dst->direction.y = mMatrix.getBase(1).dot(camera_pos); + dst->direction.z = mMatrix.getBase(2).dot(camera_pos); + dst->direction.normalize(); + + dst->position.x = ((-mMatrix(0, 0) * mMatrix(0, 3)) - mMatrix(1, 0) * mMatrix(1, 3)) - + mMatrix(2, 0) * mMatrix(2, 3); + dst->position.y = ((-mMatrix(0, 1) * mMatrix(0, 3)) - mMatrix(1, 1) * mMatrix(1, 3)) - + mMatrix(2, 1) * mMatrix(2, 3); + dst->position.z = ((-mMatrix(0, 2) * mMatrix(0, 3)) - mMatrix(1, 2) * mMatrix(1, 3)) - + mMatrix(2, 2) * mMatrix(2, 3); + dst->position *= -1.0f; } LookAtCamera::~LookAtCamera() = default; diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index df9d9751..346a8417 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -58,7 +58,7 @@ void Projection::unprojectRay(Ray* dst, const Vector3f& screenPos, const Camera& camera) const { Vector3f newVec; - doScreenPosToCameraPosTo(dst, screenPos); + doScreenPosToCameraPosTo(&dst->position, screenPos); camera.unprojectRayByMatrix(dst, newVec); } diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp index 8bfe1508..9de7d6e0 100644 --- a/modules/src/gfx/seadViewport.cpp +++ b/modules/src/gfx/seadViewport.cpp @@ -3,7 +3,7 @@ #include #include #include "math/seadBoundBox.h" -#include "math/seadMathCalcCommon.h" +#include "nn/gfx/gfx_StateInfo.h" namespace sead { diff --git a/modules/src/math/seadGeometry.cpp b/modules/src/math/seadGeometry.cpp new file mode 100644 index 00000000..0efcdf76 --- /dev/null +++ b/modules/src/math/seadGeometry.cpp @@ -0,0 +1,25 @@ +#include + +namespace sead +{ + +float Geometry::calcSquaredDistancePointToRay(Vector2* point, Ray>* ray, + float* scalar) +{ + auto diff = *point - ray->position; + + auto numerator = diff.dot(ray->direction); + auto squaredLength = diff.squaredLength(); + if (numerator < 0.0f) + { + numerator = 0.0f; + squaredLength = diff.squaredLength(); + } + if (scalar != nullptr) + { + *scalar = numerator; + } + return squaredLength; +} + +} // namespace sead From 8158278a2f4160b5211da0149c95f090896198b6 Mon Sep 17 00:00:00 2001 From: Esras Date: Mon, 25 Aug 2025 08:56:14 -0600 Subject: [PATCH 07/12] Swap where constructors / deconstructors are defaulted, based on PR feedback. Remove extraneous 'this->' from a function. --- include/gfx/seadCamera.h | 4 ++-- include/gfx/seadDrawContext.h | 2 +- include/math/seadGeometry.h | 2 ++ modules/src/gfx/seadCamera.cpp | 4 ++-- modules/src/gfx/seadProjection.cpp | 4 ++-- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/gfx/seadCamera.h b/include/gfx/seadCamera.h index bc4bda29..79a80d2b 100644 --- a/include/gfx/seadCamera.h +++ b/include/gfx/seadCamera.h @@ -78,7 +78,7 @@ class DirectCamera : public Camera { SEAD_RTTI_OVERRIDE(DirectCamera, Camera) public: - DirectCamera(); + DirectCamera() = default; ~DirectCamera() override; void doUpdateMatrix(Matrix34f* dst) const override; @@ -92,7 +92,7 @@ class OrthoCamera : public LookAtCamera { SEAD_RTTI_OVERRIDE(OrthoCamera, LookAtCamera) public: - OrthoCamera() = default; + OrthoCamera(); OrthoCamera(const Vector2f&, float); OrthoCamera(const OrthoProjection&); ~OrthoCamera() override; diff --git a/include/gfx/seadDrawContext.h b/include/gfx/seadDrawContext.h index 35b1323b..d5dc3215 100644 --- a/include/gfx/seadDrawContext.h +++ b/include/gfx/seadDrawContext.h @@ -12,7 +12,7 @@ class DrawContext SEAD_RTTI_BASE(DrawContext) public: DrawContext(); - virtual ~DrawContext() = default; + virtual ~DrawContext(); nn::gfx::CommandBuffer* getCommandBuffer() { return &mCommandBuffer; } diff --git a/include/math/seadGeometry.h b/include/math/seadGeometry.h index 4053293c..1ae70d93 100644 --- a/include/math/seadGeometry.h +++ b/include/math/seadGeometry.h @@ -4,6 +4,7 @@ namespace sead { + template struct Ray { @@ -12,6 +13,7 @@ struct Ray T position; T direction; }; + namespace Geometry { float calcSquaredDistancePointToRay(Vector2* point, Ray>* ray, float* scalar); diff --git a/modules/src/gfx/seadCamera.cpp b/modules/src/gfx/seadCamera.cpp index 2ea69a06..5c4bc980 100644 --- a/modules/src/gfx/seadCamera.cpp +++ b/modules/src/gfx/seadCamera.cpp @@ -87,10 +87,10 @@ LookAtCamera::LookAtCamera(const Vector3f& pos, const Vector3f& at, const Vector void LookAtCamera::doUpdateMatrix(Matrix34f* dst) const {} -DirectCamera::DirectCamera() {} - DirectCamera::~DirectCamera() = default; +OrthoCamera::OrthoCamera() = default; + OrthoCamera::~OrthoCamera() = default; } // namespace sead diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 346a8417..8b56f6f0 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -280,8 +280,8 @@ f32 OrthoProjection::getAspect() const void OrthoProjection::getOffset(Vector2f* offset) const { - offset->x = ((float)0.5 * (this->mLeft + this->mRight)) / (this->mRight - this->mLeft); - offset->y = ((float)0.5 * (this->mTop + this->mBottom)) / (this->mTop - this->mBottom); + offset->x = ((float)0.5 * (mLeft + mRight)) / (mRight - mLeft); + offset->y = ((float)0.5 * (mTop + mBottom)) / (mTop - mBottom); } void OrthoProjection::setNear(f32 near) From eba6b0b0a01abf22dd042cf952f047230c27d46b Mon Sep 17 00:00:00 2001 From: Esras Date: Mon, 25 Aug 2025 09:25:24 -0600 Subject: [PATCH 08/12] Change uses of the Geometry header to the Line header and fix Camera::getWorldPosByMatrix. --- CMakeLists.txt | 2 ++ include/gfx/seadCamera.h | 7 +++---- include/gfx/seadProjection.h | 4 +--- include/gfx/seadViewport.h | 6 ++---- modules/src/gfx/seadCamera.cpp | 12 ++++++++---- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d78b8083..b41c613f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,8 @@ add_library(sead OBJECT modules/src/math/seadQuat.cpp modules/src/math/seadVector.cpp + include/geom/seadLine.h + include/mc/seadCoreInfo.h include/mc/seadJob.h include/mc/seadJobQueue.h diff --git a/include/gfx/seadCamera.h b/include/gfx/seadCamera.h index 79a80d2b..b387ed35 100644 --- a/include/gfx/seadCamera.h +++ b/include/gfx/seadCamera.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -31,7 +31,7 @@ class Camera void projectByMatrix(Vector2f* dst, const Vector3f& world_pos, const Projection& projection, const Viewport& viewport) const; - void unprojectRayByMatrix(Ray* dst, const Vector3f& camera_pos) const; + void unprojectRayByMatrix(Ray3f* dst, const Vector3f& camera_pos) const; Matrix34f& getMatrix() { return mMatrix; } const Matrix34f& getMatrix() const { return mMatrix; } @@ -84,8 +84,7 @@ class DirectCamera : public Camera void doUpdateMatrix(Matrix34f* dst) const override; private: - Matrix34f mDirectMatrix = Matrix34f::ident; // I don't think this is right, the Matrix has 0, 2 - // and 1, 3 populated as 1.0f + Matrix34f mDirectMatrix = Matrix34f::ident; }; class OrthoCamera : public LookAtCamera diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index b51e3f47..d0f4fd3f 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -14,9 +15,6 @@ namespace sead class Camera; class Viewport; -template -struct Ray; - class Projection { SEAD_RTTI_BASE(Projection) diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index b8156ced..a3601420 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,9 +10,6 @@ namespace sead class Camera; class Projection; -template -struct Ray; - class Viewport : public BoundBox2f { SEAD_RTTI_BASE(Viewport) @@ -34,7 +32,7 @@ class Viewport : public BoundBox2f void project(Vector2f*, const Vector3f&) const; void project(Vector2f*, const Vector2f&) const; void unproject(Vector3f*, const Vector2f&, const Projection&, const Camera&) const; - void unprojectRay(Ray*, const Vector2f&, const Projection&, const Camera&) const; + void unprojectRay(Ray3f*, const Vector2f&, const Projection&, const Camera&) const; private: Graphics::DevicePosture mDevicePosture = Graphics::getDefaultDevicePosture(); diff --git a/modules/src/gfx/seadCamera.cpp b/modules/src/gfx/seadCamera.cpp index 5c4bc980..8b3e3d2d 100644 --- a/modules/src/gfx/seadCamera.cpp +++ b/modules/src/gfx/seadCamera.cpp @@ -2,6 +2,7 @@ #include #include #include "basis/seadRawPrint.h" +#include "math/seadMatrixCalcCommon.h" namespace sead { @@ -9,10 +10,13 @@ Camera::~Camera() = default; void Camera::getWorldPosByMatrix(Vector3f* dst) const { - dst->x = mMatrix.getBase(3).dot(mMatrix.getBase(0)); - dst->x = mMatrix.getBase(3).dot(mMatrix.getBase(1)); - dst->x = mMatrix.getBase(3).dot(mMatrix.getBase(2)); - *dst *= -1.0f; + f32 x = (-mMatrix(0, 0) * mMatrix(0, 3) - mMatrix(1, 0) * mMatrix(1, 3)) - + mMatrix(2, 0) * mMatrix(2, 3); + f32 y = (-mMatrix(0, 1) * mMatrix(0, 3) - mMatrix(1, 1) * mMatrix(1, 3)) - + mMatrix(2, 1) * mMatrix(2, 3); + f32 z = (-mMatrix(0, 2) * mMatrix(0, 3) - mMatrix(1, 2) * mMatrix(1, 3)) - + mMatrix(2, 2) * mMatrix(2, 3); + dst->set(x, y, z); } void Camera::getLookVectorByMatrix(Vector3f* dst) const From 7c073f9f5ca179a3b9b0a2f01202e961d865ae01 Mon Sep 17 00:00:00 2001 From: AboodXD Date: Mon, 17 Apr 2023 18:17:13 +0400 Subject: [PATCH 09/12] engine/geom: Add Segment --- include/geom/seadLine.h | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 include/geom/seadLine.h diff --git a/include/geom/seadLine.h b/include/geom/seadLine.h new file mode 100644 index 00000000..e356a608 --- /dev/null +++ b/include/geom/seadLine.h @@ -0,0 +1,62 @@ +#ifndef SEAD_LINE_H_ +#define SEAD_LINE_H_ + +#include + +namespace sead { + +template +class Segment +{ +public: + typedef typename VectorType::ValueType T; + +public: + Segment() + : mP0(VectorType::zero) + , mP1(VectorType::ex) + { + } + + Segment(const VectorType& p0, const VectorType& p1) + : mP0(p0) + , mP1(p1) + { + } + + const VectorType& getPos0() const + { + return mP0; + } + + void setPos0(const VectorType& p0) + { + mP0 = p0; + } + + const VectorType& getPos1() const + { + return mP1; + } + + void setPos1(const VectorType& p1) + { + mP1 = p1; + } + +private: + VectorType mP0; + VectorType mP1; +}; + +typedef Segment Segment2f; +typedef Segment Segment3f; + +#ifdef cafe +static_assert(sizeof(Segment2f) == 0x10, "sead::Segment size mismatch"); +static_assert(sizeof(Segment3f) == 0x18, "sead::Segment size mismatch"); +#endif // cafe + +} // namespace sead + +#endif // #define SEAD_LINE_H_ From d9611508ef1d4bc6f76a1a3801788b818c18b7f2 Mon Sep 17 00:00:00 2001 From: Esras Date: Mon, 25 Aug 2025 09:31:42 -0600 Subject: [PATCH 10/12] Add / Merge in Ray changes to seadLine.h --- include/geom/seadLine.h | 66 ++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/include/geom/seadLine.h b/include/geom/seadLine.h index e356a608..4a624717 100644 --- a/include/geom/seadLine.h +++ b/include/geom/seadLine.h @@ -1,62 +1,48 @@ -#ifndef SEAD_LINE_H_ -#define SEAD_LINE_H_ +#pragma once #include -namespace sead { +namespace sead +{ template class Segment { public: - typedef typename VectorType::ValueType T; + using T = typename VectorType::ValueType; public: - Segment() - : mP0(VectorType::zero) - , mP1(VectorType::ex) - { - } - - Segment(const VectorType& p0, const VectorType& p1) - : mP0(p0) - , mP1(p1) - { - } - - const VectorType& getPos0() const - { - return mP0; - } - - void setPos0(const VectorType& p0) - { - mP0 = p0; - } - - const VectorType& getPos1() const - { - return mP1; - } - - void setPos1(const VectorType& p1) - { - mP1 = p1; - } + Segment() : mP0(VectorType::zero), mP1(VectorType::ex) {} + Segment(const VectorType& p0, const VectorType& p1) : mP0(p0), mP1(p1) {} + + const VectorType& getPos0() const { return mP0; } + void setPos0(const VectorType& p0) { mP0 = p0; } + + const VectorType& getPos1() const { return mP1; } + void setPos1(const VectorType& p1) { mP1 = p1; } private: VectorType mP0; VectorType mP1; }; -typedef Segment Segment2f; -typedef Segment Segment3f; +using Segment2f = Segment; +using Segment3f = Segment; #ifdef cafe static_assert(sizeof(Segment2f) == 0x10, "sead::Segment size mismatch"); static_assert(sizeof(Segment3f) == 0x18, "sead::Segment size mismatch"); -#endif // cafe +#endif // cafe -} // namespace sead +template +class Ray +{ +public: + T position; + T direction; +}; -#endif // #define SEAD_LINE_H_ +using Ray2f = Ray; +using Ray3f = Ray; + +} // namespace sead From 9e121295f9c2f4ea049b7abf425f73d8bc0e646f Mon Sep 17 00:00:00 2001 From: Esras Date: Mon, 25 Aug 2025 09:38:19 -0600 Subject: [PATCH 11/12] Remove the seadGeometry.h that I created for now from the CMakeLists.txt, update the function definitions in seadGeometry (even though they are commented out), and match Camera::worldPosToCameraPosByMatrix. --- CMakeLists.txt | 2 -- include/gfx/seadProjection.h | 2 +- include/math/seadGeometry.h | 25 +++++++------------------ modules/src/gfx/seadCamera.cpp | 2 +- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b41c613f..ac1881ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,7 +138,6 @@ add_library(sead OBJECT include/math/seadBoundBox.h include/math/seadBoundBox.hpp - include/math/seadGeometry.h include/math/seadMathBase.h include/math/seadMathCalcCommon.h include/math/seadMathCalcCommon.hpp @@ -158,7 +157,6 @@ add_library(sead OBJECT include/math/seadVectorCalcCommon.hpp include/math/seadVectorFwd.h modules/src/math/seadBoundBox.cpp - modules/src/math/seadGeometry.cpp modules/src/math/seadMathCalcCommon.cpp modules/src/math/seadMatrix.cpp modules/src/math/seadQuat.cpp diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index d0f4fd3f..a3ef4fc7 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -140,7 +140,7 @@ class PerspectiveProjection : public Projection f32 mFovySin; f32 mFovyCos; f32 mFovyTan; - f32 mAspect = 1.333333f; + f32 mAspect = 4.0f / 3.0f; Vector2f mOffset = Vector2f::zero; }; #ifdef cafe diff --git a/include/math/seadGeometry.h b/include/math/seadGeometry.h index 1ae70d93..43877782 100644 --- a/include/math/seadGeometry.h +++ b/include/math/seadGeometry.h @@ -1,28 +1,17 @@ #pragma once +#include #include namespace sead { - -template -struct Ray -{ - Ray(); - - T position; - T direction; -}; - namespace Geometry { -float calcSquaredDistancePointToRay(Vector2* point, Ray>* ray, float* scalar); -// float calcSquaredDistancePointToLine(Vector2* const, Line>* const, -// float*); float calcSquaredDistancePointToSegment(Vector3* const, Segment>* -// const, float*); float calcSquaredDistancePointToSegment(); -// float calcSquaredDistanceSegmentToSegment(Segment>* const, -// Segment>* const, float*, float*); -// float calcSquaredDistanceRayToSegment(Ray> const&, Segment>* const, -// float*, float*); +float calcSquaredDistancePointToRay(Vector2f* point, Ray2f* ray, float* scalar); +// float calcSquaredDistancePointToLine(Vector2f* const, Line2f* const, float*); +// float calcSquaredDistancePointToSegment(Vector3f* const, Segment3f* const, float*); +// float calcSquaredDistancePointToSegment(); +// float calcSquaredDistanceSegmentToSegment(Segment2f* const, Segment2f* const, float*, float*); +// float calcSquaredDistanceRayToSegment(Ray2f const&, Segment2f* const, float*, float*); } // namespace Geometry } // namespace sead diff --git a/modules/src/gfx/seadCamera.cpp b/modules/src/gfx/seadCamera.cpp index 8b3e3d2d..05128893 100644 --- a/modules/src/gfx/seadCamera.cpp +++ b/modules/src/gfx/seadCamera.cpp @@ -40,7 +40,7 @@ void Camera::getUpVectorByMatrix(Vector3f* dst) const void Camera::worldPosToCameraPosByMatrix(Vector3f* dst, const Vector3f& world_pos) const { - *dst = mMatrix * world_pos; + dst->setMul(mMatrix, world_pos); } void Camera::cameraPosToWorldPosByMatrix(Vector3f* dst, const Vector3f& camera_pos) const From 91186dac05d10312377ba2bea9e2c88ab4007d8a Mon Sep 17 00:00:00 2001 From: Esras Date: Mon, 25 Aug 2025 09:41:51 -0600 Subject: [PATCH 12/12] Remove seadDrawContext from the CMakeLists. It was accidentally commited while working through other Projection code. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac1881ee..66e353a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,6 @@ add_library(sead OBJECT modules/src/gfx/nvn/seadDebugFontMgrNvn.cpp modules/src/gfx/seadCamera.cpp modules/src/gfx/seadColor.cpp - modules/src/gfx/seadDrawContext.cpp modules/src/gfx/seadDrawLockContext.cpp modules/src/gfx/seadFrameBuffer.cpp modules/src/gfx/seadGraphics.cpp