Advertisement
Guest User

Untitled

a guest
Jan 27th, 2015
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.11 KB | None | 0 0
  1. #include "CAreaReader.hpp"
  2. #include "CAreaFile.hpp"
  3. #include "CMaterialReader.hpp"
  4. #include "CMaterialSet.hpp"
  5. #include "GXCommon.hpp"
  6. #include "RetroCommon.hpp"
  7.  
  8. #include <Athena/InvalidDataException.hpp>
  9.  
  10. #include <algorithm>
  11. #include <map>
  12. #include <glm/glm.hpp>
  13.  
  14. CAreaReader::CAreaReader(const atUint8 *data, atUint64 length)
  15.     : base(data, length),
  16.       m_sectionReader(new atUint8[2], 2)
  17. {
  18.     base::setEndian(Athena::Endian::BigEndian);
  19. }
  20.  
  21. CAreaReader::CAreaReader(const std::string &filepath)
  22.     : base(filepath),
  23.       m_sectionReader(new atUint8[2], 2)
  24. {
  25.     base::setEndian(Athena::Endian::BigEndian);
  26. }
  27.  
  28. CAreaReader::~CAreaReader()
  29. {
  30. }
  31.  
  32. CAreaFile* CAreaReader::read()
  33. {
  34.     {
  35.         Athena::io::BinaryWriter out;
  36.         if (decompressMREA(*this, out))
  37.             setData(out.data(), out.length());
  38.     }
  39.  
  40.     seek(0, Athena::SeekOrigin::Begin);
  41.  
  42.     atUint32 magic   = base::readUint32();
  43.     atUint32 version = base::readUint32();
  44.  
  45.     if (magic != 0xDEADBEEF)
  46.         THROW_INVALID_DATA_EXCEPTION("Not valid MREA file, expected magic 0xDEADBEEF got %.8X\n", magic);
  47.  
  48.     if (version != CAreaFile::MetroidPrime1 && version != CAreaFile::MetroidPrime2
  49.             && version != CAreaFile::MetroidPrime3)
  50.         THROW_INVALID_DATA_EXCEPTION("Unsupported version, got %i\n", version);
  51.  
  52.     CAreaFile* ret = new CAreaFile;
  53.     ret->m_version = (CAreaFile::Version)version;
  54.  
  55.     for (int i= 0; i < 3; i++)
  56.     {
  57.         ret->m_transformMatrix[i].x = base::readFloat();
  58.         ret->m_transformMatrix[i].y = base::readFloat();
  59.         ret->m_transformMatrix[i].z = base::readFloat();
  60.         ret->m_transformMatrix[i].w = base::readFloat();
  61.     }
  62.  
  63.     atUint32 modelCount = base::readUint32();
  64.     // This is also valid for MP2 and DKCR
  65.     atUint32 sclyLayerCount = 1;
  66.     if (version != CAreaFile::MetroidPrime1)
  67.         atUint32 sclyLayerCount = base::readUint32();
  68.  
  69.     atUint32 sectionCount = base::readUint32();
  70.  
  71.     if (version == CAreaFile::MetroidPrime1 || version == CAreaFile::MetroidPrime2)
  72.     {
  73.         m_materialSection  = base::readUint32();
  74.         m_sclySection      = base::readUint32();
  75.         if (version == CAreaFile::MetroidPrime2)
  76.             m_scgnSection  = base::readUint32();
  77.         m_collisionSection = base::readUint32();
  78.         m_unknownSection   = base::readUint32();
  79.         m_lightSection     = base::readUint32();
  80.         m_visiSection      = base::readUint32();
  81.         m_pathSection      = base::readUint32();
  82.         m_arotSection      = base::readUint32();
  83.         if (version == CAreaFile::MetroidPrime2)
  84.         {
  85.             m_ptlaSection  = base::readUint32();
  86.             m_egmcSection  = base::readUint32();
  87.         }
  88.     }
  89.  
  90.     atUint32 compressedBlockCount = 0;
  91.     if (version != CAreaFile::MetroidPrime1)
  92.         compressedBlockCount = base::readUint32();
  93.     atUint32 sectionIndexCount = 0;
  94.     if (version == CAreaFile::MetroidPrime3 || version == CAreaFile::DKCR)
  95.         sectionIndexCount = base::readUint32();
  96.  
  97.     base::seek((base::position() + 31) & ~31, Athena::SeekOrigin::Begin);
  98.  
  99.     m_sectionSizes.resize(sectionCount);
  100.     for (atUint32 i = 0; i < sectionCount; i++)
  101.         m_sectionSizes[i] = base::readUint32();
  102.  
  103.     base::seek((base::position() + 31) & ~31, Athena::SeekOrigin::Begin);
  104.  
  105.     if (version != CAreaFile::MetroidPrime1)
  106.     {
  107.         for (atUint32 i = 0; i < compressedBlockCount; i++)
  108.         {
  109.             base::readUint32(); // Block size
  110.             base::readUint32(); // Data size
  111.             base::readUint32(); // Compressed size
  112.             base::readUint32(); // Section Count
  113.         }
  114.     }
  115.  
  116.     base::seek((base::position() + 31) & ~31, Athena::SeekOrigin::Begin);
  117.  
  118.     if (version == CAreaFile::MetroidPrime3 || version == CAreaFile::DKCR)
  119.     {
  120.         m_sectionIndices.resize(sectionIndexCount);
  121.         for (atUint32 i = 0; i < sectionIndexCount; i++)
  122.         {
  123.             atUint32 tmp = base::readUint32();
  124.             Athena::utility::BigUint32(tmp);
  125.             m_sectionIndices[i].tag = std::string(((char*)&tmp), 4);
  126.             m_sectionIndices[i].index = base::readUint32();
  127.         }
  128.     }
  129.  
  130.     base::seek((base::position() + 31) & ~31, Athena::SeekOrigin::Begin);
  131.  
  132.     m_modelMeshOffsets.resize(modelCount);
  133.  
  134.     if (version == CAreaFile::MetroidPrime3 || version == CAreaFile::DKCR)
  135.         readSectionsMP3DKCR(ret);
  136.     else
  137.         readSections(ret);
  138.  
  139.     return ret;
  140. }
  141.  
  142. IRenderableModel* CAreaReader::load(const std::string& filepath)
  143. {
  144.     CAreaReader reader(filepath);
  145.     return reader.read();
  146. }
  147.  
  148. void CAreaReader::readSections(CAreaFile* ret)
  149. {
  150.     m_sectionReader.setEndian(endian());
  151.     for (atUint32 i = 0; i < m_sectionSizes.size(); i++)
  152.     {
  153.         atUint64 sectionStart = base::position();
  154.  
  155.         if (i == 0)
  156.         {
  157.             CMaterial::Version matVer = (ret->m_version == CAreaFile::MetroidPrime1 ?
  158.                                              CMaterial::MetroidPrime1 : CMaterial::MetroidPrime2);
  159.  
  160.             atUint8* data = base::readUBytes(m_sectionSizes[i]);
  161.             CMaterialReader matReader(data, m_sectionSizes[i]);
  162.             ret->m_materialSets.push_back(matReader.read(matVer));
  163.         }
  164.         else if ((i - 1) < m_modelMeshOffsets.size())
  165.         {
  166.             for (atUint32 j = 0; j < m_modelMeshOffsets.size(); j++)
  167.                 readModelHeader(ret, sectionStart, i);
  168.         }
  169.  
  170.         base::seek(sectionStart + m_sectionSizes[i], Athena::SeekOrigin::Begin);
  171.     }
  172. }
  173.  
  174. void CAreaReader::readSectionsMP3DKCR(CAreaFile* ret)
  175. {
  176.     m_sectionReader.setEndian(endian());
  177.  
  178.     for (atUint32 i = 0; i < m_sectionSizes.size(); i++)
  179.     {
  180.         atUint64 sectionStart = base::position();
  181.         if (i == 0)
  182.         {
  183.             atUint8* data = base::readUBytes(m_sectionSizes[i]);
  184.             CMaterialReader matReader(data, m_sectionSizes[i]);
  185.             ret->m_materialSets.push_back(matReader.read(CMaterial::MetroidPrime3));
  186.         }
  187.         else if (i == 1)
  188.         {
  189.             for (atUint32 m = 0; m < m_modelMeshOffsets.size(); m++)
  190.                 readModelHeader(ret, sectionStart, i);
  191.         }
  192.         else
  193.         {
  194.             std::vector<SAreaSectionIndex>::iterator iter = std::find_if(m_sectionIndices.begin(), m_sectionIndices.end(),
  195.                                                                          [&i](SAreaSectionIndex si)->bool{return si.index == i; });
  196.  
  197.             if (iter != m_sectionIndices.end())
  198.             {
  199.                 SAreaSectionIndex idx = *iter;
  200.                 if (!idx.tag.compare("GPUD"))
  201.                 {
  202.                     for (atUint32 m = 0; m < ret->m_models.size(); m++)
  203.                     {
  204.                         CModelData& model = ret->m_models[m];
  205.                         readModelData(ret, model, sectionStart, i);
  206.                         readMeshes(ret, model, sectionStart, i, m);
  207.                         model.indexIBOs(ret->m_materialSets[0]);
  208.                     }
  209.                 }
  210.             }
  211.         }
  212.  
  213.         base::seek(sectionStart + m_sectionSizes[i], Athena::SeekOrigin::Begin);
  214.     }
  215. }
  216.  
  217. void CAreaReader::readModelHeader(CAreaFile* ret, atUint64& sectionStart, atUint32& i)
  218. {
  219.     ret->m_models.push_back(CModelData());
  220.     CModelData& model = ret->m_models.back();
  221.  
  222.     base::readUint32(); // not really useful
  223.  
  224.     for (atUint32 j = 0; j < 3; j++)
  225.     {
  226.         model.m_transform[j].x = base::readFloat();
  227.         model.m_transform[j].y = base::readFloat();
  228.         model.m_transform[j].z = base::readFloat();
  229.         model.m_transform[j].w = base::readFloat();
  230.     }
  231.  
  232.     for (atUint32 j = 0; j < 2; j++)
  233.     {
  234.         model.m_boundingBox[j].x = base::readFloat();
  235.         model.m_boundingBox[j].y = base::readFloat();
  236.         model.m_boundingBox[j].z = base::readFloat();
  237.     }
  238.  
  239.     base::seek((base::position() + 31) & ~31, Athena::SeekOrigin::Begin);
  240.     sectionStart = base::position();
  241.     i++;
  242.  
  243.     if (ret->m_version == CAreaFile::MetroidPrime1 || ret->m_version == CAreaFile::MetroidPrime2)
  244.         readModelData(ret, model, sectionStart, i);
  245.  
  246.     atUint32 meshCount = base::readUint32();
  247.     while((meshCount--) > 0)
  248.         m_modelMeshOffsets[ret->m_models.size() - 1].push_back(base::readUint32());
  249.  
  250.     base::seek((base::position() + 31) & ~31, Athena::SeekOrigin::Begin);
  251.     sectionStart = base::position();
  252.     i++;
  253.  
  254.     if (ret->m_version == CAreaFile::MetroidPrime1 || ret->m_version == CAreaFile::MetroidPrime2)
  255.         readMeshes(ret, model, sectionStart, i, ret->m_models.size() - 1);
  256.  
  257.     if (ret->m_version != CAreaFile::MetroidPrime1)
  258.     {
  259.         base::seek(sectionStart + m_sectionSizes[i], Athena::SeekOrigin::Begin);
  260.         sectionStart = base::position();
  261.         i++;
  262.  
  263.         base::seek(sectionStart + m_sectionSizes[i], Athena::SeekOrigin::Begin);
  264.         sectionStart = base::position();
  265.         i++;
  266.     }
  267. }
  268.  
  269. void CAreaReader::readModelData(CAreaFile* ret, CModelData& model, atUint64& sectionStart, atUint32& i)
  270. {
  271.     atUint8* data = base::readUBytes(m_sectionSizes[i]);
  272.     m_sectionReader.setData(data, m_sectionSizes[i]);
  273.     readVertices(model, m_sectionReader);
  274.     sectionStart = base::position();
  275.     i++;
  276.  
  277.     data = base::readUBytes(m_sectionSizes[i]);
  278.     m_sectionReader.setData(data, m_sectionSizes[i]);
  279.     readNormals(model, m_sectionReader);
  280.     sectionStart = base::position();
  281.     i++;
  282.  
  283.     data = base::readUBytes(m_sectionSizes[i]);
  284.     m_sectionReader.setData(data, m_sectionSizes[i]);
  285.     readColors(model, m_sectionReader);
  286.     sectionStart = base::position();
  287.     i++;
  288.  
  289.     data = base::readUBytes(m_sectionSizes[i]);
  290.     m_sectionReader.setData(data, m_sectionSizes[i]);
  291.     readTexCoords(model, m_sectionReader, false);
  292.     sectionStart = base::position();
  293.     i++;
  294.  
  295.     // Something else goes here in DKCR, is it a short UV table?
  296.     if (ret->m_version == CAreaFile::MetroidPrime1 || ret->m_version == CAreaFile::MetroidPrime2)
  297.     {
  298.         data = base::readUBytes(m_sectionSizes[i]);
  299.         m_sectionReader.setData(data, m_sectionSizes[i]);
  300.         readTexCoords(model, m_sectionReader, true);
  301.         sectionStart = base::position();
  302.         i++;
  303.     }
  304. }
  305.  
  306. void CAreaReader::readVertices(CModelData& model, Athena::io::BinaryReader& in)
  307. {
  308.     atInt32 vertexCount = in.length() / sizeof(glm::vec3);
  309.  
  310.     while ((vertexCount--) > 0)
  311.     {
  312.         glm::vec3 vert;
  313.         vert.x = in.readFloat();
  314.         vert.y = in.readFloat();
  315.         vert.z = in.readFloat();
  316.         model.m_vertices.push_back(vert);
  317.     }
  318. }
  319.  
  320. void CAreaReader::readNormals(CModelData& model, Athena::io::BinaryReader& in)
  321. {
  322.     atInt32 normalCount = in.length() / (sizeof(atUint16) * 3);
  323.     while ((normalCount--) > 0)
  324.     {
  325.         glm::vec3 nrm;
  326.         nrm.x = in.readUint16() / 32768.f; // really shouldn't do this here
  327.         nrm.y = in.readUint16() / 32768.f; // but it's constant enough to be reliable
  328.         nrm.z = in.readUint16() / 32768.f;
  329.         model.m_normals.push_back(nrm);
  330.     }
  331. }
  332.  
  333. void CAreaReader::readColors(CModelData& model, Athena::io::BinaryReader& in)
  334. {
  335.     atInt32 colorCount = in.length() / sizeof(atUint32);
  336.  
  337.     while ((colorCount--) > 0)
  338.         model.m_colors.push_back(in.readUint32());
  339. }
  340.  
  341. void CAreaReader::readTexCoords(CModelData& model, Athena::io::BinaryReader& in, bool isLightmap)
  342. {
  343.     if (isLightmap)
  344.     {
  345.         atInt32 texCoordCount = in.length() / (sizeof(atUint16) * 2);
  346.         while ((texCoordCount--) > 0)
  347.         {
  348.             glm::vec2 texCoord;
  349.             texCoord.s = in.readUint16() / 32768.f; // really shouldn't do this here
  350.             texCoord.s = in.readUint16() / 32768.f; // but it's constant enough to be reliable
  351.             model.m_lightmapCoords.push_back(texCoord);
  352.         }
  353.     }
  354.     else
  355.     {
  356.         atUint32 texCoordCount = in.length() / sizeof(glm::vec2);
  357.  
  358.         while ((texCoordCount--) > 0)
  359.         {
  360.             glm::vec2 texCoord;
  361.             texCoord.x = in.readFloat();
  362.             texCoord.y = in.readFloat();
  363.             model.m_texCoords.push_back(texCoord);
  364.         }
  365.     }
  366. }
  367.  
  368. void CAreaReader::readMesh(CModelData& model, CAreaFile* ret, Athena::io::BinaryReader& in)
  369. {
  370.     model.m_meshes.push_back(CMesh());
  371.     CMesh& mesh = model.m_meshes.back();
  372.  
  373.     mesh.m_pivot.x    = in.readFloat();
  374.     mesh.m_pivot.y    = in.readFloat();
  375.     mesh.m_pivot.z    = in.readFloat();
  376.     atUint16 dataSize = 0;
  377.     if (ret->m_version != CAreaFile::DKCR)
  378.     {
  379.         mesh.m_materialID = in.readUint32();
  380.         mesh.m_mantissa   = in.readUint16();
  381.         dataSize = in.readUint16();
  382.         atUint32 extraDataSize = 0;
  383.         if (ret->m_version == CAreaFile::MetroidPrime3)
  384.         {
  385.             in.readUint32();
  386.             in.readUint32();
  387.             in.readUint32();
  388.             in.readUint32();
  389.             in.readUint32();
  390.             in.readUint32();
  391.             in.readUint16();
  392.             in.readUint16();
  393.         }
  394.         else
  395.         {
  396.             in.readUint32();
  397.             in.readUint32();
  398.             extraDataSize = in.readUint32();
  399.             for (int i = 0; i < 3; i++)
  400.                 in.readFloat(); // Normalized vector
  401.         }
  402.  
  403.         for (atUint32 v = 0; v < 6; v++)
  404.             in.readFloat();
  405.  
  406.         base::seek(extraDataSize);
  407.     }
  408.  
  409.     in.seek((in.position() + 31) & ~31, Athena::SeekOrigin::Begin);
  410.  
  411.     const CMaterial& material = ret->m_materialSets[0].material(mesh.m_materialID);
  412.  
  413.     readPrimitives(mesh, material, dataSize, in);
  414. }
  415.  
  416. void CAreaReader::readMeshes(CAreaFile* ret, CModelData& model, atUint64& sectionStart, atUint32& i, atUint32 m)
  417. {
  418.     atUint32 meshCount = m_modelMeshOffsets[m].size();
  419.     atUint64 meshStart = base::position();
  420.  
  421.     for (atUint32 s = 0; s < meshCount; s++)
  422.     {
  423.         atUint8* data = base::readUBytes(m_sectionSizes[i]);
  424.         m_sectionReader.setData(data, m_sectionSizes[i]);
  425.         readMesh(model, ret, m_sectionReader);
  426.         base::seek(meshStart + m_modelMeshOffsets[m][s], Athena::SeekOrigin::Begin);
  427.         sectionStart = base::position();
  428.         i++;
  429.     }
  430. }
  431.  
  432. REGISTER_MODEL_LOADER(CAreaReader, "mrea", "Metroid Prime Level Data (*.mrea *.MREA)", load);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement