diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index cd07e0cc..ec707064 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -11974,7 +11974,7 @@ fn_802BEAD8 = .text:0x802BEAD8; // type:function size:0x17C fn_802BEC54 = .text:0x802BEC54; // type:function size:0x1FC fn_802BEE50 = .text:0x802BEE50; // type:function size:0x210 __ct__13CCubeRendererFR12IObjectStoreR10COsContextR10CMemorySysR11CResFactory = .text:0x802BF060; // type:function size:0x304 scope:global -__ct__Q213CCubeRenderer13CAreaListItem = .text:0x802BF364; // type:function size:0x48 scope:global +__ct__Q213CCubeRenderer13CAreaListItemFPCQ24rstl58vector<21CMetroidModelInstance,Q24rstl17rmemory_allocator>PC12CAreaOctTreeRCQ24rstl79auto_ptr,Q24rstl17rmemory_allocator>>RCQ24rstl85auto_ptr,Q24rstl17rmemory_allocator>>i = .text:0x802BF364; // type:function size:0x48 scope:global Clear__7BucketsFv = .text:0x802BF3AC; // type:function size:0x1F8 scope:global Sort__7BucketsFv = .text:0x802BF5A4; // type:function size:0x578 scope:global InsertPlaneObject__7BucketsFffRC6CAABoxbRC6CPlaneb13EDrawableTypePCv = .text:0x802BFB1C; // type:function size:0x78 scope:global @@ -12003,7 +12003,7 @@ fn_802C082C = .text:0x802C082C; // type:function size:0x8C fn_802C08B8 = .text:0x802C08B8; // type:function size:0xDC fn_802C0994 = .text:0x802C0994; // type:function size:0xA8 __sinit_CCubeRenderer_cpp = .text:0x802C0A3C; // type:function size:0x114 scope:local -fn_802C0B50 = .text:0x802C0B50; // type:function size:0x94 +__dt__Q24rstl22reserved_vectorFv = .text:0x802C0B50; // type:function size:0x94 @4@AddParticleGen__13CCubeRendererFRC12CParticleGen = .text:0x802C0BE4; // type:function size:0x8 scope:global @4@__dt__13CCubeRendererFv = .text:0x802C0BEC; // type:function size:0x8 scope:global InitializeApplicationUI__FR7CGuiSys = .text:0x802C0BF4; // type:function size:0x4 scope:global diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index 8f6e2ccc..a4565f83 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -11974,7 +11974,7 @@ fn_802BEAD8 = .text:0x802BEB84; // type:function size:0x17C scope:global fn_802BEC54 = .text:0x802BED00; // type:function size:0x1FC scope:global fn_802BEE50 = .text:0x802BEEFC; // type:function size:0x210 scope:global __ct__13CCubeRendererFR12IObjectStoreR10COsContextR10CMemorySysR11CResFactory = .text:0x802BF10C; // type:function size:0x304 scope:global -__ct__Q213CCubeRenderer13CAreaListItem = .text:0x802BF410; // type:function size:0x48 scope:global +__ct__Q213CCubeRenderer13CAreaListItemFPCQ24rstl58vector<21CMetroidModelInstance,Q24rstl17rmemory_allocator>PC12CAreaOctTreeRCQ24rstl79auto_ptr,Q24rstl17rmemory_allocator>>RCQ24rstl85auto_ptr,Q24rstl17rmemory_allocator>>i = .text:0x802BF410; // type:function size:0x48 scope:global Clear__7BucketsFv = .text:0x802BF458; // type:function size:0x1F8 scope:global Sort__7BucketsFv = .text:0x802BF650; // type:function size:0x578 scope:global InsertPlaneObject__7BucketsFffRC6CAABoxbRC6CPlaneb13EDrawableTypePCv = .text:0x802BFBC8; // type:function size:0x78 scope:global @@ -12003,7 +12003,7 @@ fn_802C082C = .text:0x802C08D8; // type:function size:0x8C scope:global fn_802C08B8 = .text:0x802C0964; // type:function size:0xDC scope:global fn_802C0994 = .text:0x802C0A40; // type:function size:0xA8 scope:global __sinit_CCubeRenderer_cpp = .text:0x802C0AE8; // type:function size:0x114 scope:global -fn_802C0B50 = .text:0x802C0BFC; // type:function size:0x94 scope:global +__dt__Q24rstl22reserved_vectorFv = .text:0x802C0BFC; // type:function size:0x94 scope:global @4@AddParticleGen__13CCubeRendererFRC12CParticleGen = .text:0x802C0C90; // type:function size:0x8 scope:global @4@__dt__13CCubeRendererFv = .text:0x802C0C98; // type:function size:0x8 scope:global InitializeApplicationUI__FR7CGuiSys = .text:0x802C0CA0; // type:function size:0x4 scope:global diff --git a/include/Kyoto/Graphics/CDrawable.hpp b/include/Kyoto/Graphics/CDrawable.hpp new file mode 100644 index 00000000..86f61e83 --- /dev/null +++ b/include/Kyoto/Graphics/CDrawable.hpp @@ -0,0 +1,44 @@ +#ifndef _CDRAWABLE +#define _CDRAWABLE + +#include "types.h" + +#include "Kyoto/Math/CAABox.hpp" + +// TODO +enum EDrawableType { + WorldSurface, + Particle, + Actor, + SimpleShadow, + Decal, + Invalid = 0xFFFF, +}; + +class CDrawable { +public: + CDrawable(EDrawableType dtype, ushort extraSort, float planeDot, const CAABox& aabb, void* data) + : x0_type(dtype), x2_extraSort(extraSort), x4_data(data), x8_aabb(aabb), x20_viewDist(planeDot) {} + // CDrawable(const CDrawable& other) + // : x0_type(other.x0_type) + // , x2_extraSort(other.x2_extraSort) + // , x4_data(other.x4_data) + // , x8_aabb(other.x8_aabb) + // , x20_viewDist(other.x20_viewDist) {} + + EDrawableType GetType() const { return EDrawableType(x0_type); } + const CAABox& GetBounds() const { return x8_aabb; } + float GetDistance() const { return x20_viewDist; } + void* GetData() { return x4_data; } + const void* GetData() const { return x4_data; } + u16 GetExtraSort() const { return x2_extraSort; } + +private: + ushort x0_type; + ushort x2_extraSort; + void* x4_data; + CAABox x8_aabb; + float x20_viewDist; +}; + +#endif // _CDRAWABLE diff --git a/include/Kyoto/Graphics/CDrawablePlaneObject.hpp b/include/Kyoto/Graphics/CDrawablePlaneObject.hpp new file mode 100644 index 00000000..e505290e --- /dev/null +++ b/include/Kyoto/Graphics/CDrawablePlaneObject.hpp @@ -0,0 +1,29 @@ +#ifndef _CDRAWABLEPLANEOBJECT +#define _CDRAWABLEPLANEOBJECT + +#include "types.h" + +#include "Kyoto/Graphics/CDrawable.hpp" +#include "Kyoto/Math/CAABox.hpp" +#include "Kyoto/Math/CPlane.hpp" + +class CDrawablePlaneObject : public CDrawable { + ushort x24_targetBucket; + float x28_farDist; + CPlane x2c_plane; + bool x3c_24_invertTest : 1; + bool x3c_25_zOnly : 1; + +public: + CDrawablePlaneObject(EDrawableType dtype, float closeDist, float farDist, const CAABox& aabb, + bool invertTest, const CPlane& plane, bool zOnly, void* data) + : CDrawable(dtype, 0, closeDist, aabb, data) + , x28_farDist(farDist) + , x2c_plane(plane) + , x3c_24_invertTest(invertTest) + , x3c_25_zOnly(zOnly) {} + + const CPlane& GetPlane() const { return x2c_plane; } +}; + +#endif // _CDRAWABLEPLANEOBJECT diff --git a/include/Kyoto/PVS/CPVSVisSet.hpp b/include/Kyoto/PVS/CPVSVisSet.hpp index 132b2ab0..19c93b2e 100644 --- a/include/Kyoto/PVS/CPVSVisSet.hpp +++ b/include/Kyoto/PVS/CPVSVisSet.hpp @@ -5,13 +5,18 @@ class CPVSVisSet { public: - static CPVSVisSet Reset(int); + CPVSVisSet(int); + void SetFromMemory(int numBits, int numLights, const char* leafPtr); + + static CPVSVisSet Reset(int); + private: int x0_state; uint x4_numBits; uint x8_numLights; rstl::auto_ptr< u8 > x10_ptr; }; +CHECK_SIZEOF(CPVSVisSet, 0x14); #endif // _CPVSVISSET diff --git a/include/Kyoto/Text/CFont.hpp b/include/Kyoto/Text/CFont.hpp index 6a996bee..98f50246 100644 --- a/include/Kyoto/Text/CFont.hpp +++ b/include/Kyoto/Text/CFont.hpp @@ -1,6 +1,8 @@ #ifndef _CFONT #define _CFONT +#include "types.h" + #include "Kyoto/Graphics/CColor.hpp" class CFont { @@ -9,9 +11,11 @@ public: ~CFont(); int CharWidth(char) const; void DrawString(const char* str, long x, long y, const CColor& col) const; + private: int mFontSize; float mScale; }; +CHECK_SIZEOF(CFont, 0x8); #endif // _CFONT diff --git a/include/MetaRender/CCubeRenderer.hpp b/include/MetaRender/CCubeRenderer.hpp index 17728dda..87167708 100644 --- a/include/MetaRender/CCubeRenderer.hpp +++ b/include/MetaRender/CCubeRenderer.hpp @@ -6,22 +6,71 @@ #include #include "MetaRender/IRenderer.hpp" -#include "Weapons/IWeaponRenderer.hpp" +#include "Kyoto/CRandom16.hpp" +#include "Kyoto/CResFactory.hpp" #include "Kyoto/Graphics/CColor.hpp" +#include "Kyoto/Graphics/CGraphicsPalette.hpp" +#include "Kyoto/Graphics/CLight.hpp" +#include "Kyoto/Graphics/CTexture.hpp" +#include "Kyoto/IObjectStore.hpp" #include "Kyoto/Math/CAABox.hpp" +#include "Kyoto/Math/CFrustumPlanes.hpp" #include "Kyoto/Math/CTransform4f.hpp" #include "Kyoto/Math/CVector2f.hpp" #include "Kyoto/Math/CVector3f.hpp" +#include "Kyoto/PVS/CPVSVisSet.hpp" #include "Kyoto/TToken.hpp" +#include "Kyoto/Text/CFont.hpp" +#include "Weapons/IWeaponRenderer.hpp" + +#include "WorldFormat/CAreaOctTree.hpp" + +#include "rstl/list.hpp" +#include "rstl/optional_object.hpp" #include "rstl/pair.hpp" +#include "rstl/single_ptr.hpp" +#include "rstl/vector.hpp" -class CSkinnedModel; +class CAreaOctTree; +class CCubeModel; +class CMetroidModelInstance; class CModel; +class CSkinnedModel; class CCubeRenderer : public IRenderer, public IWeaponRenderer { +private: + class CAreaListItem { + CAreaListItem( + const rstl::vector< CMetroidModelInstance, rstl::rmemory_allocator >* geometry, + const CAreaOctTree* octTree, + const rstl::auto_ptr< rstl::vector< TCachedToken< CTexture >, rstl::rmemory_allocator > >& + textures, + const rstl::auto_ptr< + rstl::vector< rstl::auto_ptr< CCubeModel >, rstl::rmemory_allocator > >& models, + int areaIdx); + + private: + const rstl::vector< CMetroidModelInstance, rstl::rmemory_allocator >* x0_geometry; + const CAreaOctTree* x4_octTree; + const rstl::auto_ptr< rstl::vector< TCachedToken< CTexture >, rstl::rmemory_allocator > > + x8_textures; + const rstl::auto_ptr< rstl::vector< rstl::auto_ptr< CCubeModel >, rstl::rmemory_allocator > > + xc_models; + int x18_areaIdx; + rstl::vector< uint > x1c_lightOctreeWords; + }; + class CFogVolumeListItem { + CTransform4f x0_xf; + CColor x30_color; + CAABox x34_aabb; + rstl::optional_object< TCachedToken< CModel > > x4c_model; + const CSkinnedModel* x5c_skinnedModel; + }; + public: + CCubeRenderer(IObjectStore&, COsContext&, CMemorySys&, CResFactory&); ~CCubeRenderer() override; // TODO types void AddStaticGeometry() override; @@ -92,9 +141,43 @@ public: void Something() override; void PrepareDynamicLights(const rstl::vector< CLight >& lights) override; - void AllocatePhazonSuitMaskTexture(); - - uchar x8_pad[0x310]; +private: + CResFactory& x8_factory; + IObjectStore& xc_objStore; + CFont x10_font; + int x18_primVertCount; + rstl::list< CAreaListItem > x1c_areaListItems; + int x34_unk1; + int x38_unk2; + int x3c_unk3; + int x40_unk4; + CFrustumPlanes x44_frustumPlanes; + TDrawableCallback xa8_drawableCallback; + void* xac_drawableCallbackUserData; + CPlane xb0_viewPlane; + uchar xc0_pvsMode; + int xc4_unk5; + rstl::optional_object< CPVSVisSet > xc8_pvsVisSet; + int xe0_pvsAreaIdx; + CTexture xe4_blackTex; + rstl::single_ptr< CTexture > x14c_reflectionTex; + CTexture x150_reflectionTex; + CTexture x1b8_fogVolumeRamp; + CTexture x220_sphereRamp; + CGraphicsPalette x288_thermalPalette; + CRandom16 x2a8_thermalRand; + rstl::list< CFogVolumeListItem > x2ac_fogVolumes; + rstl::list< rstl::pair< CVector3f, float > > x2c4_spaceWarps; + int x2dc_reflectionAge; + CColor x2e0_primColor; + CVector3f x2e4_primNormal; + float x2f0_thermalVisorLevel; + CColor x2f4_thermalColor; + uchar x2f8_thermalColdScale; + CColor x2fc_tevReg1Color; + rstl::vector< CLight > x300_dynamicLights; + int x310_phazonSuitMaskCountdown; + rstl::single_ptr< CTexture > x314_phazonSuitMask; bool x318_24_reflectionDirty : 1; bool x318_25_drawWireframe : 1; bool x318_26_requestRGBA6 : 1; @@ -103,7 +186,16 @@ public: bool x318_29_thermalVisor : 1; bool x318_30_inAreaDraw : 1; bool x318_31_persistRGBA6 : 1; + + void AllocatePhazonSuitMaskTexture(); + void GenerateReflectionTex(); + void GenerateFogVolumeRampTex(); + void GenerateSphereRampTex(); + void LoadThermoPalette(); + + static CCubeRenderer* sRenderer; }; +CHECK_SIZEOF(CCubeRenderer, 0x31C); extern CCubeRenderer* gpRender; diff --git a/include/dolphin/types.h b/include/dolphin/types.h index 84efb061..d2b70146 100644 --- a/include/dolphin/types.h +++ b/include/dolphin/types.h @@ -99,4 +99,12 @@ typedef int BOOL; #endif #endif +#if (defined(__cplusplus) && __cplusplus >= 201103L) || defined(__clang__) +// Use C++11 auto keyword +#define AUTO(name, val) auto name = val +#else +// Use __typeof__ extension +#define AUTO(name, val) __typeof__(val) name = val +#endif + #endif // _DOLPHIN_TYPES diff --git a/libc/type_traits b/libc/type_traits new file mode 100644 index 00000000..21496db9 --- /dev/null +++ b/libc/type_traits @@ -0,0 +1,11 @@ +#ifndef _TYPE_TRAITS +#define _TYPE_TRAITS + +namespace std { +template < typename T > +struct type_identity { + typedef T type; +}; +} // namespace std + +#endif // _TYPE_TRAITS diff --git a/src/MetaRender/CCubeRenderer.cpp b/src/MetaRender/CCubeRenderer.cpp new file mode 100644 index 00000000..93597519 --- /dev/null +++ b/src/MetaRender/CCubeRenderer.cpp @@ -0,0 +1,172 @@ +#include "MetaRender/CCubeRenderer.hpp" + +#include "Kyoto/Graphics/CDrawable.hpp" +#include "Kyoto/Graphics/CDrawablePlaneObject.hpp" +#include "Kyoto/Graphics/CGraphicsPalette.hpp" +#include "Kyoto/Graphics/CModelFlags.hpp" +#include "Kyoto/Graphics/CTexture.hpp" +#include "Kyoto/Math/CTransform4f.hpp" +#include "Kyoto/Math/CUnitVector3f.hpp" +#include "Kyoto/Math/CVector3f.hpp" +#include "dolphin/types.h" +#include "rstl/math.hpp" +#include "rstl/pair.hpp" +#include "rstl/reserved_vector.hpp" +#include "rstl/vector.hpp" + +#include +#include + +CCubeRenderer* CCubeRenderer::sRenderer = nullptr; +static CModelFlags skNormalFlag = CModelFlags::Normal(); +static CModelFlags skNormalFlagNoUpdate = CModelFlags::Normal().DepthCompareUpdate(true, false); + +namespace Buckets { +typedef rstl::reserved_vector< CDrawable*, 128 > BucketHolderType; + +static rstl::pair< float, float > skWorstMinMaxDistance(99999.f, -99999.f); +static rstl::reserved_vector< ushort, 50 > sBucketIndex; +static rstl::reserved_vector< CDrawable, 512 >* sData; +static rstl::reserved_vector< BucketHolderType, 50 >* sBuckets; +static rstl::pair< float, float > sMinMaxDistance = skWorstMinMaxDistance; +static rstl::reserved_vector< CDrawablePlaneObject, 8 >* sPlaneObjectData; +static rstl::reserved_vector< ushort, 8 >* sPlaneObjectBucket; + +void Init() { +#define HOLDER(var) \ + static uchar var##Holder[sizeof(__typeof__(*var))]; \ + var = new (var##Holder) std::type_identity< __typeof__(*var) >::type(); + + HOLDER(sData); + HOLDER(sBuckets); + HOLDER(sPlaneObjectData); + HOLDER(sPlaneObjectBucket); + + sBuckets->resize(50, BucketHolderType()); + sMinMaxDistance = skWorstMinMaxDistance; +} + +void Shutdown() { + sData = nullptr; + sBuckets = nullptr; + sPlaneObjectData = nullptr; + sPlaneObjectBucket = nullptr; +} + +// TODO non-matching +void Insert(const CVector3f& pos, const CAABox& aabb, EDrawableType dtype, const void* data, + const CPlane& plane, ushort extraSort) { + if (sData->size() == sData->capacity()) { + return; + } + float dist = plane.GetHeight(pos); + sData->push_back(CDrawable(dtype, extraSort, dist, aabb, const_cast< void* >(data))); + sMinMaxDistance.first = rstl::min_val(dist, sMinMaxDistance.first); + sMinMaxDistance.second = rstl::max_val(dist, sMinMaxDistance.second); +#ifdef __MWERKS__ + __dcbt(&sData->back(), 0); +#endif +} + +void InsertPlaneObject(float closeDist, float farDist, const CAABox& aabb, bool invertTest, + const CPlane& plane, bool zOnly, EDrawableType dtype, const void* data) { + // TODO +} + +void Sort() { + // TODO +} + +void Clear() { + sData->clear(); + sBucketIndex.clear(); + sPlaneObjectData->clear(); + sPlaneObjectBucket->clear(); + for (AUTO(it, sBuckets->begin()); it != sBuckets->end(); ++it) { + it->clear(); + } + sMinMaxDistance = skWorstMinMaxDistance; +} +} // namespace Buckets + +CCubeRenderer::CAreaListItem::CAreaListItem( + const rstl::vector< CMetroidModelInstance, rstl::rmemory_allocator >* geometry, + const CAreaOctTree* octTree, + const rstl::auto_ptr< rstl::vector< TCachedToken< CTexture >, rstl::rmemory_allocator > >& + textures, + const rstl::auto_ptr< rstl::vector< rstl::auto_ptr< CCubeModel >, rstl::rmemory_allocator > >& + models, + int areaIdx) +: x0_geometry(geometry) +, x4_octTree(octTree) +, x8_textures(textures) +, xc_models(models) +, x18_areaIdx(areaIdx) +, x1c_lightOctreeWords() {} + +// TODO CSkinnedModel +extern "C" void fn_80352740(); + +CCubeRenderer::CCubeRenderer(IObjectStore& objStore, COsContext& osContext, CMemorySys& memorySys, + CResFactory& resFactory) +: x8_factory(resFactory) +, xc_objStore(objStore) +, x10_font(1.f) +, x18_primVertCount(0) +, x1c_areaListItems() +#if NONMATCHING +, x34_unk1(0) +#endif +, x38_unk2(0) +, x3c_unk3(0) +, x40_unk4(0) +, x44_frustumPlanes(CTransform4f::Identity(), 1.5707964f, 1.f, 1.f, false, 100.f) +, xa8_drawableCallback(nullptr) +#if NONMATCHING +, xac_drawableCallbackUserData(nullptr) +#endif +, xb0_viewPlane(0.f, CUnitVector3f(0.f, 1.f, 0.f, CUnitVector3f::kN_Yes)) +, xc0_pvsMode(0) +#if NONMATCHING +, xc4_unk5(0) +#endif +, xc8_pvsVisSet() +, xe0_pvsAreaIdx(-1) +, xe4_blackTex(kTF_RGB565, 4, 4, 1) +, x14c_reflectionTex() +, x150_reflectionTex(kTF_IA8, 32, 32, 1) +, x1b8_fogVolumeRamp(kTF_I8, 256, 256, 1) +, x220_sphereRamp(kTF_I8, 32, 32, 1) +, x288_thermalPalette(kPF_RGB565, 16) +, x2a8_thermalRand(20) +, x2ac_fogVolumes() +, x2c4_spaceWarps() +, x2dc_reflectionAge(2) +, x2e0_primColor(CColor::White()) +, x2e4_primNormal(CVector3f::Forward()) +, x2f0_thermalVisorLevel(1.f) +, x2f4_thermalColor(static_cast< uchar >(255), static_cast< uchar >(0), static_cast< uchar >(255)) +, x2f8_thermalColdScale(0) +, x2fc_tevReg1Color(static_cast< uchar >(255), static_cast< uchar >(0), static_cast< uchar >(255)) +, x300_dynamicLights() +, x310_phazonSuitMaskCountdown(0) +, x314_phazonSuitMask() +, x318_24_reflectionDirty(false) +, x318_25_drawWireframe(false) +, x318_26_requestRGBA6(false) +, x318_27_currentRGBA6(false) +, x318_28_disableFog(false) +, x318_29_thermalVisor(false) +, x318_30_inAreaDraw(false) +, x318_31_persistRGBA6(false) { + void* data = xe4_blackTex.Lock(); + memset(data, 0, 32); + xe4_blackTex.UnLock(); + GenerateReflectionTex(); + GenerateFogVolumeRampTex(); + GenerateSphereRampTex(); + LoadThermoPalette(); + sRenderer = this; + Buckets::Init(); + fn_80352740(); +}