#include "stdafx.h" #include "MeshFilterLoader.h" MeshFilter* MeshFilterLoader::LoadContent(const ContentLoadInfo& loadInfo) { const auto pReader = new BinaryReader(); pReader->Open(loadInfo.assetFullPath); if (!pReader->Exists()) return nullptr; //READ OVM FILE const int versionMajor = pReader->Read(); const int versionMinor = pReader->Read(); MeshFilter* pMeshFilter{ nullptr }; //OVM 1.1 if (versionMajor == 1 && versionMinor == 1) pMeshFilter = ParseOVM11(pReader); //OVM 2.0 else if (versionMajor == 2 && versionMinor == 0) pMeshFilter = ParseOVM20(pReader); else { Logger::LogWarning(L"Unsupported OVM Version ({}.{})\n\tFile: \"{}\"", loadInfo.assetFullPath.filename().wstring(), versionMajor, versionMinor); delete pReader; return nullptr; } delete pReader; return pMeshFilter; } void MeshFilterLoader::Destroy(MeshFilter* objToDestroy) { SafeDelete(objToDestroy); } #pragma region OVM 1.1 Parser MeshFilter* MeshFilterLoader::ParseOVM11(BinaryReader* pReader) { #pragma region Header Definitions //OVM 1.0 Header Definitions enum class OVM_HEADER { END = 0, HEADER = 1, POSITIONS = 2, INDICES = 3, NORMALS = 4, BINORMALS = 5, TANGENTS = 6, COLORS = 7, TEXCOORDS = 8, BLENDINDICES = 9, BLENDWEIGHTS = 10, ANIMATIONCLIPS = 11, SKELETON = 12 }; #pragma endregion //Parsing Logic const auto pMeshFilter = new MeshFilter(); SubMeshFilter subMesh{}; subMesh.id = 0; for (;;) { const auto blockID = static_cast(pReader->Read()); if (blockID == OVM_HEADER::END) break; const auto blockSize = pReader->Read(); switch (blockID) { case OVM_HEADER::HEADER: { pMeshFilter->m_MeshName = pReader->ReadString(); subMesh.name = pMeshFilter->m_MeshName; subMesh.vertexCount = pReader->Read(); subMesh.indexCount = pReader->Read(); } break; case OVM_HEADER::POSITIONS: { subMesh.layoutElements |= ILSemantic::POSITION; subMesh.positions.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.positions.emplace_back(pReader->Read()); } break; case OVM_HEADER::INDICES: { subMesh.indices.reserve(subMesh.indexCount); for (UINT i = 0; i < subMesh.indexCount; ++i) subMesh.indices.emplace_back(pReader->Read()); } break; case OVM_HEADER::NORMALS: { subMesh.layoutElements |= ILSemantic::NORMAL; subMesh.normals.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.normals.emplace_back(pReader->Read()); } break; case OVM_HEADER::TANGENTS: { subMesh.layoutElements |= ILSemantic::TANGENT; subMesh.tangents.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.tangents.emplace_back(pReader->Read()); } break; case OVM_HEADER::BINORMALS: { subMesh.layoutElements |= ILSemantic::BINORMAL; subMesh.binormals.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.binormals.emplace_back(pReader->Read()); } break; case OVM_HEADER::TEXCOORDS: { subMesh.layoutElements |= ILSemantic::TEXCOORD; subMesh.texCoords.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.texCoords.emplace_back(pReader->Read()); } break; case OVM_HEADER::COLORS: { subMesh.layoutElements |= ILSemantic::COLOR; subMesh.colors.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.colors.emplace_back(pReader->Read()); } break; case OVM_HEADER::BLENDINDICES: { subMesh.layoutElements |= ILSemantic::BLENDINDICES; subMesh.blendIndices.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.blendIndices.emplace_back(pReader->Read()); } break; case OVM_HEADER::BLENDWEIGHTS: { subMesh.layoutElements |= ILSemantic::BLENDWEIGHTS; subMesh.blendWeights.reserve(subMesh.vertexCount); for (UINT i = 0; i < subMesh.vertexCount; ++i) subMesh.blendWeights.emplace_back(pReader->Read()); } break; case OVM_HEADER::ANIMATIONCLIPS: { pMeshFilter->m_HasAnimations = true; const auto clipCount = pReader->Read(); for (auto j = 0; j < clipCount; ++j) { AnimationClip clip{}; clip.name = pReader->ReadString(); clip.duration = pReader->Read(); clip.ticksPerSecond = pReader->Read(); const auto keyCount = pReader->Read(); for (auto key = 0; key < keyCount; ++key) { AnimationKey animKey{}; animKey.tick = pReader->Read(); const auto transformCount = pReader->Read(); for (auto i = 0; i < transformCount; ++i) { animKey.boneTransforms.emplace_back(pReader->Read()); } clip.keys.emplace_back(animKey); } pMeshFilter->m_AnimationClips.emplace_back(clip); } } break; case OVM_HEADER::SKELETON: { pMeshFilter->m_BoneCount = pReader->Read(); pReader->MoveBufferPosition(blockSize - sizeof(USHORT)); } break; default: pReader->MoveBufferPosition(blockSize); break; } } pMeshFilter->m_Meshes.push_back(subMesh); return pMeshFilter; } #pragma endregion #pragma region OVM 2.0 Parser MeshFilter* MeshFilterLoader::ParseOVM20(BinaryReader* pReader) { #pragma region Header Definitions //OVM 2.0 Header Definitions enum class OVM_HEADER { END = 0, HEADER = 1, MESHES = 2, ANIMATIONS = 3 }; enum class OVM_HEADER_MESHES { END = 0, POSITIONS = 1, INDICES = 2, NORMALS = 3, BINORMALS = 4, TANGENTS = 5, COLORS = 6, TEXCOORDS = 7, BLENDINDICES = 8, BLENDWEIGHTS = 9 }; enum class OVM_HEADER_ANIMATIONS { END = 0, CLIPS = 1, SKELETON = 2 }; #pragma endregion auto pMeshFilter = new MeshFilter(); for (;;) { const auto blockId = static_cast(pReader->Read()); if (blockId == OVM_HEADER::END) break; /*auto blockSize = */pReader->Read(); //HEADER BLOCK if (blockId == OVM_HEADER::HEADER) { pMeshFilter->m_MeshName = pReader->ReadString(); continue; //Advance to Next Block } //MESHES BLOCK if (blockId == OVM_HEADER::MESHES) { const auto meshCount = pReader->Read(); //SUB_MESH for (auto meshId{ 0 }; meshId < meshCount; ++meshId) { #pragma region SubMeshes SubMeshFilter subMesh{}; /*subMesh.id = */pReader->Read(); subMesh.id = static_cast(meshId); subMesh.name = pReader->ReadString(); subMesh.vertexCount = pReader->Read(); subMesh.indexCount = pReader->Read(); subMesh.uvChannelCount = pReader->Read(); for (;;) { const auto meshBlockId = static_cast(pReader->Read()); if (meshBlockId == OVM_HEADER_MESHES::END)break; /*auto meshBlockSize = */pReader->Read(); switch (meshBlockId) { case OVM_HEADER_MESHES::POSITIONS: { subMesh.layoutElements |= ILSemantic::POSITION; subMesh.positions.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.positions.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::INDICES: { subMesh.indices.reserve(subMesh.indexCount); for (size_t i{ 0 }; i < subMesh.indexCount; ++i) subMesh.indices.emplace_back(pReader->Read ()); } break; case OVM_HEADER_MESHES::NORMALS: { subMesh.layoutElements |= ILSemantic::NORMAL; subMesh.normals.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.normals.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::TANGENTS: { subMesh.layoutElements |= ILSemantic::TANGENT; subMesh.tangents.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.tangents.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::BINORMALS: { subMesh.layoutElements |= ILSemantic::BINORMAL; subMesh.binormals.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.binormals.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::COLORS: { subMesh.layoutElements |= ILSemantic::COLOR; subMesh.colors.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.colors.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::TEXCOORDS: { subMesh.layoutElements |= ILSemantic::TEXCOORD; const auto texCoordCount = static_cast(subMesh.vertexCount) * subMesh.uvChannelCount; subMesh.texCoords.reserve(texCoordCount); for (size_t i{ 0 }; i < texCoordCount; ++i) subMesh.texCoords.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::BLENDINDICES: { subMesh.layoutElements |= ILSemantic::BLENDINDICES; subMesh.blendIndices.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.blendIndices.emplace_back(pReader->Read()); } break; case OVM_HEADER_MESHES::BLENDWEIGHTS: { subMesh.layoutElements |= ILSemantic::BLENDWEIGHTS; subMesh.blendWeights.reserve(subMesh.vertexCount); for (size_t i{ 0 }; i < subMesh.vertexCount; ++i) subMesh.blendWeights.emplace_back(pReader->Read()); } break; } } //Add SubMesh to MeshFilter pMeshFilter->m_Meshes.emplace_back(subMesh); #pragma endregion } continue; //Advance to Next Block } //ANIMATION BLOCK if (blockId == OVM_HEADER::ANIMATIONS) { for (;;) { const auto animationBlockId = static_cast(pReader->Read()); if (animationBlockId == OVM_HEADER_ANIMATIONS::END) break; const auto animationBlockSize = pReader->Read(); #pragma region Animation Blocks switch (animationBlockId) { case OVM_HEADER_ANIMATIONS::CLIPS: { pMeshFilter->m_HasAnimations = true; const auto clipCount = pReader->Read(); for (auto j = 0; j < clipCount; ++j) { AnimationClip clip{}; clip.name = pReader->ReadString(); clip.duration = pReader->Read(); clip.ticksPerSecond = pReader->Read(); const auto keyCount = static_cast(pReader->Read()); clip.keys.reserve(keyCount); for (size_t key{ 0 }; key < keyCount; ++key) { AnimationKey animKey{}; animKey.tick = pReader->Read(); const auto transformCount = static_cast(pReader->Read()); animKey.boneTransforms.reserve(transformCount); for (size_t i = 0; i < transformCount; ++i) { animKey.boneTransforms.emplace_back(pReader->Read()); } clip.keys.emplace_back(animKey); } pMeshFilter->m_AnimationClips.emplace_back(clip); } } break; case OVM_HEADER_ANIMATIONS::SKELETON: { pMeshFilter->m_BoneCount = pReader->Read(); pReader->MoveBufferPosition(animationBlockSize - sizeof(UINT16)); } break; } #pragma endregion } } } return pMeshFilter; } #pragma endregion