diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index 852076b83..77852dc68 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -1473,7 +1473,8 @@ template bool WriteCMDL (const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh); template -bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh) +bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const Mesh& mesh, hecl::PoolSkinIndex& poolSkinIndex) { Header head; head.magic = 0xDEADBABE; @@ -1536,7 +1537,7 @@ bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& in } } - hecl::HMDLBuffers bufs = mesh.getHMDLBuffers(false); + hecl::HMDLBuffers bufs = mesh.getHMDLBuffers(false, poolSkinIndex); /* Metadata */ size_t secSz = bufs.m_meta.binarySize(0); @@ -1643,7 +1644,8 @@ bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& in } template bool WriteHMDLCMDL -(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh); +(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh, + hecl::PoolSkinIndex& poolSkinIndex); template bool WriteMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, @@ -1757,7 +1759,8 @@ bool WriteHMDLMREASecs(std::vector>& secsOut, const hecl::P meshHeader.write(w); } - hecl::HMDLBuffers bufs = mesh.getHMDLBuffers(true); + hecl::PoolSkinIndex poolSkinIndex; + hecl::HMDLBuffers bufs = mesh.getHMDLBuffers(true, poolSkinIndex); std::vector surfEndOffs; surfEndOffs.reserve(bufs.m_surfaces.size()); diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index 21ac4403f..d5c5a90be 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -169,7 +169,8 @@ template bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh); template -bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh); +bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const Mesh& mesh, hecl::PoolSkinIndex& poolSkinIndex); template bool WriteMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp index 139ce8cfb..b607a6831 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp @@ -34,12 +34,12 @@ struct SChargedShotParam : SShotParam struct ITweakPlayerGun : ITweak { DECL_YAML - virtual float GetX24() const = 0; // x24 - virtual float GetX28() const = 0; // x28 - virtual float GetX2c() const = 0; // x2c - virtual float GetX30() const = 0; // x30 - virtual float GetX34() const = 0; // x34 - virtual float GetX38() const = 0; // x38 + virtual float GetAimVerticalSpeed() const = 0; // x24 + virtual float GetAimHorizontalSpeed() const = 0; // x28 + virtual float GetBombFuseTime() const = 0; // x2c + virtual float GetBombDropDelayTime() const = 0; // x30 + virtual float GetHoloHoldTime() const = 0; // x34 + virtual float GetGunTransformTime() const = 0; // x38 virtual float GetGunHolsterTime() const=0; virtual float GetGunNotFiringTime() const=0; virtual float GetFixedVerticalAim() const=0; diff --git a/DataSpec/DNAMP1/ANCS.cpp b/DataSpec/DNAMP1/ANCS.cpp index c12a81bdc..c202d28d9 100644 --- a/DataSpec/DNAMP1/ANCS.cpp +++ b/DataSpec/DNAMP1/ANCS.cpp @@ -1263,6 +1263,30 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, for (uint32_t i=0 ; i>> skins; + uint32_t skinCount = skinIO.readUint32Big(); + skins.resize(skinCount); + for (uint32_t i=0 ; i>& virtualBone = skins[i]; + uint32_t bindCount = skinIO.readUint32Big(); + virtualBone.reserve(bindCount); + for (uint32_t j=0 ; jsecond, weight); + } + } + + atUint64 uniquePoolIndexLen = skinIO.length() - skinIO.position(); + auto uniquePoolIndexData = skinIO.readUBytes(uniquePoolIndexLen); + skinIO.close(); athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); @@ -1282,6 +1306,19 @@ bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, } } + skinOut.writeUint32Big(skins.size()); + for (auto& virtuaBone : skins) + { + skinOut.writeUint32Big(virtuaBone.size()); + for (auto& bind : virtuaBone) + { + skinOut.writeUint32Big(bind.first); + skinOut.writeFloatBig(bind.second); + } + } + + skinOut.writeUBytes(uniquePoolIndexData.get(), uniquePoolIndexLen); + return true; } diff --git a/DataSpec/DNAMP1/CMDL.hpp b/DataSpec/DNAMP1/CMDL.hpp index 65de75ac6..1f99f6307 100644 --- a/DataSpec/DNAMP1/CMDL.hpp +++ b/DataSpec/DNAMP1/CMDL.hpp @@ -120,9 +120,11 @@ struct CMDL const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh) { + hecl::PoolSkinIndex poolSkinIndex; if (mesh.skins.size()) { - if (!DNACMDL::WriteHMDLCMDL(outPath, inPath, mesh)) + if (!DNACMDL::WriteHMDLCMDL( + outPath, inPath, mesh, poolSkinIndex)) return false; /* Output skinning intermediate */ @@ -137,8 +139,26 @@ struct CMDL writer.writeUint32Big(mesh.boneNames.size()); for (const std::string& boneName : mesh.boneNames) writer.writeString(boneName); + + /* CVirtualBone structure just like original (for CPU skinning) */ + writer.writeUint32Big(mesh.skins.size()); + for (auto& s : mesh.skins) + { + writer.writeUint32Big(s.size()); + for (auto& b : s) + { + writer.writeUint32Big(b.boneIdx); + writer.writeFloatBig(b.weight); + } + } + + /* Write indirection table mapping pool verts to CVirtualBones */ + writer.writeUint32Big(poolSkinIndex.m_poolSz); + for (uint32_t i=0 ; i(outPath, inPath, mesh)) + else if (!DNACMDL::WriteHMDLCMDL( + outPath, inPath, mesh, poolSkinIndex)) return false; return true; } diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp index 257c3aa71..7d443b8ef 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp @@ -19,12 +19,12 @@ struct CTweakPlayerGun : ITweakPlayerGun Value x18_; Value x1c_; Value x20_; - Value x24_; - Value x28_; - Value x2c_; - Value x30_; - Value x34_; - Value x38_; + Value x24_aimVerticalSpeed; + Value x28_aimHorizontalSpeed; + Value x2c_bombFuseTime; + Value x30_bombDropDelayTime; + Value x34_holoHoldTime; + Value x38_gunTransformTime; Value x3c_gunHolsterTime; Value x40_gunNotFiringTime; Value x44_fixedVerticalAim; @@ -53,12 +53,12 @@ struct CTweakPlayerGun : ITweakPlayerGun x44_fixedVerticalAim = zeus::degToRad(x44_fixedVerticalAim); } - float GetX24() const { return x24_; } - float GetX28() const { return x28_; } - float GetX2c() const { return x2c_; } - float GetX30() const { return x30_; } - float GetX34() const { return x34_; } - float GetX38() const { return x38_; } + float GetAimVerticalSpeed() const { return x24_aimVerticalSpeed; } + float GetAimHorizontalSpeed() const { return x28_aimHorizontalSpeed; } + float GetBombFuseTime() const { return x2c_bombFuseTime; } + float GetBombDropDelayTime() const { return x30_bombDropDelayTime; } + float GetHoloHoldTime() const { return x34_holoHoldTime; } + float GetGunTransformTime() const { return x38_gunTransformTime; } float GetGunHolsterTime() const { return x3c_gunHolsterTime; } float GetGunNotFiringTime() const { return x40_gunNotFiringTime; } float GetFixedVerticalAim() const { return x44_fixedVerticalAim; } diff --git a/Runtime/Character/CSkinRules.cpp b/Runtime/Character/CSkinRules.cpp index 6bbc6d9b7..9fb3c6ca1 100644 --- a/Runtime/Character/CSkinRules.cpp +++ b/Runtime/Character/CSkinRules.cpp @@ -1,5 +1,7 @@ #include "CSkinRules.hpp" #include "CToken.hpp" +#include "Graphics/CModel.hpp" +#include "CPoseAsTransforms.hpp" namespace urde { @@ -10,6 +12,37 @@ CSkinRules::CSkinRules(CInputStream& in) x0_skinBanks.reserve(bankCount); for (u32 i=0 ; i>& vnOut, + const CPoseAsTransforms& pose, const CModel& model) const +{ + vnOut.resize(m_poolToSkinIdx.size()); + for (size_t i=0 ; i m_weights; +public: + explicit CVirtualBone(CInputStream& in) + { + u32 weightCount = in.readUint32Big(); + m_weights.reserve(weightCount); + for (u32 i=0 ; i& GetWeights() const { return m_weights; } +}; class CSkinRules { std::vector x0_skinBanks; + //u32 x10_vertexCount; + //u32 x14_normalCount; + std::vector m_virtualBones; + std::vector m_poolToSkinIdx; + public: - CSkinRules(CInputStream& in); - void BuildAccumulatedTransforms(); + explicit CSkinRules(CInputStream& in); + void GetBankTransforms(std::vector& out, const CPoseAsTransforms& pose, int skinBankIdx) const - { - x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose); - } + { x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose); } + + void TransformVerticesCPU(std::vector>& vnOut, + const CPoseAsTransforms& pose, const CModel& model) const; }; CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params, diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index d29a791ce..dfc6dcfc4 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -66,6 +66,7 @@ set(GRAPHICS_SOURCES CPVSAreaSet.hpp CPVSAreaSet.cpp CGraphics.hpp CGraphics.cpp CSimpleShadow.hpp CSimpleShadow.cpp + CModelPointSelector.hpp CModelPointSelector.cpp Shaders/TShader.hpp Shaders/TMultiBlendShader.hpp Shaders/TShaderDecl.hpp Shaders/TMultiBlendShaderDecl.hpp Shaders/CLineRendererShaders.hpp Shaders/CLineRendererShaders.cpp Shaders/CLineRendererShadersGLSL.cpp Shaders/CTexturedQuadFilter.hpp Shaders/CTexturedQuadFilter.cpp Shaders/CTexturedQuadFilterGLSL.cpp diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 969371866..9fc855de1 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -105,11 +105,6 @@ private: const MaterialSet* x4_matSet; int m_matSetIdx = -1; const std::vector>* m_pipelines; - boo::IVertexFormat* m_vtxFmt; - boo::IGraphicsBufferS* x8_vbo; - boo::IGraphicsBufferS* xc_ibo; - size_t m_weightVecCount; - size_t m_skinBankCount; std::vector> x1c_textures; zeus::CAABox x20_aabb; CBooSurface* x38_firstUnsortedSurface = nullptr; @@ -135,9 +130,18 @@ private: boo::GraphicsDataToken m_gfxToken; boo::IGraphicsBufferD* m_uniformBuffer; std::vector> m_shaderDataBindings; + boo::IVertexFormat* m_dynamicVtxFmt = nullptr; + boo::IGraphicsBufferD* m_dynamicVbo = nullptr; + + boo::IGraphicsBuffer* GetBooVBO(const CBooModel& model, boo::IGraphicsDataFactory::Context& ctx); + boo::IVertexFormat* GetBooVtxFmt(const CBooModel& model, boo::IGraphicsDataFactory::Context& ctx); }; std::vector m_instances; + boo::IVertexFormat* m_staticVtxFmt = nullptr; + boo::IGraphicsBufferS* m_staticVbo = nullptr; + boo::IGraphicsBufferS* m_staticIbo = nullptr; + boo::ITexture* m_txtrOverrides[8] = {}; ModelInstance* PushNewModelInstance(); @@ -156,7 +160,7 @@ public: ~CBooModel(); CBooModel(TToken& token, std::vector* surfaces, SShader& shader, boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, - size_t weightVecCount, size_t skinBankCount, const zeus::CAABox& aabb, u8 renderMask, + const zeus::CAABox& aabb, u8 renderMask, int numInsts, boo::ITexture* txtrOverrides[8]); static void MakeTexturesFromMats(const MaterialSet& matSet, @@ -173,9 +177,9 @@ public: void UnlockTextures() const; void Touch(int shaderIdx) const; void VerifyCurrentShader(int shaderIdx); - void UpdateUniformData(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const; + boo::IGraphicsBufferD* UpdateUniformData(const CModelFlags& flags, + const CSkinRules* cskr, + const CPoseAsTransforms* pose) const; void DrawAlpha(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const; @@ -224,12 +228,11 @@ class CModel /* urde addition: boo! */ boo::GraphicsDataToken m_gfxToken; - boo::IGraphicsBufferS* m_vbo; + boo::IVertexFormat* m_staticVtxFmt = nullptr; + boo::IGraphicsBufferS* m_staticVbo = nullptr; + hecl::HMDLMeta m_hmdlMeta; + std::unique_ptr m_dynamicVertexData; boo::IGraphicsBufferS* m_ibo; - boo::IVertexFormat* m_vtxFmt; - - u32 m_weightVecCount; - u32 m_skinBankCount; public: using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; @@ -246,6 +249,13 @@ public: const CBooModel& GetInstance() const {return *x28_modelInst;} std::unique_ptr MakeNewInstance(int shaderIdx, int subInsts, boo::ITexture* txtrOverrides[8] = nullptr); void UpdateLastFrame() const { const_cast(*this).x38_lastFrame = CGraphics::GetFrameCounter(); } + + size_t GetPoolVertexOffset(size_t idx) const; + zeus::CVector3f GetPoolVertex(size_t idx) const; + size_t GetPoolNormalOffset(size_t idx) const; + zeus::CVector3f GetPoolNormal(size_t idx) const; + void ApplyVerticesCPU(boo::IGraphicsBufferD* vertBuf, + const std::vector>& vn) const; }; CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 86bab39bd..b06992d14 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -135,12 +135,12 @@ CBooModel::~CBooModel() CBooModel::CBooModel(TToken& token, std::vector* surfaces, SShader& shader, boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, - size_t weightVecCount, size_t skinBankCount, const zeus::CAABox& aabb, u8 renderMask, - int instCount, boo::ITexture* txtrOverrides[8]) + const zeus::CAABox& aabb, u8 renderMask, + int numInsts, boo::ITexture* txtrOverrides[8]) : m_model(token), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), m_matSetIdx(shader.m_matSetIdx), - m_pipelines(&shader.m_shaders), m_vtxFmt(vtxFmt), x8_vbo(vbo), xc_ibo(ibo), m_weightVecCount(weightVecCount), - m_skinBankCount(skinBankCount), x1c_textures(shader.x0_textures), x20_aabb(aabb), - x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask) + m_pipelines(&shader.m_shaders), x1c_textures(shader.x0_textures), x20_aabb(aabb), + x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask), + m_staticVtxFmt(vtxFmt), m_staticVbo(vbo), m_staticIbo(ibo) { if (txtrOverrides) for (int i=0 ; i<8 ; ++i) @@ -174,11 +174,41 @@ CBooModel::CBooModel(TToken& token, std::vector* surfaces, } } - m_instances.reserve(instCount); - for (int i=0 ; iload(parent.m_dynamicVertexData.get(), + parent.m_hmdlMeta.vertStride * parent.m_hmdlMeta.vertCount); + } + return m_dynamicVbo; +} + +boo::IVertexFormat* CBooModel::ModelInstance::GetBooVtxFmt(const CBooModel& model, + boo::IGraphicsDataFactory::Context& ctx) +{ + if (model.m_staticVtxFmt) + return model.m_staticVtxFmt; + if (!m_dynamicVtxFmt && model.m_model) + { + const CModel& parent = *model.m_model; + m_dynamicVtxFmt = hecl::Runtime::HMDLData::NewVertexFormat(ctx, parent.m_hmdlMeta, + GetBooVBO(model, ctx), parent.m_ibo); + } + return m_dynamicVtxFmt; +} + CBooModel::ModelInstance* CBooModel::PushNewModelInstance() { if (!x40_24_texturesLoaded) @@ -188,6 +218,13 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() Log.report(logvisor::Fatal, "Model buffer overflow"); m_instances.emplace_back(); ModelInstance& newInst = m_instances.back(); + size_t skinBankCount = 0; + size_t weightVecCount = 0; + if (const CModel* model = m_model.GetObj()) + { + skinBankCount = model->m_hmdlMeta.bankCount; + weightVecCount = model->m_hmdlMeta.weightCount; + } newInst.m_gfxToken = CGraphics::CommitResources( [&](boo::IGraphicsDataFactory::Context& ctx) -> bool @@ -195,8 +232,8 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() /* Determine space required by uniform buffer */ std::vector skinOffs; std::vector skinSizes; - skinOffs.reserve(std::max(size_t(1), m_skinBankCount)); - skinSizes.reserve(std::max(size_t(1), m_skinBankCount)); + skinOffs.reserve(std::max(size_t(1), skinBankCount)); + skinSizes.reserve(std::max(size_t(1), skinBankCount)); std::vector uvOffs; std::vector uvSizes; @@ -205,12 +242,12 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() /* Vert transform matrices */ size_t uniBufSize = 0; - if (m_skinBankCount) + if (skinBankCount) { /* Skinned */ - for (size_t i=0 ; ix220_sphereRamp; - if (m_skinBankCount) + if (skinBankCount) { thisOffs[0] = skinOffs[surf.m_data.skinMtxBankIdx]; thisSizes[0] = skinSizes[surf.m_data.skinMtxBankIdx]; @@ -361,9 +398,9 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance() ltexs = texs; } extendeds.push_back( - ctx.newShaderDataBinding(pipeline, m_vtxFmt, - x8_vbo, nullptr, xc_ibo, 4, bufs, stages, - thisOffs, thisSizes, texCount, ltexs, nullptr, nullptr)); + ctx.newShaderDataBinding(pipeline, newInst.GetBooVtxFmt(*this, ctx), + newInst.GetBooVBO(*this, ctx), nullptr, m_staticIbo, 4, bufs, + stages, thisOffs, thisSizes, texCount, ltexs, nullptr, nullptr)); ++idx; } } @@ -695,16 +732,24 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet } } -void CBooModel::UpdateUniformData(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const +boo::IGraphicsBufferD* CBooModel::UpdateUniformData(const CModelFlags& flags, + const CSkinRules* cskr, + const CPoseAsTransforms* pose) const { + size_t skinBankCount = 0; + size_t weightVecCount = 0; + if (const CModel* model = m_model.GetObj()) + { + skinBankCount = model->m_hmdlMeta.bankCount; + weightVecCount = model->m_hmdlMeta.weightCount; + } + const ModelInstance* inst; if (m_instances.size() <= m_uniUpdateCount) { inst = const_cast(this)->PushNewModelInstance(); if (!inst) - return; + return nullptr; } else inst = &m_instances[m_uniUpdateCount]; @@ -713,13 +758,13 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags, u8* dataOut = reinterpret_cast(inst->m_uniformBuffer->map(m_uniformDataSize)); u8* dataCur = dataOut; - if (m_skinBankCount) + if (skinBankCount) { /* Skinned */ std::vector bankTransforms; - size_t weightCount = m_weightVecCount * 4; + size_t weightCount = weightVecCount * 4; bankTransforms.reserve(weightCount); - for (size_t i=0 ; im_uniformBuffer->unmap(); + return inst->m_dynamicVbo; } void CBooModel::DrawAlpha(const CModelFlags& flags, @@ -879,10 +925,10 @@ void CBooModel::Draw(const CModelFlags& flags, } } -static const u8* MemoryFromPartData(const u8*& dataCur, const s32*& secSizeCur) +static const u8* MemoryFromPartData(const u8*& dataCur, const u32*& secSizeCur) { const u8* ret; - if (*secSizeCur) + if (*secSizeCur != 0) ret = dataCur; else ret = nullptr; @@ -897,7 +943,7 @@ std::unique_ptr CModel::MakeNewInstance(int shaderIdx, int subInsts, if (shaderIdx >= x18_matSets.size()) shaderIdx = 0; return std::make_unique(m_selfToken, &x8_surfaces, x18_matSets[shaderIdx], - m_vtxFmt, m_vbo, m_ibo, m_weightVecCount, m_skinBankCount, + m_staticVtxFmt, m_staticVbo, m_ibo, m_aabb, (m_flags & 0x2) != 0, subInsts, txtrOverrides); } @@ -916,7 +962,7 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor u32 matSetCount = hecl::SBig(*reinterpret_cast(data.get() + 0x28)); x18_matSets.reserve(matSetCount); const u8* dataCur = data.get() + ROUND_UP_32(0x2c + secCount * 4); - const s32* secSizeCur = reinterpret_cast(data.get() + 0x2c); + const u32* secSizeCur = reinterpret_cast(data.get() + 0x2c); for (u32 i=0 ; i&& in, u32 /* dataLen */, IObjectStore* stor CBooModel::MakeTexturesFromMats(shader.m_matSet, shader.x0_textures, *store); } - hecl::HMDLMeta hmdlMeta; { u32 hmdlSz = hecl::SBig(*secSizeCur); const u8* hmdlMetadata = MemoryFromPartData(dataCur, secSizeCur); athena::io::MemoryReader r(hmdlMetadata, hmdlSz); - hmdlMeta.read(r); + m_hmdlMeta.read(r); } - m_weightVecCount = hmdlMeta.weightCount; - m_skinBankCount = hmdlMeta.bankCount; const u8* vboData = MemoryFromPartData(dataCur, secSizeCur); const u8* iboData = MemoryFromPartData(dataCur, secSizeCur); @@ -955,8 +998,8 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor else reflectionType = hecl::Backend::ReflectionType::None; hecl::Runtime::ShaderTag tag(mat.heclIr, - hmdlMeta.colorCount, hmdlMeta.uvCount, hmdlMeta.weightCount, - hmdlMeta.weightCount * 4, 8, boo::Primitive(hmdlMeta.topology), + m_hmdlMeta.colorCount, m_hmdlMeta.uvCount, m_hmdlMeta.weightCount, + m_hmdlMeta.weightCount * 4, 8, boo::Primitive(m_hmdlMeta.topology), reflectionType, true, true, true); matSet.m_shaders.push_back(CModelShaders::g_ModelShaders->buildExtendedShader (tag, mat.heclIr, "CMDL", *CGraphics::g_BooFactory)); @@ -965,9 +1008,23 @@ CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* stor m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool { - 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); + if (!m_hmdlMeta.bankCount) + { + /* Non-skinned models use static vertex buffers shared with CBooModel instances */ + m_staticVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vboData, + m_hmdlMeta.vertStride, m_hmdlMeta.vertCount); + m_staticVtxFmt = hecl::Runtime::HMDLData::NewVertexFormat(ctx, m_hmdlMeta, m_staticVbo, m_ibo); + } + else + { + /* Skinned models use per-instance dynamic buffers for vertex manipulation effects */ + size_t vboSz = m_hmdlMeta.vertStride * m_hmdlMeta.vertCount; + m_dynamicVertexData.reset(new uint8_t[vboSz]); + memmove(m_dynamicVertexData.get(), vboData, vboSz); + } + + /* Index buffer is always static */ + m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, iboData, 4, m_hmdlMeta.indexCount); return true; }); @@ -1042,6 +1099,46 @@ bool CModel::IsLoaded(int shaderIdx) const return loaded; } +size_t CModel::GetPoolVertexOffset(size_t idx) const +{ + return m_hmdlMeta.vertStride * idx; +} + +zeus::CVector3f CModel::GetPoolVertex(size_t idx) const +{ + auto* floats = reinterpret_cast(m_dynamicVertexData.get() + GetPoolVertexOffset(idx)); + return {floats[0], floats[1], floats[2]}; +} + +size_t CModel::GetPoolNormalOffset(size_t idx) const +{ + return m_hmdlMeta.vertStride * idx + 12; +} + +zeus::CVector3f CModel::GetPoolNormal(size_t idx) const +{ + auto* floats = reinterpret_cast(m_dynamicVertexData.get() + GetPoolNormalOffset(idx)); + return {floats[0], floats[1], floats[2]}; +} + +void CModel::ApplyVerticesCPU(boo::IGraphicsBufferD* vertBuf, + const std::vector>& vn) const +{ + u8* data = reinterpret_cast(vertBuf->map(m_hmdlMeta.vertStride * m_hmdlMeta.vertCount)); + for (u32 i=0 ; i& avn = vn[i]; + float* floats = reinterpret_cast(data + GetPoolVertexOffset(i)); + floats[0] = avn.first.x; + floats[1] = avn.first.y; + floats[2] = avn.first.z; + floats[3] = avn.second.x; + floats[4] = avn.second.y; + floats[5] = avn.second.z; + } + vertBuf->unmap(); +} + CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, const urde::CVParamTransfer& vparms, diff --git a/Runtime/Graphics/CModelPointSelector.cpp b/Runtime/Graphics/CModelPointSelector.cpp new file mode 100644 index 000000000..f89f3db2f --- /dev/null +++ b/Runtime/Graphics/CModelPointSelector.cpp @@ -0,0 +1,16 @@ +#include "CModelPointSelector.hpp" + +namespace urde +{ + +CModelPointSelector::CModelPointSelector(const zeus::CVector3f& scale, int, int, float, float) +{ + +} + +void CModelPointSelector::GeneratePoints(const std::vector>& vn) +{ + +} + +} diff --git a/Runtime/Graphics/CModelPointSelector.hpp b/Runtime/Graphics/CModelPointSelector.hpp new file mode 100644 index 000000000..eb63d22a1 --- /dev/null +++ b/Runtime/Graphics/CModelPointSelector.hpp @@ -0,0 +1,18 @@ +#ifndef URDE_CMODELPOINTSELECTOR_HPP +#define URDE_CMODELPOINTSELECTOR_HPP + +#include "RetroTypes.hpp" + +namespace urde +{ + +class CModelPointSelector +{ +public: + CModelPointSelector(const zeus::CVector3f& scale, int, int, float, float); + void GeneratePoints(const std::vector>& vn); +}; + +} + +#endif // URDE_CMODELPOINTSELECTOR_HPP diff --git a/Runtime/Graphics/CSkinnedModel.cpp b/Runtime/Graphics/CSkinnedModel.cpp index 05824b543..638c7ed5d 100644 --- a/Runtime/Graphics/CSkinnedModel.cpp +++ b/Runtime/Graphics/CSkinnedModel.cpp @@ -1,5 +1,6 @@ #include "CSkinnedModel.hpp" #include "Character/CSkinRules.hpp" +#include "CVertexMorphEffect.hpp" namespace urde { @@ -35,7 +36,20 @@ void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const rstl::optional_object& morphEffect, const float* morphMagnitudes) { - m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose); + if (morphEffect || g_PointGenFunc) + { + boo::IGraphicsBufferD* vertBuf = m_modelInst->UpdateUniformData(drawFlags, nullptr, nullptr); + x10_skinRules->TransformVerticesCPU(m_vertWorkspace, pose, *x4_model); + if (morphEffect) + morphEffect->MorphVertices(m_vertWorkspace, morphMagnitudes, x10_skinRules, pose); + if (g_PointGenFunc) + g_PointGenFunc(g_PointGenCtx, m_vertWorkspace); + x4_model->ApplyVerticesCPU(vertBuf, m_vertWorkspace); + } + else + { + m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose); + } } void CSkinnedModel::Draw(const CModelFlags& drawFlags) const diff --git a/Runtime/Graphics/CSkinnedModel.hpp b/Runtime/Graphics/CSkinnedModel.hpp index 1c991820f..15b0a1797 100644 --- a/Runtime/Graphics/CSkinnedModel.hpp +++ b/Runtime/Graphics/CSkinnedModel.hpp @@ -21,6 +21,7 @@ class CSkinnedModel TLockedToken x4_model; TLockedToken x10_skinRules; TLockedToken x1c_layoutInfo; + std::vector> m_vertWorkspace; public: enum class EDataOwnership { @@ -45,7 +46,7 @@ public: const float* morphMagnitudes); void Draw(const CModelFlags& drawFlags) const; - typedef void(*FPointGenerator)(void* item, const zeus::CVector3f* v1, const zeus::CVector3f* v2, int w1); + typedef void(*FPointGenerator)(void* item, const std::vector>& vn); static void SetPointGeneratorFunc(void* ctx, FPointGenerator func) { g_PointGenFunc = func; diff --git a/Runtime/Graphics/CVertexMorphEffect.cpp b/Runtime/Graphics/CVertexMorphEffect.cpp index e69de29bb..efddf2b1c 100644 --- a/Runtime/Graphics/CVertexMorphEffect.cpp +++ b/Runtime/Graphics/CVertexMorphEffect.cpp @@ -0,0 +1,14 @@ +#include "CVertexMorphEffect.hpp" +#include "Character/CSkinRules.hpp" + +namespace urde +{ + +void CVertexMorphEffect::MorphVertices(std::vector>& vn, + const float* magnitudes, const TLockedToken& skinRules, + const CPoseAsTransforms& pose) const +{ + +} + +} \ No newline at end of file diff --git a/Runtime/Graphics/CVertexMorphEffect.hpp b/Runtime/Graphics/CVertexMorphEffect.hpp index 0333d465a..0baa8ee68 100644 --- a/Runtime/Graphics/CVertexMorphEffect.hpp +++ b/Runtime/Graphics/CVertexMorphEffect.hpp @@ -1,11 +1,19 @@ #ifndef __URDE_CVERTEXMORPHEFFECT_HPP__ #define __URDE_CVERTEXMORPHEFFECT_HPP__ +#include "CToken.hpp" +#include "Character/CPoseAsTransforms.hpp" + namespace urde { +class CSkinRules; class CVertexMorphEffect { +public: + void MorphVertices(std::vector>& vn, + const float* magnitudes, const TLockedToken& skinRules, + const CPoseAsTransforms& pose) const; }; } diff --git a/Runtime/Weapon/CAuxWeapon.cpp b/Runtime/Weapon/CAuxWeapon.cpp index e69de29bb..d6e79fa8a 100644 --- a/Runtime/Weapon/CAuxWeapon.cpp +++ b/Runtime/Weapon/CAuxWeapon.cpp @@ -0,0 +1,11 @@ +#include "CAuxWeapon.hpp" + +namespace urde +{ + +CAuxWeapon::CAuxWeapon(TUniqueId id) +{ + +} + +} diff --git a/Runtime/Weapon/CAuxWeapon.hpp b/Runtime/Weapon/CAuxWeapon.hpp index 8de01b4b1..c4b08ed2e 100644 --- a/Runtime/Weapon/CAuxWeapon.hpp +++ b/Runtime/Weapon/CAuxWeapon.hpp @@ -9,7 +9,7 @@ namespace urde class CAuxWeapon { public: - CAuxWeapon(TUniqueId id); + explicit CAuxWeapon(TUniqueId id); }; } diff --git a/Runtime/Weapon/CGunMotion.cpp b/Runtime/Weapon/CGunMotion.cpp index e69de29bb..48aab1215 100644 --- a/Runtime/Weapon/CGunMotion.cpp +++ b/Runtime/Weapon/CGunMotion.cpp @@ -0,0 +1,11 @@ +#include "CGunMotion.hpp" + +namespace urde +{ + +CGunMotion::CGunMotion(CAssetId, const zeus::CVector3f& vec) +{ + +} + +} diff --git a/Runtime/Weapon/CGunMotion.hpp b/Runtime/Weapon/CGunMotion.hpp index 02909e97e..dff82702b 100644 --- a/Runtime/Weapon/CGunMotion.hpp +++ b/Runtime/Weapon/CGunMotion.hpp @@ -13,7 +13,7 @@ class CGunMotion CModelData x0_modelData; public: - CGunMotion(u32, const zeus::CVector3f& vec); + CGunMotion(CAssetId, const zeus::CVector3f& vec); }; } diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index c750e2a92..3b4b539e3 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -5,21 +5,32 @@ namespace urde { +static const zeus::CVector3f sGunScale(2.f); + CPlayerGun::CPlayerGun(TUniqueId id) : x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, 0, 0, 0, 0.1f), x538_thisId(id), x550_camBob(CPlayerCameraBob::ECameraBobType::One, - zeus::CVector2f(0.071f, 0.141f), 0.47f), - x678_morph(g_tweakPlayerGun->GetX38(), g_tweakPlayerGun->GetX34()) + zeus::CVector2f(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY), + CPlayerCameraBob::kCameraBobPeriod), + x678_morph(g_tweakPlayerGun->GetGunTransformTime(), g_tweakPlayerGun->GetHoloHoldTime()), + x6c8_(zeus::CVector3f(-0.29329199f, 0.f, -0.2481945f), + zeus::CVector3f(0.29329199f, 1.292392f, 0.2481945f)), + x6e0_rightHandModel(CAnimRes(g_tweakGunRes->xc_rightHand, 0, zeus::CVector3f(3.f), 0, true)) { - x354_ = g_tweakPlayerGun->GetX2c(); - x358_ = g_tweakPlayerGun->GetX30(); - x668_ = g_tweakPlayerGun->GetX24(); - x66c_ = g_tweakPlayerGun->GetX28(); + x354_bombFuseTime = g_tweakPlayerGun->GetBombFuseTime(); + x358_bombDropDelayTime = g_tweakPlayerGun->GetBombDropDelayTime(); + x668_aimVerticalSpeed = g_tweakPlayerGun->GetAimVerticalSpeed(); + x66c_aimHorizontalSpeed = g_tweakPlayerGun->GetAimHorizontalSpeed(); + + x73c_gunMotion = std::make_unique(g_tweakGunRes->x4_gunMotion, sGunScale); + x740_grappleArm = std::make_unique(sGunScale); + x744_auxWeapon = std::make_unique(id); + x832_31_ = true; x833_24_isFidgeting = true; x833_30_ = true; - x6e0_.SetSortThermal(true); + x6e0_rightHandModel.SetSortThermal(true); /* TODO: Finish */ } diff --git a/Runtime/Weapon/CPlayerGun.hpp b/Runtime/Weapon/CPlayerGun.hpp index 225cdd28e..58c0428e5 100644 --- a/Runtime/Weapon/CPlayerGun.hpp +++ b/Runtime/Weapon/CPlayerGun.hpp @@ -19,6 +19,7 @@ #include "Character/CModelData.hpp" #include "World/CWorldShadow.hpp" #include "World/ScriptObjectSupport.hpp" +#include "Graphics/CModelPointSelector.hpp" namespace urde { @@ -40,10 +41,10 @@ private: class CGunMorph { float x0_ = 0.f; - float x4_; + float x4_gunTransformTime; float x8_ = 0.f; float xc_ = 0.1f; - float x10_; + float x10_holoHoldTime; float x14_ = 2.f; float x18_transitionFactor = 1.f; u32 x1c_ = 2; @@ -60,8 +61,8 @@ private: }; public: - CGunMorph(float a, float b) - : x4_(a), x10_(std::fabs(b)) {} + CGunMorph(float gunTransformTime, float holoHoldTime) + : x4_gunTransformTime(gunTransformTime), x10_holoHoldTime(std::fabs(holoHoldTime)) {} float GetTransitionFactor() const { return x18_transitionFactor; } }; @@ -100,8 +101,8 @@ private: float x348_ = 0.f; float x34c_ = 0.f; float x350_ = 0.f; - float x354_; - float x358_; + float x354_bombFuseTime; + float x358_bombDropDelayTime; float x35c_bombTime = 0.f; float x360_ = 0.f; float x364_ = 0.f; @@ -140,8 +141,8 @@ private: float x65c_ = 0.f; float x660_ = 0.f; float x664_ = 0.f; - float x668_; - float x66c_; + float x668_aimVerticalSpeed; + float x66c_aimHorizontalSpeed; TUniqueId x670_ = kInvalidUniqueId; u32 x674_ = 0; CGunMorph x678_morph; @@ -156,7 +157,7 @@ private: u32 x6c0_ = 0; u32 x6c4_ = 0; zeus::CAABox x6c8_; - CModelData x6e0_; + CModelData x6e0_rightHandModel; CGunWeapon* x72c_currentBeam = nullptr; u32 x730_ = 0; u32 x734_ = 0; @@ -164,6 +165,7 @@ private: std::unique_ptr x73c_gunMotion; std::unique_ptr x740_grappleArm; std::unique_ptr x744_auxWeapon; + std::unique_ptr x748_modelPointSelector; std::unique_ptr x74c_powerBeam; std::unique_ptr x750_iceBeam; std::unique_ptr x754_waveBeam; diff --git a/Runtime/World/CActor.hpp b/Runtime/World/CActor.hpp index e7cabd22a..cd1398645 100644 --- a/Runtime/World/CActor.hpp +++ b/Runtime/World/CActor.hpp @@ -63,10 +63,12 @@ protected: bool xe5_26_muted : 1; bool xe5_27_useInSortedLists : 1; bool xe5_28_callTouch : 1; + bool xe5_31_ : 1; u8 xe6_24_fluidCounter : 3; u8 xe6_27_renderVisorFlags : 3; // 2: thermal cold, 4: thermal hot bool xe6_30_enablePitchBend : 1; u8 xe6_31_targetableVisorFlags : 4; + bool xe7_27_ : 1; bool xe7_29_ : 1; bool xe7_30_doTargetDistanceTest : 1; bool xe7_31_targetable : 1; diff --git a/Runtime/World/CActorModelParticles.cpp b/Runtime/World/CActorModelParticles.cpp index 0fd60b466..59c307b22 100644 --- a/Runtime/World/CActorModelParticles.cpp +++ b/Runtime/World/CActorModelParticles.cpp @@ -19,15 +19,15 @@ CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& par x8_.resize(8); } -u32 GetNextBestPt(s32 start, const zeus::CVector3f* vecPtr, s32 vecCount, CRandom16& rnd) +u32 GetNextBestPt(s32 start, const std::vector>& vn, CRandom16& rnd) { - const zeus::CVector3f& startVec = vecPtr[start]; + const zeus::CVector3f& startVec = vn[start].first; u32 ret; float lastMag = 0.f; for (s32 i = 0; i < 10; ++i) { - u32 idx = u32(rnd.Range(0, vecCount - 1)); - const zeus::CVector3f& rndVec = vecPtr[idx]; + u32 idx = u32(rnd.Range(0, s32(vn.size()) - 1)); + const zeus::CVector3f& rndVec = vn[idx].first; float mag = (startVec - rndVec).magSquared(); if (mag > lastMag) { @@ -37,14 +37,14 @@ u32 GetNextBestPt(s32 start, const zeus::CVector3f* vecPtr, s32 vecCount, CRando } return ret; } -void CActorModelParticles::CItem::GeneratePoints(const zeus::CVector3f* v1, const zeus::CVector3f* v2, int w1) +void CActorModelParticles::CItem::GeneratePoints(const std::vector>& vn) { for (std::pair, u32>& pair: x8_) { if (pair.first) { CRandom16 rnd(pair.second); - zeus::CVector3f vec = v1[u32(rnd.Float() * (w1 - 1))]; + const zeus::CVector3f& vec = vn[u32(rnd.Float() * (vn.size() - 1))].first; pair.first->SetTranslation(xec_ * vec); } } @@ -57,9 +57,9 @@ void CActorModelParticles::CItem::GeneratePoints(const zeus::CVector3f* v1, cons u32 idx = x80_; for (u32 i = 0; i < count; ++i) { - idx = GetNextBestPt(idx, v1, w1, rnd); - x78_->SetTranslation(xec_ * v1[idx]); - zeus::CVector3f v = v2[idx]; + idx = GetNextBestPt(idx, vn, rnd); + x78_->SetTranslation(xec_ * vn[idx].first); + zeus::CVector3f v = vn[idx].second; if (v.canBeNormalized()) { v.normalize(); @@ -79,10 +79,10 @@ void CActorModelParticles::CItem::GeneratePoints(const zeus::CVector3f* v1, cons std::unique_ptr iceGen = x128_parent.MakeIceGen(); iceGen->SetGlobalOrientAndTrans(xf8_); - u32 next = GetNextBestPt(xb0_, v1, w1, rnd); - iceGen->SetTranslation(xec_ * v1[next]); + u32 next = GetNextBestPt(xb0_, vn, rnd); + iceGen->SetTranslation(xec_ * vn[next].first); - iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(v2[next]))); + iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(vn[next].second))); x8c_.push_back(std::move(iceGen)); xb0_ = (x8c_.size() == 4 ? -1 : next); @@ -99,9 +99,9 @@ void CActorModelParticles::CItem::GeneratePoints(const zeus::CVector3f* v1, cons u32 lastRnd; for (u32 i = 0; i < end; ++i) { - xc0_particleElectric->SetOverrideIPos(v1[u32(rnd.Range(0, w1 - 1))] * xec_); - lastRnd = u32(rnd.Range(0, w1 - 1)); - xc0_particleElectric->SetOverrideFPos(v1[lastRnd] * xec_); + xc0_particleElectric->SetOverrideIPos(vn[u32(rnd.Range(0, s32(vn.size()) - 1))].first * xec_); + lastRnd = u32(rnd.Range(0, s32(vn.size()) - 1)); + xc0_particleElectric->SetOverrideFPos(vn[lastRnd].first * xec_); xc0_particleElectric->ForceParticleCreation(1); } @@ -261,10 +261,10 @@ void CActorModelParticles::Update(float dt, CStateManager& mgr) } -void CActorModelParticles::PointGenerator(void* item, const zeus::CVector3f* v1, - const zeus::CVector3f* v2, int w1) +void CActorModelParticles::PointGenerator(void* ctx, + const std::vector>& vn) { - reinterpret_cast(item)->GeneratePoints(v1, v2, w1); + reinterpret_cast(ctx)->GeneratePoints(vn); } void CActorModelParticles::SetupHook(TUniqueId uid) diff --git a/Runtime/World/CActorModelParticles.hpp b/Runtime/World/CActorModelParticles.hpp index 193428a3b..b45150f7a 100644 --- a/Runtime/World/CActorModelParticles.hpp +++ b/Runtime/World/CActorModelParticles.hpp @@ -7,6 +7,7 @@ #include "zeus/CTransform.hpp" #include "Particle/CParticleElectric.hpp" #include "Particle/CParticleSwoosh.hpp" +#include "Graphics/CModelPointSelector.hpp" namespace urde { @@ -41,7 +42,7 @@ public: u32 xc8_ = 0; u32 xcc_seed3 = 99; zeus::CColor xd0_; - std::unique_ptr xd4_; + std::unique_ptr xd4_pointSelector; TToken xdc_ashy; std::unique_ptr xe4_; zeus::CVector3f xec_ = zeus::CVector3f::skOne; @@ -60,7 +61,7 @@ public: u8 x134_bits = 0; public: CItem(const CEntity& ent, CActorModelParticles& parent); - void GeneratePoints(const zeus::CVector3f* v1, const zeus::CVector3f* v2, int w1); + void GeneratePoints(const std::vector>& vn); void Update(float, CStateManager&); }; @@ -87,7 +88,7 @@ private: public: CActorModelParticles(); - static void PointGenerator(void* item, const zeus::CVector3f* v1, const zeus::CVector3f* v2, int w1); + static void PointGenerator(void* item, const std::vector>& vn); void AddStragglersToRenderer(const CStateManager& mgr); void Update(float dt, CStateManager& mgr); void SetupHook(TUniqueId uid); diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 82f95a652..2d8eef9f7 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -1007,7 +1007,7 @@ void CGameArea::FillInStaticGeometry() TToken nullModel; inst.m_instance = std::make_unique (nullModel, &inst.m_surfaces, x12c_postConstructed->m_materialSet, vtxFmt, vbo, ibo, - hmdlMeta.weightCount, hmdlMeta.bankCount, inst.x34_aabb, inst.x0_visorFlags, 1, nullptr); + inst.x34_aabb, inst.x0_visorFlags, 1, nullptr); } return true; diff --git a/hecl b/hecl index f63a6a704..77e859a81 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit f63a6a704b1e2ce3534e4d83cb2d2efd78b4966d +Subproject commit 77e859a8176e58efadd8d49e2ee58f0a2b831dd0