diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt index 35a2545bb..cb5ec4278 100644 --- a/DataSpec/DNACommon/CMakeLists.txt +++ b/DataSpec/DNACommon/CMakeLists.txt @@ -1,5 +1,6 @@ make_dnalist(liblist - CMDL) + CMDL + MAPA) add_library(DNACommon DNACommon.hpp DNACommon.cpp @@ -8,7 +9,6 @@ add_library(DNACommon GX.hpp MLVL.hpp CMDL.cpp - MAPA.hpp STRG.hpp STRG.cpp TXTR.hpp TXTR.cpp ANCS.hpp diff --git a/DataSpec/DNACommon/MAPA.hpp b/DataSpec/DNACommon/MAPA.hpp index 7ab8528ec..3207d2652 100644 --- a/DataSpec/DNACommon/MAPA.hpp +++ b/DataSpec/DNACommon/MAPA.hpp @@ -8,8 +8,236 @@ namespace Retro { namespace DNAMAPA { +struct MAPA : BigDNA +{ + Delete _d; + Value magic; + Value version; + struct IMAPAHeader : BigDNA + { + Delete _d; + virtual atUint32 mappableObjectCount() const=0; + virtual atUint32 vertexCount() const=0; + virtual atUint32 surfaceCount() const=0; + }; -template + struct HeaderMP1 : IMAPAHeader + { + DECL_DNA + Value unknown1; + Value unknown2; + Value boundingBox[2]; + Value moCount; + Value vtxCount; + Value surfCount; + virtual atUint32 mappableObjectCount() const { return moCount;} + virtual atUint32 vertexCount() const { return vtxCount; } + virtual atUint32 surfaceCount() const { return surfCount; } + }; + + struct HeaderMP2 : IMAPAHeader + { + DECL_DNA + Value unknown1; + Value unknown2; + Value boundingBox[2]; + Value unknown3; + Value unknown4; + Value unknown5; + Value moCount; + Value vtxCount; + Value surfCount; + atUint32 mappableObjectCount() const { return moCount;} + atUint32 vertexCount() const { return vtxCount; } + atUint32 surfaceCount() const { return surfCount; } + }; + + struct HeaderMP3 : IMAPAHeader + { + DECL_DNA + Value unknown1; + Value unknown2; + Value boundingBox[2]; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value moCount; + Value vtxCount; + Value surfCount; + Value internalNameLength; + Value unknown7; + String internalName; + atUint32 mappableObjectCount() const { return moCount;} + atUint32 vertexCount() const { return vtxCount; } + atUint32 surfaceCount() const { return surfCount; } + }; + + + void read(Athena::io::IStreamReader& __dna_reader) + { + /* magic */ + magic = __dna_reader.readUint32Big(); + /* version */ + version = __dna_reader.readUint32Big(); + if (version == 2) + header.reset(new HeaderMP1); + else if (version == 3) + header.reset(new HeaderMP2); + else if (version == 5) + header.reset(new HeaderMP3); + header->read(__dna_reader); + + for (int i = 0; i < header->mappableObjectCount(); i++) + { + std::unique_ptr mo = nullptr; + if (version != 5) + mo.reset(new MappableObjectMP1_2); + else + mo.reset(new MappableObjectMP3); + mo->read(__dna_reader); + mappableObjects.push_back(std::move(mo)); + } + + /* vertices */ + __dna_reader.enumerateBig(vertices, header->vertexCount()); + /* surfaceHeaders */ + __dna_reader.enumerate(surfaceHeaders, header->surfaceCount()); + /* surfaces */ + __dna_reader.enumerate(surfaces, header->surfaceCount()); + } + + void write(Athena::io::IStreamWriter& __dna_writer) const + { + /* magic */ + __dna_writer.writeUint32Big(magic); + /* version */ + __dna_writer.writeUint32Big(version); + header->write(__dna_writer); + + /* mappableObjects */ + for (const std::unique_ptr& mo : mappableObjects) + mo->write(__dna_writer); + /* vertices */ + __dna_writer.enumerateBig(vertices); + /* surfaceHeaders */ + __dna_writer.enumerate(surfaceHeaders); + /* surfaces */ + __dna_writer.enumerate(surfaces); + } + + size_t binarySize(size_t __isz) const + { + __isz = header->binarySize(__isz); + + for (const std::unique_ptr& mo : mappableObjects) + __isz = mo->binarySize(__isz); + + __isz += vertices.size() * 12; + __isz = __EnumerateSize(__isz, surfaceHeaders); + __isz = __EnumerateSize(__isz, surfaces); + return __isz + 8; + } + + std::unique_ptr header; + + struct IMappableObject : BigDNA + { + Delete _d; + enum class Type : atUint32 + { + BlueDoor = 0, + ShieldDoor = 1, + IceDoor = 2, + WaveDoor = 3, + PlasmaDoor = 4, + BigDoor1 = 5, + BigDoor2 = 6, + IceDoorCeiling = 7, + IceDoorFloor = 8, + WaveDoorCeiling = 9, + WaveDoorFloor = 10, + IceDoorFloor2 = 13, + WaveDoorFloor2 = 14, + DownArrowYellow = 27, /* Maintenance Tunnel */ + UpArrowYellow = 28, /* Phazon Processing Center */ + DownArrowGreen = 29, /* Elevator A */ + UpArrowGreen = 30, /* Elite Control Access */ + DownArrowRed = 31, /* Elevator B */ + UpArrowRed = 32, /* Fungal Hall Access */ + TransportLift = 33, + SaveStation = 34, + MissileStation = 37 + }; + }; + + struct MappableObjectMP1_2 : IMappableObject + { + DECL_DNA + Value type; + Value unknown1; + Value sclyId; + Seek seek1; + Value transformMtx[3]; + Seek seek2; + }; + + struct MappableObjectMP3 : IMappableObject + { + DECL_DNA + Value type; + Value unknown1; + Value sclyId; + Buffer unknownHash; + Seek seek1; + Value transformMtx[3]; + Seek seek2; + }; + + std::vector> mappableObjects; + VectorvertexCount())> vertices; + + struct SurfaceHeader : BigDNA + { + DECL_DNA + Value normal; + Value centroid; + Value polyOff; + Value edgeOff; + }; + + VectorsurfaceCount())> surfaceHeaders; + + struct Surface : BigDNA + { + DECL_DNA + Value primitiveCount; + struct Primitive : BigDNA + { + DECL_DNA + Value type; + Value indexCount; + Vector indices; + Align<4> align; + }; + Vector primitives; + Value borderCount; + struct Border : BigDNA + { + DECL_DNA + Value indexCount; + Vector indices; + Align<4> align; + }; + Vector borders; + }; + + VectorsurfaceCount())> surfaces; + + +}; + +template bool ReadMAPAToBlender(HECL::BlenderConnection& conn, const MAPA& mapa, const HECL::ProjectPath& outPath, @@ -59,24 +287,50 @@ bool ReadMAPAToBlender(HECL::BlenderConnection& conn, /* Add empties representing MappableObjects */ int moIdx = 0; - for (const typename MAPA::MappableObject& mo : mapa.mappableObjects) + for (const std::unique_ptr& mo : mapa.mappableObjects) { - os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.retro_mappable_type = %d\n" - "obj.retro_mappable_unk = %d\n" - "obj.retro_mappable_sclyid = '%08X'\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = mtxd[2]\n", - moIdx, mo.type, mo.unknown1, mo.sclyId, - mo.transformMtx[0].vec[0], mo.transformMtx[0].vec[1], mo.transformMtx[0].vec[2], mo.transformMtx[0].vec[3], - mo.transformMtx[1].vec[0], mo.transformMtx[1].vec[1], mo.transformMtx[1].vec[2], mo.transformMtx[1].vec[3], - mo.transformMtx[2].vec[0], mo.transformMtx[2].vec[1], mo.transformMtx[2].vec[2], mo.transformMtx[2].vec[3]); - ++moIdx; + const MAPA::MappableObjectMP1_2* moMP12 = dynamic_cast(mo.get()); + if (moMP12) + { + os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.retro_mappable_type = %d\n" + "obj.retro_mappable_unk = %d\n" + "obj.retro_mappable_sclyid = '%08X'\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + moIdx, moMP12->type, moMP12->unknown1, moMP12->sclyId, + moMP12->transformMtx[0].vec[0], moMP12->transformMtx[0].vec[1], moMP12->transformMtx[0].vec[2], moMP12->transformMtx[0].vec[3], + moMP12->transformMtx[1].vec[0], moMP12->transformMtx[1].vec[1], moMP12->transformMtx[1].vec[2], moMP12->transformMtx[1].vec[3], + moMP12->transformMtx[2].vec[0], moMP12->transformMtx[2].vec[1], moMP12->transformMtx[2].vec[2], moMP12->transformMtx[2].vec[3]); + ++moIdx; + continue; + } + const MAPA::MappableObjectMP3* moMP3 = dynamic_cast(mo.get()); + if (moMP3) + { + os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.retro_mappable_type = %d\n" + "obj.retro_mappable_unk = %d\n" + "obj.retro_mappable_sclyid = '%08X'\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + moIdx, moMP3->type, moMP3->unknown1, moMP3->sclyId, + moMP3->transformMtx[0].vec[0], moMP3->transformMtx[0].vec[1], moMP3->transformMtx[0].vec[2], moMP3->transformMtx[0].vec[3], + moMP3->transformMtx[1].vec[0], moMP3->transformMtx[1].vec[1], moMP3->transformMtx[1].vec[2], moMP3->transformMtx[1].vec[3], + moMP3->transformMtx[2].vec[0], moMP3->transformMtx[2].vec[1], moMP3->transformMtx[2].vec[2], moMP3->transformMtx[2].vec[3]); + ++moIdx; + continue; + } } os << "# Begin bmesh\n" diff --git a/DataSpec/DNAMP1/CMakeLists.txt b/DataSpec/DNAMP1/CMakeLists.txt index f7193cd8d..2e7633982 100644 --- a/DataSpec/DNAMP1/CMakeLists.txt +++ b/DataSpec/DNAMP1/CMakeLists.txt @@ -8,7 +8,6 @@ make_dnalist(liblist CINF CSKR EVNT - MAPA CMDLMaterials MREA DeafBabe @@ -28,6 +27,7 @@ add_library(DNAMP1 EVNT.cpp CMDL.hpp CMDLMaterials.cpp + MAPA.hpp MREA.cpp SCLY.hpp SCLY.cpp DeafBabe.cpp) diff --git a/DataSpec/DNAMP1/MAPA.hpp b/DataSpec/DNAMP1/MAPA.hpp index d8724b38c..1c3b90411 100644 --- a/DataSpec/DNAMP1/MAPA.hpp +++ b/DataSpec/DNAMP1/MAPA.hpp @@ -11,94 +11,9 @@ namespace Retro { namespace DNAMP1 { -struct MAPA : BigDNA + +struct MAPA : DNAMAPA::MAPA { - DECL_DNA - Value magic; - Value version; - Value unknown1; - Value unknown2; - Value aabbMin; - Value aabbMax; - Value mappableObjectCount; - Value vertexCount; - Value surfaceCount; - - struct MappableObject : BigDNA - { - DECL_DNA - enum class Type : atUint32 - { - BlueDoor = 0, - ShieldDoor = 1, - IceDoor = 2, - WaveDoor = 3, - PlasmaDoor = 4, - BigDoor1 = 5, - BigDoor2 = 6, - IceDoorCeiling = 7, - IceDoorFloor = 8, - WaveDoorCeiling = 9, - WaveDoorFloor = 10, - IceDoorFloor2 = 13, - WaveDoorFloor2 = 14, - DownArrowYellow = 27, /* Maintenance Tunnel */ - UpArrowYellow = 28, /* Phazon Processing Center */ - DownArrowGreen = 29, /* Elevator A */ - UpArrowGreen = 30, /* Elite Control Access */ - DownArrowRed = 31, /* Elevator B */ - UpArrowRed = 32, /* Fungal Hall Access */ - TransportLift = 33, - SaveStation = 34, - MissileStation = 37 - }; - Value type; - Value unknown1; - Value sclyId; - Seek seek1; - Value transformMtx[3]; - Seek seek2; - }; - Vector mappableObjects; - Vector vertices; - - struct SurfaceHeader : BigDNA - { - DECL_DNA - Value normal; - Value centroid; - Value polyOff; - Value edgeOff; - }; - - Vector surfaceHeaders; - - struct Surface : BigDNA - { - DECL_DNA - Value primitiveCount; - struct Primitive : BigDNA - { - DECL_DNA - Value type; - Value indexCount; - Vector indices; - Align<4> align; - }; - Vector primitives; - Value borderCount; - struct Border : BigDNA - { - DECL_DNA - Value indexCount; - Vector indices; - Align<4> align; - }; - Vector borders; - }; - - Vector surfaces; - static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath, diff --git a/DataSpec/DNAMP2/MAPA.hpp b/DataSpec/DNAMP2/MAPA.hpp index a76e7ee1a..022748ea3 100644 --- a/DataSpec/DNAMP2/MAPA.hpp +++ b/DataSpec/DNAMP2/MAPA.hpp @@ -2,14 +2,14 @@ #define __DNAMP2_MAPA_HPP__ #include "../DNACommon/PAK.hpp" -#include "../DNAMP1/MAPA.hpp" +#include "../DNACommon/MAPA.hpp" #include "DNAMP2.hpp" namespace Retro { namespace DNAMP2 { -struct MAPA : DNAMP1::MAPA +struct MAPA : DNAMAPA::MAPA { static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, diff --git a/DataSpec/DNAMP3/CMakeLists.txt b/DataSpec/DNAMP3/CMakeLists.txt index dfbb205a2..f106778b1 100644 --- a/DataSpec/DNAMP3/CMakeLists.txt +++ b/DataSpec/DNAMP3/CMakeLists.txt @@ -16,4 +16,5 @@ add_library(DNAMP3 CMDL.hpp CMDLMaterials.cpp STRG.hpp STRG.cpp + MAPA.hpp MREA.cpp) diff --git a/DataSpec/DNAMP3/DNAMP3.cpp b/DataSpec/DNAMP3/DNAMP3.cpp index dcbf5d09d..b6f4906c8 100644 --- a/DataSpec/DNAMP3/DNAMP3.cpp +++ b/DataSpec/DNAMP3/DNAMP3.cpp @@ -7,6 +7,7 @@ #include "CMDL.hpp" #include "CHAR.hpp" #include "MREA.hpp" +#include "MAPA.hpp" #include "../DNACommon/TXTR.hpp" namespace Retro @@ -233,6 +234,8 @@ ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) return {nullptr, MLVL::Extract, {_S(".blend")}, 3}; case SBIG('MREA'): return {nullptr, MREA::Extract, {_S(".blend")}, 4}; + case SBIG('MAPA'): + return {nullptr, MAPA::Extract, {_S(".blend")}, 4}; } return {}; }