vector<KeyFrame> ModelLoaderMD2::loadKeyFrames(const FileName &fileName, const FileName &skinName, TextureFactory &textureFactory) const { FILE *stream=0; // fopen_s(&stream, fileName.c_str(), "rb"); stream = fopen(fileName.c_str(), "rb"); VERIFY(stream && !ferror(stream), "MD2 failed to open: "+fileName.str()); Header header = readHeader(stream); Skin *skins = readSkins(stream, header); TexCoord *texCoords = readTexCoords(stream, header); Triangle *triangles = readTriangles(stream, header); Frame *frames = readFrames(stream, header); fclose(stream); Material skin; if (header.numOfSkins>0) { skin.setTexture(textureFactory.load(FileName((const char*)skins[0].name))); } else { skin.setTexture(textureFactory.load(skinName)); } vector<KeyFrame> keyFrames = buildKeyFrames(fileName, skin, header, texCoords, triangles, frames); delete [] skins; delete [] texCoords; delete [] triangles; delete [] frames; return keyFrames; }
static void readTrimesh(const uint8_t* ptr, a3dsObjectDataT* obj) { chunkT* chunk = (chunkT*)ptr; ptr = chunk->data; assert(chunk->id == 0x4100); assert(obj->mesh == NULL); obj->mesh = calloc(1, sizeof(a3dsMeshDataT)); obj->mesh->num_verts = (-1); void* chunk_end = (uint8_t*)chunk + chunk->length; while (ptr < chunk_end) { chunk = (chunkT*)ptr; if (chunk->id == 0x4110) readVertCoords(ptr, obj->mesh); else if (chunk->id == 0x4120) readTriIndices(ptr, obj->mesh); else if (chunk->id == 0x4140) readTexCoords (ptr, obj->mesh); ptr = (uint8_t*)chunk + chunk->length; } }
CModelFile* CModelReader::read() { atUint32 magic = base::readUint32(); if (magic != 0xDEADBABE) { Athena::io::MemoryWriter tmp; decompressFile(tmp, base::data(), base::length()); if (tmp.length() > 0x10) base::setData(tmp.data(), tmp.length()); magic = base::readUint32(); } if (magic != 0xDEADBABE /*&& magic != 0x9381000A*/) THROW_INVALID_DATA_EXCEPTION("Not a valid CMDL magic, expected 0xDEADBABE got 0x%.8X\n", magic); atUint32 version; if (magic != 0x9381000A) version = base::readUint32(); else version = CModelFile::DKCR; if (!(version >= CModelFile::MetroidPrime1 && version <= CModelFile::DKCR)) THROW_INVALID_DATA_EXCEPTION("Only Metroid Prime 1 to 3 models are supported got v%i\n", version); try { m_result = new CModelFile; m_result->m_version = (CModelFile::Version)version; m_result->m_flags = base::readUint32(); m_result->m_boundingBox.min.x = base::readFloat(); m_result->m_boundingBox.min.y = base::readFloat(); m_result->m_boundingBox.min.z = base::readFloat(); m_result->m_boundingBox.max.x = base::readFloat(); m_result->m_boundingBox.max.y = base::readFloat(); m_result->m_boundingBox.max.z = base::readFloat(); atUint32 sectionCount = base::readUint32(); atInt32 materialCount = base::readInt32(); m_sectionSizes.resize(sectionCount); if (m_result->m_flags & 0x10) { base::readUint32(); atUint32 visGroupCount = base::readUint32(); while((visGroupCount--) > 0) { atUint32 len = base::readUint32(); base::readString(len); } base::readUint32(); base::readUint32(); base::readUint32(); base::readUint32(); base::readUint32(); } m_result->m_materialSets.resize(materialCount); for (atUint32 i = 0; i < sectionCount; i++) m_sectionSizes[i] = base::readUint32(); base::seekAlign32(); const atUint32 sectionBias = ((m_result->m_version == CModelFile::DKCR || m_result->m_version == CModelFile::MetroidPrime3) ? 1 : materialCount); Athena::io::MemoryReader sectionReader(new atUint8[2], 2); sectionReader.setEndian(endian()); for (atUint32 i = 0; i < sectionCount; i++) { if (m_sectionSizes[i] == 0) continue; if (materialCount > 0) { if (m_result->m_version != CModelFile::DKCR && m_result->m_version != CModelFile::MetroidPrime3) { atUint8* data = base::readUBytes(m_sectionSizes[i]); CMaterialReader reader(data, m_sectionSizes[i]); CMaterialSet materialSet; switch(m_result->m_version) { case CModelFile::MetroidPrime1: materialSet = reader.read(CMaterial::MetroidPrime1); break; case CModelFile::MetroidPrime2: materialSet = reader.read(CMaterial::MetroidPrime2); break; default: break; } m_result->m_materialSets[i] = materialSet; materialCount--; continue; } else { atUint8* data = base::readUBytes(m_sectionSizes[i]); CMaterialReader reader(data, m_sectionSizes[i]); atUint32 setIdx = 0; while ((materialCount--) > 0) { CMaterialSet& materialSet = m_result->m_materialSets[setIdx]; switch(m_result->m_version) { case CModelFile::MetroidPrime3: materialSet = reader.read(CMaterial::MetroidPrime3); break; case CModelFile::DKCR: materialSet = reader.read(CMaterial::DKCR); default: break; } setIdx++; } continue; } } else { SectionType section = (SectionType)(i - sectionBias); atUint8* data = base::readUBytes(m_sectionSizes[i]); sectionReader.setData(data, m_sectionSizes[i]); switch(section) { case SectionType::Vertices: { if (m_result->m_flags & 0x20) readVertices(sectionReader, true); else readVertices(sectionReader); } break; case SectionType::Normals: readNormals(sectionReader); break; case SectionType::Colors: readColors(sectionReader); break; case SectionType::TexCoord0: readTexCoords(0, sectionReader); break; case SectionType::TexCoord1orMeshOffsets: { if (m_result->m_flags & EFormatFlags::TexCoord1 || m_result->m_version == CModelFile::DKCR) readTexCoords(1, sectionReader); else readMeshOffsets(sectionReader); break; } case SectionType::MeshInfo: { if (m_meshOffsets.size() == 0) { readMeshOffsets(sectionReader); break; } } default: if ((i - sectionBias) >= 5) readMesh(sectionReader); break; } } } } catch(...) { delete m_result; m_result = nullptr; throw; } return m_result; }