#pragma once #include #include #include "CToken.hpp" #include "GCNTypes.hpp" #include "Graphics/CCubeModel.hpp" #include "Graphics/CCubeSurface.hpp" #include "Graphics/CTexture.hpp" #include "IObjectStore.hpp" #include "Flags.hpp" namespace metaforce { class CCubeMaterial; enum class CModelFlagBits : u16 { DepthTest = 0x1, DepthUpdate = 0x2, NoTextureLock = 0x4, DepthGreater = 0x8, DepthNonInclusive = 0x10, DrawNormal = 0x20, ThermalUnsortedOnly = 0x40, }; using CModelFlagsFlags = Flags; struct CModelFlags { /** * 2: add color * >6: additive * >4: blend * else opaque */ u8 x0_blendMode = 0; u8 x1_matSetIdx = 0; CModelFlagsFlags x2_flags{}; /** * Set into kcolor slot specified by material */ zeus::CColor x4_color; constexpr CModelFlags() = default; constexpr CModelFlags(u8 blendMode, u8 shadIdx, u16 flags, const zeus::CColor& col) : x0_blendMode(blendMode), x1_matSetIdx(shadIdx), x2_flags(flags), x4_color(col) {} constexpr CModelFlags(u8 blendMode, u8 shadIdx, CModelFlagsFlags flags, const zeus::CColor& col) : x0_blendMode(blendMode), x1_matSetIdx(shadIdx), x2_flags(flags), x4_color(col) {} bool operator==(const CModelFlags& other) const { return x0_blendMode == other.x0_blendMode && x1_matSetIdx == other.x1_matSetIdx && x2_flags == other.x2_flags && x4_color == other.x4_color; } bool operator!=(const CModelFlags& other) const { return !operator==(other); } }; class CModel { public: struct SShader { std::vector> x0_textures; u8* x10_data; explicit SShader(u8* data) : x10_data(data) {} void UnlockTextures(); }; private: static u32 sTotalMemory; static u32 sFrameCounter; static bool sIsTextureTimeoutEnabled; static CModel* sThisFrameList; static CModel* sOneFrameList; static CModel* sTwoFrameList; std::unique_ptr x0_data; u32 x4_dataLen; std::vector x8_surfaces; // was rstl::vector std::vector x18_matSets; std::unique_ptr x28_modelInst = nullptr; u16 x2c_currentMatIdx = 0; u16 x2e_lastFrame = 0; // Last frame that the model switched materials CModel* x30_prev = nullptr; CModel* x34_next; u32 x38_lastFrame; /* Resident copies of maintained data */ std::vector m_positions; std::vector m_normals; std::vector m_colors; std::vector> m_floatUVs; std::vector> m_shortUVs; public: CModel(std::unique_ptr in, u32 dataLen, IObjectStore* store); ~CModel(); void UpdateLastFrame(); void MoveToThisFrameList(); void RemoveFromList(); void VerifyCurrentShader(u32 matIdx); void Touch(u32 matIdx); void Draw(CModelFlags flags); void Draw(TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags); void DrawSortedParts(CModelFlags flags); void DrawUnsortedParts(CModelFlags flags); bool IsLoaded(u32 matIdx); [[nodiscard]] TVectorRef GetPositions(); [[nodiscard]] TConstVectorRef GetPositions() const; [[nodiscard]] TVectorRef GetNormals(); [[nodiscard]] TConstVectorRef GetNormals() const; [[nodiscard]] u32 GetNumMaterialSets() const { return x18_matSets.size(); } [[nodiscard]] bool IsOpaque() const { return x28_modelInst->x3c_firstSortedSurf == nullptr; } [[nodiscard]] const zeus::CAABox& GetAABB() const { return x28_modelInst->x20_worldAABB; } [[nodiscard]] auto& GetInstance() { return *x28_modelInst; } [[nodiscard]] const auto& GetInstance() const { return *x28_modelInst; } static void FrameDone(); static void EnableTextureTimeout(); static void DisableTextureTimeout(); }; CFactoryFnReturn FModelFactory(const metaforce::SObjectTag& tag, std::unique_ptr&& in, u32 len, const metaforce::CVParamTransfer& vparms, CObjectReference* selfRef); } // namespace metaforce