void WorldModelRoot::ReadHeader() { Chunk* chunk = Data->GetChunkByName("MOHD"); if (!chunk) return; FILE* stream = chunk->GetStream(); Header = WorldModelHeader::Read(stream); }
void WorldModelGroup::ReadHeader() { Chunk* chunk = Data->GetChunkByName("MOGP"); if (!chunk) return; FILE* stream = chunk->GetStream(); Header = WMOGroupHeader::Read(stream); }
void WorldModelGroup::ReadLiquid() { Chunk* chunk = SubData->GetChunkByName("MLIQ"); if (!chunk) return; HasLiquidData = true; FILE* stream = chunk->GetStream(); LiquidDataHeader = LiquidHeader::Read(stream); LiquidDataGeometry = LiquidData::Read(stream, LiquidDataHeader); }
void WorldModelGroup::ReadVertices() { Chunk* chunk = SubData->GetChunkByName("MOVT"); if (!chunk) return; uint32 verticeCount = chunk->Length / 12; Vertices.reserve(verticeCount); FILE* stream = chunk->GetStream(); for (uint32 i = 0; i < verticeCount; i++) Vertices.push_back(Vector3::Read(stream)); }
void WorldModelGroup::ReadBatches() { Chunk* chunk = Data->GetChunkByName("MOBA"); if (!chunk) return; MOBALength = chunk->Length / 2; MOBA = new uint16[MOBALength]; uint32 count = (uint32)fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream()); if (count != MOBALength) printf("WorldModelGroup::ReadBatches: Error reading data, expected %u, read %u\n", MOBALength, count); }
void WorldModelRoot::ReadDoodadSets() { Chunk* chunk = Data->GetChunkByName("MODS"); if (!chunk) return; FILE* stream = chunk->GetStream(); ASSERT(chunk->Length / 32 == Header.CountSets && "chunk.Length / 32 == Header.CountSets"); DoodadSets.reserve(Header.CountSets); for (uint32 i = 0; i < Header.CountSets; i++) DoodadSets.push_back(DoodadSet::Read(stream)); }
void WorldModelHandler::ReadModelPaths() { Chunk* mwid = Source->ObjectData->GetChunkByName("MWID"); Chunk* mwmo = Source->ObjectData->GetChunkByName("MWMO"); if (!mwid || !mwmo) return; uint32 paths = mwid->Length / 4; _paths = new std::vector<std::string>; _paths->reserve(paths); for (uint32 i = 0; i < paths; i++) { Stream* stream = mwid->GetStream(); stream->Seek(i * 4, SEEK_CUR); uint32 offset = stream->Read<uint32>(); Stream* dataStream = mwmo->GetStream(); dataStream->Seek(offset + mwmo->Offset, SEEK_SET); _paths->push_back(dataStream->ReadString()); } }
void WorldModelHandler::ReadModelPaths() { Chunk* mwid = Source->ObjectData->GetChunkByName("MWID"); Chunk* mwmo = Source->ObjectData->GetChunkByName("MWMO"); if (!mwid || !mwmo) return; uint32 paths = mwid->Length / 4; _paths = new std::vector<std::string>; _paths->reserve(paths); for (uint32 i = 0; i < paths; i++) { FILE* stream = mwid->GetStream(); fseek(stream, i * 4, SEEK_CUR); uint32 offset; fread(&offset, sizeof(uint32), 1, stream); FILE* dataStream = mwmo->GetStream(); fseek(dataStream, offset + mwmo->Offset, SEEK_SET); _paths->push_back(Utils::ReadString(dataStream)); } }
void WorldModelGroup::ReadNormals() { Chunk* chunk = SubData->GetChunkByName("MONR"); if (!chunk) return; uint32 normalCount = chunk->Length / 12; ASSERT(normalCount == Vertices.size() && "normalCount is different than the Vertices count"); Normals.reserve(normalCount); FILE* stream = chunk->GetStream(); for (uint32 i = 0; i < normalCount; i++) Normals.push_back(Vector3::Read(stream)); }
void WorldModelHandler::ReadDefinitions() { Chunk* chunk = Source->ObjectData->GetChunkByName("MODF"); if (!chunk) return; const int32 definitionSize = 64; uint32 definitionCount = chunk->Length / definitionSize; _definitions = new std::vector<WorldModelDefinition>; _definitions->reserve(definitionCount); FILE* stream = chunk->GetStream(); for (uint32 i = 0; i < definitionCount; i++) _definitions->push_back(WorldModelDefinition::Read(stream)); }
void WorldModelRoot::ReadDoodadInstances() { Chunk* chunk = Data->GetChunkByName("MODD"); Chunk* nameChunk = Data->GetChunkByName("MODN"); if (!chunk || !nameChunk) return; const uint32 instanceSize = 40; uint32 countInstances = chunk->Length / instanceSize; DoodadInstances.reserve(countInstances); for (uint32 i = 0; i < countInstances; i++) { FILE* stream = chunk->GetStream(); fseek(stream, instanceSize * i, SEEK_CUR); DoodadInstance instance = DoodadInstance::Read(stream); FILE* nameStream = nameChunk->GetStream(); if (instance.FileOffset >= nameChunk->Length) continue; fseek(nameStream, instance.FileOffset, SEEK_CUR); instance.File = Utils::ReadString(nameStream); DoodadInstances.push_back(instance); } }
void ObjectDataHandler::ProcessMapChunk( MapChunk* chunk ) { if (!Source->HasObjectData) return; // f**k it blizzard, why is this crap necessary? int32 firstIndex = Source->ObjectData->GetFirstIndex("MCNK"); if (firstIndex == -1) return; if (uint32(firstIndex + chunk->Index) > Source->ObjectData->Chunks.size()) return; Chunk* ourChunk = Source->ObjectData->Chunks[firstIndex + chunk->Index]; if (ourChunk->Length == 0) return; ChunkedData* subChunks = new ChunkedData(ourChunk->GetStream(), ourChunk->Length, 2); ProcessInternal(subChunks); }
void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) { if (!IsSane()) return; Chunk* wmoReferencesChunk = subChunks->GetChunkByName("MCRW"); if (!wmoReferencesChunk) return; FILE* stream = wmoReferencesChunk->GetStream(); uint32 refCount = wmoReferencesChunk->Length / 4; for (uint32 i = 0; i < refCount; i++) { int32 index; if (fread(&index, sizeof(int32), 1, stream) != 1) printf("WorldModelDefinition::Read: Error reading data, expected 1, read 0\n"); if (index < 0 || uint32(index) >= _definitions->size()) continue; WorldModelDefinition wmo = (*_definitions)[index]; if (_drawn.find(wmo.UniqueId) != _drawn.end()) continue; _drawn.insert(wmo.UniqueId); if (wmo.MwidIndex >= _paths->size()) continue; std::string path = (*_paths)[wmo.MwidIndex]; WorldModelRoot* model = Cache->WorldModelCache.Get(path); if (!model) { model = new WorldModelRoot(path); Cache->WorldModelCache.Insert(path, model); } Vertices.reserve(1000); Triangles.reserve(1000); InsertModelGeometry(Vertices, Triangles, wmo, model); } }
void WorldModelGroup::ReadMaterials() { Chunk* chunk = SubData->GetChunkByName("MOPY"); if (!chunk) return; FILE* stream = chunk->GetStream(); uint32 triangleCount = chunk->Length / 2; TriangleFlags.reserve(triangleCount); TriangleMaterials.reserve(triangleCount); for (uint32 i = 0; i < triangleCount; i++) { uint8 tmp; if (fread(&tmp, sizeof(uint8), 1, stream) != 1) printf("WorldModelGroup::ReadMaterials: Error reading data, expected 1, read 0\n"); TriangleFlags.push_back(tmp); // Read again for material. if (fread(&tmp, sizeof(uint8), 1, stream) != 1) printf("WorldModelGroup::ReadMaterials: Error reading data, expected 1, read 0\n"); TriangleMaterials.push_back(tmp); } }
void LiquidHandler::HandleNewLiquid() { Chunk* chunk = Source->Data->GetChunkByName("MH2O"); if (!chunk) return; Vertices.reserve(1000); Triangles.reserve(1000); FILE* stream = chunk->GetStream(); H2OHeader header[256]; MCNKData.reserve(256); for (int i = 0; i < 256; i++) header[i] = H2OHeader::Read(stream); for (int i = 0; i < 256; i++) { H2OHeader h = header[i]; if (h.LayerCount == 0) { // Need to fill in missing data with dummies. MCNKData.push_back(MCNKLiquidData(NULL, H2ORenderMask())); continue; } fseek(stream, chunk->Offset + h.OffsetInformation, SEEK_SET); H2OInformation information = H2OInformation::Read(stream); float** heights = new float*[9]; for (int j = 0; j < 9; ++i) { heights[j] = new float[9]; memset(heights[j], 0, sizeof(float) * 9); } H2ORenderMask renderMask; if (information.LiquidType != 2) { fseek(stream, chunk->Offset + h.OffsetRender, SEEK_SET); renderMask = H2ORenderMask::Read(stream); if ((Utils::IsAllZero(renderMask.Mask, 8) || (information.Width == 8 && information.Height == 8)) && information.OffsetMask2) { fseek(stream, chunk->Offset + information.OffsetMask2, SEEK_SET); uint32 size = ceil(information.Width * information.Height / 8.0f); uint8* altMask = new uint8[size]; if (fread(altMask, sizeof(uint8), size, stream) == size) for (uint32 mi = 0; mi < size; mi++) renderMask.Mask[mi + information.OffsetY] |= altMask[mi]; delete[] altMask; } fseek(stream, chunk->Offset + information.OffsetHeightmap, SEEK_SET); for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++) for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++) if (fread(&heights[x][y], sizeof(float), 1, stream) != 1) return; } else { // Fill with ocean data for (uint32 i = 0; i < 8; ++i) renderMask.Mask[i] = 0xFF; for (uint32 y = 0; y < 9; ++y) for (uint32 x = 0; x < 9; ++x) heights[x][y] = information.HeightLevel1; } MCNKData.push_back(MCNKLiquidData(heights, renderMask)); for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++) { for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++) { if (!renderMask.ShouldRender(x, y)) continue; MapChunk* mapChunk = Source->MapChunks[i]; Vector3 location = mapChunk->Header.Position; location.y = location.y - (x * Constants::UnitSize); location.x = location.x - (y * Constants::UnitSize); location.z = heights[x][y]; uint32 vertOffset = Vertices.size(); Vertices.push_back(location); Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y, location.z)); Vertices.push_back(Vector3(location.x, location.y - Constants::UnitSize, location.z)); Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y - Constants::UnitSize, location.z)); Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset+2, vertOffset + 1)); Triangles.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1)); } } } }