From bf8a007514fceafcb8eaa38952951843b804f019 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 18 Oct 2015 17:28:47 -1000 Subject: [PATCH] Initial CMDL cooking in place --- DataSpec/DNACommon/CMDL.hpp | 244 +++++++++++++++++++++++++++--- DataSpec/DNACommon/DNACommon.hpp | 18 +++ DataSpec/DNAMP1/CMDLMaterials.hpp | 32 +++- DataSpec/DNAMP3/CMDLMaterials.hpp | 4 + DataSpec/SpecMP1.cpp | 2 +- hecl | 2 +- 6 files changed, 280 insertions(+), 22 deletions(-) diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index 297db33b0..443576cad 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -24,7 +24,7 @@ struct Header : BigDNA struct Flags : BigDNA { DECL_DNA - Value flags; + Value flags = 0; bool shortNormals() const {return (flags & 0x2) != 0;} void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;} bool shortUVs() const {return (flags & 0x4) != 0;} @@ -42,12 +42,12 @@ struct SurfaceHeader_1_2 : BigDNA { DECL_DNA Value centroid; - Value matIdx; - Value qDiv; - Value dlSize; - Value unk1; - Value unk2; - Value aabbSz; + Value matIdx = 0; + Value qDiv = 0x8000; + Value dlSize = 0; + Value unk1 = 0; + Value unk2 = 0; + Value aabbSz = 0; Value reflectionNormal; Seek seek2; Align<32> align; @@ -60,12 +60,12 @@ struct SurfaceHeader_3 : BigDNA { DECL_DNA Value centroid; - Value matIdx; - Value qDiv; - Value dlSize; - Value unk1; - Value unk2; - Value aabbSz; + Value matIdx = 0; + Value qDiv = 0x8000; + Value dlSize = 0; + Value unk1 = 0; + Value unk2 = 0; + Value aabbSz = 0; Value reflectionNormal; Value skinMtxBankIdx; Value unk3; @@ -1024,21 +1024,39 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn, return true; } +static void WriteDLVal(Athena::io::FileWriter& writer, GX::AttrType type, atUint32 val) +{ + switch (type) + { + case GX::DIRECT: + case GX::INDEX8: + writer.writeUByte(atUint8(val)); + break; + case GX::INDEX16: + writer.writeUint16Big(atUint16(val)); + break; + default: break; + } +} + template bool WriteCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath, const Mesh& mesh) { - //Athena::io::FileWriter writer(outPath.getAbsolutePath()); + Athena::io::FileWriter writer(outPath.getWithExtension(_S(".recook")).getAbsolutePath()); Header head; head.magic = 0xDEADBABE; head.version = Version; - head.flags.flags = 0; head.aabbMin = mesh.aabbMin.val; head.aabbMax = mesh.aabbMax.val; head.matSetCount = mesh.materialSets.size(); head.secCount = head.matSetCount + 5 + mesh.surfaces.size(); head.secSizes.reserve(head.secCount); + /* Lengths of padding to insert while writing */ + std::vector paddingSizes; + paddingSizes.reserve(head.secCount); + /* Build material sets */ std::vector matSets; matSets.reserve(mesh.materialSets.size()); @@ -1049,23 +1067,213 @@ bool WriteCMDL(const HECL::ProjectPath& outPath, const HECL::ProjectPath& inPath matSets.emplace_back(); MaterialSet& targetMSet = matSets.back(); std::vector texPaths; + std::vector setBackends; + setBackends.reserve(mset.size()); + size_t endOff = 0; + atUint32 nextGroupIdx = 0; for (const Mesh::Material& mat : mset) { std::string diagName = HECL::Format("%s:%s", inPath.getLastComponentUTF8(), mat.name.c_str()); HECL::Frontend::IR matIR = FE.compileSource(mat.source, diagName); - HECL::Backend::GX matGX; + setBackends.emplace_back(); + HECL::Backend::GX& matGX = setBackends.back(); matGX.reset(matIR, FE.getDiagnostics()); + + atUint32 groupIdx = -1; + if (matSets.size() == 1) + { + for (size_t i=0 ; i surfEndOffs; + surfEndOffs.reserve(mesh.surfaces.size()); + secSz = mesh.surfaces.size() * 4 + 4; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Surfaces */ + size_t endOff = 0; + for (const Mesh::Surface& surf : mesh.surfaces) + { + size_t vertSz = matSets.at(0).materials.at(surf.materialIdx).getVAFlags().vertDLSize(); + if (surf.verts.size() > 65536) + LogDNACommon.report(LogVisor::FatalError, "GX DisplayList overflow"); + size_t secSz = 67 + surf.verts.size() * vertSz; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + endOff += secSz32; + surfEndOffs.push_back(endOff); + } + + /* Write sections */ + head.write(writer); + std::vector::const_iterator padIt = paddingSizes.cbegin(); + + /* Material Sets */ + for (const MaterialSet& mset : matSets) + { + mset.write(writer); + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + /* Vertex Positions */ + for (const atVec3f& pos : mesh.pos) + writer.writeVec3fBig(pos); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Vertex Normals */ + for (const atVec3f& norm : mesh.norm) + writer.writeVec3fBig(norm); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Vertex Colors */ + for (const atVec3f& col : mesh.color) + { + GX::Color qCol(col); + qCol.write(writer); + } + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* UV coords */ + for (const atVec2f& uv : mesh.uv) + writer.writeVec2fBig(uv); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surface index */ + writer.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + writer.writeUint32Big(off); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surfaces */ + for (const Mesh::Surface& surf : mesh.surfaces) + { + const typename MaterialSet::Material::VAFlags& vaFlags = + matSets.at(0).materials.at(surf.materialIdx).getVAFlags(); + size_t vertSz = vaFlags.vertDLSize(); + + SurfaceHeader header; + header.centroid = surf.centroid; + header.matIdx = surf.materialIdx; + header.dlSize = 3 + surf.verts.size() * vertSz; + header.reflectionNormal = surf.reflectionNormal; + header.write(writer); + + writer.writeUByte(GX::TRIANGLESTRIP); + writer.writeUint16Big(surf.verts.size()); + + for (const Mesh::Surface::Vert& vert : surf.verts) + { + atUint32 skinIdx = vert.iBankSkin * 3; + WriteDLVal(writer, vaFlags.pnMatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex0MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex1MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex2MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex3MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex4MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex5MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex6MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.position(), vert.iPos); + WriteDLVal(writer, vaFlags.normal(), vert.iNorm); + WriteDLVal(writer, vaFlags.color0(), vert.iColor[0]); + WriteDLVal(writer, vaFlags.color1(), vert.iColor[1]); + WriteDLVal(writer, vaFlags.tex0(), vert.iUv[0]); + WriteDLVal(writer, vaFlags.tex1(), vert.iUv[1]); + WriteDLVal(writer, vaFlags.tex2(), vert.iUv[2]); + WriteDLVal(writer, vaFlags.tex3(), vert.iUv[3]); + WriteDLVal(writer, vaFlags.tex4(), vert.iUv[4]); + WriteDLVal(writer, vaFlags.tex5(), vert.iUv[5]); + WriteDLVal(writer, vaFlags.tex6(), vert.iUv[6]); + } + + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + writer.close(); return true; } diff --git a/DataSpec/DNACommon/DNACommon.hpp b/DataSpec/DNACommon/DNACommon.hpp index ab37c27bd..89073fb42 100644 --- a/DataSpec/DNACommon/DNACommon.hpp +++ b/DataSpec/DNACommon/DNACommon.hpp @@ -71,6 +71,15 @@ public: snprintf(buf, 9, "%08X", m_id); return std::string(buf); } + + UniqueID32() = default; + UniqueID32(const char* hexStr) + { + char copy[9]; + strncpy(copy, hexStr, 8); + copy[8] = '\0'; + m_id = strtoul(copy, nullptr, 16); + } }; /* PAK 64-bit Unique ID */ @@ -100,6 +109,15 @@ public: snprintf(buf, 17, "%016" PRIX64, m_id); return std::string(buf); } + + UniqueID64() = default; + UniqueID64(const char* hexStr) + { + char copy[17]; + strncpy(copy, hexStr, 16); + copy[16] = '\0'; + m_id = strtouq(copy, nullptr, 16); + } }; /* PAK 128-bit Unique ID */ diff --git a/DataSpec/DNAMP1/CMDLMaterials.hpp b/DataSpec/DNAMP1/CMDLMaterials.hpp index 05f8c3061..8d6b0439e 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.hpp +++ b/DataSpec/DNAMP1/CMDLMaterials.hpp @@ -20,11 +20,13 @@ struct MaterialSet : BigDNA struct MaterialSetHead : BigDNA { DECL_DNA - Value textureCount; + Value textureCount = 0; Vector textureIDs; - Value materialCount; + Value materialCount = 0; Vector materialEndOffs; } head; + void addTexture(const UniqueID32& id) {head.textureIDs.push_back(id); ++head.textureCount;} + void addMaterialEndOff(atUint32 off) {head.materialEndOffs.push_back(off); ++head.materialCount;} struct Material : BigDNA { @@ -102,6 +104,32 @@ struct MaterialSet : BigDNA void setTex5MatIdx(GX::AttrType val) {vaFlags &= ~0x40000000; vaFlags |= atUint32(val & 0x1) << 30;} GX::AttrType tex6MatIdx() const {return GX::AttrType(vaFlags >> 31 & 0x1);} void setTex6MatIdx(GX::AttrType val) {vaFlags &= ~0x80000000; vaFlags |= atUint32(val & 0x1) << 31;} + + size_t vertDLSize() const + { + static size_t ATTR_SZ[] = {0,1,1,2}; + size_t ret = 0; + ret += ATTR_SZ[position()]; + ret += ATTR_SZ[normal()]; + ret += ATTR_SZ[color0()]; + ret += ATTR_SZ[color1()]; + ret += ATTR_SZ[tex0()]; + ret += ATTR_SZ[tex1()]; + ret += ATTR_SZ[tex2()]; + ret += ATTR_SZ[tex3()]; + ret += ATTR_SZ[tex4()]; + ret += ATTR_SZ[tex5()]; + ret += ATTR_SZ[tex6()]; + ret += ATTR_SZ[pnMatIdx()]; + ret += ATTR_SZ[tex0MatIdx()]; + ret += ATTR_SZ[tex1MatIdx()]; + ret += ATTR_SZ[tex2MatIdx()]; + ret += ATTR_SZ[tex3MatIdx()]; + ret += ATTR_SZ[tex4MatIdx()]; + ret += ATTR_SZ[tex5MatIdx()]; + ret += ATTR_SZ[tex6MatIdx()]; + return ret; + } } vaFlags; const VAFlags& getVAFlags() const {return vaFlags;} Value groupIdx; diff --git a/DataSpec/DNAMP3/CMDLMaterials.hpp b/DataSpec/DNAMP3/CMDLMaterials.hpp index 58b3de8df..ea887ac8c 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.hpp +++ b/DataSpec/DNAMP3/CMDLMaterials.hpp @@ -18,6 +18,10 @@ struct MaterialSet : BigDNA DECL_DNA Value materialCount; + /* Dummy methods from MP1/2 */ + void addTexture(const UniqueID32&) {} + void addMaterialEndOff(atUint32) {++materialCount;} + struct Material : BigDNA { Delete expl; diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 4c7256869..c9418a18a 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -282,7 +282,7 @@ struct SpecMP1 : SpecBase void cookMesh(const HECL::ProjectPath& out, const HECL::ProjectPath& in, BlendStream& ds) const { - Mesh mesh = ds.compileMesh(); + Mesh mesh = ds.compileMesh(-1); DNAMP1::CMDL::Cook(out, in, mesh); } diff --git a/hecl b/hecl index 7dac1ffef..ad061af83 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 7dac1ffef13697a8fe2478c1f29292cd2c95e67d +Subproject commit ad061af83e93d766aab3bd0985a7984f9cbea5bf