diff --git a/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.cpp b/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.cpp index 9b9e7de3..f5630412 100644 --- a/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.cpp +++ b/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.cpp @@ -68,6 +68,17 @@ namespace Model output.write(reinterpret_cast(&flags), sizeof(ComplexModel::Flags)); } + // Write Global Loops + { + u32 numElements = static_cast(globalLoops.size()); + output.write(reinterpret_cast(&numElements), sizeof(u32)); + + if (numElements > 0) + { + output.write(reinterpret_cast(&globalLoops[0]), numElements * sizeof(u32)); + } + } + // Write Sequences { u32 numElements = modelHeader.numSequences; @@ -433,6 +444,12 @@ namespace Model return false; } + // Read Global Loops + { + if (!ReadVectorFromBuffer(buffer, out.globalLoops)) + return false; + } + // Read Sequences { if (!buffer->GetVector(out.sequences, out.modelHeader.numSequences)) @@ -764,23 +781,29 @@ namespace Model template void GetAnimationTrack(std::shared_ptr& rootBuffer, const Layout& file, ComplexModel::AnimationData& animationData, M2Track& m2Track) { + i16 globalLoopIndex = m2Track.globalSequence; u32 numTracks = m2Track.values.size; animationData.interpolationType = static_cast(m2Track.interpolationType); - animationData.isGlobalSequence = m2Track.globalSequence != -1; + animationData.globalLoopIndex = globalLoopIndex; animationData.tracks.reserve(numTracks); - // Handle Global Sequence - if (animationData.isGlobalSequence) + if (globalLoopIndex != -1) { - u32 sequenceID = file.md21.sequences.size + m2Track.globalSequence; - - if (sequenceID < file.md21.sequences.size) + if (globalLoopIndex < static_cast(file.md21.sequences.size)) { - M2Sequence* m2Sequence = file.md21.sequences.GetElement(rootBuffer, sequenceID); + M2Sequence* m2Sequence = file.md21.sequences.GetElement(rootBuffer, globalLoopIndex); + + while (m2Sequence->flags.IsAlias) + { + if (m2Sequence->nextAliasID >= file.md21.sequences.size) + break; + + m2Sequence = file.md21.sequences.GetElement(rootBuffer, m2Sequence->nextAliasID); + } bool hasExternalAnimationData = !m2Sequence->flags.HasEmbeddedAnimationData; - if (hasExternalAnimationData || m2Sequence->flags.IsAlias) + if (hasExternalAnimationData && !m2Sequence->flags.IsAlias) { // TODO : Animation is stored externally return; @@ -794,8 +817,6 @@ namespace Model { ComplexModel::AnimationTrack& track = animationData.tracks.emplace_back(); - track.sequenceID = sequenceID; - track.timestamps.resize(m2Timestamps->size); memcpy(track.timestamps.data(), m2Timestamps->Get(rootBuffer), sizeof(u32) * m2Timestamps->size); @@ -803,7 +824,6 @@ namespace Model memcpy(track.values.data(), m2Values->Get(rootBuffer), sizeof(T) * m2Values->size); } } - // Read All Sequence Tracks else { for (u32 i = 0; i < numTracks; i++) @@ -812,23 +832,29 @@ namespace Model { M2Sequence* m2Sequence = file.md21.sequences.GetElement(rootBuffer, i); + while (m2Sequence->flags.IsAlias) + { + if (m2Sequence->nextAliasID >= file.md21.sequences.size) + break; + + m2Sequence = file.md21.sequences.GetElement(rootBuffer, m2Sequence->nextAliasID); + } + bool hasExternalAnimationData = !m2Sequence->flags.HasEmbeddedAnimationData; - if (hasExternalAnimationData || m2Sequence->flags.IsAlias) + if (hasExternalAnimationData && !m2Sequence->flags.IsAlias) { // TODO : Animation is stored externally continue; } } + ComplexModel::AnimationTrack& track = animationData.tracks.emplace_back(); + M2Array* m2Timestamps = m2Track.timestamps.GetElement(rootBuffer, i); M2Array* m2Values = m2Track.values.GetElement(rootBuffer, i); if (m2Timestamps->size > 0 && m2Values->size > 0) { - ComplexModel::AnimationTrack& track = animationData.tracks.emplace_back(); - - track.sequenceID = i; - track.timestamps.resize(m2Timestamps->size); memcpy(track.timestamps.data(), m2Timestamps->Get(rootBuffer), sizeof(u32) * m2Timestamps->size); @@ -843,7 +869,7 @@ namespace Model u32 numTracks = static_cast(src.tracks.size()); dest.interpolationType = src.interpolationType; - dest.isGlobalSequence = src.isGlobalSequence; + dest.globalLoopIndex = src.globalLoopIndex; dest.tracks.resize(numTracks); for (u32 i = 0; i < numTracks; i++) @@ -851,8 +877,6 @@ namespace Model ComplexModel::AnimationTrack& srcTrack = src.tracks[i]; ComplexModel::AnimationTrack& destTrack = dest.tracks[i]; - destTrack.sequenceID = srcTrack.sequenceID; - // Copy Timestamps { u32 numTimestamps = static_cast(srcTrack.values.size()); @@ -880,12 +904,22 @@ namespace Model out.flags = *reinterpret_cast(&layout.md21.flags); out.flags.IsConvertedMapObject = false; - u32 numGlobalSequences = layout.md21.loopingSequenceTimestamps.size; u32 numSequences = layout.md21.sequences.size; + // Read Global Loops + { + out.globalLoops.resize(layout.md21.globalLoops.size); + + for (u32 i = 0; i < layout.md21.globalLoops.size; i++) + { + u32* m2GlobalLoop = layout.md21.globalLoops.GetElement(rootBuffer, i); + out.globalLoops[i] = *m2GlobalLoop; + } + } + // Read Sequences { - out.sequences.resize(numSequences + numGlobalSequences); + out.sequences.resize(numSequences); for (u32 i = 0; i < layout.md21.sequences.size; i++) { @@ -898,7 +932,6 @@ namespace Model sequence.duration = m2Sequence->duration; sequence.moveSpeed = m2Sequence->moveSpeed; - sequence.flags.isAlwaysPlaying = false; sequence.flags.isAlias = m2Sequence->flags.IsAlias; sequence.flags.blendTransition = m2Sequence->flags.BlendTransition; sequence.flags.blendTransitionIfActive = m2Sequence->flags.SetBlendTransitionOnLoad; @@ -920,38 +953,6 @@ namespace Model } } - // Add Global Sequences (Important GlobalSequences are added at the end, otherwise we have to patch nextVariationId && nextAliasId - { - for (u32 i = 0; i < numGlobalSequences; i++) - { - ComplexModel::AnimationSequence& sequence = out.sequences[numSequences + i]; - sequence.id = -1; - sequence.subID = -1; - - sequence.duration = *layout.md21.loopingSequenceTimestamps.GetElement(rootBuffer, i); - sequence.moveSpeed = 0; - - sequence.flags.isAlwaysPlaying = true; - sequence.flags.isAlias = false; - sequence.flags.blendTransition = false; - - sequence.frequency = 0; - sequence.repetitionRange = uvec2(0, 0); - sequence.blendTimeStart = 0; - sequence.blendTimeEnd = 0; - - vec3 aabbMin = CoordinateSpaces::ModelPosToNovus(layout.md21.cullingAABBBounds.aabb.min); - vec3 aabbMax = CoordinateSpaces::ModelPosToNovus(layout.md21.cullingAABBBounds.aabb.max); - - sequence.aabbCenter = (aabbMin + aabbMax) * 0.5f; - sequence.aabbExtents = aabbMax - sequence.aabbCenter; - sequence.radius = 0; - - sequence.nextVariationID = -1; - sequence.nextAliasID = -1; - } - } - // Read Bones { u32 numBones = layout.md21.bones.size; @@ -1086,7 +1087,32 @@ namespace Model memcpy(out.materials.data(), &rootBuffer->GetDataPointer()[materialsOffset], numMaterials * sizeof(ComplexModel::Material)); } - // TODO : Texture Transforms + // Read Texture Transforms + { + u32 numTextureTransforms = layout.md21.textureTransforms.size; + + out.textureTransforms.resize(numTextureTransforms); + for (u32 i = 0; i < numTextureTransforms; i++) + { + ComplexModel::TextureTransform& textureTransform = out.textureTransforms[i]; + M2TextureTransform* m2TextureTransform = layout.md21.textureTransforms.GetElement(rootBuffer, i); + + // Read Translation Track + { + GetAnimationTrack(rootBuffer, layout, textureTransform.translation, m2TextureTransform->translation); + } + + // Read Rotation Track + { + GetAnimationTrack(rootBuffer, layout, textureTransform.rotation, m2TextureTransform->rotation); + } + + // Read Scale Track + { + GetAnimationTrack(rootBuffer, layout, textureTransform.scale, m2TextureTransform->scale); + } + } + } // Read Texture Lookup Tables { diff --git a/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.h b/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.h index b67e9333..82939b02 100644 --- a/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.h +++ b/Source/FileFormat/FileFormat/Novus/Model/ComplexModel.h @@ -24,7 +24,7 @@ namespace Model struct ComplexModel { public: - static const u32 CURRENT_VERSION = 8; + static const u32 CURRENT_VERSION = 9; struct Flags { @@ -54,7 +54,6 @@ namespace Model struct AnimationTrack { public: - u32 sequenceID = 0; std::vector timestamps = { }; std::vector values = { }; @@ -87,11 +86,9 @@ namespace Model } } } - AnimationTrack(AnimationTrack&& other) : sequenceID(other.sequenceID), timestamps(std::move(other.timestamps)), values(std::move(other.values)) { } + AnimationTrack(AnimationTrack&& other) : timestamps(std::move(other.timestamps)), values(std::move(other.values)) { } AnimationTrack& operator=(const AnimationTrack& other) { - sequenceID = other.sequenceID; - size_t numTimestamps = other.timestamps.size(); if (numTimestamps) { @@ -134,7 +131,7 @@ namespace Model { public: AnimationInterpolationType interpolationType = AnimationInterpolationType::NONE; - bool isGlobalSequence = false; + i16 globalLoopIndex = -1; std::vector> tracks; @@ -154,11 +151,11 @@ namespace Model tracks[i] = other.tracks[i]; } } - AnimationData(AnimationData&& other) : interpolationType(other.interpolationType), isGlobalSequence(other.isGlobalSequence), tracks(std::move(other.tracks)) { } + AnimationData(AnimationData&& other) : interpolationType(other.interpolationType), globalLoopIndex(other.globalLoopIndex), tracks(std::move(other.tracks)) { } AnimationData& operator=(const AnimationData& other) { interpolationType = other.interpolationType; - isGlobalSequence = other.isGlobalSequence; + globalLoopIndex = other.globalLoopIndex; size_t numTracks = other.tracks.size(); tracks.resize(numTracks); @@ -174,7 +171,7 @@ namespace Model void Serialize(std::ofstream& stream) const { stream.write(reinterpret_cast(&interpolationType), sizeof(AnimationInterpolationType)); - stream.write(reinterpret_cast(&isGlobalSequence), sizeof(bool)); + stream.write(reinterpret_cast(&globalLoopIndex), sizeof(i16)); u32 numTracks = static_cast(tracks.size()); { @@ -184,8 +181,6 @@ namespace Model { const AnimationTrack& track = tracks[i]; - stream.write(reinterpret_cast(&track.sequenceID), sizeof(u32)); - u32 numTimestamps = static_cast(track.timestamps.size()); { stream.write(reinterpret_cast(&numTimestamps), sizeof(u32)); @@ -205,7 +200,7 @@ namespace Model if (!buffer->Get(interpolationType)) return false; - if (!buffer->Get(isGlobalSequence)) + if (!buffer->Get(globalLoopIndex)) return false; u32 numTracks = 0; @@ -218,9 +213,6 @@ namespace Model { AnimationTrack& track = tracks[i]; - if (!buffer->GetU32(track.sequenceID)) - return false; - u32 numTimestamps = 0; if (!buffer->GetU32(numTimestamps)) return false; @@ -418,7 +410,6 @@ namespace Model public: struct Flags { - u32 isAlwaysPlaying : 1; u32 isAlias : 1; u32 blendTransition : 1; // (This applies if set on either side of the transition) If set we lerp between the end -> start states, but only if end != start (Compare Bone Values) u32 blendTransitionIfActive : 1; @@ -557,6 +548,7 @@ namespace Model Flags flags = { }; + std::vector globalLoops; std::vector sequences; std::vector bones; robin_hood::unordered_map keyBoneIDToBoneIndex; @@ -600,4 +592,4 @@ namespace Model static i8 GetVertexShaderID(i16 shaderID, u16 textureCount); static i8 GetPixelShaderID(i16 shaderID, u16 textureCount); }; -} +} \ No newline at end of file diff --git a/Source/FileFormat/FileFormat/Warcraft/M2/M2.h b/Source/FileFormat/FileFormat/Warcraft/M2/M2.h index b532eb36..a7c77f11 100644 --- a/Source/FileFormat/FileFormat/Warcraft/M2/M2.h +++ b/Source/FileFormat/FileFormat/Warcraft/M2/M2.h @@ -539,7 +539,7 @@ namespace M2 M2Array uniqueName = { }; Flags flags = { }; - M2Array loopingSequenceTimestamps = { }; + M2Array globalLoops = { }; M2Array sequences = { }; M2Array sequenceIDToAnimationID = { }; M2Array bones = { }; diff --git a/Source/FileFormat/FileFormat/Warcraft/Parsers/M2Parser.cpp b/Source/FileFormat/FileFormat/Warcraft/Parsers/M2Parser.cpp index e384e481..fb30f5ee 100644 --- a/Source/FileFormat/FileFormat/Warcraft/Parsers/M2Parser.cpp +++ b/Source/FileFormat/FileFormat/Warcraft/Parsers/M2Parser.cpp @@ -117,9 +117,12 @@ static void InitAnimationArray(std::shared_ptr& buffer, M2Track& for (u32 j = 0; j < track.timestamps.size; j++) { M2Array* timestamps = track.timestamps.GetElement(buffer, j); - M2Array* values = track.values.GetElement(buffer, j); - timestamps->Init(md21Offset); + } + + for (u32 j = 0; j < track.values.size; j++) + { + M2Array* values = track.values.GetElement(buffer, j); values->Init(md21Offset); } } @@ -144,7 +147,7 @@ bool Parser::ReadMD21(const FileChunkHeader& header, std::shared_ptr // Make offsets absolute { layout.md21.uniqueName.Init(md21Offset); - layout.md21.loopingSequenceTimestamps.Init(md21Offset); + layout.md21.globalLoops.Init(md21Offset); layout.md21.sequences.Init(md21Offset); layout.md21.sequenceIDToAnimationID.Init(md21Offset); layout.md21.bones.Init(md21Offset); @@ -183,6 +186,15 @@ bool Parser::ReadMD21(const FileChunkHeader& header, std::shared_ptr InitAnimationArray(buffer, bone->scale, md21Offset); } + for (u32 i = 0; i < layout.md21.textureTransforms.size; i++) + { + M2TextureTransform* textureTransform = layout.md21.textureTransforms.GetElement(buffer, i); + + InitAnimationArray(buffer, textureTransform->translation, md21Offset); + InitAnimationArray(buffer, textureTransform->rotation, md21Offset); + InitAnimationArray(buffer, textureTransform->scale, md21Offset); + } + for (u32 i = 0; i < layout.md21.cameras.size; i++) { M2Camera* camera = layout.md21.cameras.GetElement(buffer, i); diff --git a/Source/Renderer/Renderer/GPUVector.h b/Source/Renderer/Renderer/GPUVector.h index f25358a6..624a83e1 100644 --- a/Source/Renderer/Renderer/GPUVector.h +++ b/Source/Renderer/Renderer/GPUVector.h @@ -122,7 +122,7 @@ namespace Renderer BufferRangeFrame bufferRangeFrame; if (!_allocator.Allocate(bytesToAllocate, bufferRangeFrame)) { - DebugHandler::PrintFatal("[GPUVector] : Failed to allocate GPU Vector %s", _debugName.c_str()); + DebugHandler::PrintFatal("[GPUVector] : Failed to allocate GPU Vector {0}", _debugName); } _wantsValidation = _validateTransfers; @@ -188,7 +188,7 @@ namespace Renderer BufferRangeFrame bufferRangeFrame; if (!_allocator.Allocate(bytesToAllocate, bufferRangeFrame)) { - DebugHandler::PrintFatal("[GPUVector] : Failed to allocate GPU Vector %s", _debugName.c_str()); + DebugHandler::PrintFatal("[GPUVector] : Failed to allocate GPU Vector {0}", _debugName); } _wantsValidation = _validateTransfers; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h index 343442ae..433a5f44 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h @@ -119,10 +119,10 @@ namespace Renderer // Check if we need to compile it before loading if (NeedsCompile(shaderPath)) { - //DebugHandler::Print("[ShaderCooker]: Compiling %s", shaderPath.c_str()); + //DebugHandler::Print("[ShaderCooker]: Compiling {0}", shaderPath); if (!CompileShader(shaderPath)) { - DebugHandler::PrintWarning("[ShaderCooker]: Compiling %s failed, using old version", shaderPath.c_str()); + DebugHandler::PrintWarning("[ShaderCooker]: Compiling {0} failed, using old version", shaderPath); } } @@ -144,7 +144,7 @@ namespace Renderer if (result != SPV_REFLECT_RESULT_SUCCESS) { - DebugHandler::PrintFatal("We failed to reflect the spirv of %s", shaderPath.c_str()); + DebugHandler::PrintFatal("We failed to reflect the spirv of {0}", shaderPath); } uint32_t descriptorSetCount = 0; @@ -152,7 +152,7 @@ namespace Renderer if (result != SPV_REFLECT_RESULT_SUCCESS) { - DebugHandler::PrintFatal("We failed to reflect the spirv descriptor set count of %s", shaderPath.c_str()); + DebugHandler::PrintFatal("We failed to reflect the spirv descriptor set count of {0}", shaderPath); } if (descriptorSetCount > 0) @@ -163,7 +163,7 @@ namespace Renderer if (result != SPV_REFLECT_RESULT_SUCCESS) { - DebugHandler::PrintFatal("We failed to reflect the spirv descriptor sets of %s", shaderPath.c_str()); + DebugHandler::PrintFatal("We failed to reflect the spirv descriptor sets of {0}", shaderPath); } for (auto* descriptorSet : descriptorSets) @@ -197,7 +197,7 @@ namespace Renderer if (result != SPV_REFLECT_RESULT_SUCCESS) { - DebugHandler::PrintFatal("We failed to reflect the spirv push constant count of %s", shaderPath.c_str()); + DebugHandler::PrintFatal("We failed to reflect the spirv push constant count of {0}", shaderPath); } if (pushConstantCount > 0)