static void ReadMOLT(BinaryReader br, WMORoot wmo) { wmo.LightInfo = new LightInformation[wmo.Header.LightCount]; for (int i = 0; i < wmo.LightInfo.Length; i++) { var light = new LightInformation { Byte_1 = br.ReadByte(), Byte_2 = br.ReadByte(), Byte_3 = br.ReadByte(), Byte_4 = br.ReadByte(), Color = br.ReadColor4(), Position = br.ReadVector3(), Intensity = br.ReadSingle(), AttenStart = br.ReadSingle(), AttenEnd = br.ReadSingle(), Float_4 = br.ReadSingle(), Float_5 = br.ReadSingle(), Float_6 = br.ReadSingle(), Float_7 = br.ReadSingle() }; //FixVector3(ref light.position); wmo.LightInfo[i] = light; } }
static void ReadMODD(BinaryReader br, WMORoot wmo, uint size) { // Why oh why is wmo.Header.DoodadCount wrong sometimes // 40 is the size of DoodadDefinition wmo.DoodadDefinitions = new DoodadDefinition[size / 40]; for (var i = 0; i < wmo.DoodadDefinitions.Length; i++) { var dd = new DoodadDefinition { NameIndex = br.ReadInt32(), Position = br.ReadVector3(), Rotation = br.ReadQuaternion(), Scale = br.ReadSingle(), Color = br.ReadColor4() }; if (dd.NameIndex != -1) { if (!wmo.DoodadFiles.TryGetValue(dd.NameIndex, out dd.FilePath)) { dd.FilePath = ""; log.Error(String.Format("Doodad File Path for index: {0} missing from the Dictionary!", dd.NameIndex)); } } wmo.DoodadDefinitions[i] = dd; } }
static void ReadMFOG(BinaryReader br, WMORoot wmo, uint size) { wmo.Fogs = new Fog[size / 48]; for (int i = 0; i < wmo.Fogs.Length; i++) { var fog = new Fog { Flags = (FogFlags)br.ReadUInt32(), Position = br.ReadVector3(), Start = br.ReadSingle(), End = br.ReadSingle(), FogInfo_FOG = new FogInfo { End = br.ReadSingle(), StartScalar = br.ReadSingle(), Color = br.ReadColor4() }, FogInfo_UWFOG = new FogInfo { End = br.ReadSingle(), StartScalar = br.ReadSingle(), Color = br.ReadColor4() } }; wmo.Fogs[i] = fog; } }
static void ReadMOMT(BinaryReader br, WMORoot wmo) { wmo.Materials = new Material[wmo.Header.TextureCount]; for (int i = 0; i < wmo.Materials.Length; i++) { var mt = new Material { Flags = (MaterialFlags)br.ReadUInt32(), Int_1 = br.ReadUInt32(), BlendMode = br.ReadInt32(), TextureNameStart = br.ReadInt32(), SidnColor = br.ReadColor4(), FrameSidnColor = br.ReadColor4(), TextureNameEnd = br.ReadInt32(), DiffColor = br.ReadColor4(), GroundType = br.ReadInt32(), Float_1 = br.ReadSingle(), Float_2 = br.ReadSingle(), Int_2 = br.ReadInt32(), Int_3 = br.ReadInt32(), Int_4 = br.ReadInt32() }; // these 2 are set in RAM in the client to the associated HTEXTUREs br.ReadUInt32(); // 0x38 br.ReadUInt32(); // 0x3C wmo.Materials[i] = mt; //if (mt.Flags != 0) //Console.WriteLine(); } }
static void ReadMOVV(BinaryReader br, WMORoot wmo, uint size) { wmo.VisibleVertices = new Vector3[size / 12]; // 12 = sizeof(Vector3), but we can't use sizeof with Vector3 for (int i = 0; i < wmo.VisibleVertices.Length; i++) { wmo.VisibleVertices[i] = br.ReadVector3(); } }
static void ReadMCVP(BinaryReader br, WMORoot wmo, uint size) { wmo.ComplexVolumePlanes = new Plane[size / (4 * sizeof(float))]; for (int i = 0; i < wmo.ComplexVolumePlanes.Length; i++) { wmo.ComplexVolumePlanes[i] = br.ReadPlane(); } }
public WMOHolder(WMORoot wmo) { WMO = wmo; var min = wmo.Bounds.Min; var max = wmo.Bounds.Max; var minPoint = new Point(min.X, min.Y); var maxPoint = new Point(max.X, max.Y); Bounds = new Rect(minPoint, maxPoint); }
static void ReadMOPV(BinaryReader br, WMORoot wmo) { // PortalCount of 4 x Vector3 to form a rectangle for the doorway uint vertexCount = wmo.Header.PortalCount * 4; wmo.PortalVertices = new Vector3[vertexCount]; for (var i = 0; i < vertexCount; i++) { wmo.PortalVertices[i] = br.ReadVector3(); } }
static void ReadMOVB(BinaryReader br, WMORoot wmo, uint size) { uint blockCount = size / 4; wmo.VisibleBlocks = new VertexSpan[blockCount]; for (int i = 0; i < blockCount; i++) { wmo.VisibleBlocks[i] = new VertexSpan { StartVertex = br.ReadInt16(), VertexCount = br.ReadInt16() }; } }
static void ReadMOGI(BinaryReader br, WMORoot wmo) { wmo.GroupInformation = new GroupInformation[wmo.Header.GroupCount]; for (int i = 0; i < wmo.GroupInformation.Length; i++) { var g = new GroupInformation { Flags = (WMOGroupFlags)br.ReadUInt32(), BoundingBox = new BoundingBox(br.ReadWMOVector3(), br.ReadWMOVector3()), NameIndex = br.ReadInt32() }; wmo.GroupInformation[i] = g; } }
static void ReadMOPR(BinaryReader br, WMORoot wmo) { wmo.PortalRelations = new PortalRelation[wmo.Header.PortalCount]; for (int i = 0; i < wmo.PortalRelations.Length; i++) { var r = new PortalRelation { PortalIndex = br.ReadUInt16(), GroupIndex = br.ReadUInt16(), Side = br.ReadInt16() }; br.ReadInt16(); // filler wmo.PortalRelations[i] = r; } }
static void ReadMODS(BinaryReader br, WMORoot wmo) { wmo.DoodadSets = new DoodadSet[wmo.Header.DoodadSetCount]; for (int i = 0; i < wmo.Header.DoodadSetCount; i++) { var d = new DoodadSet { SetName = br.ReadFixedString(20), FirstInstanceIndex = br.ReadUInt32(), InstanceCount = br.ReadUInt32() }; br.ReadInt32(); // padding wmo.DoodadSets[i] = d; } }
static void ReadMOGN(BinaryReader br, WMORoot wmo, uint size) { wmo.GroupNames = new Dictionary <int, string>(); long endPos = br.BaseStream.Position + size; while (br.BaseStream.Position < endPos) { if (br.PeekByte() == 0) { br.BaseStream.Position++; } else { wmo.GroupNames.Add((int)(size - (endPos - br.BaseStream.Position)), br.ReadCString()); } } }
/// <summary> /// Gets a WMOGroup from the WMO Group file /// </summary> /// <param name="manager"></param> /// <param name="filePath">File path to the WMOGroup</param> /// <param name="root"></param> /// <param name="groupIndex">Current index in the WMO Group</param> /// <returns>A WMOGroup from the WMO Group file</returns> public static WMOGroup Process(MpqManager manager, string filePath, WMORoot root, int groupIndex) { if (!manager.FileExists(filePath)) { log.Error("WMOGroup file does not exist: ", filePath); } var currentWMOGroup = new WMOGroup(root, groupIndex); using (var stream = manager.OpenFile(filePath)) using (var br = new BinaryReader(stream)) { ReadRequiredChunks(br, currentWMOGroup); ReadOptionalChunks(br, currentWMOGroup); } return currentWMOGroup; }
/// <summary> /// Gets a WMOGroup from the WMO Group file /// </summary> /// <param name="manager"></param> /// <param name="filePath">File path to the WMOGroup</param> /// <param name="root"></param> /// <param name="groupIndex">Current index in the WMO Group</param> /// <returns>A WMOGroup from the WMO Group file</returns> public static WMOGroup Process(MpqManager manager, string filePath, WMORoot root, int groupIndex) { if (!manager.FileExists(filePath)) { log.Error("WMOGroup file does not exist: ", filePath); } var currentWMOGroup = new WMOGroup(root, groupIndex); using (var stream = manager.OpenFile(filePath)) using (var br = new BinaryReader(stream)) { ReadRequiredChunks(br, currentWMOGroup); ReadOptionalChunks(br, currentWMOGroup); } return(currentWMOGroup); }
static void ReadMOPT(BinaryReader br, WMORoot wmo) { wmo.PortalInformation = new PortalInformation[wmo.Header.PortalCount]; for (var i = 0; i < wmo.Header.PortalCount; i++) { var p = new PortalInformation { Vertices = new VertexSpan { StartVertex = br.ReadInt16(), VertexCount = br.ReadInt16(), }, Plane = br.ReadPlane() }; wmo.PortalInformation[i] = p; } }
/// <summary> /// Reads the header for the root file /// </summary> static void ReadMOHD(BinaryReader br, WMORoot wmo) { wmo.Header.TextureCount = br.ReadUInt32(); wmo.Header.GroupCount = br.ReadUInt32(); wmo.Header.PortalCount = br.ReadUInt32(); wmo.Header.LightCount = br.ReadUInt32(); wmo.Header.ModelCount = br.ReadUInt32(); wmo.Header.DoodadCount = br.ReadUInt32(); wmo.Header.DoodadSetCount = br.ReadUInt32(); wmo.Header.AmbientColor = br.ReadColor4(); wmo.Header.WMOId = br.ReadUInt32(); wmo.Header.BoundingBox = new BoundingBox(br.ReadWMOVector3(), br.ReadWMOVector3()); wmo.Header.Flags = (WMORootHeaderFlags)br.ReadUInt32(); wmo.Groups = new WMOGroup[wmo.Header.GroupCount]; }
private static void WriteDoodadDefinitions(BinaryWriter writer, WMORoot root) { var doodadSets = new List<List<int>>(); foreach(var set in root.DoodadSets) { var list = new List<int>((int)set.InstanceCount); for (var i = 0; i < set.InstanceCount; i++) { var idx = set.FirstInstanceIndex + i; var def = root.DoodadDefinitions[idx]; if (def == null) continue; if (TileExtractor.ModelsToIgnore.Contains(def.FilePath)) continue; list.Add((int)idx); } doodadSets.Add(list); } writer.Write(doodadSets.Count); foreach (var doodadSet in doodadSets) { writer.Write(doodadSet.Count); foreach (var defId in doodadSet) { var def = root.DoodadDefinitions[defId]; writer.Write(defId); writer.Write(def.FilePath); writer.Write(def.Position); writer.Write(def.Extents); writer.Write(def.WMOToModel); writer.Write(def.ModelToWMO); } } }
private static void ExtractWMOM2s(WMORoot root) { foreach (var def in root.DoodadDefinitions) { ExtractM2Model(def.FilePath); } }
static void ReadMFOG(BinaryReader br, WMORoot wmo, uint size) { wmo.Fogs = new Fog[size/48]; for (int i = 0; i < wmo.Fogs.Length; i++) { var fog = new Fog { Flags = (FogFlags)br.ReadUInt32(), Position = br.ReadVector3(), Start = br.ReadSingle(), End = br.ReadSingle(), FogInfo_FOG = new FogInfo { End = br.ReadSingle(), StartScalar = br.ReadSingle(), Color = br.ReadColor4() }, FogInfo_UWFOG = new FogInfo { End = br.ReadSingle(), StartScalar = br.ReadSingle(), Color = br.ReadColor4() } }; wmo.Fogs[i] = fog; } }
static void ReadMVER(BinaryReader br, WMORoot wmo) { wmo.Version = br.ReadInt32(); }
public static WMORoot Process(MpqManager mpqManager, string filePath) { var root = new WMORoot(filePath); if (!mpqManager.FileExists(filePath)) { log.Error("WMO file does not exist: ", filePath); } using (var stream = mpqManager.OpenFile(filePath)) using (var fileReader = new BinaryReader(stream)) { uint type = 0; uint size = 0; long curPos = AdvanceToNextChunk(fileReader, 0, ref type, ref size); if (type == Signatures.MVER) { // Version ReadMVER(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MVER"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOHD) { // Root Header ReadMOHD(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOHD"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOTX) { // Texture Names ReadMOTX(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOTX"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOMT) { // Materials ReadMOMT(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOMT"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOGN) { ReadMOGN(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOGN"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOGI) { // Group Information ReadMOGI(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOGI"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOSB) { // Skybox (always 0 now, its no longer handled in WMO) ReadMOSB(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOSB"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOPV) { // Portal Vertices ReadMOPV(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOPV"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOPT) { // Portal Information ReadMOPT(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOPT"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOPR) { // Portal Relations ReadMOPR(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOPR"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOVV) { // Visible Vertices ReadMOVV(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOVV"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOVB) { // Visible Blocks ReadMOVB(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOVB"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOLT) { // Lights ReadMOLT(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOLT"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MODS) { // Doodad Set ReadMODS(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MODS"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MODN) { // Doodad Names ReadMODN(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MODN"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MODD) { // Doodad Definitions ReadMODD(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MODD"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MFOG) { // Fog info ReadMFOG(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MFOG"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); // Theres only 1 optional chunk in a WMO root if (fileReader.BaseStream.Position < fileReader.BaseStream.Length) { if (type == Signatures.MCVP) { ReadMCVP(fileReader, root, size); } //curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); } } return(root); }
static void ReadMOVV(BinaryReader br, WMORoot wmo, uint size) { wmo.VisibleVertices = new Vector3[size/12]; // 12 = sizeof(Vector3), but we can't use sizeof with Vector3 for (int i = 0; i < wmo.VisibleVertices.Length; i++) { wmo.VisibleVertices[i] = br.ReadVector3(); } }
static void ReadMOVB(BinaryReader br, WMORoot wmo, uint size) { uint blockCount = size/4; wmo.VisibleBlocks = new VertexSpan[blockCount]; for (int i = 0; i < blockCount; i++) { wmo.VisibleBlocks[i] = new VertexSpan { StartVertex = br.ReadInt16(), VertexCount = br.ReadInt16() }; } }
static void ReadMOTX(BinaryReader br, WMORoot wmo, uint size) { wmo.Textures = new Dictionary<int, string>(); long endPos = br.BaseStream.Position + size; while (br.BaseStream.Position < endPos) { if (br.PeekByte() == 0) { br.BaseStream.Position++; } else { wmo.Textures.Add((int) (size - (endPos - br.BaseStream.Position)), br.ReadCString()); } } }
static void ReadMOPV(BinaryReader br, WMORoot wmo) { // PortalCount of 4 x Vector3 to form a rectangle for the doorway uint vertexCount = wmo.Header.PortalCount*4; wmo.PortalVertices = new Vector3[vertexCount]; for (var i=0; i<vertexCount; i++) { wmo.PortalVertices[i] = br.ReadVector3(); } }
static void ReadMOGI(BinaryReader br, WMORoot wmo) { wmo.GroupInformation = new GroupInformation[wmo.Header.GroupCount]; for (int i = 0; i < wmo.GroupInformation.Length; i++) { var g = new GroupInformation { Flags = (WMOGroupFlags) br.ReadUInt32(), BoundingBox = new BoundingBox(br.ReadWMOVector3(), br.ReadWMOVector3()), NameIndex = br.ReadInt32() }; wmo.GroupInformation[i] = g; } }
private static void WriteGroups(BinaryWriter writer, WMORoot root) { if (root.GroupInformation == null) return; if (root.Groups == null) return; writer.Write(root.GroupInformation.Length); for (var i = 0; i < root.GroupInformation.Length; i++) { var info = root.GroupInformation[i]; var group = root.Groups[i]; writer.Write((uint)info.Flags); writer.Write(info.BoundingBox); writer.Write(group.Header.WMOGroupId); WriteGroupDoodadRefs(writer, root, group); writer.Write(group.Header.HasMLIQ); if (group.Header.HasMLIQ) { WriteGroupLiquidInfo(writer, group); } writer.Write(group.Vertices); WriteBSPTree(writer, group); } }
static void ReadMODD(BinaryReader br, WMORoot wmo, uint size) { // Why oh why is wmo.Header.DoodadCount wrong sometimes // 40 is the size of DoodadDefinition wmo.DoodadDefinitions = new DoodadDefinition[size / 40]; for (var i = 0; i < wmo.DoodadDefinitions.Length; i++) { var dd = new DoodadDefinition { NameIndex = br.ReadInt32(), Position = br.ReadVector3(), Rotation = br.ReadQuaternion(), Scale = br.ReadSingle(), Color = br.ReadColor4() }; if (dd.NameIndex != -1) { if(!wmo.DoodadFiles.TryGetValue(dd.NameIndex, out dd.FilePath)) { dd.FilePath = ""; log.Error(String.Format("Doodad File Path for index: {0} missing from the Dictionary!", dd.NameIndex)); } } wmo.DoodadDefinitions[i] = dd; } }
/// <summary> /// Constructor /// </summary> /// <param name="root"></param> /// <param name="index">The index into the WMOs GroupList that refers to this WMOGroup.</param> public WMOGroup(WMORoot root, int index) { Root = root; Index = index; }
static void ReadMCVP(BinaryReader br, WMORoot wmo, uint size) { wmo.ComplexVolumePlanes = new Plane[size/(4*sizeof (float))]; for (int i = 0; i < wmo.ComplexVolumePlanes.Length; i++) { wmo.ComplexVolumePlanes[i] = br.ReadPlane(); } }
public static WMORoot Process(MpqManager mpqManager, string filePath) { var root = new WMORoot(filePath); if (!mpqManager.FileExists(filePath)) { log.Error("WMO file does not exist: ", filePath); } using (var stream = mpqManager.OpenFile(filePath)) using (var fileReader = new BinaryReader(stream)) { uint type = 0; uint size = 0; long curPos = AdvanceToNextChunk(fileReader, 0, ref type, ref size); if (type == Signatures.MVER) { // Version ReadMVER(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MVER"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOHD) { // Root Header ReadMOHD(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOHD"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOTX) { // Texture Names ReadMOTX(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOTX"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOMT) { // Materials ReadMOMT(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOMT"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOGN) { ReadMOGN(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOGN"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOGI) { // Group Information ReadMOGI(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOGI"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOSB) { // Skybox (always 0 now, its no longer handled in WMO) ReadMOSB(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOSB"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOPV) { // Portal Vertices ReadMOPV(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOPV"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOPT) { // Portal Information ReadMOPT(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOPT"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOPR) { // Portal Relations ReadMOPR(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOPR"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOVV) { // Visible Vertices ReadMOVV(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOVV"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOVB) { // Visible Blocks ReadMOVB(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MOVB"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MOLT) { // Lights ReadMOLT(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MOLT"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MODS) { // Doodad Set ReadMODS(fileReader, root); } else { Console.WriteLine("WMO Root missing required chunk MODS"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MODN) { // Doodad Names ReadMODN(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MODN"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MODD) { // Doodad Definitions ReadMODD(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MODD"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); if (type == Signatures.MFOG) { // Fog info ReadMFOG(fileReader, root, size); } else { Console.WriteLine("WMO Root missing required chunk MFOG"); } curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); // Theres only 1 optional chunk in a WMO root if (fileReader.BaseStream.Position < fileReader.BaseStream.Length) { if (type == Signatures.MCVP) { ReadMCVP(fileReader, root, size); } //curPos = AdvanceToNextChunk(fileReader, curPos, ref type, ref size); } } return root; }
private static void TransformWMO(MapObjectDefinition currentMODF, WMORoot currentWMO) { currentWMO.ClearCollisionData(); var position = currentMODF.Position; var posX = (position.X - TerrainConstants.CenterPoint) * -1; var posY = (position.Y - TerrainConstants.CenterPoint) * -1; var origin = new Vector3(posX, posY, position.Z); //origin = new Vector3(0.0f); //DrawWMOPositionPoint(origin, currentWMO); //DrawBoundingBox(currentMODF.Extents, Color.Purple, currentWMO); //var rotateZ = Matrix.CreateRotationZ(0*RadiansPerDegree); var rotateZ = Matrix.CreateRotationZ((currentMODF.OrientationB + 180) * RadiansPerDegree); //var rotateX = Matrix.CreateRotationX(currentMODF.OrientationC * RadiansPerDegree); //var rotateY = Matrix.CreateRotationY(currentMODF.OrientationA * RadiansPerDegree); int offset; foreach (var currentGroup in currentWMO.Groups) { if (currentGroup == null) { continue; } //if (!currentGroup.Header.HasMLIQ) continue; var usedTris = new Dictionary <Index3, int>(); var wmoTrisUnique = new List <Index3>(); foreach (var node in currentGroup.BSPNodes) { if (node.TriIndices == null) { continue; } foreach (var index3 in node.TriIndices) { if (usedTris.ContainsKey(index3)) { continue; } usedTris.Add(index3, 0); wmoTrisUnique.Add(index3); } } var newIndices = new Dictionary <int, int>(); foreach (var tri in wmoTrisUnique) { int newIndex; if (!newIndices.TryGetValue(tri.Index0, out newIndex)) { newIndex = currentWMO.WmoVertices.Count; newIndices.Add(tri.Index0, newIndex); var basePosVec = currentGroup.Vertices[tri.Index0]; var rotatedPosVec = Vector3.Transform(basePosVec, rotateZ); var finalPosVector = rotatedPosVec + origin; currentWMO.WmoVertices.Add(finalPosVector); } currentWMO.WmoIndices.Add(newIndex); if (!newIndices.TryGetValue(tri.Index1, out newIndex)) { newIndex = currentWMO.WmoVertices.Count; newIndices.Add(tri.Index1, newIndex); var basePosVec = currentGroup.Vertices[tri.Index1]; var rotatedPosVec = Vector3.Transform(basePosVec, rotateZ); var finalPosVector = rotatedPosVec + origin; currentWMO.WmoVertices.Add(finalPosVector); } currentWMO.WmoIndices.Add(newIndex); if (!newIndices.TryGetValue(tri.Index2, out newIndex)) { newIndex = currentWMO.WmoVertices.Count; newIndices.Add(tri.Index2, newIndex); var basePosVec = currentGroup.Vertices[tri.Index2]; var rotatedPosVec = Vector3.Transform(basePosVec, rotateZ); var finalPosVector = rotatedPosVec + origin; currentWMO.WmoVertices.Add(finalPosVector); } currentWMO.WmoIndices.Add(newIndex); } //for (var i = 0; i < currentGroup.Vertices.Count; i++) //{ // var basePosVector = currentGroup.Vertices[i]; // var rotatedPosVector = Vector3.Transform(basePosVector, rotateZ); // var finalPosVector = rotatedPosVector + origin; // //var baseNormVector = currentGroup.Normals[i]; // //var rotatedNormVector = Vector3.Transform(baseNormVector, rotateZ); // currentWMO.WmoVertices.Add(finalPosVector); //} //for (var index = 0; index < currentGroup.Indices.Count; index++) //{ // currentWMO.WmoIndices.Add(currentGroup.Indices[index].Index0 + offset); // currentWMO.WmoIndices.Add(currentGroup.Indices[index].Index1 + offset); // currentWMO.WmoIndices.Add(currentGroup.Indices[index].Index2 + offset); //} // WMO Liquids if (!currentGroup.Header.HasMLIQ) { continue; } var liqInfo = currentGroup.LiquidInfo; var liqOrigin = liqInfo.BaseCoordinates; offset = currentWMO.WmoVertices.Count; for (var xStep = 0; xStep < liqInfo.XVertexCount; xStep++) { for (var yStep = 0; yStep < liqInfo.YVertexCount; yStep++) { var xPos = liqOrigin.X + xStep * TerrainConstants.UnitSize; var yPos = liqOrigin.Y + yStep * TerrainConstants.UnitSize; var zPosTop = liqInfo.HeightMapMax[xStep, yStep]; var liqVecTop = new Vector3(xPos, yPos, zPosTop); var rotatedTop = Vector3.Transform(liqVecTop, rotateZ); var vecTop = rotatedTop + origin; currentWMO.WmoLiquidVertices.Add(vecTop); } } for (var row = 0; row < liqInfo.XTileCount; row++) { for (var col = 0; col < liqInfo.YTileCount; col++) { if ((liqInfo.LiquidTileFlags[row, col] & 0x0F) == 0x0F) { continue; } var index = ((row + 1) * (liqInfo.YVertexCount) + col); currentWMO.WmoLiquidIndices.Add(offset + index); index = (row * (liqInfo.YVertexCount) + col); currentWMO.WmoLiquidIndices.Add(offset + index); index = (row * (liqInfo.YVertexCount) + col + 1); currentWMO.WmoLiquidIndices.Add(offset + index); index = ((row + 1) * (liqInfo.YVertexCount) + col + 1); currentWMO.WmoLiquidIndices.Add(offset + index); index = ((row + 1) * (liqInfo.YVertexCount) + col); currentWMO.WmoLiquidIndices.Add(offset + index); index = (row * (liqInfo.YVertexCount) + col + 1); currentWMO.WmoLiquidIndices.Add(offset + index); } } } //Rotate the M2s to the new orientation if (currentWMO.WMOM2s != null) { foreach (var currentM2 in currentWMO.WMOM2s) { offset = currentWMO.WmoVertices.Count; for (var i = 0; i < currentM2.Vertices.Count; i++) { var basePosition = currentM2.Vertices[i]; var rotatedPosition = Vector3.Transform(basePosition, rotateZ); var finalPosition = rotatedPosition + origin; //var rotatedNormal = Vector3.Transform(basePosition, rotateZ); currentWMO.WmoM2Vertices.Add(finalPosition); } foreach (var index in currentM2.Indices) { currentWMO.WmoM2Indices.Add(index + offset); } } } }
private static void ExtractWMOGroups(string filePath, WMORoot root) { for (var grpIndex = 0; grpIndex < root.Header.GroupCount; grpIndex++) { var newFile = filePath.Substring(0, filePath.LastIndexOf('.')); var newFilePath = String.Format("{0}_{1:000}.wmo", newFile, grpIndex); var group = WMOGroupParser.Process(WDTExtractor.MpqManager, newFilePath, root, grpIndex); if (group == null) continue; root.Groups[grpIndex] = group; } }
private static void PrepareWMOGroupDoodadReferences(WMORoot root, WMOGroup wmoGroup) { foreach (var dRefId in wmoGroup.DoodadReferences) { var def = root.DoodadDefinitions[dRefId]; if (def == null) continue; if (string.IsNullOrEmpty(def.FilePath)) continue; if (TileExtractor.ModelsToIgnore.Contains(def.FilePath)) continue; // Calculate and store the models' transform matrices Matrix scaleMatrix; Matrix.CreateScale(def.Scale, out scaleMatrix); Matrix rotMatrix; Matrix.CreateFromQuaternion(ref def.Rotation, out rotMatrix); Matrix modelToWMO; Matrix.Multiply(ref scaleMatrix, ref rotMatrix, out modelToWMO); Matrix wmoToModel; Matrix.Invert(ref modelToWMO, out wmoToModel); def.ModelToWMO = modelToWMO; def.WMOToModel = wmoToModel; M2Model model; if (!LoadedM2Models.TryGetValue(def.FilePath, out model)) { log.Error(String.Format("M2Model file: {0} missing from the Dictionary!", def.FilePath)); continue; } // Calculate the wmoSpace bounding box for this model CalculateModelsWMOSpaceBounds(def, model); } }
static void ReadMOMT(BinaryReader br, WMORoot wmo) { wmo.Materials = new Material[wmo.Header.TextureCount]; for (int i = 0; i < wmo.Materials.Length; i++) { var mt = new Material { Flags = (MaterialFlags)br.ReadUInt32(), Int_1 = br.ReadUInt32(), BlendMode = br.ReadInt32(), TextureNameStart = br.ReadInt32(), SidnColor = br.ReadColor4(), FrameSidnColor = br.ReadColor4(), TextureNameEnd = br.ReadInt32(), DiffColor = br.ReadColor4(), GroundType = br.ReadInt32(), Float_1 = br.ReadSingle(), Float_2 = br.ReadSingle(), Int_2 = br.ReadInt32(), Int_3 = br.ReadInt32(), Int_4 = br.ReadInt32() }; // these 2 are set in RAM in the client to the associated HTEXTUREs br.ReadUInt32();// 0x38 br.ReadUInt32();// 0x3C wmo.Materials[i] = mt; //if (mt.Flags != 0) //Console.WriteLine(); } }
private static void WriteGroupDoodadRefs(BinaryWriter writer, WMORoot root, WMOGroup group) { if (group.DoodadReferences.IsNullOrEmpty()) { writer.Write(0); return; } var list = new List<int>(); foreach (var defId in group.DoodadReferences) { var def = root.DoodadDefinitions[defId]; if (def == null) continue; if (TileExtractor.ModelsToIgnore.Contains(def.FilePath)) continue; list.Add(defId); } writer.Write(list); }
static void ReadMOSB(BinaryReader br, WMORoot wmo) { // skyboxes moved to light.dbc }
private static void WriteWMO(BinaryWriter writer, WMORoot root) { if (root == null) { Console.WriteLine("Cannot write null WMORoot to file."); return; } // Magic fileType writer.Write(wmoFileType); writer.Write(root.Header.BoundingBox); writer.Write(root.Header.WMOId); WriteDoodadDefinitions(writer, root); WriteGroups(writer, root); }
private static void TransformWMO(MapObjectDefinition currentMODF, WMORoot currentWMO) { currentWMO.ClearCollisionData(); var position = currentMODF.Position; var posX = (position.X - TerrainConstants.CenterPoint)*-1; var posY = (position.Y - TerrainConstants.CenterPoint)*-1; var origin = new Vector3(posX, posY, position.Z); //origin = new Vector3(0.0f); //DrawWMOPositionPoint(origin, currentWMO); //DrawBoundingBox(currentMODF.Extents, Color.Purple, currentWMO); //var rotateZ = Matrix.CreateRotationZ(0*RadiansPerDegree); var rotateZ = Matrix.CreateRotationZ((currentMODF.OrientationB + 180)*RadiansPerDegree); //var rotateX = Matrix.CreateRotationX(currentMODF.OrientationC * RadiansPerDegree); //var rotateY = Matrix.CreateRotationY(currentMODF.OrientationA * RadiansPerDegree); int offset; foreach (var currentGroup in currentWMO.Groups) { if (currentGroup == null) continue; //if (!currentGroup.Header.HasMLIQ) continue; var usedTris = new Dictionary<Index3, int>(); var wmoTrisUnique = new List<Index3>(); foreach (var node in currentGroup.BSPNodes) { if (node.TriIndices == null) continue; foreach (var index3 in node.TriIndices) { if (usedTris.ContainsKey(index3)) continue; usedTris.Add(index3, 0); wmoTrisUnique.Add(index3); } } var newIndices = new Dictionary<int, int>(); foreach (var tri in wmoTrisUnique) { int newIndex; if (!newIndices.TryGetValue(tri.Index0, out newIndex)) { newIndex = currentWMO.WmoVertices.Count; newIndices.Add(tri.Index0, newIndex); var basePosVec = currentGroup.Vertices[tri.Index0]; var rotatedPosVec = Vector3.Transform(basePosVec, rotateZ); var finalPosVector = rotatedPosVec + origin; currentWMO.WmoVertices.Add(finalPosVector); } currentWMO.WmoIndices.Add(newIndex); if (!newIndices.TryGetValue(tri.Index1, out newIndex)) { newIndex = currentWMO.WmoVertices.Count; newIndices.Add(tri.Index1, newIndex); var basePosVec = currentGroup.Vertices[tri.Index1]; var rotatedPosVec = Vector3.Transform(basePosVec, rotateZ); var finalPosVector = rotatedPosVec + origin; currentWMO.WmoVertices.Add(finalPosVector); } currentWMO.WmoIndices.Add(newIndex); if (!newIndices.TryGetValue(tri.Index2, out newIndex)) { newIndex = currentWMO.WmoVertices.Count; newIndices.Add(tri.Index2, newIndex); var basePosVec = currentGroup.Vertices[tri.Index2]; var rotatedPosVec = Vector3.Transform(basePosVec, rotateZ); var finalPosVector = rotatedPosVec + origin; currentWMO.WmoVertices.Add(finalPosVector); } currentWMO.WmoIndices.Add(newIndex); } //for (var i = 0; i < currentGroup.Vertices.Count; i++) //{ // var basePosVector = currentGroup.Vertices[i]; // var rotatedPosVector = Vector3.Transform(basePosVector, rotateZ); // var finalPosVector = rotatedPosVector + origin; // //var baseNormVector = currentGroup.Normals[i]; // //var rotatedNormVector = Vector3.Transform(baseNormVector, rotateZ); // currentWMO.WmoVertices.Add(finalPosVector); //} //for (var index = 0; index < currentGroup.Indices.Count; index++) //{ // currentWMO.WmoIndices.Add(currentGroup.Indices[index].Index0 + offset); // currentWMO.WmoIndices.Add(currentGroup.Indices[index].Index1 + offset); // currentWMO.WmoIndices.Add(currentGroup.Indices[index].Index2 + offset); //} // WMO Liquids if (!currentGroup.Header.HasMLIQ) continue; var liqInfo = currentGroup.LiquidInfo; var liqOrigin = liqInfo.BaseCoordinates; offset = currentWMO.WmoVertices.Count; for (var xStep = 0; xStep < liqInfo.XVertexCount; xStep++) { for (var yStep = 0; yStep < liqInfo.YVertexCount; yStep++) { var xPos = liqOrigin.X + xStep * TerrainConstants.UnitSize; var yPos = liqOrigin.Y + yStep * TerrainConstants.UnitSize; var zPosTop = liqInfo.HeightMapMax[xStep, yStep]; var liqVecTop = new Vector3(xPos, yPos, zPosTop); var rotatedTop = Vector3.Transform(liqVecTop, rotateZ); var vecTop = rotatedTop + origin; currentWMO.WmoLiquidVertices.Add(vecTop); } } for (var row = 0; row < liqInfo.XTileCount; row++) { for (var col = 0; col < liqInfo.YTileCount; col++) { if ((liqInfo.LiquidTileFlags[row, col] & 0x0F) == 0x0F) continue; var index = ((row + 1)*(liqInfo.YVertexCount) + col); currentWMO.WmoLiquidIndices.Add(offset + index); index = (row*(liqInfo.YVertexCount) + col); currentWMO.WmoLiquidIndices.Add(offset + index); index = (row*(liqInfo.YVertexCount) + col + 1); currentWMO.WmoLiquidIndices.Add(offset + index); index = ((row + 1)*(liqInfo.YVertexCount) + col + 1); currentWMO.WmoLiquidIndices.Add(offset + index); index = ((row + 1)*(liqInfo.YVertexCount) + col); currentWMO.WmoLiquidIndices.Add(offset + index); index = (row*(liqInfo.YVertexCount) + col + 1); currentWMO.WmoLiquidIndices.Add(offset + index); } } } //Rotate the M2s to the new orientation if (currentWMO.WMOM2s != null) { foreach (var currentM2 in currentWMO.WMOM2s) { offset = currentWMO.WmoVertices.Count; for (var i = 0; i < currentM2.Vertices.Count; i++) { var basePosition = currentM2.Vertices[i]; var rotatedPosition = Vector3.Transform(basePosition, rotateZ); var finalPosition = rotatedPosition + origin; //var rotatedNormal = Vector3.Transform(basePosition, rotateZ); currentWMO.WmoM2Vertices.Add(finalPosition); } foreach (var index in currentM2.Indices) { currentWMO.WmoM2Indices.Add(index + offset); } } } }