private WMOGroupFile ReadWMOGroupFile(string filename, Stream wmo) { WMOGroupFile groupFile = new WMOGroupFile(); var bin = new BinaryReader(wmo); BlizzHeader chunk; long position = 0; while (position < wmo.Length) { wmo.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = wmo.Position + chunk.Size; switch (chunk.ToString()) { case "MVER": groupFile.version = bin.Read <MVER>(); if (wmofile.version.version != 17) { throw new Exception("Unsupported WMO version! (" + wmofile.version.version + ")"); } continue; case "MOGP": groupFile.mogp = ReadMOGPChunk(chunk, bin); continue; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } } return(groupFile); }
/* GROUP */ private WMOGroupFile ReadWMOGroupFile(uint filedataid, Stream wmo) { var groupFile = new WMOGroupFile(); using (var bin = new BinaryReader(wmo)) { long position = 0; while (position < wmo.Length) { wmo.Position = position; var chunkName = (WMOChunks)bin.ReadUInt32(); var chunkSize = bin.ReadUInt32(); position = wmo.Position + chunkSize; switch (chunkName) { case WMOChunks.MVER: groupFile.version = bin.ReadUInt32(); if (wmofile.version != 17) { throw new Exception("Unsupported WMO version! (" + wmofile.version + ")"); } continue; case WMOChunks.MOGP: groupFile.mogp = ReadMOGPChunk(chunkSize, bin); continue; default: throw new Exception(string.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunkName.ToString("X"), position.ToString(), filedataid)); } } } return(groupFile); }
private void ReadWMO(string filename, Stream wmo) { var bin = new BinaryReader(wmo); BlizzHeader chunk; long position = 0; while (position < wmo.Length) { wmo.Position = position; chunk = new BlizzHeader(bin.ReadChars(4), bin.ReadUInt32()); chunk.Flip(); position = wmo.Position + chunk.Size; switch (chunk.ToString()) { case "MVER": wmofile.version = bin.Read <MVER>(); if (wmofile.version.version != 17) { throw new Exception("Unsupported WMO version! (" + wmofile.version.version + ") (" + filename + ")"); } continue; case "MOTX": wmofile.textures = ReadMOTXChunk(chunk, bin); continue; case "MOHD": wmofile.header = ReadMOHDChunk(chunk, bin, filename); continue; case "MOGN": wmofile.groupNames = ReadMOGNChunk(chunk, bin, wmofile.header.nGroups); continue; case "MOGI": wmofile.groupInfo = ReadMOGIChunk(chunk, bin, wmofile.header.nGroups); continue; case "MOMT": wmofile.materials = ReadMOMTChunk(chunk, bin, wmofile.header.nMaterials); continue; case "MODN": wmofile.doodadNames = ReadMODNChunk(chunk, bin, wmofile.header.nModels); continue; case "MODD": wmofile.doodadDefinitions = ReadMODDChunk(chunk, bin); continue; case "MOGP": //ReadMOGPChunk(chunk, bin); //continue; case "MOSB": case "MOPV": case "MOPT": case "MOPR": case "MOVV": //Visible block vertices case "MOVB": //Visible block list case "MOLT": case "MODS": case "MFOG": case "MCVP": case "GFID": // Legion continue; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunk.ToString(), position.ToString(), filename)); } } //open group files WMOGroupFile[] groupFiles = new WMOGroupFile[wmofile.header.nGroups]; for (int i = 0; i < wmofile.header.nGroups; i++) { string groupfilename = groupfilename = filename.Replace(".wmo", "_" + i.ToString().PadLeft(3, '0') + ".wmo"); if (_lod) { if (CASC.FileExists(groupfilename.Replace(".wmo", "_lod2.wmo"))) { groupfilename = groupfilename.Replace(".wmo", "_lod2.wmo"); Console.WriteLine("[LOD] Loading LOD 2 for group " + i); } else if (CASC.FileExists(groupfilename.Replace(".wmo", "_lod1.wmo"))) { groupfilename = groupfilename.Replace(".wmo", "_lod1.wmo"); Console.WriteLine("[LOD] Loading LOD 1 for group " + i); } else { Console.WriteLine("[LOD] No LOD " + i); } } if (!CASC.FileExists(groupfilename)) { new WoWFormatLib.Utils.MissingFile(groupfilename); return; } else { using (Stream wmoStream = CASC.OpenFile(groupfilename)) { groupFiles[i] = ReadWMOGroupFile(groupfilename, wmoStream); } } } wmofile.group = groupFiles; }
/* PARENT */ private void ReadWMO(string filename, Stream wmo) { using (var bin = new BinaryReader(wmo)) { long position = 0; while (position < wmo.Length) { wmo.Position = position; var chunkName = new string(bin.ReadChars(4).Reverse().ToArray()); var chunkSize = bin.ReadUInt32(); position = wmo.Position + chunkSize; switch (chunkName) { case "MVER": wmofile.version = bin.Read <MVER>(); if (wmofile.version.version != 17) { throw new Exception("Unsupported WMO version! (" + wmofile.version.version + ") (" + filename + ")"); } break; case "MOHD": wmofile.header = ReadMOHDChunk(bin, filename); break; case "MOTX": wmofile.textures = ReadMOTXChunk(chunkSize, bin); break; case "MOMT": wmofile.materials = ReadMOMTChunk(bin, wmofile.header.nMaterials); break; case "MOGN": wmofile.groupNames = ReadMOGNChunk(chunkSize, bin, wmofile.header.nGroups); break; case "MOGI": wmofile.groupInfo = ReadMOGIChunk(bin, wmofile.header.nGroups); break; case "MODS": wmofile.doodadSets = ReadMODSChunk(chunkSize, bin); break; case "MODN": wmofile.doodadNames = ReadMODNChunk(chunkSize, bin, wmofile.header.nModels); break; case "MODD": wmofile.doodadDefinitions = ReadMODDChunk(chunkSize, bin); break; case "MOSB": // Skybox case "MOPV": // Portal Vertices case "MOPR": // Portal References case "MOPT": // Portal Information case "MOVV": // Visible block vertices case "MOVB": // Visible block list case "MOLT": // Lighting Infroamtion case "MFOG": // Fog Information case "MCVP": // Convex Volume Planes case "MOUV": // 7.3 - ? case "GFID": // Legion break; default: throw new Exception(String.Format("{2} Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunkName, position.ToString(), filename)); } } } WMOGroupFile[] groupFiles = new WMOGroupFile[wmofile.header.nGroups]; for (int i = 0; i < wmofile.header.nGroups; i++) { string groupfilename = filename.ToLower().Replace(".wmo", "_" + i.ToString().PadLeft(3, '0') + ".wmo"); if (_lod) { if (CASC.cascHandler.FileExists(groupfilename.Replace(".wmo", "_lod2.wmo"))) { groupfilename = groupfilename.Replace(".wmo", "_lod2.wmo"); Console.WriteLine("[LOD] Loading LOD 2 for group " + i); } else if (CASC.cascHandler.FileExists(groupfilename.Replace(".wmo", "_lod1.wmo"))) { groupfilename = groupfilename.Replace(".wmo", "_lod1.wmo"); Console.WriteLine("[LOD] Loading LOD 1 for group " + i); } else { Console.WriteLine("[LOD] No LOD " + i); } } if (CASC.cascHandler.FileExists(groupfilename)) { using (Stream wmoStream = CASC.cascHandler.OpenFile(groupfilename)) { groupFiles[i] = ReadWMOGroupFile(groupfilename, wmoStream); } } } wmofile.group = groupFiles; }
/* PARENT */ private void ReadWMO(Stream wmo, string filename = "") { using (var bin = new BinaryReader(wmo)) { long position = 0; while (position < wmo.Length) { wmo.Position = position; var chunkName = (WMOChunks)bin.ReadUInt32(); var chunkSize = bin.ReadUInt32(); position = wmo.Position + chunkSize; switch (chunkName) { case WMOChunks.MVER: wmofile.version = bin.ReadUInt32(); if (wmofile.version != 17) { throw new Exception("Unsupported WMO version! (" + wmofile.version + ")"); } break; case WMOChunks.MOGP: throw new NotSupportedException("Trying to parse group WMO as root WMO!"); case WMOChunks.MOHD: wmofile.header = bin.Read <MOHD>(); break; case WMOChunks.MOTX: wmofile.textures = ReadMOTXChunk(chunkSize, bin); break; case WMOChunks.MOMT: wmofile.materials = ReadMOMTChunk(chunkSize, bin); break; case WMOChunks.MOGN: wmofile.groupNames = ReadMOGNChunk(chunkSize, bin); break; case WMOChunks.MOGI: wmofile.groupInfo = ReadMOGIChunk(chunkSize, bin); break; case WMOChunks.MODS: wmofile.doodadSets = ReadMODSChunk(chunkSize, bin); break; case WMOChunks.MODI: wmofile.doodadIds = ReadMODIChunk(chunkSize, bin); break; case WMOChunks.MODN: wmofile.doodadNames = ReadMODNChunk(chunkSize, bin); break; case WMOChunks.MODD: wmofile.doodadDefinitions = ReadMODDChunk(chunkSize, bin); break; case WMOChunks.MOSB: wmofile.skybox = ReadMOSBChunk(chunkSize, bin); break; case WMOChunks.MOSI: wmofile.skyboxFileDataID = ReadMOSIChunk(chunkSize, bin); break; case WMOChunks.GFID: wmofile.groupFileDataIDs = ReadGFIDChunk(chunkSize, bin); break; case WMOChunks.MOPV: // MOPV Portal Vertices case WMOChunks.MOPR: // MOPR Portal References case WMOChunks.MOPT: // MOPT Portal Information case WMOChunks.MOVV: // MOVV Visible block vertices case WMOChunks.MOVB: // MOVB Visible block list case WMOChunks.MOLT: // MOLT Lighting Information case WMOChunks.MFOG: // MFOG Fog Information case WMOChunks.MCVP: // MCVP Convex Volume Planes case WMOChunks.MOUV: // MOUV Animated texture UVs case WMOChunks.MLSP: // ? case WMOChunks.MDDI: // ? break; default: Console.WriteLine(string.Format("Found unknown header at offset {1} \"{0}\" while we should've already read them all!", chunkName.ToString("X"), position.ToString())); break; } } } var groupFiles = new WMOGroupFile[wmofile.header.nGroups]; if (wmofile.header.nLod != 0 && (lodLevel + 1) > wmofile.header.nLod) { throw new Exception("Requested LOD (" + lodLevel + ") exceeds the max LOD for this WMO (" + (wmofile.header.nLod - 1) + ")"); } var start = wmofile.header.nGroups * lodLevel; if (wmofile.groupFileDataIDs == null && !string.IsNullOrEmpty(filename)) { for (var i = 0; i < wmofile.header.nGroups; i++) { var groupFilename = filename.Replace(".wmo", "_" + i.ToString().PadLeft(3, '0') + ".wmo"); if (CASC.IsCASCInit && CASC.FileExists(groupFilename)) { var groupFileDataID = CASC.getFileDataIdByName(groupFilename); using (var wmoStream = CASC.OpenFile(groupFileDataID)) { groupFiles[i] = ReadWMOGroupFile(groupFileDataID, wmoStream); } } else { Console.WriteLine("CASC is reporting " + groupFilename + " does not exist!"); } } } else { for (var i = 0; i < wmofile.header.nGroups; i++) { var groupFileDataID = wmofile.groupFileDataIDs[start + i]; if (lodLevel == 3 && groupFileDataID == 0) // if lod is 3 and there's no lod3 available, fall back to lod1 { groupFileDataID = wmofile.groupFileDataIDs[i + (wmofile.header.nGroups * 2)]; } if (lodLevel >= 2 && groupFileDataID == 0) // if lod is 2 or higher and there's no lod2 available, fall back to lod1 { groupFileDataID = wmofile.groupFileDataIDs[i + (wmofile.header.nGroups * 1)]; } if (lodLevel >= 1 && groupFileDataID == 0) // if lod is 1 or higher check if lod1 available, fall back to lod0 { groupFileDataID = wmofile.groupFileDataIDs[i]; } if (CASC.IsCASCInit && CASC.FileExists(groupFileDataID)) { using (var wmoStream = CASC.OpenFile(groupFileDataID)) { groupFiles[i] = ReadWMOGroupFile(groupFileDataID, wmoStream); } } else { //Console.WriteLine("CASC is reporting " + groupFileDataID + " does not exist! This shouldn't happen."); } } } wmofile.group = groupFiles; }