From 5195d31e22f7b7d2ff31ac8ec2a40211d4e15097 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 18 Sep 2024 23:13:27 -0600 Subject: [PATCH] DolphinCGraphics & CDecal 99% --- .flake8 | 4 + .gitignore | 1 + include/Kyoto/Graphics/CColor.hpp | 1 + include/Kyoto/Graphics/CModelFlags.hpp | 10 +- include/Kyoto/Math/CTransform4f.hpp | 5 +- include/Kyoto/Math/CVector2i.hpp | 2 +- include/Kyoto/Particles/CGenDescription.hpp | 8 +- include/Kyoto/Particles/IElement.hpp | 2 +- include/Weapons/CDecal.hpp | 2 +- src/Kyoto/CRandom16.cpp | 3 +- src/Kyoto/Graphics/DolphinCGraphics.cpp | 28 +++-- src/Weapons/CDecal.cpp | 123 +++++++++++++++----- 12 files changed, 135 insertions(+), 54 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..3dd31e6e --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +# E203: whitespace before ':' +# E501: line too long +extend-ignore = E203,E501 diff --git a/.gitignore b/.gitignore index 51ac6183..3fb0501a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ tools/mwcc_compiler versions/ build.ninja .ninja_deps +.ninja_lock .ninja_log objdiff.json orig/*/* diff --git a/include/Kyoto/Graphics/CColor.hpp b/include/Kyoto/Graphics/CColor.hpp index 9e585f7f..3e2fae56 100644 --- a/include/Kyoto/Graphics/CColor.hpp +++ b/include/Kyoto/Graphics/CColor.hpp @@ -25,6 +25,7 @@ public: mB = b; mA = a; } + CColor(const CColor& other) : mRgba(other.mRgba) {} void Set(const float r, const float g, const float b, const float a); void Set(uchar r, uchar g, uchar b, uchar a = 255) { diff --git a/include/Kyoto/Graphics/CModelFlags.hpp b/include/Kyoto/Graphics/CModelFlags.hpp index fb296afd..8cca33ab 100644 --- a/include/Kyoto/Graphics/CModelFlags.hpp +++ b/include/Kyoto/Graphics/CModelFlags.hpp @@ -9,8 +9,8 @@ class CModelFlags { public: enum ETrans { kT_Opaque = 0, - kT_One = 1, // ? - kT_Two = 2, // ? + kT_One = 1, // ? + kT_Two = 2, // ? kT_Four = 4, // ? kT_Blend = 5, kT_Additive = 7, @@ -30,7 +30,7 @@ public: , x1_matSetIdx(0) , x2_flags(kF_DepthCompare | kF_DepthUpdate) , x4_color(1.f, 1.f, 1.f, rgba) {} - CModelFlags(ETrans trans, CColor color) + CModelFlags(ETrans trans, const CColor& color) : x0_blendMode(trans) , x1_matSetIdx(0) , x2_flags(kF_DepthCompare | kF_DepthUpdate) @@ -104,7 +104,9 @@ public: static CModelFlags AlphaBlended(float alpha) { return CModelFlags(kT_Blend, alpha); } static CModelFlags AlphaBlended(const CColor& color) { return CModelFlags(kT_Blend, color); } static CModelFlags Additive(float f) { return CModelFlags(CModelFlags::kT_Additive, f); } - static CModelFlags Additive(const CColor& color) { return CModelFlags(CModelFlags::kT_Additive, color); } + static CModelFlags Additive(const CColor& color) { + return CModelFlags(CModelFlags::kT_Additive, color); + } static CModelFlags AdditiveRGB(const CColor& color); static CModelFlags ColorModulate(const CColor& color); diff --git a/include/Kyoto/Math/CTransform4f.hpp b/include/Kyoto/Math/CTransform4f.hpp index 2329a806..ce1d430e 100644 --- a/include/Kyoto/Math/CTransform4f.hpp +++ b/include/Kyoto/Math/CTransform4f.hpp @@ -90,7 +90,10 @@ public: } void AddTranslationZ(float z) { posZ += z; } - CTransform4f& operator*=(const CTransform4f& other); + CTransform4f& operator*=(const CTransform4f& other) { + *this = *this * other; + return *this; + } CTransform4f operator*(const CTransform4f& vec) const; CVector3f operator*(const CVector3f& vec) const; diff --git a/include/Kyoto/Math/CVector2i.hpp b/include/Kyoto/Math/CVector2i.hpp index 2b679d9b..d8531557 100644 --- a/include/Kyoto/Math/CVector2i.hpp +++ b/include/Kyoto/Math/CVector2i.hpp @@ -5,7 +5,7 @@ class CVector2i { public: - CVector2i(int, int); + CVector2i(int x, int y); int GetX() const { return mX; } int GetY() const { return mY; } diff --git a/include/Kyoto/Particles/CGenDescription.hpp b/include/Kyoto/Particles/CGenDescription.hpp index a5b6970c..14fdb40f 100644 --- a/include/Kyoto/Particles/CGenDescription.hpp +++ b/include/Kyoto/Particles/CGenDescription.hpp @@ -16,10 +16,10 @@ class CSpawnSystemKeyframeData; class CGenDescription { public: - typedef rstl::optional_object< TCachedToken< CModel > > TParticleModel; - typedef rstl::optional_object< TCachedToken< CGenDescription > > TChildGeneratorDesc; - typedef rstl::optional_object< TCachedToken< CSwooshDescription > > TSwooshGeneratorDesc; - typedef TCachedToken< CElectricDescription > TElectricGeneratorDesc; + typedef rstl::optional_object< TLockedToken< CModel > > TParticleModel; + typedef rstl::optional_object< TLockedToken< CGenDescription > > TChildGeneratorDesc; + typedef rstl::optional_object< TLockedToken< CSwooshDescription > > TSwooshGeneratorDesc; + typedef TLockedToken< CElectricDescription > TElectricGeneratorDesc; CGenDescription(); ~CGenDescription(); diff --git a/include/Kyoto/Particles/IElement.hpp b/include/Kyoto/Particles/IElement.hpp index 95ddcfa0..1e9523d3 100644 --- a/include/Kyoto/Particles/IElement.hpp +++ b/include/Kyoto/Particles/IElement.hpp @@ -64,8 +64,8 @@ struct SUVElementSet { class CUVElement : public IElement { public: - virtual TLockedToken< CTexture > GetValueTexture(int frame) const = 0; virtual void GetValueUV(int frame, SUVElementSet& valOut) const = 0; + virtual TLockedToken< CTexture > GetValueTexture(int frame) const = 0; virtual bool HasConstantTexture() const = 0; virtual bool HasConstantUV() const = 0; }; diff --git a/include/Weapons/CDecal.hpp b/include/Weapons/CDecal.hpp index 5b445b34..1e05e7bd 100644 --- a/include/Weapons/CDecal.hpp +++ b/include/Weapons/CDecal.hpp @@ -54,7 +54,7 @@ private: int x54_modelLifetime; int x58_frameIdx; int x5c_flags; - CVector3f x60_rotation; + mutable CVector3f x60_rotation; void InitQuad(CQuadDecal& quad, const CDecalDescription::SQuadDescr& desc, int flag) { if (!desc.x14_TEX.null()) { diff --git a/src/Kyoto/CRandom16.cpp b/src/Kyoto/CRandom16.cpp index 59b764ee..1ba8f82a 100644 --- a/src/Kyoto/CRandom16.cpp +++ b/src/Kyoto/CRandom16.cpp @@ -1,5 +1,6 @@ #include "Kyoto/CRandom16.hpp" #include "Kyoto/Alloc/CMemory.hpp" +#include "Kyoto/Basics/CCast.hpp" CRandom16* CRandom16::gRandomNumber = nullptr; CGlobalRandom* CGlobalRandom::gCurrentGlobalRandom = nullptr; @@ -43,6 +44,6 @@ int CRandom16::Next() { } float CRandom16::Float() { - int next = Next(); + float next = CCast::ToReal32(Next()); return 1.52590222E-5f * next; } diff --git a/src/Kyoto/Graphics/DolphinCGraphics.cpp b/src/Kyoto/Graphics/DolphinCGraphics.cpp index 386585a6..94567a0d 100644 --- a/src/Kyoto/Graphics/DolphinCGraphics.cpp +++ b/src/Kyoto/Graphics/DolphinCGraphics.cpp @@ -1382,33 +1382,32 @@ CGraphics::ClipScreenRectFromVS(const CVector3f& p1, const CVector3f& p2, ETexel int maxX = abs(p1p.GetX() - p2p.GetX()); int maxY = abs(p1p.GetY() - p2p.GetY()); - int left = minX & 0xfffffffe; + int left = minX & ~1; if (left >= mViewport.mLeft + mViewport.mWidth) { return CClippedScreenRect(); } - int right = minX + maxX + 2 & 0xfffffffe; + int right = minX + maxX + 2 & ~1; if (right <= mViewport.mLeft) { return CClippedScreenRect(); } - left = rstl::max_val(left, mViewport.mLeft) & 0xfffffffe; - right = rstl::min_val(right, mViewport.mLeft + mViewport.mWidth) + 1 & 0xfffffffe; + left = rstl::max_val(left, mViewport.mLeft) & ~1; + right = rstl::min_val(right, mViewport.mLeft + mViewport.mWidth) + 1 & ~1; - int top = minY & 0xfffffffe; + int top = minY & ~1; if (top >= mViewport.mTop + mViewport.mHeight) { return CClippedScreenRect(); } - int bottom = minY + maxY + 2 & 0xfffffffe; + int bottom = minY + maxY + 2 & ~1; if (bottom <= mViewport.mTop) { return CClippedScreenRect(); } - top = rstl::max_val(top, mViewport.mTop) & 0xfffffffe; - bottom = rstl::min_val(bottom, mViewport.mTop + mViewport.mHeight) + 1 & 0xfffffffe; + top = rstl::max_val(top, mViewport.mTop) & ~1; + bottom = rstl::min_val(bottom, mViewport.mTop + mViewport.mHeight) + 1 & ~1; - // int height = bottom - top; - float minV = static_cast< float >(minY - top) / static_cast< float >(bottom - top); - float maxV = static_cast< float >(maxY + (minY - top) + 1) / static_cast< float >(bottom - top); + float minV = CCast::LtoF(minY - top) / CCast::LtoF(bottom - top); + float maxV = CCast::LtoF(maxY + (minY - top) + 1) / CCast::LtoF(bottom - top); int texAlign = 4; switch (fmt) { @@ -1424,11 +1423,10 @@ CGraphics::ClipScreenRectFromVS(const CVector3f& p1, const CVector3f& p2, ETexel texAlign = 2; break; } - // int width = right - left; - int texWidth = texAlign + (right - left) - 1 & ~(texAlign - 1); - float minU = static_cast< float >(minX - left) / static_cast< float >(texWidth); - float maxU = static_cast< float >(maxX + (minX - left) + 1) / static_cast< float >(texWidth); + int texWidth = texAlign + (right - left) - 1 & ~(texAlign - 1); + float minU = CCast::LtoF(minX - left) / CCast::LtoF(texWidth); + float maxU = CCast::LtoF(maxX + (minX - left) + 1) / CCast::LtoF(texWidth); return CClippedScreenRect(left, top, right - left, bottom - top, texWidth, minU, maxU, minV, maxV); } diff --git a/src/Weapons/CDecal.cpp b/src/Weapons/CDecal.cpp index 2b64b1b2..a7020b1e 100644 --- a/src/Weapons/CDecal.cpp +++ b/src/Weapons/CDecal.cpp @@ -1,6 +1,8 @@ #include "Weapons/CDecal.hpp" #include "Kyoto/Graphics/CGX.hpp" #include "Kyoto/Graphics/CGraphics.hpp" +#include "Kyoto/Graphics/CModel.hpp" +#include "Kyoto/Graphics/CModelFlags.hpp" #include "Kyoto/Graphics/CTexture.hpp" #include "Kyoto/Math/CRelAngle.hpp" #include "Kyoto/Particles/CParticleGlobals.hpp" @@ -57,7 +59,7 @@ void CDecal::RenderQuad(CQuadDecal& decal, const CDecalDescription::SQuadDescr& } CTransform4f modXf = xc_transform; - modXf.SetTranslation(modXf.GetTranslation() + offset); + modXf.AddTranslation(offset); CGraphics::SetModelMatrix(modXf); CGraphics::SetAlphaCompare(kAF_Always, 0, kAO_And, kAF_Always, 0); @@ -80,8 +82,12 @@ void CDecal::RenderQuad(CQuadDecal& decal, const CDecalDescription::SQuadDescr& uvSet.yMin = 0.f; uvSet.yMax = 1.f; if (!desc.x14_TEX.null()) { - TLockedToken< CTexture > tex = desc.x14_TEX->GetValueTexture(x58_frameIdx); + TToken< CTexture > tex = desc.x14_TEX->GetValueTexture(x58_frameIdx); + if (!tex.IsLoaded()) { + return; + } tex->Load(GX_TEXMAP0, CTexture::kCM_Repeat); + tex.GetObj(); // ? CGraphics::SetTevOp(kTS_Stage0, CGraphics::kEnvModulate); desc.x14_TEX->GetValueUV(x58_frameIdx, uvSet); if (redToAlpha) { @@ -116,44 +122,43 @@ void CDecal::RenderQuad(CQuadDecal& decal, const CDecalDescription::SQuadDescr& CGX::SetVtxDescv(vtxDesc); CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4); - float y = 0.001f; if (decal.x8_rotation == 0.f) { // Vertex 0 - GXPosition3f32(-size, y, size); - GXColor1u32(color.GetColor_u32()); - GXTexCoord2f32(uvSet.xMin, uvSet.yMin); - // Vertex 1 - GXPosition3f32(size, y, size); - GXColor1u32(color.GetColor_u32()); - GXTexCoord2f32(uvSet.xMax, uvSet.yMin); - // Vertex 2 - GXPosition3f32(-size, y, -size); + GXPosition3f32(-size, 0.001f, size); GXColor1u32(color.GetColor_u32()); GXTexCoord2f32(uvSet.xMin, uvSet.yMax); - // Vertex 3 - GXPosition3f32(size, y, -size); + // Vertex 1 + GXPosition3f32(size, 0.001f, size); GXColor1u32(color.GetColor_u32()); GXTexCoord2f32(uvSet.xMax, uvSet.yMax); + // Vertex 2 + GXPosition3f32(-size, 0.001f, -size); + GXColor1u32(color.GetColor_u32()); + GXTexCoord2f32(uvSet.xMin, uvSet.yMin); + // Vertex 3 + GXPosition3f32(size, 0.001f, -size); + GXColor1u32(color.GetColor_u32()); + GXTexCoord2f32(uvSet.xMax, uvSet.yMin); } else { CRelAngle ang = CRelAngle::FromDegrees(decal.x8_rotation); float sinSize = sine(ang) * size; float cosSize = cosine(ang) * size; // Vertex 0 - GXPosition3f32(sinSize - cosSize, y, cosSize + sinSize); - GXColor1u32(color.GetColor_u32()); - GXTexCoord2f32(uvSet.xMin, uvSet.yMin); - // Vertex 1 - GXPosition3f32(cosSize + sinSize, y, cosSize - sinSize); - GXColor1u32(color.GetColor_u32()); - GXTexCoord2f32(uvSet.xMax, uvSet.yMin); - // Vertex 2 - GXPosition3f32(-(cosSize + sinSize), y, -(cosSize - sinSize)); + GXPosition3f32(sinSize - cosSize, 0.001f, cosSize + sinSize); GXColor1u32(color.GetColor_u32()); GXTexCoord2f32(uvSet.xMin, uvSet.yMax); - // Vertex 3 - GXPosition3f32(-sinSize + cosSize, y, -cosSize - sinSize); + // Vertex 1 + GXPosition3f32(cosSize + sinSize, 0.001f, cosSize - sinSize); GXColor1u32(color.GetColor_u32()); GXTexCoord2f32(uvSet.xMax, uvSet.yMax); + // Vertex 2 + GXPosition3f32(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); + GXColor1u32(color.GetColor_u32()); + GXTexCoord2f32(uvSet.xMin, uvSet.yMin); + // Vertex 3 + GXPosition3f32(-sinSize + cosSize, 0.001f, -cosSize - sinSize); + GXColor1u32(color.GetColor_u32()); + GXTexCoord2f32(uvSet.xMax, uvSet.yMin); } CGX::End(); @@ -163,7 +168,73 @@ void CDecal::RenderQuad(CQuadDecal& decal, const CDecalDescription::SQuadDescr& } } -void CDecal::RenderMdl() const {} +void CDecal::RenderMdl() const { + CColor color = CColor::White(); + CVector3f offset = CVector3f::Zero(); + CTransform4f rotXf = CTransform4f::Identity(); + if (!x0_description->x5c_25_DMOO) { + rotXf = xc_transform.GetRotation(); + } + + bool dmrtIsConst = false; + if (CVectorElement* off = x0_description->x50_DMRT.get()) { + if (off->IsFastConstant()) { + dmrtIsConst = true; + } + } + + CTransform4f dmrtXf = CTransform4f::Identity(); + if (dmrtIsConst) { + x0_description->x50_DMRT->GetValue(x58_frameIdx, x60_rotation); + dmrtXf = CTransform4f::RotateZ(CRelAngle::FromDegrees(x60_rotation.GetZ())); + dmrtXf.RotateLocalY(CRelAngle::FromDegrees(x60_rotation.GetY())); + dmrtXf.RotateLocalX(CRelAngle::FromDegrees(x60_rotation.GetX())); + } + dmrtXf = rotXf * dmrtXf; + + if (CVectorElement* off = x0_description->x4c_DMOP.get()) { + off->GetValue(x58_frameIdx, offset); + } + + CTransform4f worldXf = CTransform4f::Translate(xc_transform.GetTranslation() + rotXf * offset); + if (dmrtIsConst) { + worldXf *= dmrtXf; + } else if (CVectorElement* dmrt = x0_description->x50_DMRT.get()) { + CVector3f rotation(0.f, 0.f, 0.f); + dmrt->GetValue(x58_frameIdx, rotation); + dmrtXf = CTransform4f::RotateZ(CRelAngle::FromDegrees(rotation.GetZ())); + dmrtXf.RotateLocalY(CRelAngle::FromDegrees(rotation.GetY())); + dmrtXf.RotateLocalX(CRelAngle::FromDegrees(rotation.GetX())); + worldXf *= rotXf * dmrtXf; + } else { + worldXf *= dmrtXf; + } + + if (CVectorElement* dmsc = x0_description->x54_DMSC.get()) { + CVector3f scale(0.f, 0.f, 0.f); + dmsc->GetValue(x58_frameIdx, scale); + worldXf *= CTransform4f::Scale(scale.GetX(), scale.GetY(), scale.GetZ()); + } + + if (CColorElement* dmcl = x0_description->x58_DMCL.get()) { + dmcl->GetValue(x58_frameIdx, color); + } + + CGraphics::SetModelMatrix(worldXf); + + if (x0_description->x5c_24_DMAB) { + const CModelFlags flags = CModelFlags::Additive(color).DepthCompareUpdate(true, false); + (*x0_description->x38_DMDL)->Draw(flags); + } else if (color.GetAlpha() == 1.f) { + (*x0_description->x38_DMDL)->Draw(CModelFlags::Normal()); + } else { + const CModelFlags flags = CModelFlags::AlphaBlended(color).DepthCompareUpdate(true, false); + (*x0_description->x38_DMDL)->Draw(flags); + } + + CGraphics::SetCullMode(kCM_Front); + CTevCombiners::ResetStates(); +} void CDecal::Render() const { CGlobalRandom gr(sDecalRandom);