/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "WorldModelGroup.h" #include "Chunk.h" #include "ChunkedData.h" #include "Utils.h" WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), MOBA(nullptr), IsBad(false), HasLiquidData(false) { Data = new ChunkedData(path); if (!Data->Stream) { IsBad = true; return; } Chunk* mainChunk = Data->GetChunkByName("MOGP"); int32 firstSub = mainChunk->FindSubChunkOffset("MOPY"); if (firstSub == -1) return; Name = Utils::GetPlainName(path.c_str()); FILE* stream = mainChunk->GetStream(); fseek(stream, firstSub, SEEK_SET); SubData = new ChunkedData(stream, mainChunk->Length - firstSub); ReadHeader(); ReadMaterials(); ReadTriangles(); ReadVertices(); ReadNormals(); ReadLiquid(); ReadBatches(); } 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 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::ReadTriangles() { Chunk* chunk = SubData->GetChunkByName("MOVI"); if (!chunk) return; uint32 triangleCount = chunk->Length / 6; ASSERT(triangleCount == TriangleFlags.size() && "triangleCount != TriangleFlags.size()"); FILE* stream = chunk->GetStream(); Triangles.reserve(triangleCount); for (uint32 i = 0; i < triangleCount; i++) { uint16 v0; uint16 v1; uint16 v2; int count = 0; count += fread(&v0, sizeof(uint16), 1, stream); count += fread(&v1, sizeof(uint16), 1, stream); count += fread(&v2, sizeof(uint16), 1, stream); if (count != 3) printf("WorldModelGroup::ReadMaterials: Error reading data, expected 3, read %d\n", count); Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WMO, v0, v1, v2)); } } 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 WorldModelGroup::ReadHeader() { Chunk* chunk = Data->GetChunkByName("MOGP"); if (!chunk) return; FILE* stream = chunk->GetStream(); Header = WMOGroupHeader::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); }