From b5229aaeaa3d343ff7e22a3d0745e017e3207f11 Mon Sep 17 00:00:00 2001 From: Esras Date: Fri, 9 Jun 2023 12:46:45 -0700 Subject: [PATCH 1/6] Add a number of the projection functions and headers to the library. This is not complete and not all of these match, but it's a good start on the process. --- CMakeLists.txt | 10 ++ include/gfx/seadDirectProjection.h | 38 ++++ include/gfx/seadFrustumProjection.h | 34 ++++ include/gfx/seadOrthoProjection.h | 42 +++++ include/gfx/seadPerspectiveProjection.h | 45 +++++ include/gfx/seadProjection.h | 52 ++---- include/gfx/seadViewport.h | 11 +- modules/src/gfx/seadDirectProjection.cpp | 53 ++++++ modules/src/gfx/seadFrustumProjection.cpp | 56 ++++++ modules/src/gfx/seadOrthoProjection.cpp | 98 +++++++++++ modules/src/gfx/seadPerspectiveProjection.cpp | 61 +++++++ modules/src/gfx/seadProjection.cpp | 19 +- modules/src/gfx/seadViewport.cpp | 165 ++++++++++++++++++ modules/src/resource/seadResource.cpp | 2 - 14 files changed, 642 insertions(+), 44 deletions(-) create mode 100644 include/gfx/seadDirectProjection.h create mode 100644 include/gfx/seadFrustumProjection.h create mode 100644 include/gfx/seadOrthoProjection.h create mode 100644 include/gfx/seadPerspectiveProjection.h create mode 100644 modules/src/gfx/seadDirectProjection.cpp create mode 100644 modules/src/gfx/seadFrustumProjection.cpp create mode 100644 modules/src/gfx/seadOrthoProjection.cpp create mode 100644 modules/src/gfx/seadPerspectiveProjection.cpp create mode 100644 modules/src/gfx/seadViewport.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b1c69c29..7dee2f47e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,13 +101,23 @@ add_library(sead OBJECT include/gfx/seadPrimitiveRenderer.h include/gfx/seadPrimitiveRendererUtil.h include/gfx/seadProjection.h + include/gfx/seadFrustumProjection.h + include/gfx/seadPerspectiveProjection.h + include/gfx/seadOrthoProjection.h + include/gfx/seadDirectProjection.h include/gfx/seadTexture.h + include/gfx/seadViewport.h modules/src/gfx/seadCamera.cpp modules/src/gfx/seadColor.cpp modules/src/gfx/seadFrameBuffer.cpp + modules/src/gfx/seadViewport.cpp # modules/src/gfx/seadPrimitiveRenderer.cpp # modules/src/gfx/seadPrimitiveRendererUtil.cpp modules/src/gfx/seadProjection.cpp + modules/src/gfx/seadFrustumProjection.cpp + modules/src/gfx/seadPerspectiveProjection.cpp + modules/src/gfx/seadOrthoProjection.cpp + modules/src/gfx/seadDirectProjection.cpp include/heap/seadArena.h include/heap/seadDisposer.h diff --git a/include/gfx/seadDirectProjection.h b/include/gfx/seadDirectProjection.h new file mode 100644 index 000000000..2ef50dfe1 --- /dev/null +++ b/include/gfx/seadDirectProjection.h @@ -0,0 +1,38 @@ +#pragma once +#include + +namespace sead +{ + +class DirectProjection : public Projection +{ + SEAD_RTTI_OVERRIDE(DirectProjection, Projection) +public: + DirectProjection(); + DirectProjection( + Matrix44f const& mtx, + Graphics::DevicePosture posture); // 0x7100b1e718 - Also initializes the Projection data + ~DirectProjection() override = default; + + void setDirectProjectionMatrix(Matrix44f const& mtx, Graphics::DevicePosture posture); + + float getNear() const override; + float getFar() const override; + float getFovy() const override; + float getAspect() const override; + void getOffset(sead::Vector2* offset) const override; + void updateAttributesForDirectProjection() override; + + // void setByViewport(sead::Viewport const& viewport); + // void setTBLR(float top, float bottom, float left, float right); + + // void doUpdateMatrix(Matrix44f* mtx) const override; + // void doScreenPosToCameraPosTo(sead::Vector3* pos_1, + // sead::Vector3 const& pos_2) const override; + ProjectionType getProjectionType() const override; + +private: + Matrix44f mDirectMatrix; +}; + +} // namespace sead diff --git a/include/gfx/seadFrustumProjection.h b/include/gfx/seadFrustumProjection.h new file mode 100644 index 000000000..6500ae408 --- /dev/null +++ b/include/gfx/seadFrustumProjection.h @@ -0,0 +1,34 @@ +#pragma once +#include + +namespace sead +{ + +class FrustumProjection : public Projection +{ + SEAD_RTTI_OVERRIDE(FrustumProjection, Projection) +public: + FrustumProjection(); + FrustumProjection(float near, float far, float top, float bottom, float left, float right); + ~FrustumProjection() override = default; + + float getNear() const override; + float getFar() const override; + float getFovy() const override; + float getAspect() const override; + void getOffset(Vector2f* offset) const override; + void updateAttributesForDirectProjection() override; + ProjectionType getProjectionType() const override; + void doUpdateMatrix(Matrix44f* mtx) const override; + void doScreenPosToCameraPosTo(Vector3f*, const Vector3f&) const override; + +private: + float mNear; + float mFar; + float mTop; + float mBottom; + float mLeft; + float mRight; +}; + +} // namespace sead diff --git a/include/gfx/seadOrthoProjection.h b/include/gfx/seadOrthoProjection.h new file mode 100644 index 000000000..2d8ddd9d3 --- /dev/null +++ b/include/gfx/seadOrthoProjection.h @@ -0,0 +1,42 @@ +#pragma once +#include + +namespace sead +{ + +class OrthoProjection : public Projection +{ + SEAD_RTTI_OVERRIDE(OrthoProjection, Projection) +public: + OrthoProjection(); + OrthoProjection(float near, float far, float top, float bottom, float left, float right); + OrthoProjection(float, float, Viewport* viewport); + ~OrthoProjection() override; + + float getNear() const override; + float getFar() const override; + float getFovy() const override; + float getAspect() const override; + void getOffset(sead::Vector2* offsetVec) const override; + + void setByViewport(sead::Viewport const& viewport); + void setTBLR(float top, float bottom, float left, float right); + + void doUpdateMatrix(Matrix44f* mtx) const override; + void doScreenPosToCameraPosTo(sead::Vector3* pos_1, + sead::Vector3 const& pos_2) const override; + bool checkDerivedRuntimeTypeInfo(RuntimeTypeInfo::Interface* interface); + RuntimeTypeInfo::Interface* getRuntimeTypeInfo(); + ProjectionType getProjectionType() const override; + +private: + float mNear; + float mFar; + float mTop; + float mBottom; + float mLeft; + float mRight; + // bool m01b; +}; + +} // namespace sead diff --git a/include/gfx/seadPerspectiveProjection.h b/include/gfx/seadPerspectiveProjection.h new file mode 100644 index 000000000..c2d34f946 --- /dev/null +++ b/include/gfx/seadPerspectiveProjection.h @@ -0,0 +1,45 @@ +#pragma once +#include + +namespace sead +{ + +class PerspectiveProjection : public Projection +{ + SEAD_RTTI_OVERRIDE(PerspectiveProjection, Projection) +public: + PerspectiveProjection(); + PerspectiveProjection(float near, float far, float fovy_rad, float aspect); + ~PerspectiveProjection() override; + + float getNear() const override; + float getFar() const override; + float getFovy() const override; + float getAspect() const override; + void getOffset(Vector2f* offset) const override; + void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; + ProjectionType getProjectionType() const override; + + void set(float near, float far, float fovy_rad, float aspect); + void doUpdateMatrix(Matrix44f* mtx) const override; + void setFovx_(float aFloat); + void setFovy_(float aFloat); + void createDividedProjection(sead::PerspectiveProjection* projection, int, int, int, int); + float getTop(); + float getBottom(); + float getLeft(); + float getRight(); + void setTBLR(float top, float bottom, float left, float right); + +private: + float mNear; + float mFar; + float mFovyRad; + float mFovySin; + float mFovyCos; + float mFovyTan; + float mAspect; + Vector2f mOffset; +}; + +} // namespace sead diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 4a2aa1350..001d14baa 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -14,21 +15,31 @@ class Projection SEAD_RTTI_BASE(Projection) public: + enum ProjectionType + { + cPerspectiveProjection = 0, + cOrthoProjection = 1, + cDirectProjection = 2, + }; + Projection(); - virtual ~Projection(); + virtual ~Projection() = default; + void markDirty() { this->mDirty = true; }; virtual float getNear() const = 0; virtual float getFar() const = 0; virtual float getFovy() const = 0; virtual float getAspect() const = 0; virtual void getOffset(Vector2f* offset) const = 0; virtual void updateAttributesForDirectProjection() = 0; - virtual u32 getProjectionType() const = 0; + virtual ProjectionType getProjectionType() const = 0; virtual void doUpdateMatrix(Matrix44f* mtx) const = 0; virtual void doUpdateDeviceMatrix(Matrix44f*, const Matrix44f&, Graphics::DevicePosture) const; virtual void doScreenPosToCameraPosTo(Vector3f*, const Vector3f&) const = 0; + virtual void unproject(Vector3f*, float, Camera*) const = 0; void updateMatrixImpl_() const; + const Matrix44f& getProjectionMatrix() const; const Matrix44f& getDeviceProjectionMatrix() const; private: @@ -41,43 +52,6 @@ class Projection f32 mDeviceZOffset; }; -class PerspectiveProjection : public Projection -{ - SEAD_RTTI_OVERRIDE(PerspectiveProjection, Projection) -public: - PerspectiveProjection(); - PerspectiveProjection(float near, float far, float fovy_rad, float aspect); - ~PerspectiveProjection() override; - - float getNear() const override; - float getFar() const override; - float getFovy() const override; - float getAspect() const override; - void getOffset(Vector2f* offset) const override; - void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; - u32 getProjectionType() const override; - - void set(float near, float far, float fovy_rad, float aspect); - void doUpdateMatrix(Matrix44f* mtx) const override; - void setFovx(float); - void createDividedProjection(sead::PerspectiveProjection* projection, int, int, int, int); - float getTop(); - float getBottom(); - float getLeft(); - float getRight(); - void setTBLR(float top, float bottom, float left, float right); - -private: - float mNear; - float mFar; - float mFovyRad; - float mFovySin; - float mFovyCos; - float mFovyTan; - float mAspect; - Vector2f mOffset; -}; - } // namespace sead #endif // SEAD_PROJECTION_H_ diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index 566aaf7c2..58e23bdee 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -1,25 +1,27 @@ #pragma once +#include #include #include #include +#include "prim/seadRuntimeTypeInfo.h" namespace sead { 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); explicit Viewport(const BoundBox2f& parent); - explicit Viewport(const LogicalFrameBuffer& buffer); + explicit Viewport(LogicalFrameBuffer const& buffer); virtual ~Viewport() = default; void setByFrameBuffer(const LogicalFrameBuffer& buffer); @@ -34,6 +36,11 @@ class Viewport : public BoundBox2f void unproject(Ray*, const Vector2f&, const Projection&, const Camera&) const; private: + inline void frameBufferHelper(const LogicalFrameBuffer& buffer); Graphics::DevicePosture mDevicePosture; + float mMaybeMinX; + float mMaybeMinY; + float mMaybeMaxX; + float mMaybeMaxY; }; } // namespace sead diff --git a/modules/src/gfx/seadDirectProjection.cpp b/modules/src/gfx/seadDirectProjection.cpp new file mode 100644 index 000000000..40a081fb5 --- /dev/null +++ b/modules/src/gfx/seadDirectProjection.cpp @@ -0,0 +1,53 @@ +#include + +namespace sead +{ + +DirectProjection::DirectProjection(Matrix44f const& mtx, Graphics::DevicePosture posture) +{ + mDirectMatrix = mtx; + switch (posture) + { + case Graphics::DevicePosture::cDevicePosture_RotateRight: + break; + case Graphics::DevicePosture::cDevicePosture_RotateLeft: + break; + case Graphics::DevicePosture::cDevicePosture_RotateHalfAround: + break; + case Graphics::DevicePosture::cDevicePosture_FlipY: + break; + } + + markDirty(); +} + +void DirectProjection::setDirectProjectionMatrix(const Matrix44f& mtx, + Graphics::DevicePosture posture) +{ + mDirectMatrix = mtx; + markDirty(); +} + +float DirectProjection::getNear() const +{ + return (float)0.0; +} +float DirectProjection::getFar() const +{ + return (float)0.0; +} +float DirectProjection::getFovy() const +{ + return (float)0.0; +} +float DirectProjection::getAspect() const +{ + return (float)0.0; +} +// void DirectProjection::getOffset(sead::Vector2* offset) const {} + +Projection::ProjectionType DirectProjection::getProjectionType() const +{ + return Projection::ProjectionType::cDirectProjection; +} +} // namespace sead diff --git a/modules/src/gfx/seadFrustumProjection.cpp b/modules/src/gfx/seadFrustumProjection.cpp new file mode 100644 index 000000000..62093b57d --- /dev/null +++ b/modules/src/gfx/seadFrustumProjection.cpp @@ -0,0 +1,56 @@ +#include + +namespace sead +{ +FrustumProjection::FrustumProjection(float near, float far, float top, float bottom, float left, + float right) +{ + mNear = near; + mFar = far; + mTop = top; + mBottom = bottom; + mLeft = left; + mRight = right; + markDirty(); +} + +float FrustumProjection::getNear() const +{ + return mNear; +} + +float FrustumProjection::getFar() const +{ + return mFar; +} + +void FrustumProjection::doScreenPosToCameraPosTo(Vector3f* screenPos, + const Vector3f& cameraPos) const +{ + screenPos->z = mNear; + screenPos->x = (float)0.5 * ((mRight + mLeft) + (mRight - mLeft) * cameraPos.x); + screenPos->y = (float)0.5 * ((mTop + mBottom) + (mTop - mBottom) * cameraPos.y); +} + +float FrustumProjection::getFovy() const +{ + float someVal = 1.0; // This appears to be a call into the mMatrix? + return (float)2.0 * atan2f((float)0.5 * (mTop - mBottom), someVal); +} + +float FrustumProjection::getAspect() const +{ + return (mRight - mLeft) / (mTop - mBottom); +} + +void FrustumProjection::getOffset(Vector2f* offset) const +{ + offset->x = (float)0.5 * (mRight + mLeft) / (mRight - mLeft); + offset->y = (float)0.5 * (mTop + mBottom) / (mTop - mBottom); +} + +Projection::ProjectionType FrustumProjection::getProjectionType() const +{ + return ProjectionType::cPerspectiveProjection; +} +} // namespace sead diff --git a/modules/src/gfx/seadOrthoProjection.cpp b/modules/src/gfx/seadOrthoProjection.cpp new file mode 100644 index 000000000..93fb74492 --- /dev/null +++ b/modules/src/gfx/seadOrthoProjection.cpp @@ -0,0 +1,98 @@ +#include +namespace sead +{ + +OrthoProjection::OrthoProjection(float near, float far, float top, float bottom, float left, + float right) +{ + mNear = near; + mFar = far; + mTop = top; + mBottom = bottom; + mLeft = left; + mRight = right; + markDirty(); +} + +Projection::ProjectionType OrthoProjection::getProjectionType() const +{ + return ProjectionType::cOrthoProjection; +} + +float OrthoProjection::getNear() const +{ + return this->mNear; +} + +float OrthoProjection::getFar() const +{ + return this->mFar; +} + +float OrthoProjection::getFovy() const +{ + return 0; +} + +float OrthoProjection::getAspect() const +{ + return (this->mRight - this->mLeft) / (this->mTop - this->mBottom); +} + +void OrthoProjection::getOffset(sead::Vector2f* offsetVec) const +{ + offsetVec->x = ((float)0.5 * (this->mLeft + this->mRight)) / (this->mRight - this->mLeft); + offsetVec->y = ((float)0.5 * (this->mTop + this->mBottom)) / (this->mTop - this->mBottom); +} + +void OrthoProjection::setTBLR(float top, float bottom, float left, float right) +{ + mTop = top; + mBottom = bottom; + mLeft = left; + mRight = right; + markDirty(); + // this->projectionType = ProjectionType::cOrthoProjection; +} + +// Decompiled code maybe makes assumption about initial state of the incoming matrix? +void OrthoProjection::doUpdateMatrix(Matrix44f* mtx) const +{ + // See https://learnwebgl.brown37.net/08_projections/projections_perspective.html for a + // description of the construction of the orthographic projection matrix. + + // There seems to be an assumption about the near (1) and far (2) projection planes + + mtx->m[0][0] = (float)1.0 / ((mRight - mLeft) * (float)0.5); + mtx->m[0][1] = 0; + mtx->m[0][2] = 0; + mtx->m[0][3] = -(float)1.0 * (mLeft + mRight) / (mRight - mLeft); + + mtx->m[1][0] = 0; + mtx->m[1][1] = (float)1.0 / ((mTop - mBottom) * (float)0.5); + mtx->m[1][2] = 0; + mtx->m[1][3] = -(float)1.0 * (mTop + mBottom) / (mTop - mBottom); + + mtx->m[2][0] = 0; + mtx->m[2][1] = 0; + mtx->m[2][2] = -(float)2.0 / (mFar - mNear); + mtx->m[2][3] = -((float)2.0 * mNear * mFar) / (mFar - mNear); + + mtx->m[3][0] = 0; + mtx->m[3][1] = 0; + mtx->m[3][2] = -(float)1.0; + mtx->m[3][3] = 0; +} + +void OrthoProjection::setByViewport(sead::Viewport const& viewport) +{ + Vector2f max = viewport.getMax(); + Vector2f min = viewport.getMin(); + mTop = (float)0.5 * (max.y - min.y); + mBottom = -(float)0.5 * (max.y - min.y); + mLeft = -(float)0.5 * (max.x - min.x); + mRight = (float)0.5 * (max.x - min.x); + markDirty(); +} + +} // namespace sead diff --git a/modules/src/gfx/seadPerspectiveProjection.cpp b/modules/src/gfx/seadPerspectiveProjection.cpp new file mode 100644 index 000000000..950c91895 --- /dev/null +++ b/modules/src/gfx/seadPerspectiveProjection.cpp @@ -0,0 +1,61 @@ +#include +#include + +namespace sead +{ + +PerspectiveProjection::PerspectiveProjection(float near, float far, float fovy_rad, float aspect) +{ + mNear = near; + mFar = far; + mFovyRad = fovy_rad; + mAspect = aspect; + + mFovySin = sinf((float)0.5 * fovy_rad); + mFovyCos = cosf((float)0.5 * fovy_rad); + mFovyTan = tanf((float)0.5 * fovy_rad); +} + +float PerspectiveProjection::getNear() const +{ + return mNear; +} + +float PerspectiveProjection::getFar() const +{ + return mFar; +} + +float PerspectiveProjection::getFovy() const +{ + return mFovyCos; +} + +float PerspectiveProjection::getAspect() const +{ + return mAspect; +} + +Projection::ProjectionType PerspectiveProjection::getProjectionType() const +{ + return ProjectionType::cPerspectiveProjection; +} + +// void PerspectiveProjection::setFovx_(float aFloat) {} + +void PerspectiveProjection::setFovy_(float aFloat) +{ + mFovyCos = aFloat; + mFovyTan = sinf((float)0.5 * aFloat); + mOffset.set(cosf((float)0.5 * aFloat), tanf((float)0.5 * aFloat)); +} + +// void PerspectiveProjection::doUpdateMatrix(Matrix44f* mtx) const +// { +// float temp = 1.0; +// mtx->m[0][0] = (this->mFovyRad + this->mFovyRad) * (1.0 / temp); +// mtx->m[0][1] = 0.0; +// mtx->m[0][3] = 0.0; +// } + +} // namespace sead diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 4179f1e98..83ca70dcb 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -13,7 +13,6 @@ void Projection::updateMatrixImpl_() const doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); mDeviceDirty = false; } - else if (mDeviceDirty) { doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); @@ -21,6 +20,24 @@ void Projection::updateMatrixImpl_() const } } +const Matrix44f& Projection::getProjectionMatrix() const +{ + if (!mDirty) + { + if (!mDeviceDirty) + { + return mMatrix; + } + } + else + { + updateMatrixImpl_(); + mDeviceDirty = false; + } + + return mMatrix; +} + const Matrix44f& Projection::getDeviceProjectionMatrix() const { updateMatrixImpl_(); diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp new file mode 100644 index 000000000..f44a6cf23 --- /dev/null +++ b/modules/src/gfx/seadViewport.cpp @@ -0,0 +1,165 @@ +#include +#include +#include "math/seadBoundBox.h" +#include "math/seadMathCalcCommon.h" + +namespace sead +{ + +Viewport::Viewport() +{ + mMaybeMinX = 0.0; + mMaybeMinY = 1.0; +} + +Viewport::Viewport(float left, float top, float right, float bottom) + : BoundBox2f(left, top, right, bottom) +{ + // float max = left + right; + // float min = left; + + // if (max <= min) + // { + // max = left; + // min = right; + // } + // this->mMaybeMinX = min; + // this->mMaybeMaxX = max; + + // min = top; + // max = bottom + top; + // if (max <= min) + // { + // max = top; + // min = bottom; + // } + // this->mMaybeMinY = min; + // this->mMaybeMaxY = max; + + // // If L + R is smaller, then the left bound is the max X. + // if ((left + right) <= left) + // { + // this->mMaybeMinX = left + right; + // this->mMaybeMaxX = left; + // } + // else + // { + // this->mMaybeMinX = left; + // this->mMaybeMaxX = left + right; + // } + + // // Same deal for top and bottom + // if ((top + bottom) <= top) + // { + // this->mMaybeMinY = top + bottom; + // this->mMaybeMaxY = top; + // } + // else + // { + // this->mMaybeMinY = top; + // this->mMaybeMaxY = top + bottom; + // } +} + +Viewport::Viewport(LogicalFrameBuffer const& buffer) +{ + setByFrameBuffer(buffer); +} + +void Viewport::setByFrameBuffer(const LogicalFrameBuffer& buffer) +{ + mMaybeMinX = 0.0; + mMaybeMinY = 1.0; + + // mDevicePosture = // Some Global device posture // + if (mDevicePosture <= Graphics::DevicePosture::cDevicePosture_FlipY) + { + float minX; + float maxX; + float minY; + float maxY; + if (mDevicePosture == Graphics::DevicePosture::cDevicePosture_RotateLeft || + mDevicePosture == Graphics::DevicePosture::cDevicePosture_RotateHalfAround) + { + maxX = buffer.getVirtualSize().x; + maxY = buffer.getVirtualSize().y; + } + else + { + maxY = buffer.getVirtualSize().x; + maxX = buffer.getVirtualSize().y; + } + + minY = fmin(maxY, (float)0.0); + if (maxY < 0.0) + { + maxY = 0.0; + } + + minX = fmin(maxX, (float)0.0); + if (maxX < 0.0) + { + maxX = 0.0; + } + + set(minX, minY, maxX, maxY); + } +} + +// void Viewport::apply(DrawContext*, const LogicalFrameBuffer& buffer) const {} + +// void Viewport::getOnFrameBufferPos(Vector2f* out, const LogicalFrameBuffer& buffer) const +// { +// switch (mDevicePosture) +// { +// case Graphics::DevicePosture::cDevicePosture_Same: +// case Graphics::DevicePosture::cDevicePosture_RotateRight: +// case Graphics::DevicePosture::cDevicePosture_RotateLeft: +// case Graphics::DevicePosture::cDevicePosture_RotateHalfAround: +// case Graphics::DevicePosture::cDevicePosture_FlipX: +// case Graphics::DevicePosture::cDevicePosture_FlipY: +// default: +// break; +// } +// } + +void Viewport::getOnFrameBufferSize(Vector2f* out, const LogicalFrameBuffer& buffer) const +{ + out->x = getSizeX(); + out->y = getSizeY(); + + if (mDevicePosture - 1 < Graphics::DevicePosture::cDevicePosture_RotateLeft) + { + out->x = getSizeY(); + out->y = getSizeX(); + } + out->x = out->x / buffer.getVirtualSize().x; + out->y = out->y / buffer.getVirtualSize().y; + out->x = out->x * buffer.getPhysicalArea().getSizeX(); + out->y = out->y * buffer.getPhysicalArea().getSizeY(); +} + +// void Viewport::applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const {} +// void Viewport::applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const {} + +void Viewport::project(Vector2f* aVec, const Vector2f& bVec) const +{ + aVec->x = (float)0.5 * (mMaybeMaxX - mMaybeMinX) * bVec.x; + aVec->y = (float)0.5 * (mMaybeMaxY - mMaybeMinY) * bVec.y; +} + +void Viewport::unproject(Vector3f* some3Vec, const Vector2f& some2Vec, const Projection& projection, + const Camera& camera) const +{ + float some_value; + some_value = some2Vec.x / getHalfSizeX(); +} +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 diff --git a/modules/src/resource/seadResource.cpp b/modules/src/resource/seadResource.cpp index 5b8c0d159..539781eff 100644 --- a/modules/src/resource/seadResource.cpp +++ b/modules/src/resource/seadResource.cpp @@ -22,8 +22,6 @@ s32 DirectResource::getLoadDataAlignment() const return 4; } -void DirectResource::doCreate_(u8*, u32, Heap*) {} - void DirectResource::create(u8* buffer, u32 bufferSize, u32 allocSize, bool allocated, Heap* heap) { if (mRawData) From 82b43bdfb03cb557752f077a98b8da229e7b5cb0 Mon Sep 17 00:00:00 2001 From: Esras Date: Fri, 9 Jun 2023 13:30:24 -0700 Subject: [PATCH 2/6] Match sead::Projection::getProjectionMatrix() --- modules/src/gfx/seadProjection.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 83ca70dcb..4e85f3a5c 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -31,10 +31,13 @@ const Matrix44f& Projection::getProjectionMatrix() const } else { - updateMatrixImpl_(); - mDeviceDirty = false; + doUpdateMatrix(const_cast(&mMatrix)); + mDirty = false; + mDeviceDirty = true; } + doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); + mDeviceDirty = false; return mMatrix; } From ab1c16f7e0996195248869110ac4361b3fca82f6 Mon Sep 17 00:00:00 2001 From: Esras Date: Fri, 9 Jun 2023 18:33:06 -0700 Subject: [PATCH 3/6] Add more functions and matching for the library functions for Projection. --- include/gfx/seadDirectProjection.h | 6 ++ include/gfx/seadOrthoProjection.h | 3 +- include/gfx/seadPerspectiveProjection.h | 4 +- include/gfx/seadProjection.h | 11 +++- include/gfx/seadViewport.h | 8 +-- modules/src/gfx/seadDirectProjection.cpp | 44 +++++++++----- modules/src/gfx/seadFrustumProjection.cpp | 10 ++-- modules/src/gfx/seadOrthoProjection.cpp | 12 ++++ modules/src/gfx/seadPerspectiveProjection.cpp | 58 ++++++++++++++----- modules/src/gfx/seadProjection.cpp | 42 ++++++++++++++ modules/src/gfx/seadViewport.cpp | 12 ++-- 11 files changed, 164 insertions(+), 46 deletions(-) diff --git a/include/gfx/seadDirectProjection.h b/include/gfx/seadDirectProjection.h index 2ef50dfe1..01c38c47f 100644 --- a/include/gfx/seadDirectProjection.h +++ b/include/gfx/seadDirectProjection.h @@ -33,6 +33,12 @@ class DirectProjection : public Projection private: Matrix44f mDirectMatrix; + float mNear; + float mFar; + float mFovy; + float mAspect; + Vector2f mOffset; + float mUnknown7; }; } // namespace sead diff --git a/include/gfx/seadOrthoProjection.h b/include/gfx/seadOrthoProjection.h index 2d8ddd9d3..7bd019404 100644 --- a/include/gfx/seadOrthoProjection.h +++ b/include/gfx/seadOrthoProjection.h @@ -11,13 +11,14 @@ class OrthoProjection : public Projection OrthoProjection(); OrthoProjection(float near, float far, float top, float bottom, float left, float right); OrthoProjection(float, float, Viewport* viewport); - ~OrthoProjection() override; + ~OrthoProjection() override = default; float getNear() const override; float getFar() const override; float getFovy() const override; float getAspect() const override; void getOffset(sead::Vector2* offsetVec) const override; + void updateAttributesForDirectProjection() override; void setByViewport(sead::Viewport const& viewport); void setTBLR(float top, float bottom, float left, float right); diff --git a/include/gfx/seadPerspectiveProjection.h b/include/gfx/seadPerspectiveProjection.h index c2d34f946..4ae84dcc9 100644 --- a/include/gfx/seadPerspectiveProjection.h +++ b/include/gfx/seadPerspectiveProjection.h @@ -10,7 +10,7 @@ class PerspectiveProjection : public Projection public: PerspectiveProjection(); PerspectiveProjection(float near, float far, float fovy_rad, float aspect); - ~PerspectiveProjection() override; + ~PerspectiveProjection() override = default; float getNear() const override; float getFar() const override; @@ -23,7 +23,7 @@ class PerspectiveProjection : public Projection void set(float near, float far, float fovy_rad, float aspect); void doUpdateMatrix(Matrix44f* mtx) const override; void setFovx_(float aFloat); - void setFovy_(float aFloat); + void setFovy_(float newFovy); void createDividedProjection(sead::PerspectiveProjection* projection, int, int, int, int); float getTop(); float getBottom(); diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 001d14baa..774ecc127 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -8,6 +8,8 @@ #include #include +#define GLOBAL_DEVICE_Z_SCALE 1.0 + namespace sead { class Projection @@ -25,17 +27,20 @@ class Projection Projection(); virtual ~Projection() = default; - void markDirty() { this->mDirty = true; }; + void markDirty() { mDirty = true; }; + void markDeviceDirty() { mDeviceDirty = true; }; virtual float getNear() const = 0; virtual float getFar() const = 0; virtual float getFovy() const = 0; virtual float getAspect() const = 0; virtual void getOffset(Vector2f* offset) const = 0; - virtual void updateAttributesForDirectProjection() = 0; + virtual void updateAttributesForDirectProjection(); virtual ProjectionType getProjectionType() const = 0; virtual void doUpdateMatrix(Matrix44f* mtx) const = 0; virtual void doUpdateDeviceMatrix(Matrix44f*, const Matrix44f&, Graphics::DevicePosture) const; - virtual void doScreenPosToCameraPosTo(Vector3f*, const Vector3f&) const = 0; + virtual void doScreenPosToCameraPosTo(Vector3f* screen, const Vector3f& cam) const; + virtual void someFunction(Camera* camera) const; + virtual void project(Vector2f* aVec, Vector3f* bVec) const; virtual void unproject(Vector3f*, float, Camera*) const = 0; void updateMatrixImpl_() const; diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index 58e23bdee..0a04443e9 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -38,9 +38,9 @@ class Viewport : public BoundBox2f private: inline void frameBufferHelper(const LogicalFrameBuffer& buffer); Graphics::DevicePosture mDevicePosture; - float mMaybeMinX; - float mMaybeMinY; - float mMaybeMaxX; - float mMaybeMaxY; + float mMinX; + float mMinY; + float mMaxX; + float mMaxY; }; } // namespace sead diff --git a/modules/src/gfx/seadDirectProjection.cpp b/modules/src/gfx/seadDirectProjection.cpp index 40a081fb5..3867d48f8 100644 --- a/modules/src/gfx/seadDirectProjection.cpp +++ b/modules/src/gfx/seadDirectProjection.cpp @@ -3,7 +3,26 @@ namespace sead { +DirectProjection::DirectProjection() +{ + mDirectMatrix.makeIdentity(); + mNear = 0.0; + mFar = 0.0; + mFovy = 0.0; + mAspect = 0.0; + mOffset.set(0.0, 0.0); + mUnknown7 = 1; + markDirty(); + markDeviceDirty(); +} + DirectProjection::DirectProjection(Matrix44f const& mtx, Graphics::DevicePosture posture) +{ + setDirectProjectionMatrix(mtx, posture); +} + +void DirectProjection::setDirectProjectionMatrix(const Matrix44f& mtx, + Graphics::DevicePosture posture) { mDirectMatrix = mtx; switch (posture) @@ -17,34 +36,33 @@ DirectProjection::DirectProjection(Matrix44f const& mtx, Graphics::DevicePosture case Graphics::DevicePosture::cDevicePosture_FlipY: break; } - - markDirty(); -} - -void DirectProjection::setDirectProjectionMatrix(const Matrix44f& mtx, - Graphics::DevicePosture posture) -{ - mDirectMatrix = mtx; markDirty(); } float DirectProjection::getNear() const { - return (float)0.0; + return mNear; } + float DirectProjection::getFar() const { - return (float)0.0; + return mFar; } + float DirectProjection::getFovy() const { - return (float)0.0; + return mFovy; } + float DirectProjection::getAspect() const { - return (float)0.0; + return mAspect; +} + +void DirectProjection::getOffset(sead::Vector2* offset) const +{ + offset->set(mOffset); } -// void DirectProjection::getOffset(sead::Vector2* offset) const {} Projection::ProjectionType DirectProjection::getProjectionType() const { diff --git a/modules/src/gfx/seadFrustumProjection.cpp b/modules/src/gfx/seadFrustumProjection.cpp index 62093b57d..f00c55445 100644 --- a/modules/src/gfx/seadFrustumProjection.cpp +++ b/modules/src/gfx/seadFrustumProjection.cpp @@ -34,8 +34,7 @@ void FrustumProjection::doScreenPosToCameraPosTo(Vector3f* screenPos, float FrustumProjection::getFovy() const { - float someVal = 1.0; // This appears to be a call into the mMatrix? - return (float)2.0 * atan2f((float)0.5 * (mTop - mBottom), someVal); + return (float)2.0 * atan2f((float)0.5 * (mTop - mBottom), getNear()); } float FrustumProjection::getAspect() const @@ -45,8 +44,11 @@ float FrustumProjection::getAspect() const void FrustumProjection::getOffset(Vector2f* offset) const { - offset->x = (float)0.5 * (mRight + mLeft) / (mRight - mLeft); - offset->y = (float)0.5 * (mTop + mBottom) / (mTop - mBottom); + float denom = mRight - mLeft; + offset->x = (float)0.5 * (mRight + mLeft) / denom; + + denom = mTop - mBottom; + offset->y = (float)0.5 * (mTop + mBottom) / denom; } Projection::ProjectionType FrustumProjection::getProjectionType() const diff --git a/modules/src/gfx/seadOrthoProjection.cpp b/modules/src/gfx/seadOrthoProjection.cpp index 93fb74492..5e0717ace 100644 --- a/modules/src/gfx/seadOrthoProjection.cpp +++ b/modules/src/gfx/seadOrthoProjection.cpp @@ -2,6 +2,17 @@ namespace sead { +OrthoProjection::OrthoProjection() +{ + mFar = 1.0; + mNear = 0.0; + mTop = 0.5; + mBottom = -0.5; + mLeft = -0.5; + mRight = 0.5; + markDirty(); +} + OrthoProjection::OrthoProjection(float near, float far, float top, float bottom, float left, float right) { @@ -84,6 +95,7 @@ void OrthoProjection::doUpdateMatrix(Matrix44f* mtx) const mtx->m[3][3] = 0; } +// NON-MATCHING: Registers for multiplation, looks like ordering? void OrthoProjection::setByViewport(sead::Viewport const& viewport) { Vector2f max = viewport.getMax(); diff --git a/modules/src/gfx/seadPerspectiveProjection.cpp b/modules/src/gfx/seadPerspectiveProjection.cpp index 950c91895..553166e65 100644 --- a/modules/src/gfx/seadPerspectiveProjection.cpp +++ b/modules/src/gfx/seadPerspectiveProjection.cpp @@ -4,16 +4,22 @@ namespace sead { -PerspectiveProjection::PerspectiveProjection(float near, float far, float fovy_rad, float aspect) +PerspectiveProjection::PerspectiveProjection() { - mNear = near; - mFar = far; - mFovyRad = fovy_rad; - mAspect = aspect; + mNear = 1.0; + mFar = 1000.0; + mOffset.set(float(4.0 / 3.0), 0.0); + mFovyRad = M_PI / 4.0; // pi / 4 radians or 45 degrees + mFovySin = sinf(mFovyRad / (float)2.0); + mFovyCos = cosf(mFovyRad / (float)2.0); + mFovyTan = tanf(mFovyRad / (float)2.0); + markDirty(); +} - mFovySin = sinf((float)0.5 * fovy_rad); - mFovyCos = cosf((float)0.5 * fovy_rad); - mFovyTan = tanf((float)0.5 * fovy_rad); +PerspectiveProjection::PerspectiveProjection(float near, float far, float fovy_rad, float aspect) +{ + mOffset.set((float)0.0, (float)0.0); + set(near, far, fovy_rad, aspect); } float PerspectiveProjection::getNear() const @@ -28,7 +34,7 @@ float PerspectiveProjection::getFar() const float PerspectiveProjection::getFovy() const { - return mFovyCos; + return mFovyRad; } float PerspectiveProjection::getAspect() const @@ -36,18 +42,44 @@ float PerspectiveProjection::getAspect() const return mAspect; } +void PerspectiveProjection::getOffset(Vector2f* offset) const +{ + offset->set(mOffset); +} + Projection::ProjectionType PerspectiveProjection::getProjectionType() const { return ProjectionType::cPerspectiveProjection; } +void PerspectiveProjection::set(float near, float far, float fovy_rad, float aspect) +{ + mNear = near; + mFar = far; + markDirty(); + mFovyRad = fovy_rad; + + mFovySin = sinf((float)0.5 * fovy_rad); + mFovyCos = cosf((float)0.5 * fovy_rad); + mFovyTan = tanf((float)0.5 * fovy_rad); + + mAspect = aspect; + markDirty(); +} + +// set +// do Update + // void PerspectiveProjection::setFovx_(float aFloat) {} -void PerspectiveProjection::setFovy_(float aFloat) +void PerspectiveProjection::setFovy_(float newFovy) { - mFovyCos = aFloat; - mFovyTan = sinf((float)0.5 * aFloat); - mOffset.set(cosf((float)0.5 * aFloat), tanf((float)0.5 * aFloat)); + float local = (float)0.5 * newFovy; + mFovyRad = newFovy; + mFovySin = sinf(local); + mFovyCos = cosf(local); + mFovyTan = tanf(local); + markDirty(); } // void PerspectiveProjection::doUpdateMatrix(Matrix44f* mtx) const diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 4e85f3a5c..6ad0da40f 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -2,6 +2,16 @@ namespace sead { + +Projection::Projection() +{ + markDirty(); + markDeviceDirty(); + mDevicePosture = Graphics::DevicePosture::cDevicePosture_Same; // Global + mDeviceZScale = GLOBAL_DEVICE_Z_SCALE; // Global + mDeviceZOffset = 1.0; // Some Global Var. +} + void Projection::updateMatrixImpl_() const { if (mDirty) @@ -47,4 +57,36 @@ const Matrix44f& Projection::getDeviceProjectionMatrix() const return mDeviceMatrix; } +void Projection::doUpdateDeviceMatrix(Matrix44f* deviceMatrix, const Matrix44f& projMatrix, + Graphics::DevicePosture posture) const +{ + /* What this does: + 1. Copy the data into the device matrix + 2. Modify the device matrix based on the device orientation + a. + 3. Scale the Z axis by the Device Z scale and include the zOffset. + + */ + *deviceMatrix = projMatrix; + switch (posture) + { + case Graphics::DevicePosture::cDevicePosture_RotateRight: + case Graphics::DevicePosture::cDevicePosture_RotateLeft: + case Graphics::DevicePosture::cDevicePosture_RotateHalfAround: + case Graphics::DevicePosture::cDevicePosture_FlipX: + case Graphics::DevicePosture::cDevicePosture_FlipY: + default: + break; + } +} + +// void sead::Projection::someFunction(Camera* camera) +// { +// doScreenPosToCameraPosTo(Vector3f*, const Vector3f&); +// camera.Camera(); // ??? +// } + +// Intentional empty implementation +void Projection::updateAttributesForDirectProjection() {} + } // namespace sead diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp index f44a6cf23..bc4b17942 100644 --- a/modules/src/gfx/seadViewport.cpp +++ b/modules/src/gfx/seadViewport.cpp @@ -8,8 +8,8 @@ namespace sead Viewport::Viewport() { - mMaybeMinX = 0.0; - mMaybeMinY = 1.0; + mMinX = 0.0; + mMinY = 1.0; } Viewport::Viewport(float left, float top, float right, float bottom) @@ -68,8 +68,8 @@ Viewport::Viewport(LogicalFrameBuffer const& buffer) void Viewport::setByFrameBuffer(const LogicalFrameBuffer& buffer) { - mMaybeMinX = 0.0; - mMaybeMinY = 1.0; + mMinX = 0.0; + mMinY = 1.0; // mDevicePosture = // Some Global device posture // if (mDevicePosture <= Graphics::DevicePosture::cDevicePosture_FlipY) @@ -144,8 +144,8 @@ void Viewport::getOnFrameBufferSize(Vector2f* out, const LogicalFrameBuffer& buf void Viewport::project(Vector2f* aVec, const Vector2f& bVec) const { - aVec->x = (float)0.5 * (mMaybeMaxX - mMaybeMinX) * bVec.x; - aVec->y = (float)0.5 * (mMaybeMaxY - mMaybeMinY) * bVec.y; + aVec->x = (float)0.5 * (mMaxX - mMinX) * bVec.x; + aVec->y = (float)0.5 * (mMaxY - mMinY) * bVec.y; } void Viewport::unproject(Vector3f* some3Vec, const Vector2f& some2Vec, const Projection& projection, From 87db9b3a5a00b6fef6b25b4f1e2cf00af1c22153 Mon Sep 17 00:00:00 2001 From: Esras Date: Fri, 9 Jun 2023 18:33:23 -0700 Subject: [PATCH 4/6] Fix a minor bug where Matrix44f couldn't use the makeIdentity 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 d8f2a39e8..c366e3153 100644 --- a/include/math/seadMatrix.hpp +++ b/include/math/seadMatrix.hpp @@ -605,7 +605,7 @@ inline Matrix44& Matrix44::operator=(const Self& n) template inline void Matrix44::makeIdentity() { - Matrix44CalcCommon::makeIdentity(); + Matrix44CalcCommon::makeIdentity(*this); } template From c6dbabd1af0077768680911a74ece12e59c67afe Mon Sep 17 00:00:00 2001 From: Esras Date: Wed, 14 Jun 2023 18:33:45 -0700 Subject: [PATCH 5/6] WIP: Merge work from another branch and split among files again. --- CMakeLists.txt | 2 + include/gfx/nin/seadGraphicsNvn.h | 68 +++++ include/gfx/seadCamera.h | 66 ++++- include/gfx/seadDirectProjection.h | 46 +-- include/gfx/seadDrawContext.h | 16 +- include/gfx/seadDrawLockContext.h | 23 ++ include/gfx/seadFrustumProjection.h | 59 ++-- include/gfx/seadGraphics.h | 253 ++++++++++++++++- include/gfx/seadOrthoProjection.h | 61 ++-- include/gfx/seadPerspectiveProjection.h | 97 +++++-- include/gfx/seadProjection.h | 72 +++-- include/gfx/seadViewport.h | 44 +-- include/math/seadMatrix.hpp | 2 +- modules/src/gfx/seadDirectProjection.cpp | 67 ++--- modules/src/gfx/seadDrawLockContext.cpp | 20 ++ modules/src/gfx/seadFrustumProjection.cpp | 80 ++++-- modules/src/gfx/seadGraphics.cpp | 44 +++ modules/src/gfx/seadOrthoProjection.cpp | 133 +++++---- modules/src/gfx/seadPerspectiveProjection.cpp | 132 +++++---- modules/src/gfx/seadProjection.cpp | 160 +++++++---- modules/src/gfx/seadViewport.cpp | 264 ++++++++++-------- 21 files changed, 1180 insertions(+), 529 deletions(-) create mode 100644 include/gfx/nin/seadGraphicsNvn.h create mode 100644 include/gfx/seadDrawLockContext.h create mode 100644 modules/src/gfx/seadDrawLockContext.cpp create mode 100644 modules/src/gfx/seadGraphics.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dee2f47e..74fa3aaf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,7 @@ add_library(sead OBJECT include/gfx/seadCamera.h include/gfx/seadColor.h include/gfx/seadDrawContext.h + include/gfx/seadDrawLockContext.h include/gfx/seadFrameBuffer.h include/gfx/seadPrimitiveRenderer.h include/gfx/seadPrimitiveRendererUtil.h @@ -109,6 +110,7 @@ add_library(sead OBJECT include/gfx/seadViewport.h modules/src/gfx/seadCamera.cpp modules/src/gfx/seadColor.cpp + modules/src/gfx/seadDrawLockContext.cpp modules/src/gfx/seadFrameBuffer.cpp modules/src/gfx/seadViewport.cpp # modules/src/gfx/seadPrimitiveRenderer.cpp diff --git a/include/gfx/nin/seadGraphicsNvn.h b/include/gfx/nin/seadGraphicsNvn.h new file mode 100644 index 000000000..db6207b17 --- /dev/null +++ b/include/gfx/nin/seadGraphicsNvn.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include "nvn/nvn.h" + +namespace sead +{ +class GraphicsNvn : public Graphics +{ +public: + class CreateArg; + + GraphicsNvn(const CreateArg& arg); + + void initializeDrawLockContext(Heap*); + void initializeImpl(Heap*); + + int getNewTextureId(); + NVNdevice* getNvnDevice() const { return mNvnDevice; } + NVNtexturePool* getTexturePool() { return &mNvnTexturePool; } + int getTextureSamplerID() const { return mTextureSamplerID; } + CriticalSection* getCriticalSection2() { return &mCriticalSection2; } + +private: + NVNdevice* mNvnDevice; + void* _38; + void* _40; + void* _48; + void* _50; + NVNtexturePool mNvnTexturePool; + void* _78; + void* _80; + void* _88; + void* _90; + void* _98; + void* _A0; + void* _A8; + void* _B0; + void* _B8; + void* _C0; + void* _C8; + void* _D0; + void* _D8; + void* _E0; + void* _E8; + void* _F0; + int mTextureSamplerID; + void* _100; + int _108; + int _10C; + int _110; + int _114; + CriticalSection mCriticalSection1; + CriticalSection mCriticalSection2; + CriticalSection mCriticalSection3; + void* _1D8; + void* _1E0; + void* _1E8; + void* _1F0; + void* _1F8; + bool _200; + bool _201; + bool _202; +}; +// static_assert(sizeof(GraphicsNvn) == 0x208); + +} // namespace sead diff --git a/include/gfx/seadCamera.h b/include/gfx/seadCamera.h index a5519ca8c..fdee22523 100644 --- a/include/gfx/seadCamera.h +++ b/include/gfx/seadCamera.h @@ -1,5 +1,4 @@ -#ifndef SEAD_CAMERA_H_ -#define SEAD_CAMERA_H_ +#pragma once #include #include @@ -7,6 +6,12 @@ namespace sead { +class OrthoProjection; +class Projection; +class Viewport; +template +class Ray; + class Camera { SEAD_RTTI_BASE(Camera) @@ -15,8 +20,26 @@ class Camera Camera() = default; virtual ~Camera(); - virtual void doUpdateMatrix(Matrix34f* mtx) const = 0; + virtual void doUpdateMatrix(Matrix34f* dst) const = 0; + + void getWorldPosByMatrix(Vector3f* dst) const; + void getLookVectorByMatrix(Vector3f* dst) const; + void getRightVectorByMatrix(Vector3f* dst) const; + void getUpVectorByMatrix(Vector3f* dst) const; + + void worldPosToCameraPosByMatrix(Vector3f* dst, const Vector3f& world_pos) const; + void cameraPosToWorldPosByMatrix(Vector3f* dst, const Vector3f& camera_pos) const; + + void projectByMatrix(Vector2f* dst, const Vector3f& world_pos, const Projection& projection, + const Viewport& viewport) const; + void unprojectRayByMatrix(Ray* dst, const Vector3f& camera_pos) const; + + Matrix34f& getMatrix() { return mMatrix; } + const Matrix34f& getMatrix() const { return mMatrix; } + void updateViewMatrix() { doUpdateMatrix(&mMatrix); } + +private: Matrix34f mMatrix = Matrix34f::ident; }; @@ -24,7 +47,11 @@ class LookAtCamera : public Camera { SEAD_RTTI_OVERRIDE(LookAtCamera, Camera) public: + LookAtCamera() = default; LookAtCamera(const Vector3f& pos, const Vector3f& at, const Vector3f& up); + ~LookAtCamera() override; + + void doUpdateMatrix(Matrix34f* dst) const override; Vector3f& getPos() { return mPos; } Vector3f& getAt() { return mAt; } @@ -33,13 +60,34 @@ class LookAtCamera : public Camera const Vector3f& getAt() const { return mAt; } const Vector3f& getUp() const { return mUp; } - void doUpdateMatrix(Matrix34f* mtx) const override; +private: + Vector3f mPos = {0.0f, 0.0f, 10.0f}; + Vector3f mAt = {0.0f, 0.0f, 0.0f}; + Vector3f mUp = {0.0f, 1.0f, 0.0f}; +}; + +class DirectCamera : public Camera +{ + SEAD_RTTI_OVERRIDE(DirectCamera, Camera) +public: + virtual ~DirectCamera(); + + void doUpdateMatrix(Matrix34f* dst) const override; private: - Vector3f mPos; - Vector3f mAt; - Vector3f mUp; + Matrix34f mDirectMatrix = Matrix34f::ident; }; -} // namespace sead -#endif // SEAD_CAMERA_H_ +class OrthoCamera : public LookAtCamera +{ + SEAD_RTTI_OVERRIDE(OrthoCamera, LookAtCamera) +public: + OrthoCamera(); + OrthoCamera(const Vector2f&, float); + OrthoCamera(const OrthoProjection&); + ~OrthoCamera() override; + + void setByOrthoProjection(const OrthoProjection&); + void setRotation(float rotation); +}; +} // namespace sead diff --git a/include/gfx/seadDirectProjection.h b/include/gfx/seadDirectProjection.h index 01c38c47f..4d268e3d5 100644 --- a/include/gfx/seadDirectProjection.h +++ b/include/gfx/seadDirectProjection.h @@ -7,38 +7,38 @@ namespace sead class DirectProjection : public Projection { SEAD_RTTI_OVERRIDE(DirectProjection, Projection) + public: DirectProjection(); - DirectProjection( - Matrix44f const& mtx, - Graphics::DevicePosture posture); // 0x7100b1e718 - Also initializes the Projection data + DirectProjection(const Matrix44f* mtx, Graphics::DevicePosture posture); ~DirectProjection() override = default; - void setDirectProjectionMatrix(Matrix44f const& mtx, Graphics::DevicePosture posture); - - float getNear() const override; - float getFar() const override; - float getFovy() const override; - float getAspect() const override; - void getOffset(sead::Vector2* offset) const override; void updateAttributesForDirectProjection() 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; } - // void setByViewport(sead::Viewport const& viewport); - // void setTBLR(float top, float bottom, float left, float right); + f32 getAspect() const override { return mAspect; } + void getOffset(Vector2f* offset) const override { *offset = mOffset; } - // void doUpdateMatrix(Matrix44f* mtx) const override; - // void doScreenPosToCameraPosTo(sead::Vector3* pos_1, - // sead::Vector3 const& pos_2) const override; - ProjectionType getProjectionType() const override; + void doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const override; private: - Matrix44f mDirectMatrix; - float mNear; - float mFar; - float mFovy; - float mAspect; - Vector2f mOffset; - float mUnknown7; + 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 diff --git a/include/gfx/seadDrawContext.h b/include/gfx/seadDrawContext.h index 7845b403a..d5dc3215e 100644 --- a/include/gfx/seadDrawContext.h +++ b/include/gfx/seadDrawContext.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include "basis/seadTypes.h" #include "prim/seadRuntimeTypeInfo.h" @@ -12,17 +14,11 @@ class DrawContext DrawContext(); virtual ~DrawContext(); + nn::gfx::CommandBuffer* getCommandBuffer() { return &mCommandBuffer; } + private: - u32 _8; - u32 _c; - u64 _10; - u8 _18[0xC0 - 0x18]; - u64 _c0; - u64 _c8; - u64 _d0; - u64 _d8; - u64 _e0; - u64 _e8; + nn::gfx::CommandBuffer mCommandBuffer; }; +static_assert(sizeof(DrawContext) == 0xF0); } // namespace sead diff --git a/include/gfx/seadDrawLockContext.h b/include/gfx/seadDrawLockContext.h new file mode 100644 index 000000000..693428668 --- /dev/null +++ b/include/gfx/seadDrawLockContext.h @@ -0,0 +1,23 @@ +#pragma once + +#include "hostio/seadHostIONode.h" +#include "thread/seadCriticalSection.h" + +namespace sead +{ +class DrawLockContext : public hostio::Node +{ +public: + DrawLockContext(); + + void initialize(Heap* heap); + void lock(); + void unlock(); + void genMessage(hostio::Context* context); + +private: + [[maybe_unused]] u32 _8 = 0; + CriticalSection mCriticalSection{}; +}; + +} // namespace sead diff --git a/include/gfx/seadFrustumProjection.h b/include/gfx/seadFrustumProjection.h index 6500ae408..313ae6b9a 100644 --- a/include/gfx/seadFrustumProjection.h +++ b/include/gfx/seadFrustumProjection.h @@ -7,28 +7,53 @@ namespace sead class FrustumProjection : public Projection { SEAD_RTTI_OVERRIDE(FrustumProjection, Projection) + public: - FrustumProjection(); - FrustumProjection(float near, float far, float top, float bottom, float left, float right); + 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; - float getNear() const override; - float getFar() const override; - float getFovy() const override; - float getAspect() const override; - void getOffset(Vector2f* offset) const override; - void updateAttributesForDirectProjection() override; - ProjectionType getProjectionType() const override; - void doUpdateMatrix(Matrix44f* mtx) const override; - void doScreenPosToCameraPosTo(Vector3f*, const Vector3f&) const override; + 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 getFovy() const override; + f32 getAspect() const override; + void getOffset(Vector2f* dst) const override; + f32 getOffsetX() const; + f32 getOffsetY() const; + + void setFovyAspectOffset(f32 fovy, f32 aspect, const Vector2f& offset); private: - float mNear; - float mFar; - float mTop; - float mBottom; - float mLeft; - float mRight; + f32 mNear; + f32 mFar; + f32 mTop; + f32 mBottom; + f32 mLeft; + f32 mRight; }; } // namespace sead diff --git a/include/gfx/seadGraphics.h b/include/gfx/seadGraphics.h index 73928d9d2..19628bf60 100644 --- a/include/gfx/seadGraphics.h +++ b/include/gfx/seadGraphics.h @@ -1,14 +1,21 @@ -#pragma once +#ifndef SEAD_GRAPHICS_H_ +#define SEAD_GRAPHICS_H_ #include +#include + +#ifdef cafe +#include +#endif // cafe namespace sead { -// no content yet, just for the enum -class Graphics : public IDisposer -{ - SEAD_SINGLETON_DISPOSER(Graphics) +class Color4f; +class Thread; + +class Graphics : public sead::IDisposer +{ public: enum DevicePosture { @@ -19,11 +26,245 @@ class Graphics : public IDisposer cDevicePosture_FlipX = 4, cDevicePosture_FlipY = 5, cDevicePosture_FlipXY = 3, - cDevicePosture_Invalid = 4, + cDevicePosture_Invalid = 4 + }; + +public: + static const u32 cRenderTarget_Num = 8; + +public: + static DevicePosture getDefaultDevicePosture() { return sDefaultDevicePosture; } + static f32 getDefaultDeviceZScale() { return sDefaultDeviceZScale; } + static f32 getDefaultDeviceZOffset() { return sDefaultDeviceZOffset; } + +public: + // 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 }; +public: + static Graphics* instance() { return sInstance; } + static void setInstance(Graphics* impl) { sInstance = impl; } + + Graphics(); + ~Graphics() override; + +private: + 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 + +#endif // SEAD_GRAPHICS_H_ diff --git a/include/gfx/seadOrthoProjection.h b/include/gfx/seadOrthoProjection.h index 7bd019404..263ba27d9 100644 --- a/include/gfx/seadOrthoProjection.h +++ b/include/gfx/seadOrthoProjection.h @@ -7,37 +7,52 @@ namespace sead class OrthoProjection : public Projection { SEAD_RTTI_OVERRIDE(OrthoProjection, Projection) + public: OrthoProjection(); - OrthoProjection(float near, float far, float top, float bottom, float left, float right); - OrthoProjection(float, float, Viewport* viewport); + 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; - float getNear() const override; - float getFar() const override; - float getFovy() const override; - float getAspect() const override; - void getOffset(sead::Vector2* offsetVec) const override; - void updateAttributesForDirectProjection() 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; - void setByViewport(sead::Viewport const& viewport); - void setTBLR(float top, float bottom, float left, float right); + 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; - void doUpdateMatrix(Matrix44f* mtx) const override; - void doScreenPosToCameraPosTo(sead::Vector3* pos_1, - sead::Vector3 const& pos_2) const override; - bool checkDerivedRuntimeTypeInfo(RuntimeTypeInfo::Interface* interface); - RuntimeTypeInfo::Interface* getRuntimeTypeInfo(); - ProjectionType getProjectionType() const override; + 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: - float mNear; - float mFar; - float mTop; - float mBottom; - float mLeft; - float mRight; - // bool m01b; + f32 mNear; + f32 mFar; + f32 mTop; + f32 mBottom; + f32 mLeft; + f32 mRight; + Vector2f mOffset; }; +#ifdef cafe +static_assert(sizeof(OrthoProjection) == 0xAC, "sead::OrthoProjection size mismatch"); +#endif // cafe } // namespace sead diff --git a/include/gfx/seadPerspectiveProjection.h b/include/gfx/seadPerspectiveProjection.h index 4ae84dcc9..5935512cc 100644 --- a/include/gfx/seadPerspectiveProjection.h +++ b/include/gfx/seadPerspectiveProjection.h @@ -1,5 +1,11 @@ -#pragma once +#include +#include #include +#include +#include +#include +#include +#include "math/seadMathNumbers.h" namespace sead { @@ -7,39 +13,74 @@ namespace sead class PerspectiveProjection : public Projection { SEAD_RTTI_OVERRIDE(PerspectiveProjection, Projection) + public: PerspectiveProjection(); - PerspectiveProjection(float near, float far, float fovy_rad, float aspect); + PerspectiveProjection(f32 near, f32 far, f32 fovy_rad, f32 aspect); ~PerspectiveProjection() override = default; - float getNear() const override; - float getFar() const override; - float getFovy() const override; - float getAspect() const override; - void getOffset(Vector2f* offset) const override; - void doScreenPosToCameraPosTo(Vector3f* cameraPos, const Vector3f& screenPos) const override; - ProjectionType getProjectionType() const override; - - void set(float near, float far, float fovy_rad, float aspect); - void doUpdateMatrix(Matrix44f* mtx) const override; - void setFovx_(float aFloat); - void setFovy_(float newFovy); - void createDividedProjection(sead::PerspectiveProjection* projection, int, int, int, int); - float getTop(); - float getBottom(); - float getLeft(); - float getRight(); - void setTBLR(float top, float bottom, float left, float right); + void set(f32 _near, f32 _far, f32 fovy_rad, f32 aspect); + + void setNear(f32 near) + { + mNear = near; + setDirty(); + } + void setFar(f32 far) + { + mFar = far; + setDirty(); + } + void setFovx(f32 fovx); + void setFovy(f32 fovy) { setFovy_(fovy); } + void setAspect(f32 aspect) + { + mAspect = aspect; + setDirty(); + } + void setOffset(const Vector2f& offset) + { + mOffset = offset; + 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: - float mNear; - float mFar; - float mFovyRad; - float mFovySin; - float mFovyCos; - float mFovyTan; - float mAspect; - Vector2f mOffset; + 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; + f32 mFovySin; + f32 mFovyCos; + f32 mFovyTan; + f32 mAspect = 1.333333f; + Vector2f mOffset = Vector2f::zero; }; +#ifdef cafe +static_assert(sizeof(PerspectiveProjection) == 0xB8, "sead::PerspectiveProjection size mismatch"); +#endif // cafe } // namespace sead diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 774ecc127..7b0500da1 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -1,53 +1,74 @@ -#ifndef SEAD_PROJECTION_H_ -#define SEAD_PROJECTION_H_ +#pragma once -#include #include -#include +#include #include #include -#include - -#define GLOBAL_DEVICE_Z_SCALE 1.0 +#include "math/seadMathNumbers.h" +#include "prim/seadRuntimeTypeInfo.h" namespace sead { + +class Camera; +class Viewport; + +template +class Ray; + class Projection { SEAD_RTTI_BASE(Projection) public: - enum ProjectionType + enum Type { - cPerspectiveProjection = 0, - cOrthoProjection = 1, - cDirectProjection = 2, + cType_Perspective = 0, + cType_Ortho = 1, + cType_Undefined = 2 }; Projection(); virtual ~Projection() = default; - void markDirty() { mDirty = true; }; - void markDeviceDirty() { mDeviceDirty = true; }; + void setDirty() { mDirty = true; } + void setDeviceDirty() { mDeviceDirty = true; } + + void setDevicePosture(Graphics::DevicePosture pose) + { + mDevicePosture = pose; + setDeviceDirty(); + } + + const Matrix44f& getProjectionMatrix() const; + Matrix44f& getProjectionMatrixMutable(); + + const Matrix44f& getDeviceProjectionMatrix() const; + + 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 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; + virtual float getNear() const = 0; virtual float getFar() const = 0; virtual float getFovy() const = 0; virtual float getAspect() const = 0; virtual void getOffset(Vector2f* offset) const = 0; + virtual void updateAttributesForDirectProjection(); - virtual ProjectionType getProjectionType() const = 0; - virtual void doUpdateMatrix(Matrix44f* mtx) const = 0; - virtual void doUpdateDeviceMatrix(Matrix44f*, const Matrix44f&, Graphics::DevicePosture) const; - virtual void doScreenPosToCameraPosTo(Vector3f* screen, const Vector3f& cam) const; - virtual void someFunction(Camera* camera) const; - virtual void project(Vector2f* aVec, Vector3f* bVec) const; - virtual void unproject(Vector3f*, float, Camera*) const = 0; + virtual Type getProjectionType() const = 0; + virtual void doUpdateMatrix(Matrix44f* dst) const = 0; + virtual void doUpdateDeviceMatrix(Matrix44f* dst, const Matrix44f& src, + Graphics::DevicePosture pose) const; + virtual void doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const; +private: void updateMatrixImpl_() const; - const Matrix44f& getProjectionMatrix() const; - const Matrix44f& getDeviceProjectionMatrix() const; -private: mutable bool mDirty; mutable bool mDeviceDirty; Matrix44f mMatrix; @@ -56,7 +77,8 @@ class Projection f32 mDeviceZScale; f32 mDeviceZOffset; }; +#ifdef cafe +static_assert(sizeof(Projection) == 0x94, "sead::Projection size mismatch"); +#endif // cafe } // namespace sead - -#endif // SEAD_PROJECTION_H_ diff --git a/include/gfx/seadViewport.h b/include/gfx/seadViewport.h index 0a04443e9..ede1556be 100644 --- a/include/gfx/seadViewport.h +++ b/include/gfx/seadViewport.h @@ -1,33 +1,35 @@ -#pragma once +#ifndef SEAD_VIEWPORT_H_ +#define SEAD_VIEWPORT_H_ #include #include -#include -#include -#include "prim/seadRuntimeTypeInfo.h" +#include namespace sead { + +class Camera; +class Projection; + template class Ray; -class DrawContext; -class Projection; -class Camera; class Viewport : public BoundBox2f { SEAD_RTTI_BASE(Viewport) public: Viewport(); - Viewport(float left, float top, float right, float bottom); - explicit Viewport(const BoundBox2f& parent); - explicit Viewport(LogicalFrameBuffer const& buffer); + Viewport(f32 left, f32 top, f32 sizeX, f32 sizeY); + // explicit Viewport(const BoundBox2f& box); + explicit Viewport(const LogicalFrameBuffer& frame_buffer); 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 setByFrameBuffer(const LogicalFrameBuffer& frame_buffer); + + void getOnFrameBufferPos(Vector2f* dst, const LogicalFrameBuffer& fb) const; + void getOnFrameBufferSize(Vector2f* dst, const LogicalFrameBuffer& fb) const; + + void apply(DrawContext* context, const LogicalFrameBuffer& frame_buffer) const; void applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const; void applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const; void project(Vector2f*, const Vector3f&) const; @@ -36,11 +38,13 @@ class Viewport : public BoundBox2f void unproject(Ray*, const Vector2f&, const Projection&, const Camera&) const; private: - inline void frameBufferHelper(const LogicalFrameBuffer& buffer); - Graphics::DevicePosture mDevicePosture; - float mMinX; - float mMinY; - float mMaxX; - float mMaxY; + Graphics::DevicePosture mDevicePos = Graphics::getDefaultDevicePosture(); + Vector2f mDepthBounds = Vector2f(0.0f, 1.0f); }; +#ifdef cafe +static_assert(sizeof(Viewport) == 0x18, "sead::Viewport size mismatch"); +#endif // cafe + } // namespace sead + +#endif // SEAD_VIEWPORT_H_ diff --git a/include/math/seadMatrix.hpp b/include/math/seadMatrix.hpp index c366e3153..36ee383f5 100644 --- a/include/math/seadMatrix.hpp +++ b/include/math/seadMatrix.hpp @@ -713,7 +713,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 diff --git a/modules/src/gfx/seadDirectProjection.cpp b/modules/src/gfx/seadDirectProjection.cpp index 3867d48f8..5eb0fdd57 100644 --- a/modules/src/gfx/seadDirectProjection.cpp +++ b/modules/src/gfx/seadDirectProjection.cpp @@ -5,67 +5,42 @@ namespace sead DirectProjection::DirectProjection() { - mDirectMatrix.makeIdentity(); - mNear = 0.0; - mFar = 0.0; - mFovy = 0.0; - mAspect = 0.0; - mOffset.set(0.0, 0.0); - mUnknown7 = 1; - markDirty(); - markDeviceDirty(); + setDirty(); } -DirectProjection::DirectProjection(Matrix44f const& mtx, Graphics::DevicePosture posture) +DirectProjection::DirectProjection(const Matrix44f* mtx, Graphics::DevicePosture posture) { setDirectProjectionMatrix(mtx, posture); } -void DirectProjection::setDirectProjectionMatrix(const Matrix44f& mtx, - Graphics::DevicePosture posture) -{ - mDirectMatrix = mtx; - switch (posture) - { - case Graphics::DevicePosture::cDevicePosture_RotateRight: - break; - case Graphics::DevicePosture::cDevicePosture_RotateLeft: - break; - case Graphics::DevicePosture::cDevicePosture_RotateHalfAround: - break; - case Graphics::DevicePosture::cDevicePosture_FlipY: - break; - } - markDirty(); -} - -float DirectProjection::getNear() const +void DirectProjection::updateAttributesForDirectProjection() { - return mNear; + Matrix44f newMatrix; + newMatrix.setInverse(mDirectMatrix); } -float DirectProjection::getFar() const +void DirectProjection::doUpdateMatrix(Matrix44f* dst) const { - return mFar; + *dst = mDirectMatrix; } -float DirectProjection::getFovy() const -{ - return mFovy; -} - -float DirectProjection::getAspect() const -{ - return mAspect; -} - -void DirectProjection::getOffset(sead::Vector2* offset) const +void DirectProjection::setDirectProjectionMatrix(const Matrix44f* mtx, + Graphics::DevicePosture posture) { - offset->set(mOffset); + mDirectMatrix = (*mtx); } -Projection::ProjectionType DirectProjection::getProjectionType() const +void DirectProjection::doScreenPosToCameraPosTo(Vector3f* dst, const Vector3f& screen_pos) const { - return Projection::ProjectionType::cDirectProjection; + 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/seadDrawLockContext.cpp b/modules/src/gfx/seadDrawLockContext.cpp new file mode 100644 index 000000000..d5ebb683e --- /dev/null +++ b/modules/src/gfx/seadDrawLockContext.cpp @@ -0,0 +1,20 @@ +#include "gfx/seadDrawLockContext.h" + +namespace sead +{ +DrawLockContext::DrawLockContext() = default; + +void DrawLockContext::initialize(Heap*) {} + +void DrawLockContext::lock() +{ + mCriticalSection.lock(); +} +void DrawLockContext::unlock() +{ + mCriticalSection.unlock(); +} + +void DrawLockContext::genMessage(hostio::Context*) {} + +} // namespace sead diff --git a/modules/src/gfx/seadFrustumProjection.cpp b/modules/src/gfx/seadFrustumProjection.cpp index f00c55445..d431ff770 100644 --- a/modules/src/gfx/seadFrustumProjection.cpp +++ b/modules/src/gfx/seadFrustumProjection.cpp @@ -2,57 +2,79 @@ namespace sead { -FrustumProjection::FrustumProjection(float near, float far, float top, float bottom, float left, - float right) +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) { - mNear = near; - mFar = far; - mTop = top; - mBottom = bottom; - mLeft = left; - mRight = right; - markDirty(); + setDirty(); } -float FrustumProjection::getNear() const +FrustumProjection::FrustumProjection(f32 _near, f32 _far, const BoundBox2f& box) + : mNear(_near), mFar(_far) { - return mNear; } -float FrustumProjection::getFar() const +void FrustumProjection::setNear(f32 near) { - return mFar; + mNear = near; + setDirty(); } -void FrustumProjection::doScreenPosToCameraPosTo(Vector3f* screenPos, - const Vector3f& cameraPos) const +void FrustumProjection::setFar(f32 far) { - screenPos->z = mNear; - screenPos->x = (float)0.5 * ((mRight + mLeft) + (mRight - mLeft) * cameraPos.x); - screenPos->y = (float)0.5 * ((mTop + mBottom) + (mTop - mBottom) * cameraPos.y); + mFar = far; + setDirty(); } -float FrustumProjection::getFovy() const +void FrustumProjection::setTop(f32 top) { - return (float)2.0 * atan2f((float)0.5 * (mTop - mBottom), getNear()); + mTop = top; + setDirty(); } -float FrustumProjection::getAspect() const +void FrustumProjection::setBottom(f32 bottom) { - return (mRight - mLeft) / (mTop - mBottom); + mBottom = bottom; + setDirty(); } -void FrustumProjection::getOffset(Vector2f* offset) const +void FrustumProjection::setLeft(f32 left) { - float denom = mRight - mLeft; - offset->x = (float)0.5 * (mRight + mLeft) / denom; + mLeft = left; + setDirty(); +} - denom = mTop - mBottom; - offset->y = (float)0.5 * (mTop + mBottom) / denom; +void FrustumProjection::setRight(f32 right) +{ + mRight = right; + setDirty(); } -Projection::ProjectionType FrustumProjection::getProjectionType() const +void FrustumProjection::doUpdateMatrix(Matrix44f* dst) const { - return ProjectionType::cPerspectiveProjection; + 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; } } // namespace sead diff --git a/modules/src/gfx/seadGraphics.cpp b/modules/src/gfx/seadGraphics.cpp new file mode 100644 index 000000000..f49405f63 --- /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/seadOrthoProjection.cpp b/modules/src/gfx/seadOrthoProjection.cpp index 5e0717ace..748e36fc9 100644 --- a/modules/src/gfx/seadOrthoProjection.cpp +++ b/modules/src/gfx/seadOrthoProjection.cpp @@ -1,59 +1,69 @@ #include +#include namespace sead { - OrthoProjection::OrthoProjection() + : mNear(0.0), mFar(1.0), mTop(0.5), mBottom(-0.5), mLeft(-0.5), mRight(0.5) { - mFar = 1.0; - mNear = 0.0; - mTop = 0.5; - mBottom = -0.5; - mLeft = -0.5; - mRight = 0.5; - markDirty(); } -OrthoProjection::OrthoProjection(float near, float far, float top, float bottom, float left, - float right) +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) { - mNear = near; - mFar = far; - mTop = top; - mBottom = bottom; - mLeft = left; - mRight = right; - markDirty(); + 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); } -Projection::ProjectionType OrthoProjection::getProjectionType() const +void OrthoProjection::setNear(f32 near) { - return ProjectionType::cOrthoProjection; + mNear = near; + setDirty(); } -float OrthoProjection::getNear() const +void OrthoProjection::setFar(f32 far) { - return this->mNear; + mFar = far; + setDirty(); } -float OrthoProjection::getFar() const +void OrthoProjection::setTop(f32 top) { - return this->mFar; + mTop = top; + setDirty(); } -float OrthoProjection::getFovy() const +void OrthoProjection::setBottom(f32 bottom) { - return 0; + mBottom = bottom; + setDirty(); } -float OrthoProjection::getAspect() const +void OrthoProjection::setLeft(f32 left) { - return (this->mRight - this->mLeft) / (this->mTop - this->mBottom); + mLeft = left; + setDirty(); } -void OrthoProjection::getOffset(sead::Vector2f* offsetVec) const +void OrthoProjection::setRight(f32 right) { - offsetVec->x = ((float)0.5 * (this->mLeft + this->mRight)) / (this->mRight - this->mLeft); - offsetVec->y = ((float)0.5 * (this->mTop + this->mBottom)) / (this->mTop - this->mBottom); + mRight = right; + setDirty(); } void OrthoProjection::setTBLR(float top, float bottom, float left, float right) @@ -62,49 +72,48 @@ void OrthoProjection::setTBLR(float top, float bottom, float left, float right) mBottom = bottom; mLeft = left; mRight = right; - markDirty(); + setDirty(); // this->projectionType = ProjectionType::cOrthoProjection; } -// Decompiled code maybe makes assumption about initial state of the incoming matrix? -void OrthoProjection::doUpdateMatrix(Matrix44f* mtx) const +void OrthoProjection::doUpdateMatrix(Matrix44f* dst) const { - // See https://learnwebgl.brown37.net/08_projections/projections_perspective.html for a - // description of the construction of the orthographic projection matrix. - - // There seems to be an assumption about the near (1) and far (2) projection planes - - mtx->m[0][0] = (float)1.0 / ((mRight - mLeft) * (float)0.5); - mtx->m[0][1] = 0; - mtx->m[0][2] = 0; - mtx->m[0][3] = -(float)1.0 * (mLeft + mRight) / (mRight - mLeft); - - mtx->m[1][0] = 0; - mtx->m[1][1] = (float)1.0 / ((mTop - mBottom) * (float)0.5); - mtx->m[1][2] = 0; - mtx->m[1][3] = -(float)1.0 * (mTop + mBottom) / (mTop - mBottom); - - mtx->m[2][0] = 0; - mtx->m[2][1] = 0; - mtx->m[2][2] = -(float)2.0 / (mFar - mNear); - mtx->m[2][3] = -((float)2.0 * mNear * mFar) / (mFar - mNear); - - mtx->m[3][0] = 0; - mtx->m[3][1] = 0; - mtx->m[3][2] = -(float)1.0; - mtx->m[3][3] = 0; + 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: Registers for multiplation, looks like ordering? -void OrthoProjection::setByViewport(sead::Viewport const& viewport) +void OrthoProjection::setByViewport(const Viewport& vp) { - Vector2f max = viewport.getMax(); - Vector2f min = viewport.getMin(); + Vector2f max = vp.getMax(); + Vector2f min = vp.getMin(); mTop = (float)0.5 * (max.y - min.y); mBottom = -(float)0.5 * (max.y - min.y); mLeft = -(float)0.5 * (max.x - min.x); mRight = (float)0.5 * (max.x - min.x); - markDirty(); + setDirty(); } } // namespace sead diff --git a/modules/src/gfx/seadPerspectiveProjection.cpp b/modules/src/gfx/seadPerspectiveProjection.cpp index 553166e65..244b0ee26 100644 --- a/modules/src/gfx/seadPerspectiveProjection.cpp +++ b/modules/src/gfx/seadPerspectiveProjection.cpp @@ -3,91 +3,113 @@ namespace sead { +PerspectiveProjection::PerspectiveProjection() = default; -PerspectiveProjection::PerspectiveProjection() +PerspectiveProjection::PerspectiveProjection(f32 near, f32 far, f32 fovy_rad, f32 aspect) + : mNear(near), mFar(far), mAspect(aspect), mOffset(Vector2f::zero) { - mNear = 1.0; - mFar = 1000.0; - mOffset.set(float(4.0 / 3.0), 0.0); - mFovyRad = M_PI / 4.0; // pi / 4 radians or 45 degrees - mFovySin = sinf(mFovyRad / (float)2.0); - mFovyCos = cosf(mFovyRad / (float)2.0); - mFovyTan = tanf(mFovyRad / (float)2.0); - markDirty(); -} - -PerspectiveProjection::PerspectiveProjection(float near, float far, float fovy_rad, float aspect) -{ - mOffset.set((float)0.0, (float)0.0); set(near, far, fovy_rad, aspect); } -float PerspectiveProjection::getNear() const +void PerspectiveProjection::set(f32 _near, f32 _far, f32 fovy_rad, f32 aspect) { - return mNear; + setNear(_near); + setFar(_far); + setFovy_(fovy_rad); + setAspect(aspect); } -float PerspectiveProjection::getFar() const +void PerspectiveProjection::setFovy_(f32 fovy) { - return mFar; + mAngle = fovy; + + fovy *= 0.5f; + mFovySin = Mathf::sin(fovy); + mFovyCos = Mathf::cos(fovy); + mFovyTan = Mathf::tan(fovy); + + setDirty(); } -float PerspectiveProjection::getFovy() const +f32 PerspectiveProjection::getTop() const { - return mFovyRad; + f32 clip_height = calcNearClipHeight_(); + f32 center_y = mOffset.y * clip_height; + return clip_height * 0.5f + center_y; } -float PerspectiveProjection::getAspect() const +f32 PerspectiveProjection::getBottom() const { - return mAspect; + f32 clip_height = calcNearClipHeight_(); + f32 center_y = mOffset.y * clip_height; + return -clip_height * 0.5f + center_y; } -void PerspectiveProjection::getOffset(Vector2f* offset) const +f32 PerspectiveProjection::getLeft() const { - offset->set(mOffset); + f32 clip_width = calcNearClipWidth_(); + f32 center_x = mOffset.x * clip_width; + return -clip_width * 0.5f + center_x; } -Projection::ProjectionType PerspectiveProjection::getProjectionType() const +f32 PerspectiveProjection::getRight() const { - return ProjectionType::cPerspectiveProjection; + f32 clip_width = calcNearClipWidth_(); + f32 center_x = mOffset.x * clip_width; + return clip_width * 0.5f + center_x; } -void PerspectiveProjection::set(float near, float far, float fovy_rad, float aspect) +void PerspectiveProjection::doUpdateMatrix(Matrix44f* dst) const { - mNear = near; - mFar = far; - markDirty(); - mFovyRad = fovy_rad; + f32 clip_height = calcNearClipHeight_(); + f32 clip_width = calcNearClipWidth_(); - mFovySin = sinf((float)0.5 * fovy_rad); - mFovyCos = cosf((float)0.5 * fovy_rad); - mFovyTan = tanf((float)0.5 * fovy_rad); + f32 center_x = clip_width * mOffset.x; + f32 center_y = clip_height * mOffset.y; - mAspect = aspect; - markDirty(); -} + clip_height *= 0.5f; + clip_width *= 0.5f; -// set -// do Update + f32 top = clip_height + center_y; + f32 bottom = -clip_height + center_y; -// void PerspectiveProjection::setFovx_(float aFloat) {} + f32 left = -clip_width + center_x; + f32 right = clip_width + center_x; -void PerspectiveProjection::setFovy_(float newFovy) -{ - float local = (float)0.5 * newFovy; - mFovyRad = newFovy; - mFovySin = sinf(local); - mFovyCos = cosf(local); - mFovyTan = tanf(local); - markDirty(); + 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::doUpdateMatrix(Matrix44f* mtx) const -// { -// float temp = 1.0; -// mtx->m[0][0] = (this->mFovyRad + this->mFovyRad) * (1.0 / temp); -// mtx->m[0][1] = 0.0; -// mtx->m[0][3] = 0.0; -// } +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); +} } // namespace sead diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 6ad0da40f..da11883d4 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -1,15 +1,15 @@ +#include #include +#include namespace sead { - Projection::Projection() + : mDirty(true), mDeviceDirty(true), mMatrix(), mDeviceMatrix(), + mDevicePosture(Graphics::getDefaultDevicePosture()), + mDeviceZScale(Graphics::getDefaultDeviceZScale()), + mDeviceZOffset(Graphics::getDefaultDeviceZOffset()) { - markDirty(); - markDeviceDirty(); - mDevicePosture = Graphics::DevicePosture::cDevicePosture_Same; // Global - mDeviceZScale = GLOBAL_DEVICE_Z_SCALE; // Global - mDeviceZOffset = 1.0; // Some Global Var. } void Projection::updateMatrixImpl_() const @@ -18,12 +18,10 @@ void Projection::updateMatrixImpl_() const { 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; @@ -32,22 +30,7 @@ void Projection::updateMatrixImpl_() const const Matrix44f& Projection::getProjectionMatrix() const { - if (!mDirty) - { - if (!mDeviceDirty) - { - return mMatrix; - } - } - else - { - doUpdateMatrix(const_cast(&mMatrix)); - mDirty = false; - mDeviceDirty = true; - } - - doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); - mDeviceDirty = false; + updateMatrixImpl_(); return mMatrix; } @@ -57,36 +40,111 @@ const Matrix44f& Projection::getDeviceProjectionMatrix() const return mDeviceMatrix; } -void Projection::doUpdateDeviceMatrix(Matrix44f* deviceMatrix, const Matrix44f& projMatrix, - Graphics::DevicePosture posture) const +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 { - /* What this does: - 1. Copy the data into the device matrix - 2. Modify the device matrix based on the device orientation - a. - 3. Scale the Z axis by the Device Z scale and include the zOffset. - - */ - *deviceMatrix = projMatrix; - switch (posture) + 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::DevicePosture::cDevicePosture_RotateRight: - case Graphics::DevicePosture::cDevicePosture_RotateLeft: - case Graphics::DevicePosture::cDevicePosture_RotateHalfAround: - case Graphics::DevicePosture::cDevicePosture_FlipX: - case Graphics::DevicePosture::cDevicePosture_FlipY: - default: + 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)); } -} -// void sead::Projection::someFunction(Camera* camera) -// { -// doScreenPosToCameraPosTo(Vector3f*, const Vector3f&); -// camera.Camera(); // ??? -// } + (*dst)(2, 0) = (*dst)(2, 0) * mDeviceZScale; + (*dst)(2, 1) = (*dst)(2, 1) * mDeviceZScale; -// Intentional empty implementation -void Projection::updateAttributesForDirectProjection() {} + (*dst)(2, 2) = ((*dst)(2, 2) + (*dst)(3, 2) * mDeviceZOffset) * mDeviceZScale; + (*dst)(2, 3) = (*dst)(2, 3) * mDeviceZScale + (*dst)(3, 3) * mDeviceZOffset; +} } // namespace sead diff --git a/modules/src/gfx/seadViewport.cpp b/modules/src/gfx/seadViewport.cpp index bc4b17942..776467059 100644 --- a/modules/src/gfx/seadViewport.cpp +++ b/modules/src/gfx/seadViewport.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "math/seadBoundBox.h" @@ -8,158 +9,173 @@ namespace sead Viewport::Viewport() { - mMinX = 0.0; - mMinY = 1.0; + setUndef(); } -Viewport::Viewport(float left, float top, float right, float bottom) - : BoundBox2f(left, top, right, bottom) +Viewport::Viewport(f32 left, f32 top, f32 sizeX, f32 sizeY) + : BoundBox2f(left, top, left + sizeX, top + sizeY) { - // float max = left + right; - // float min = left; - - // if (max <= min) - // { - // max = left; - // min = right; - // } - // this->mMaybeMinX = min; - // this->mMaybeMaxX = max; - - // min = top; - // max = bottom + top; - // if (max <= min) - // { - // max = top; - // min = bottom; - // } - // this->mMaybeMinY = min; - // this->mMaybeMaxY = max; - - // // If L + R is smaller, then the left bound is the max X. - // if ((left + right) <= left) - // { - // this->mMaybeMinX = left + right; - // this->mMaybeMaxX = left; - // } - // else - // { - // this->mMaybeMinX = left; - // this->mMaybeMaxX = left + right; - // } - - // // Same deal for top and bottom - // if ((top + bottom) <= top) - // { - // this->mMaybeMinY = top + bottom; - // this->mMaybeMaxY = top; - // } - // else - // { - // this->mMaybeMinY = top; - // this->mMaybeMaxY = top + bottom; - // } } - -Viewport::Viewport(LogicalFrameBuffer const& buffer) +Viewport::Viewport(const LogicalFrameBuffer& frame_buffer) { - setByFrameBuffer(buffer); + setByFrameBuffer(frame_buffer); } -void Viewport::setByFrameBuffer(const LogicalFrameBuffer& buffer) +void Viewport::setByFrameBuffer(const LogicalFrameBuffer& frame_buffer) { - mMinX = 0.0; - mMinY = 1.0; - - // mDevicePosture = // Some Global device posture // - if (mDevicePosture <= Graphics::DevicePosture::cDevicePosture_FlipY) + switch (mDevicePos) { - float minX; - float maxX; - float minY; - float maxY; - if (mDevicePosture == Graphics::DevicePosture::cDevicePosture_RotateLeft || - mDevicePosture == Graphics::DevicePosture::cDevicePosture_RotateHalfAround) - { - maxX = buffer.getVirtualSize().x; - maxY = buffer.getVirtualSize().y; - } - else - { - maxY = buffer.getVirtualSize().x; - maxX = buffer.getVirtualSize().y; - } - - minY = fmin(maxY, (float)0.0); - if (maxY < 0.0) - { - maxY = 0.0; - } - - minX = fmin(maxX, (float)0.0); - if (maxX < 0.0) - { - maxX = 0.0; - } - - set(minX, minY, maxX, maxY); + 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::apply(DrawContext*, const LogicalFrameBuffer& buffer) const {} +void Viewport::getOnFrameBufferPos(Vector2f* dst, const LogicalFrameBuffer& fb) const +{ + *dst = getMin(); -// void Viewport::getOnFrameBufferPos(Vector2f* out, const LogicalFrameBuffer& buffer) const -// { -// switch (mDevicePosture) -// { -// case Graphics::DevicePosture::cDevicePosture_Same: -// case Graphics::DevicePosture::cDevicePosture_RotateRight: -// case Graphics::DevicePosture::cDevicePosture_RotateLeft: -// case Graphics::DevicePosture::cDevicePosture_RotateHalfAround: -// case Graphics::DevicePosture::cDevicePosture_FlipX: -// case Graphics::DevicePosture::cDevicePosture_FlipY: -// default: -// break; -// } -// } + switch (mDevicePos) + { + 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)); + } -void Viewport::getOnFrameBufferSize(Vector2f* out, const LogicalFrameBuffer& buffer) const + 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 { - out->x = getSizeX(); - out->y = getSizeY(); + dst->set(getSizeX(), getSizeY()); - if (mDevicePosture - 1 < Graphics::DevicePosture::cDevicePosture_RotateLeft) + switch (mDevicePos) { - out->x = getSizeY(); - out->y = getSizeX(); + 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)); } - out->x = out->x / buffer.getVirtualSize().x; - out->y = out->y / buffer.getVirtualSize().y; - out->x = out->x * buffer.getPhysicalArea().getSizeX(); - out->y = out->y * buffer.getPhysicalArea().getSizeY(); + + dst->x /= fb.getVirtualSize().x; + dst->y /= fb.getVirtualSize().y; + dst->x *= fb.getPhysicalArea().getSizeX(); + dst->y *= fb.getPhysicalArea().getSizeY(); } -// void Viewport::applyViewport(DrawContext* context, const LogicalFrameBuffer& buffer) const {} -// void Viewport::applyScissor(DrawContext* context, const LogicalFrameBuffer& buffer) const {} +void Viewport::apply(DrawContext* context, const LogicalFrameBuffer& frame_buffer) const +{ + sead::Vector2f real_pos; + getOnFrameBufferPos(&real_pos, frame_buffer); -void Viewport::project(Vector2f* aVec, const Vector2f& bVec) const + 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 = (float)0.5 * (mMaxX - mMinX) * bVec.x; - aVec->y = (float)0.5 * (mMaxY - mMinY) * bVec.y; + 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 +void Viewport::project(Vector2f* aVec, const Vector2f& bVec) const { - float some_value; - some_value = some2Vec.x / getHalfSizeX(); + aVec->x = getHalfSizeX() * bVec.x; + aVec->y = getHalfSizeY() * bVec.y; } -void Viewport::unproject(Ray* ray, const Vector2f& someVec, const Projection& projection, + +void Viewport::unproject(Vector3f* some3Vec, const Vector2f& some2Vec, const Projection& projection, const Camera& camera) const { - float some_value; - some_value = someVec.x / (getHalfSizeX()); - // projection.unproject(ray, some_value, camera); + 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 7500ec5789c4cadb7082cbd75e3b0acc0894f055 Mon Sep 17 00:00:00 2001 From: Esras Date: Wed, 14 Jun 2023 20:43:17 -0700 Subject: [PATCH 6/6] Pull in more files from Aboood's branch and try to merge it into the current repo state. --- CMakeLists.txt | 4 + include/gfx/seadFrustumProjection.h | 2 - include/gfx/seadGraphicsContext.h | 550 ++++++++++++++++++ include/gfx/seadPerspectiveProjection.h | 2 +- modules/src/gfx/seadFrustumProjection.cpp | 67 ++- modules/src/gfx/seadGraphicsContext.cpp | 193 ++++++ modules/src/gfx/seadOrthoProjection.cpp | 13 +- modules/src/gfx/seadPerspectiveProjection.cpp | 8 +- modules/src/gfx/seadProjection.cpp | 3 +- 9 files changed, 806 insertions(+), 36 deletions(-) create mode 100644 include/gfx/seadGraphicsContext.h create mode 100644 modules/src/gfx/seadGraphicsContext.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 74fa3aaf0..e0a17ef10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,8 @@ 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/seadPrimitiveRenderer.h include/gfx/seadPrimitiveRendererUtil.h include/gfx/seadProjection.h @@ -112,6 +114,8 @@ 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 diff --git a/include/gfx/seadFrustumProjection.h b/include/gfx/seadFrustumProjection.h index 313ae6b9a..42ff94643 100644 --- a/include/gfx/seadFrustumProjection.h +++ b/include/gfx/seadFrustumProjection.h @@ -42,8 +42,6 @@ class FrustumProjection : public Projection f32 getFovy() const override; f32 getAspect() const override; void getOffset(Vector2f* dst) const override; - f32 getOffsetX() const; - f32 getOffsetY() const; void setFovyAspectOffset(f32 fovy, f32 aspect, const Vector2f& offset); diff --git a/include/gfx/seadGraphicsContext.h b/include/gfx/seadGraphicsContext.h new file mode 100644 index 000000000..09d9840d7 --- /dev/null +++ b/include/gfx/seadGraphicsContext.h @@ -0,0 +1,550 @@ +#ifndef SEAD_GRAPHICS_CONTEXT_H_ +#define SEAD_GRAPHICS_CONTEXT_H_ + +#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 + +#endif // SEAD_GRAPHICS_CONTEXT_H_ +#ifndef SEAD_GRAPHICS_CONTEXT_H_ +#define SEAD_GRAPHICS_CONTEXT_H_ + +#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 + +#endif // SEAD_GRAPHICS_CONTEXT_H_ diff --git a/include/gfx/seadPerspectiveProjection.h b/include/gfx/seadPerspectiveProjection.h index 5935512cc..031ff56a9 100644 --- a/include/gfx/seadPerspectiveProjection.h +++ b/include/gfx/seadPerspectiveProjection.h @@ -72,7 +72,7 @@ class PerspectiveProjection : public Projection f32 mNear = 1.0f; f32 mFar = 10000.0f; - f32 mAngle; + f32 mAngle = numbers::pi / 2.0f; f32 mFovySin; f32 mFovyCos; f32 mFovyTan; diff --git a/modules/src/gfx/seadFrustumProjection.cpp b/modules/src/gfx/seadFrustumProjection.cpp index d431ff770..8b2eaa320 100644 --- a/modules/src/gfx/seadFrustumProjection.cpp +++ b/modules/src/gfx/seadFrustumProjection.cpp @@ -1,4 +1,5 @@ #include +#include "math/seadVectorFwd.h" namespace sead { @@ -13,6 +14,35 @@ FrustumProjection::FrustumProjection(f32 _near, f32 _far, const BoundBox2f& box) { } +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; @@ -49,32 +79,23 @@ void FrustumProjection::setRight(f32 right) setDirty(); } -void FrustumProjection::doUpdateMatrix(Matrix44f* dst) const +f32 FrustumProjection::getFovy() 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; + return 2 * Mathf::atan2(0.5f * (mTop - mBottom), getNear()); +} - inv_size = 1.0f / (mFar - mNear); +f32 FrustumProjection::getAspect() const +{ + return (mRight - mLeft) / (mTop - mBottom); +} - (*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; +void FrustumProjection::getOffset(Vector2f* dst) const +{ + float denom = mRight - mLeft; + dst->x = (float)0.5 * (mRight + mLeft) / denom; - (*dst)(3, 0) = 0.0f; - (*dst)(3, 1) = 0.0f; - (*dst)(3, 2) = -1.0f; - (*dst)(3, 3) = 0.0f; + denom = mTop - mBottom; + dst->y = (float)0.5 * (mTop + mBottom) / denom; } + } // namespace sead diff --git a/modules/src/gfx/seadGraphicsContext.cpp b/modules/src/gfx/seadGraphicsContext.cpp new file mode 100644 index 000000000..745a15fbd --- /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/seadOrthoProjection.cpp b/modules/src/gfx/seadOrthoProjection.cpp index 748e36fc9..2184b44ef 100644 --- a/modules/src/gfx/seadOrthoProjection.cpp +++ b/modules/src/gfx/seadOrthoProjection.cpp @@ -105,14 +105,15 @@ void OrthoProjection::doUpdateMatrix(Matrix44f* dst) const (*dst)(3, 3) = -1.0f; } +// NON-MATCHING: Adds an additional register for a multiplication void OrthoProjection::setByViewport(const Viewport& vp) { - Vector2f max = vp.getMax(); - Vector2f min = vp.getMin(); - mTop = (float)0.5 * (max.y - min.y); - mBottom = -(float)0.5 * (max.y - min.y); - mLeft = -(float)0.5 * (max.x - min.x); - mRight = (float)0.5 * (max.x - min.x); + f32 halfY = vp.getHalfSizeY(); + f32 halfX = vp.getHalfSizeX(); + mTop = halfY; + mBottom = -halfY; + mLeft = -halfX; + mRight = halfX; setDirty(); } diff --git a/modules/src/gfx/seadPerspectiveProjection.cpp b/modules/src/gfx/seadPerspectiveProjection.cpp index 244b0ee26..e9cae0eea 100644 --- a/modules/src/gfx/seadPerspectiveProjection.cpp +++ b/modules/src/gfx/seadPerspectiveProjection.cpp @@ -3,12 +3,16 @@ namespace sead { -PerspectiveProjection::PerspectiveProjection() = default; +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) { - set(near, far, fovy_rad, aspect); + setFovy_(fovy_rad); + setDirty(); } void PerspectiveProjection::set(f32 _near, f32 _far, f32 fovy_rad, f32 aspect) diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index da11883d4..359555cbc 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -5,8 +5,7 @@ namespace sead { Projection::Projection() - : mDirty(true), mDeviceDirty(true), mMatrix(), mDeviceMatrix(), - mDevicePosture(Graphics::getDefaultDevicePosture()), + : mDirty(true), mDeviceDirty(true), mDevicePosture(Graphics::getDefaultDevicePosture()), mDeviceZScale(Graphics::getDefaultDeviceZScale()), mDeviceZOffset(Graphics::getDefaultDeviceZOffset()) {