#pragma once #include "athena/FileWriter.hpp" #include "hecl/Frontend.hpp" #include "hecl/Backend/GX.hpp" #include "PAK.hpp" #include "GX.hpp" #include "TXTR.hpp" #include "zeus/CAABox.hpp" namespace DataSpec::DNACMDL { using Mesh = hecl::blender::Mesh; using Material = hecl::blender::Material; struct Header : BigDNA { AT_DECL_DNA Value magic; Value version; struct Flags : BigDNA { AT_DECL_DNA Value flags = 0; bool skinned() const { return (flags & 0x1) != 0; } void setSkinned(bool val) { flags &= ~0x1; flags |= val; } bool shortNormals() const { return (flags & 0x2) != 0; } void setShortNormals(bool val) { flags &= ~0x2; flags |= val << 1; } bool shortUVs() const { return (flags & 0x4) != 0; } void setShortUVs(bool val) { flags &= ~0x4; flags |= val << 2; } } flags; Value aabbMin; Value aabbMax; Value secCount; Value matSetCount; Vector secSizes; Align<32> align; }; struct SurfaceHeader_1 : BigDNA { AT_DECL_EXPLICIT_DNA Value centroid; Value matIdx = 0; Value dlSize = 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 aabb[2]; Align<32> align; static constexpr bool UseMatrixSkinning() { return false; } static constexpr atInt16 skinMatrixBankIdx() { return -1; } }; struct SurfaceHeader_2 : BigDNA { AT_DECL_EXPLICIT_DNA Value centroid; Value matIdx = 0; Value dlSize = 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; Value surfaceGroup; Value aabb[2]; Align<32> align; static constexpr bool UseMatrixSkinning() { return false; } atInt16 skinMatrixBankIdx() const { return skinMtxBankIdx; } }; struct SurfaceHeader_3 : BigDNA { AT_DECL_EXPLICIT_DNA Value centroid; Value matIdx = 0; Value dlSize = 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; Value surfaceGroup; Value aabb[2]; Value unk3; Align<32> align; static constexpr bool UseMatrixSkinning() { return true; } atInt16 skinMatrixBankIdx() const { return skinMtxBankIdx; } }; struct VertexAttributes { GX::AttrType pos = GX::NONE; GX::AttrType norm = GX::NONE; GX::AttrType color0 = GX::NONE; GX::AttrType color1 = GX::NONE; unsigned uvCount = 0; GX::AttrType uvs[7] = {GX::NONE}; GX::AttrType pnMtxIdx = GX::NONE; unsigned texMtxIdxCount = 0; GX::AttrType texMtxIdx[7] = {GX::NONE}; bool shortUVs; }; template void GetVertexAttributes(const MaterialSet& matSet, std::vector& attributesOut); template void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, unsigned setIdx); template void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, unsigned setIdx); void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath, bool solidShading); void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx); template atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::IStreamReader& reader, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const RigPair& rp, bool shortNormals, bool shortUVs, std::vector& vertAttribs, int meshIdx, atUint32 secCount, atUint32 matSetCount, const atUint32* secSizes, atUint32 surfaceCount = 0); template bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, const RigPair& rp); template void NameCMDL(athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename PAKRouter::EntryType& entry, const SpecBase& dataspec); 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, hecl::blender::PoolSkinIndex& poolSkinIndex); template bool WriteMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs); template bool WriteHMDLMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs); } // namespace DataSpec::DNACMDL