diff --git a/include/gfx/seadGraphics.h b/include/gfx/seadGraphics.h index 1beb2c34..0321838a 100644 --- a/include/gfx/seadGraphics.h +++ b/include/gfx/seadGraphics.h @@ -30,6 +30,9 @@ class Graphics : public IDisposer void initializeDrawLockContext(Heap*); static Graphics* instance() { return sInstance; } + static DevicePosture sDefaultDevicePosture; + static f32 sDefaultDeviceZScale; + static f32 sDefaultDeviceZOffset; private: UnknownCallback _20; diff --git a/include/gfx/seadProjection.h b/include/gfx/seadProjection.h index 4f70db7d..f3d64fa7 100644 --- a/include/gfx/seadProjection.h +++ b/include/gfx/seadProjection.h @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -11,13 +10,18 @@ namespace sead { +class Camera; +template +class Ray; +class Viewport; + class Projection { SEAD_RTTI_BASE(Projection) public: Projection(); - virtual ~Projection(); + virtual ~Projection() = default; virtual f32 getNear() const = 0; virtual f32 getFar() const = 0; @@ -28,10 +32,19 @@ class Projection virtual u32 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* camera_pos, + const Vector3f& screen_pos) const = 0; + const Matrix44f& getProjectionMatrix() const; void updateMatrixImpl_() const; + Matrix44f* getProjectionMatrixMutable(); const Matrix44f& getDeviceProjectionMatrix() const; + void cameraPosToScreenPos(Vector3f* screen_pos, const Vector3f& camera_pos) const; + void screenPosToCameraPos(Vector3f* camera_pos, const Vector3f& screen_pos) const; + void screenPosToCameraPos(Vector3f* camera_pos, const Vector2f& screen_pos) const; + void project(Vector2f* dst, const Vector3f& camera_pos, const Viewport& viewport) const; + void unproject(Vector3f* world_pos, const Vector3f& screen_pos, const Camera& camera) const; + void unprojectRay(Ray* dst, const Vector3f& screen_pos, const Camera& camera) const; void setDirty() { mDirty = true; } void setDeviceDirty() { mDeviceDirty = true; } @@ -43,8 +56,8 @@ class Projection } private: - mutable bool mDirty; - mutable bool mDeviceDirty; + mutable bool mDirty = true; + mutable bool mDeviceDirty = true; Matrix44f mMatrix; Matrix44f mDeviceMatrix; Graphics::DevicePosture mDevicePosture; diff --git a/include/math/seadVector.h b/include/math/seadVector.h index 20263987..0d2e97be 100644 --- a/include/math/seadVector.h +++ b/include/math/seadVector.h @@ -81,6 +81,7 @@ struct Vector3 : public Policies::Vec3Base { using Mtx33 = typename Policies::Mtx33Base; using Mtx34 = typename Policies::Mtx34Base; + using Mtx44 = typename Policies::Mtx44Base; using Quat = typename Policies::QuatBase; /// @warning This constructor leaves member variables uninitialized. @@ -111,6 +112,7 @@ struct Vector3 : public Policies::Vec3Base Vector3& operator*=(T t); Vector3& operator*=(const Mtx33& m); Vector3& operator*=(const Mtx34& m); + Vector3& operator*=(const Mtx44& m); friend Vector3 operator*(const Vector3& a, T t) { Vector3 o; @@ -130,6 +132,12 @@ struct Vector3 : public Policies::Vec3Base o.setMul(m, a); return o; } + friend Vector3 operator*(const Mtx44& m, const Vector3& a) + { + Vector3 o; + o.setMul(m, a); + return o; + } Vector3& operator/=(T t); friend Vector3 operator/(const Vector3& a, T t) { return {a.x / t, a.y / t, a.z / t}; } @@ -156,6 +164,8 @@ struct Vector3 : public Policies::Vec3Base void mul(const Mtx33& m); /// Apply a transformation `m` (rotation then translation) to this vector. void mul(const Mtx34& m); + /// Apply a transformation `m` (rotation, translation, homogenous coordinates) to this vector. + void mul(const Mtx44& m); /// Apply a rotation `m` to this vector. void rotate(const Mtx33& m); /// Apply a rotation `m` to this vector. @@ -174,6 +184,7 @@ struct Vector3 : public Policies::Vec3Base void setScaleAdd(T t, const Vector3& a, const Vector3& b); void setMul(const Mtx33& m, const Vector3& a); void setMul(const Mtx34& m, const Vector3& a); + void setMul(const Mtx44& m, const Vector3& a); void setRotated(const Mtx33& m, const Vector3& a); void setRotated(const Mtx34& m, const Vector3& a); void setRotated(const Quat& q, const Vector3& a); diff --git a/include/math/seadVector.hpp b/include/math/seadVector.hpp index c48afb2a..26868815 100644 --- a/include/math/seadVector.hpp +++ b/include/math/seadVector.hpp @@ -179,6 +179,13 @@ inline Vector3& Vector3::operator*=(const Mtx34& m) return *this; } +template +inline Vector3& Vector3::operator*=(const Mtx44& m) +{ + mul(m); + return *this; +} + template inline Vector3& Vector3::operator/=(T t) { @@ -230,6 +237,12 @@ inline void Vector3::mul(const Mtx34& m) setMul(m, *this); } +template +inline void Vector3::mul(const Mtx44& m) +{ + setMul(m, *this); +} + template inline void Vector3::rotate(const Mtx33& m) { @@ -314,6 +327,12 @@ inline void Vector3::setMul(const Mtx34& m, const Vector3& a) Vector3CalcCommon::mul(*this, m, a); } +template +inline void Vector3::setMul(const Mtx44& m, const Vector3& a) +{ + Vector3CalcCommon::mul(*this, m, a); +} + template inline void Vector3::setRotated(const Mtx33& m, const Vector3& a) { diff --git a/include/math/seadVectorCalcCommon.h b/include/math/seadVectorCalcCommon.h index c84b8275..8918d9c6 100644 --- a/include/math/seadVectorCalcCommon.h +++ b/include/math/seadVectorCalcCommon.h @@ -33,6 +33,7 @@ class Vector3CalcCommon using Base = typename Policies::Vec3Base; using Mtx33 = typename Policies::Mtx33Base; using Mtx34 = typename Policies::Mtx34Base; + using Mtx44 = typename Policies::Mtx44Base; using Quat = typename Policies::QuatBase; static void add(Base& o, const Base& a, const Base& b); @@ -41,6 +42,8 @@ class Vector3CalcCommon static void mul(Base& o, const Mtx33& m, const Base& a); /// Apply a transformation `m` (rotation then translation) to the vector `a`. static void mul(Base& o, const Mtx34& m, const Base& a); + /// Apply a transformation `m` (rotation, translation, homogenous coord) to the vector `a`. + static void mul(Base& o, const Mtx44& m, const Base& a); /// Apply a rotation `m` to the vector `a`. static void rotate(Base& o, const Mtx33& m, const Base& a); diff --git a/include/math/seadVectorCalcCommon.hpp b/include/math/seadVectorCalcCommon.hpp index 572608a3..801274a2 100644 --- a/include/math/seadVectorCalcCommon.hpp +++ b/include/math/seadVectorCalcCommon.hpp @@ -146,6 +146,17 @@ inline void Vector3CalcCommon::mul(Base& o, const Mtx34& m, const Base& a) o.z = m.m[2][0] * tmp.x + m.m[2][1] * tmp.y + m.m[2][2] * tmp.z + m.m[2][3]; } +template +inline void Vector3CalcCommon::mul(Base& o, const Mtx44& m, const Base& a) +{ + const Base tmp = a; + T inv = T(1) / (m.m[3][0] * tmp.x + m.m[3][1] * tmp.y + m.m[3][2] * tmp.z + m.m[3][3]); + + o.x = inv * (m.m[0][0] * tmp.x + m.m[0][1] * tmp.y + m.m[0][2] * tmp.z + m.m[0][3]); + o.y = inv * (m.m[1][0] * tmp.x + m.m[1][1] * tmp.y + m.m[1][2] * tmp.z + m.m[1][3]); + o.z = inv * (m.m[2][0] * tmp.x + m.m[2][1] * tmp.y + m.m[2][2] * tmp.z + m.m[2][3]); +} + template inline void Vector3CalcCommon::rotate(Base& o, const Mtx33& m, const Base& a) { diff --git a/modules/src/gfx/seadProjection.cpp b/modules/src/gfx/seadProjection.cpp index 4179f1e9..9cd07d2d 100644 --- a/modules/src/gfx/seadProjection.cpp +++ b/modules/src/gfx/seadProjection.cpp @@ -1,30 +1,89 @@ #include +#include +#include + namespace sead { +Projection::Projection() +{ + mDevicePosture = Graphics::sDefaultDevicePosture; + mDeviceZScale = Graphics::sDefaultDeviceZScale; + mDeviceZOffset = Graphics::sDefaultDeviceZOffset; +} + +void Projection::updateAttributesForDirectProjection() {} + +const Matrix44f& Projection::getProjectionMatrix() const +{ + updateMatrixImpl_(); + return mMatrix; +} + void Projection::updateMatrixImpl_() const { if (mDirty) { doUpdateMatrix(const_cast(&mMatrix)); mDirty = false; - mDeviceDirty = true; - doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); - mDeviceDirty = false; } - else if (mDeviceDirty) + if (mDeviceDirty) { doUpdateDeviceMatrix(const_cast(&mDeviceMatrix), mMatrix, mDevicePosture); mDeviceDirty = false; } } +Matrix44f* Projection::getProjectionMatrixMutable() +{ + updateMatrixImpl_(); + return &mMatrix; +} + const Matrix44f& Projection::getDeviceProjectionMatrix() const { updateMatrixImpl_(); return mDeviceMatrix; } +void Projection::cameraPosToScreenPos(Vector3f* screen_pos, const Vector3f& camera_pos) const +{ + screen_pos->setMul(getProjectionMatrix(), camera_pos); +} + +void Projection::screenPosToCameraPos(Vector3f* camera_pos, const Vector3f& screen_pos) const +{ + doScreenPosToCameraPosTo(camera_pos, screen_pos); +} + +void Projection::screenPosToCameraPos(Vector3f* camera_pos, const Vector2f& screen_pos) const +{ + screenPosToCameraPos(camera_pos, {screen_pos.x, screen_pos.y, 0.0f}); +} + +void Projection::project(Vector2f* dst, const Vector3f& camera_pos, const Viewport& viewport) const +{ + Vector3f screen_pos; + cameraPosToScreenPos(&screen_pos, camera_pos); + viewport.project(dst, screen_pos); +} + +void Projection::unproject(Vector3f* world_pos, const Vector3f& screen_pos, + const Camera& camera) const +{ + Vector3f camera_pos; + screenPosToCameraPos(&camera_pos, screen_pos); + camera.cameraPosToWorldPosByMatrix(world_pos, camera_pos); +} + +void Projection::unprojectRay(Ray* dst, const Vector3f& screen_pos, + const Camera& camera) const +{ + Vector3f camera_pos; + screenPosToCameraPos(&camera_pos, screen_pos); + camera.unprojectRayByMatrix(dst, camera_pos); +} + } // namespace sead