diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index 7a220effd..124498f77 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -1613,8 +1613,8 @@ bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& in header.centroid = osurf.centroid; header.matIdx = osurf.materialIdx; header.reflectionNormal = osurf.reflectionNormal; - header.unk1 = surf.m_start; - header.unk2 = surf.m_count; + header.idxStart = surf.m_start; + header.idxCount = surf.m_count; header.write(writer); writer.fill(atUint8(0), *padIt); diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index fedef26fb..9ea2c68cb 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -45,8 +45,8 @@ struct SurfaceHeader_1 : BigDNA Value matIdx = 0; Value qDiv = 0x8000; Value dlSize = 0; - Value unk1 = 0; - Value unk2 = 0; + Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ + Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ Value aabbSz = 0; Value reflectionNormal; Seek seek2; @@ -63,8 +63,8 @@ struct SurfaceHeader_2 : BigDNA Value matIdx = 0; Value qDiv = 0x8000; Value dlSize = 0; - Value unk1 = 0; - Value unk2 = 0; + Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ + Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ Value aabbSz = 0; Value reflectionNormal; Value skinMtxBankIdx; @@ -83,8 +83,8 @@ struct SurfaceHeader_3 : BigDNA Value matIdx = 0; Value qDiv = 0x8000; Value dlSize = 0; - Value unk1 = 0; - Value unk2 = 0; + Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ + Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ Value aabbSz = 0; Value reflectionNormal; Value skinMtxBankIdx; diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 0ffd9e784..983d72738 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -1,4 +1,4 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ./../Runtime) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/DataSpec ${CMAKE_SOURCE_DIR}/Runtime) add_subdirectory(locale) add_subdirectory(icons) @@ -47,8 +47,8 @@ target_link_libraries(urde RuntimeCommon DNAMP3 DNAMP2 DNAMP1 DNACommon specter specter-fonts freetype ${DATA_SPEC_LIBS} - hecl-database hecl-backend hecl-frontend hecl-blender hecl-runtime hecl-common athena-core nod - logvisor athena-libyaml boo ${PNG_LIB} libjpeg-turbo squish xxhash zeus + hecl-database hecl-runtime hecl-backend hecl-frontend hecl-hmdl hecl-blender hecl-common + athena-core nod logvisor athena-libyaml boo ${PNG_LIB} libjpeg-turbo squish xxhash zeus ${ZLIB_LIBRARIES} ${LZO_LIB} ${BOO_SYS_LIBS}) diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index b4c8747e4..b9fcbf37f 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -24,11 +24,11 @@ namespace urde ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc) : ProjectResourceFactoryBase(clientProc) { - m_factoryMgr.AddFactory(FOURCC('TXTR'), FFactoryFunc(urde::FTextureFactory)); - m_factoryMgr.AddFactory(FOURCC('PART'), FFactoryFunc(urde::FParticleFactory)); - m_factoryMgr.AddFactory(FOURCC('FRME'), FFactoryFunc(urde::RGuiFrameFactoryInGame)); - m_factoryMgr.AddFactory(FOURCC('FONT'), FFactoryFunc(urde::FRasterFontFactory)); - m_factoryMgr.AddFactory(FOURCC('CMDL'), FMemFactoryFunc(urde::FModelFactory)); + m_factoryMgr.AddFactory(FOURCC('TXTR'), FFactoryFunc(FTextureFactory)); + m_factoryMgr.AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory)); + m_factoryMgr.AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame)); + m_factoryMgr.AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory)); + m_factoryMgr.AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory)); } void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj) diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 62c465534..5c7a56d22 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -245,6 +245,7 @@ void ViewManager::init(boo::IApplication* app) float pixelFactor = 1.0; boo::IGraphicsDataFactory* gf = m_mainWindow->getMainContextDataFactory(); + m_shaderCacheManager.emplace(m_fileStoreManager, gf); m_viewResources.init(gf, &m_fontCache, &m_themeData, pixelFactor); m_iconsToken = InitializeIcons(m_viewResources); m_viewResources.prepFontCacheAsync(m_mainWindow.get()); @@ -256,7 +257,7 @@ void ViewManager::init(boo::IApplication* app) m_mainWindow->setWaitCursor(false); m_voiceEngine = boo::NewAudioVoiceEngine(); - CGraphics::InitializeBoo(gf, m_mainWindow->getCommandQueue(), root->renderTex()); + CGraphics::InitializeBoo(gf, m_mainWindow->getCommandQueue(), root->renderTex(), &*m_shaderCacheManager); CElementGen::Initialize(); CMoviePlayer::Initialize(); CLineRenderer::Initialize(); @@ -322,6 +323,7 @@ void ViewManager::stop() m_iconsToken.doDestroy(); m_viewResources.destroyResData(); m_fontCache.destroyAtlases(); + m_shaderCacheManager = std::experimental::nullopt; m_mainWindow->getCommandQueue()->stopRenderer(); } diff --git a/Editor/ViewManager.hpp b/Editor/ViewManager.hpp index 2f846fa4b..be366cb5c 100644 --- a/Editor/ViewManager.hpp +++ b/Editor/ViewManager.hpp @@ -22,6 +22,7 @@ class ViewManager : public specter::IViewManager friend class SplitSpace; hecl::Runtime::FileStoreManager& m_fileStoreManager; + std::experimental::optional m_shaderCacheManager; hecl::CVarManager& m_cvarManager; ProjectManager m_projManager; specter::FontCache m_fontCache; diff --git a/Runtime/CFactoryMgr.hpp b/Runtime/CFactoryMgr.hpp index 65596718d..01299e624 100644 --- a/Runtime/CFactoryMgr.hpp +++ b/Runtime/CFactoryMgr.hpp @@ -28,14 +28,8 @@ public: bool CanMakeMemory(const urde::SObjectTag& tag) const; CFactoryFnReturn MakeObjectFromMemory(const SObjectTag& tag, std::unique_ptr&& buf, int size, bool compressed, const CVParamTransfer& paramXfer); - void AddFactory(FourCC key, FFactoryFunc func) - { - m_factories[key] = func; - } - void AddFactory(FourCC key, FMemFactoryFunc func) - { - m_memFactories[key] = func; - } + void AddFactory(FourCC key, FFactoryFunc func) {m_factories[key] = func;} + void AddFactory(FourCC key, FMemFactoryFunc func) {m_memFactories[key] = func;} }; } diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index 5fb298d37..e0cbead93 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -1,4 +1,5 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${BOO_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${BOO_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/DataSpec) add_subdirectory(Audio) add_subdirectory(Character) diff --git a/Runtime/CToken.hpp b/Runtime/CToken.hpp index 87808f14f..abeaccb14 100644 --- a/Runtime/CToken.hpp +++ b/Runtime/CToken.hpp @@ -143,6 +143,7 @@ public: x4_lockHeld = true; } } + bool IsLocked() const {return x4_lockHeld;} bool IsLoaded() const { if (!x0_objRef) @@ -210,6 +211,12 @@ public: ++x0_objRef->x0_refCount; Lock(); } + CToken(std::unique_ptr&& obj) + { + x0_objRef = new CObjectReference(std::move(obj)); + ++x0_objRef->x0_refCount; + Lock(); + } CToken(CObjectReference* obj) { x0_objRef = obj; @@ -243,12 +250,17 @@ public: TToken() = default; TToken(const CToken& other) : CToken(other) {} TToken(CToken&& other) : CToken(std::move(other)) {} - TToken(T* obj) : CToken(GetIObjObjectFor(std::unique_ptr(obj))) {} - TToken& operator=(T* obj) {*this = CToken(GetIObjObjectFor(obj)); return this;} + TToken(std::unique_ptr&& obj) : CToken(GetIObjObjectFor(std::move(obj))) {} + TToken& operator=(std::unique_ptr&& obj) + { + *this = CToken(GetIObjObjectFor(std::move(obj))); + return this; + } T* GetObj() { - if (CToken::GetObj()) - return static_cast*>(CToken::GetObj())->GetObj(); + TObjOwnerDerivedFromIObj* owner = static_cast*>(CToken::GetObj()); + if (owner) + return owner->GetObj(); return nullptr; } const T* GetObj() const @@ -260,15 +272,38 @@ public: }; template -class TLockedToken : public TToken +class TCachedToken : public TToken { - T* m_obj; +protected: + T* m_obj = nullptr; public: - TLockedToken() : m_obj(nullptr) {} - TLockedToken(const CToken& other) : TToken(other) {m_obj = TToken::GetObj();} - TLockedToken(CToken&& other) : TToken(std::move(other)) {m_obj = TToken::GetObj();} - T* GetObj() const {return m_obj;} - T* operator->() const {return m_obj;} + TCachedToken() = default; + TCachedToken(const CToken& other) : TToken(other) {} + TCachedToken(CToken&& other) : TToken(std::move(other)) {} + T* GetObj() + { + if (!m_obj) + m_obj = TToken::GetObj(); + return m_obj; + } + const T* GetObj() const + { + return ((TCachedToken*)this)->GetObj(); + } + T* operator->() {return GetObj();} + const T* operator->() const {return GetObj();} + void Unlock() {TToken::Unlock(); m_obj = nullptr;} +}; + +template +class TLockedToken : public TCachedToken +{ +public: + TLockedToken() = default; + TLockedToken(const CToken& other) : TCachedToken(other) + {TCachedToken::m_obj = TToken::GetObj();} + TLockedToken(CToken&& other) : TCachedToken(std::move(other)) + {TCachedToken::m_obj = TToken::GetObj();} }; } diff --git a/Runtime/Graphics/CGraphics.cpp b/Runtime/Graphics/CGraphics.cpp index 25d105821..b9eb095fb 100644 --- a/Runtime/Graphics/CGraphics.cpp +++ b/Runtime/Graphics/CGraphics.cpp @@ -300,5 +300,6 @@ void CGraphics::SetViewportResolution(const zeus::CVector2i& res) boo::IGraphicsDataFactory* CGraphics::g_BooFactory = nullptr; boo::IGraphicsCommandQueue* CGraphics::g_BooMainCommandQueue = nullptr; boo::ITextureR* CGraphics::g_SpareTexture = nullptr; +hecl::Runtime::ShaderCacheManager* CGraphics::g_ShaderCacheMgr = nullptr; } diff --git a/Runtime/Graphics/CGraphics.hpp b/Runtime/Graphics/CGraphics.hpp index 13ae16e63..152d44493 100644 --- a/Runtime/Graphics/CGraphics.hpp +++ b/Runtime/Graphics/CGraphics.hpp @@ -8,6 +8,8 @@ #include "boo/graphicsdev/IGraphicsDataFactory.hpp" #include "boo/graphicsdev/IGraphicsCommandQueue.hpp" +#include "hecl/Runtime.hpp" + namespace urde { class CLight; @@ -212,14 +214,17 @@ public: static boo::IGraphicsDataFactory* g_BooFactory; static boo::IGraphicsCommandQueue* g_BooMainCommandQueue; static boo::ITextureR* g_SpareTexture; + static hecl::Runtime::ShaderCacheManager* g_ShaderCacheMgr; static void InitializeBoo(boo::IGraphicsDataFactory* factory, boo::IGraphicsCommandQueue* cc, - boo::ITextureR* spareTex) + boo::ITextureR* spareTex, + hecl::Runtime::ShaderCacheManager* shadCacheMgr) { g_BooFactory = factory; g_BooMainCommandQueue = cc; g_SpareTexture = spareTex; + g_ShaderCacheMgr = shadCacheMgr; } static boo::GraphicsDataToken CommitResources(const boo::FactoryCommitFunc& commitFunc) @@ -243,6 +248,10 @@ public: { g_BooMainCommandQueue->draw(start, count); } + static void DrawArrayIndexed(size_t start, size_t count) + { + g_BooMainCommandQueue->drawIndexed(start, count); + } }; } diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 61c5148ba..00b0ad271 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -6,6 +6,8 @@ #include "CFactoryMgr.hpp" #include "CToken.hpp" #include "zeus/CAABox.hpp" +#include "DNACommon/CMDL.hpp" +#include "DNAMP1/CMDLMaterials.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" @@ -22,69 +24,80 @@ struct CModelFlags zeus::CColor color; /* Set into kcolor slot specified by material */ /* depth flags + 0x4: render without texture lock 0x8: greater 0x10: non-inclusive */ }; -class CBooSurface +/* urde addition: doesn't require hacky stashing of + * pointers within loaded CMDL buffer */ +struct CBooSurface { - + DataSpec::DNACMDL::SurfaceHeader_1 m_data; + class CBooModel* m_parent = nullptr; + CBooSurface* m_next = nullptr; }; class CBooModel { public: - /* urde addition: doesn't require hacky stashing of - * pointers within loaded CMDL buffer */ - struct CSurfaceView + struct SShader { - const u8* m_data; - CBooModel* m_parent = nullptr; - CSurfaceView* m_next = nullptr; + std::vector> x0_textures; + std::vector m_shaders; + DataSpec::DNAMP1::HMDLMaterialSet m_matSet; + void UnlockTextures(); }; + private: - std::vector* x0_surfaces; - const u8* x4_matSet; + std::vector* x0_surfaces; + const DataSpec::DNAMP1::HMDLMaterialSet* x4_matSet; + const std::vector* m_pipelines; + boo::IVertexFormat* m_vtxFmt; boo::IGraphicsBufferS* x8_vbo; boo::IGraphicsBufferS* xc_ibo; - std::vector>* x1c_textures; + std::vector>* x1c_textures; zeus::CAABox x20_aabb; - CSurfaceView* x38_firstUnsortedSurface = nullptr; - CSurfaceView* x3c_firstSortedSurface = nullptr; - bool x40_24_ : 1; + CBooSurface* x38_firstUnsortedSurface = nullptr; + CBooSurface* x3c_firstSortedSurface = nullptr; + bool x40_24_texturesLoaded : 1; bool x40_25_ : 1; u8 x41_shortNormals; /* urde addition: boo! */ boo::GraphicsDataToken m_gfxToken; boo::IGraphicsBufferD* m_uniformBuffer; - boo::IShaderDataBinding* m_shaderDataBinding; + std::vector m_shaderDataBindings; void DrawAlphaSurfaces(const CModelFlags& flags) const; void DrawNormalSurfaces(const CModelFlags& flags) const; void DrawSurfaces(const CModelFlags& flags) const; void DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const; -public: - CBooModel(std::vector* surfaces, - std::vector>* textures, - const u8* matSet, - boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, - const zeus::CAABox& aabb, - u8 shortNormals, bool unk); + void BuildGfxToken(); - static void MakeTexuresFromMats(const u8* dataIn, - std::vector>& toksOut, +public: + CBooModel(std::vector* surfaces, SShader& shader, + boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, + const zeus::CAABox& aabb, + u8 shortNormals, bool texturesLoaded); + + static void MakeTexuresFromMats(const DataSpec::DNAMP1::HMDLMaterialSet& matSet, + std::vector>& toksOut, IObjectStore& store); - void TryLockTextures() const; + void RemapMaterialData(SShader& shader); + bool TryLockTextures() const; void UnlockTextures() const; void DrawAlpha(const CModelFlags& flags) const; void DrawNormal(const CModelFlags& flags) const; void Draw(const CModelFlags& flags) const; - const u8* GetMaterialByIndex(int idx) const; + const DataSpec::DNAMP1::HMDLMaterialSet::Material& GetMaterialByIndex(int idx) const + { + return x4_matSet->materials.at(idx); + } static bool g_DrawingOccluders; static void SetDrawingOccluders(bool occ) {g_DrawingOccluders = occ;} @@ -92,17 +105,10 @@ public: class CModel { -public: - struct SShader - { - std::vector> x0_textures; - const u8* x10_data; - }; -private: std::unique_ptr x0_data; u32 x4_dataLen; - std::vector x8_surfaces; - std::vector x18_matSets; + std::vector x8_surfaces; + std::vector x18_matSets; std::unique_ptr x28_modelInst; CModel* x30_next = nullptr; CModel* x34_prev = nullptr; @@ -111,12 +117,17 @@ private: boo::GraphicsDataToken m_gfxToken; boo::IGraphicsBufferS* m_vbo; boo::IGraphicsBufferS* m_ibo; + boo::IVertexFormat* m_vtxFmt; + + void VerifyCurrentShader(int shaderIdx) const; public: CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store); + void DrawSortedParts(const CModelFlags& flags) const; + void DrawUnsortedParts(const CModelFlags& flags) const; void Draw(const CModelFlags& flags) const; - void Touch(int) const; - bool IsLoaded(int) const; + void Touch(int shaderIdx) const; + bool IsLoaded(int shaderIdx) const; }; CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index a6949f23f..39125e9cc 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -2,27 +2,36 @@ #include "Graphics/CTexture.hpp" #include "Graphics/CGraphics.hpp" #include "hecl/HMDLMeta.hpp" +#include "hecl/Runtime.hpp" namespace urde { static logvisor::Module Log("urde::CModelBoo"); bool CBooModel::g_DrawingOccluders = false; -CBooModel::CBooModel(std::vector* surfaces, std::vector>* textures, - const u8* matSet, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, const zeus::CAABox& aabb, - u8 shortNormals, bool unk) -: x0_surfaces(surfaces), x4_matSet(matSet), x8_vbo(vbo), xc_ibo(ibo), x1c_textures(textures), - x20_aabb(aabb), x40_24_(unk), x40_25_(0), x41_shortNormals(shortNormals) +struct SUnskinnedUniforms { - for (CSurfaceView& surf : *x0_surfaces) + zeus::CMatrix4f mv; + zeus::CMatrix4f mvinv; + zeus::CMatrix4f proj; + zeus::CMatrix4f tex[8]; +}; + +CBooModel::CBooModel(std::vector* surfaces, SShader& shader, + boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, + const zeus::CAABox& aabb, u8 shortNormals, bool texturesLoaded) +: x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), m_pipelines(&shader.m_shaders), + m_vtxFmt(vtxFmt), x8_vbo(vbo), xc_ibo(ibo), x1c_textures(&shader.x0_textures), x20_aabb(aabb), + x40_24_texturesLoaded(texturesLoaded), x40_25_(0), x41_shortNormals(shortNormals) +{ + for (CBooSurface& surf : *x0_surfaces) surf.m_parent = this; for (auto it=x0_surfaces->rbegin() ; it != x0_surfaces->rend() ; ++it) { - u32 matId = hecl::SBig(*reinterpret_cast(it->m_data + 0xc)); - const u8* matData = GetMaterialByIndex(matId); - u32 matFlags = hecl::SBig(*reinterpret_cast(matData)); - if (matFlags & 0x10) + u32 matId = it->m_data.matIdx; + const DataSpec::DNAMP1::HMDLMaterialSet::Material& matData = GetMaterialByIndex(matId); + if (matData.flags.depthSorting()) { it->m_next = x3c_firstSortedSurface; x3c_firstSortedSurface = &*it; @@ -33,71 +42,152 @@ CBooModel::CBooModel(std::vector* surfaces, std::vector>& toksOut, +void CBooModel::BuildGfxToken() +{ + m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool + { + m_uniformBuffer = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SUnskinnedUniforms), 1); + boo::IGraphicsBuffer* bufs[] = {m_uniformBuffer}; + m_shaderDataBindings.reserve(x4_matSet->materials.size()); + auto pipelineIt = m_pipelines->begin(); + std::vector texs; + for (const DataSpec::DNAMP1::HMDLMaterialSet::Material& mat : x4_matSet->materials) + { + texs.clear(); + texs.reserve(mat.textureIdxs.size()); + for (atUint32 idx : mat.textureIdxs) + { + TCachedToken& tex = (*x1c_textures)[idx]; + texs.push_back(tex.GetObj()->GetBooTexture()); + } + m_shaderDataBindings.push_back(ctx.newShaderDataBinding(*pipelineIt, m_vtxFmt, x8_vbo, nullptr, xc_ibo, 1, bufs, + mat.textureIdxs.size(), texs.data())); + ++pipelineIt; + } + return true; + }); +} + +void CBooModel::MakeTexuresFromMats(const DataSpec::DNAMP1::HMDLMaterialSet& matSet, + std::vector>& toksOut, IObjectStore& store) { - u32 texCount = hecl::SBig(*reinterpret_cast(dataIn)); - dataIn += 4; - toksOut.reserve(texCount); - for (u32 i=0 ; i(dataIn)); - dataIn += 4; - toksOut.emplace_back(store.GetObj({SBIG('TXTR'), id})); - } + toksOut.reserve(matSet.head.textureIDs.size()); + for (const DataSpec::UniqueID32& id : matSet.head.textureIDs) + toksOut.emplace_back(store.GetObj({SBIG('TXTR'), id.toUint32()})); } -void CBooModel::TryLockTextures() const +void CBooModel::RemapMaterialData(SShader& shader) { + x4_matSet = &shader.m_matSet; + x1c_textures = &shader.x0_textures; + m_pipelines = &shader.m_shaders; + x40_24_texturesLoaded = false; + m_gfxToken.doDestroy(); +} + +bool CBooModel::TryLockTextures() const +{ + if (!x40_24_texturesLoaded) + { + bool allLoad = true; + for (TCachedToken& tex : *x1c_textures) + { + tex.Lock(); + if (!tex.IsLoaded()) + allLoad = false; + } + + if (allLoad) + ((CBooModel*)this)->BuildGfxToken(); + + ((CBooModel*)this)->x40_24_texturesLoaded = allLoad; + } + return x40_24_texturesLoaded; } void CBooModel::UnlockTextures() const { + for (TCachedToken& tex : *x1c_textures) + tex.Unlock(); + ((CBooModel*)this)->x40_24_texturesLoaded = false; } void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const { + if (TryLockTextures()) + { + const CBooSurface* surf = x3c_firstSortedSurface; + while (surf) + { + DrawSurface(*surf, flags); + surf = surf->m_next; + } + } } void CBooModel::DrawNormalSurfaces(const CModelFlags& flags) const { + if (TryLockTextures()) + { + const CBooSurface* surf = x38_firstUnsortedSurface; + while (surf) + { + DrawSurface(*surf, flags); + surf = surf->m_next; + } + } } void CBooModel::DrawSurfaces(const CModelFlags& flags) const { + if (!(flags.f3 & 0x4)) + if (!TryLockTextures()) + return; + + const CBooSurface* surf = x38_firstUnsortedSurface; + while (surf) + { + DrawSurface(*surf, flags); + surf = surf->m_next; + } + + surf = x3c_firstSortedSurface; + while (surf) + { + DrawSurface(*surf, flags); + surf = surf->m_next; + } } void CBooModel::DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const { + const DataSpec::DNAMP1::HMDLMaterialSet::Material& data = GetMaterialByIndex(surf.m_data.matIdx); + if (data.flags.shadowOccluderMesh() && !g_DrawingOccluders) + return; + + CGraphics::SetShaderDataBinding(m_shaderDataBindings[surf.m_data.matIdx]); + CGraphics::DrawArrayIndexed(surf.m_data.idxStart, surf.m_data.idxCount); } void CBooModel::DrawAlpha(const CModelFlags& flags) const { + DrawAlphaSurfaces(flags); } void CBooModel::DrawNormal(const CModelFlags& flags) const { + DrawNormalSurfaces(flags); } void CBooModel::Draw(const CModelFlags& flags) const { -} - -const u8* CBooModel::GetMaterialByIndex(int idx) const -{ - const u32* matOffs = reinterpret_cast(x4_matSet + (x1c_textures->size() + 1) * 4); - u32 matCount = hecl::SBig(*matOffs); - ++matOffs; - - const u8* materialBase = reinterpret_cast(matOffs + matCount); - if (idx == 0) - return materialBase; - - u32 offset = hecl::SBig(matOffs[idx-1]); - return materialBase + offset; + DrawSurfaces(flags); } static const u8* MemoryFromPartData(const u8*& dataCur, const s32*& secSizeCur) @@ -128,17 +218,20 @@ CModel::CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store) const s32* secSizeCur = reinterpret_cast(x0_data.get() + 0x2c); for (u32 i=0 ; i&& in, u32 dataLen, IObjectStore* store) { m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vboData, hmdlMeta.vertStride, hmdlMeta.vertCount); m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, iboData, 4, hmdlMeta.indexCount); + m_vtxFmt = hecl::Runtime::HMDLData::NewVertexFormat(ctx, hmdlMeta, m_vbo, m_ibo); + + for (CBooModel::SShader& matSet : x18_matSets) + { + matSet.m_shaders.reserve(matSet.m_matSet.materials.size()); + for (const DataSpec::DNAMP1::HMDLMaterialSet::Material& mat : matSet.m_matSet.materials) + { + hecl::Runtime::ShaderTag tag(mat.heclIr, + hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount, + 0, mat.uvAnims.size(), true, true, true); + matSet.m_shaders.push_back(CGraphics::g_ShaderCacheMgr->buildShader(tag, mat.heclIr, "CMDL", ctx)); + } + } + return true; }); @@ -157,30 +264,55 @@ CModel::CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store) x8_surfaces.reserve(surfCount); for (u32 i=0 ; i(x0_data.get() + 0x18); zeus::CAABox aabb(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); - x28_modelInst = std::make_unique(&x8_surfaces, &x18_matSets[0].x0_textures, - x18_matSets[0].x10_data, m_vbo, m_ibo, + x28_modelInst = std::make_unique(&x8_surfaces, x18_matSets[0], + m_vtxFmt, m_vbo, m_ibo, aabb, flags & 0x2, true); } +void CBooModel::SShader::UnlockTextures() +{ + for (TCachedToken& tex : x0_textures) + tex.Unlock(); +} + +void CModel::VerifyCurrentShader(int shaderIdx) const +{ + int idx = 0; + for (const CBooModel::SShader& shader : x18_matSets) + if (idx++ != shaderIdx) + ((CBooModel::SShader&)shader).UnlockTextures(); +} + +void CModel::DrawSortedParts(const CModelFlags& flags) const +{ +} + +void CModel::DrawUnsortedParts(const CModelFlags& flags) const +{ +} + void CModel::Draw(const CModelFlags& flags) const { } -void CModel::Touch(int) const +void CModel::Touch(int shaderIdx) const { } -bool CModel::IsLoaded(int) const +bool CModel::IsLoaded(int shaderIdx) const { + VerifyCurrentShader(shaderIdx); return false; } diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index e17db48f8..d7a592134 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -44,7 +44,7 @@ public: ETexelFormat GetTexelFormat() const {return x0_fmt;} u16 GetWidth() const {return x4_w;} u16 GetHeight() const {return x6_h;} - void Load(int slot, EClampMode clamp); + void Load(int slot, EClampMode clamp) const; boo::ITexture* GetBooTexture() {return m_booTex;} }; diff --git a/Runtime/Graphics/CTextureBoo.cpp b/Runtime/Graphics/CTextureBoo.cpp index 960b1e92a..ee859a556 100644 --- a/Runtime/Graphics/CTextureBoo.cpp +++ b/Runtime/Graphics/CTextureBoo.cpp @@ -692,7 +692,7 @@ CTexture::CTexture(CInputStream& in) } } -void CTexture::Load(int slot, EClampMode clamp) +void CTexture::Load(int slot, EClampMode clamp) const { } diff --git a/Runtime/GuiSys/CGuiModel.cpp b/Runtime/GuiSys/CGuiModel.cpp index 3a4fb6a31..eb5b49b34 100644 --- a/Runtime/GuiSys/CGuiModel.cpp +++ b/Runtime/GuiSys/CGuiModel.cpp @@ -28,7 +28,7 @@ bool CGuiModel::GetIsFinishedLoadingWidgetSpecific() const { if (!xf8_model) return true; - CModel* model = xf8_model.GetObj(); + const CModel* model = xf8_model.GetObj(); if (!model) return false; model->Touch(0); @@ -37,7 +37,7 @@ bool CGuiModel::GetIsFinishedLoadingWidgetSpecific() const void CGuiModel::Touch() const { - CModel* model = xf8_model.GetObj(); + const CModel* model = xf8_model.GetObj(); if (model) model->Touch(0); } @@ -49,7 +49,7 @@ void CGuiModel::Draw(const CGuiWidgetDrawParms& parms) const return; if (!GetIsFinishedLoading()) return; - CModel* model = xf8_model.GetObj(); + const CModel* model = xf8_model.GetObj(); if (!model) return; diff --git a/hecl b/hecl index c8d586615..c6feb6438 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit c8d5866157ceb8a571ea2ba63c7a9306afb32dfa +Subproject commit c6feb64383aa84fee18afa423e741bfa3dca4a74