private static TileModel ExtractModel(MapObjectDefinition wmo, DoodadDefinition definition) { var filePath = definition.FilePath; var m2model = ExtractM2Model(filePath); return(TransformM2Model(wmo, definition, m2model)); }
static void ReadMODF(BinaryReader fileReader, WDT wdt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var endPos = fileReader.BaseStream.Position + size; while (fileReader.BaseStream.Position < endPos) { var objectDef = new MapObjectDefinition(); var nameIndex = fileReader.ReadInt32(); // 4 bytes objectDef.FilePath = wdt.WmoFiles[nameIndex]; objectDef.UniqueId = fileReader.ReadUInt32(); // 4 bytes objectDef.Position = fileReader.ReadVector3(); // 12 bytes objectDef.OrientationA = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationB = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationC = fileReader.ReadSingle(); // 4 Bytes objectDef.Extents = fileReader.ReadBoundingBox(); // 12*2 bytes objectDef.Flags = fileReader.ReadUInt16(); // 2 bytes objectDef.DoodadSetId = fileReader.ReadUInt16(); // 2 bytes objectDef.NameSet = fileReader.ReadUInt16(); // 2 bytes fileReader.ReadUInt16(); // padding wdt.WmoDefinitions.Add(objectDef); } }
public void AddWMO(MapObjectDefinition currentMODF) { if (currentMODF is ExtractedWMODefinition) { Add((ExtractedWMODefinition)currentMODF); } }
private static void ExtractWMOM2s(MapObjectDefinition wmo, WMORoot root, TileModels tileModels) { var setIndices = new List <int> { 0 }; if (wmo.DoodadSet != 0) { setIndices.Add(wmo.DoodadSet); } foreach (var index in setIndices) { var set = root.DoodadSets[index]; for (var k = 0; k < set.InstanceCount; k++) { var dd = root.DoodadDefinitions[(int)set.FirstInstanceIndex + k]; if (string.IsNullOrEmpty(dd.FilePath)) { continue; } var model = ExtractModel(wmo, dd); if (model.Vertices.Length < 1) { continue; } tileModels.Models.Add(model); } } }
public WMORoot GetOrReadWMO(MapObjectDefinition definition) { WMORoot wmo; if (!WMOs.TryGetValue(definition.FilePath, out wmo)) { WMOs.Add(definition.FilePath, wmo = WMOReader.ReadWMO(WCellTerrainSettings.GetDefaultMPQFinder(), definition)); } return(wmo); }
private static void LoadWMO(MpqManager manager, MapObjectDefinition def) { if (LoadedWmoIds.Contains(def.UniqueId)) { return; } LoadedWmoIds.Add(def.UniqueId); if (!WorldObjectExtractor.LoadedWMORoots.ContainsKey(def.FilePath)) { var root = WMORootParser.Process(manager, def.FilePath); WorldObjectExtractor.LoadedWMORoots.Add(def.FilePath, root); } PrepareWMOInfo(def); }
private static TileModel TransformM2Model(MapObjectDefinition wmo, DoodadDefinition definition, M2Model m2model) { var model = new TileModel { Vertices = new Vector3[m2model.BoundingVertices.Length] }; var origin = new Vector3(-definition.Position.X, definition.Position.Z, definition.Position.Y); var wmoOrigin = CorrectWMOOrigin(wmo.Position); var rotation = definition.Rotation; var rotateY = Matrix.CreateRotationY((wmo.OrientationB - 90) * RadiansPerDegree); for (var i = 0; i < m2model.BoundingVertices.Length; i++) { var vector = m2model.BoundingVertices[i]; var rotatedVector = Vector3.Transform(vector, rotation); rotatedVector = TransformToIntermediateCoords(rotatedVector); var finalModelVector = rotatedVector + origin; var rotatedWMOVector = Vector3.Transform(finalModelVector, rotateY); var finalWMOVector = rotatedWMOVector + wmoOrigin; model.Vertices[i] = finalWMOVector; } // Add the triangle indices to the model model.Triangles = new Index3[m2model.BoundingTriangles.Length]; for (var i = 0; i < m2model.BoundingTriangles.Length; i++) { var tri = m2model.BoundingTriangles[i]; model.Triangles[i] = new Index3 { Index0 = (short)tri[2], Index1 = (short)tri[1], Index2 = (short)tri[0] }; } // Calculate the boundingbox model.Bounds = new BoundingBox(model.Vertices); return(model); }
static void ReadMODF(BinaryReader fileReader, ADT adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); long endPos = fileReader.BaseStream.Position + size; while (fileReader.BaseStream.Position < endPos) { var objectDef = new MapObjectDefinition(); int nameIndex = fileReader.ReadInt32(); // 4 bytes objectDef.FilePath = adt.ObjectFiles[nameIndex]; objectDef.UniqueId = fileReader.ReadUInt32(); // 4 bytes // This Position appears to be in the wrong order. // To get WoW coords, read it as: {Y, Z, X} var Y = fileReader.ReadSingle(); var Z = fileReader.ReadSingle(); var X = fileReader.ReadSingle(); objectDef.Position = new Vector3(X, Y, Z); // 12 bytes objectDef.OrientationA = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationB = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationC = fileReader.ReadSingle(); // 4 Bytes var min = new Vector3(); min.Y = fileReader.ReadSingle(); min.Z = fileReader.ReadSingle(); min.X = fileReader.ReadSingle(); var max = new Vector3(); max.Y = fileReader.ReadSingle(); max.Z = fileReader.ReadSingle(); max.X = fileReader.ReadSingle(); objectDef.Extents = new BoundingBox(min, max); // 12*2 bytes objectDef.Flags = fileReader.ReadUInt16(); // 2 bytes objectDef.DoodadSetId = fileReader.ReadUInt16(); // 2 bytes objectDef.NameSet = fileReader.ReadUInt16(); // 2 bytes fileReader.ReadUInt16(); // padding adt.ObjectDefinitions.Add(objectDef); } }
private static void PrepareWMOInfo(MapObjectDefinition def) { TerrainConstants.TilePositionToWorldPosition(ref def.Position); TerrainConstants.TileExtentsToWorldExtents(ref def.Extents); Matrix modelToWorld; Matrix.CreateRotationZ(MathHelper.ToRadians(def.OrientationB + 180), out modelToWorld); Matrix worldToModel; Matrix.Invert(ref modelToWorld, out worldToModel); def.WMOToWorld = modelToWorld; def.WorldToWMO = worldToModel; // Reposition the m2s contained within the wmos //WMORoot root; //if (!LoadedWmoRoots.TryGetValue(def.FilePath, out root)) //{ // log.Error(String.Format("WMORoot file: {0} missing from the Dictionary!", def.FilePath)); // continue; //} //var setIndices = new List<int> { 0 }; //if (def.DoodadSet > 0) setIndices.Add(def.DoodadSet); //foreach (var index in setIndices) //{ // var doodadSet = root.DoodadSets[index]; // for (var i = 0; i < doodadSet.InstanceCount; i++) // { // var dDef = root.DoodadDefinitions[doodadSet.FirstInstanceIndex + i]; // if (string.IsNullOrEmpty(dDef.FilePath)) continue; // M2Model model; // if (!LoadedM2Models.TryGetValue(dDef.FilePath, out model)) // { // log.Error(String.Format("M2Model file: {0} missing from the Dictionary!", dDef.FilePath)); // continue; // } // // Calculate and store the models' transform matrices // Matrix scaleMatrix; // Matrix.CreateScale(dDef.Scale, out scaleMatrix); // Matrix rotMatrix; // Matrix.CreateFromQuaternion(ref dDef.Rotation, out rotMatrix); // Matrix modelToWMO; // Matrix.Multiply(ref scaleMatrix, ref rotMatrix, out modelToWMO); // Matrix wmoToModel; // Matrix.Invert(ref modelToWMO, out wmoToModel); // dDef.ModelToWMO = modelToWMO; // dDef.WMOToModel = wmoToModel; // // Calculate the wmoSpace bounding box for this model // var wmoSpaceVecs = new List<Vector3>(model.BoundingVertices.Length); // for (var j = 0; j < model.BoundingVertices.Length; j++) // { // Vector3 rotated; // Vector3.Transform(ref model.BoundingVertices[i], ref modelToWMO, out rotated); // Vector3 final; // Vector3.Add(ref rotated, ref dDef.Position, out final); // wmoSpaceVecs.Add(final); // } // dDef.Extents = new BoundingBox(wmoSpaceVecs.ToArray()); // def.M2Refs.Add(dDef); // } //} }
private static void LoadWMO(MpqManager manager, MapObjectDefinition def) { if (LoadedWmoIds.Contains(def.UniqueId)) return; LoadedWmoIds.Add(def.UniqueId); if (!WorldObjectExtractor.LoadedWMORoots.ContainsKey(def.FilePath)) { var root = WMORootParser.Process(manager, def.FilePath); WorldObjectExtractor.LoadedWMORoots.Add(def.FilePath, root); } PrepareWMOInfo(def); }
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) * MathUtil.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 HashSet <Index3>(); var wmoTrisUnique = new List <Index3>(); foreach (var node in currentGroup.BSPNodes) { if (node.TriIndices == null) { continue; } foreach (var triangle in node.TriIndices) { if (usedTris.Contains(triangle)) { continue; } usedTris.Add(triangle); wmoTrisUnique.Add(triangle); } } var newIndices = new Dictionary <int, int>(); foreach (var tri in wmoTrisUnique) { // add all vertices, uniquely 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.WmoLiquidVertices.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.WmoM2Vertices.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); } } } }
/// <summary> /// Adds a WMO to the manager /// </summary> public static WMORoot ReadWMO(MpqLibrarian librarian, MapObjectDefinition currentMODF) { // Parse the WMORoot var wmoRoot = WMOReader.ReadWMO(librarian, currentMODF.FilePath); // Parse the WMOGroups for (var wmoGroup = 0; wmoGroup < wmoRoot.Header.GroupCount; wmoGroup++) { var newFile = wmoRoot.FilePath.Substring(0, wmoRoot.FilePath.LastIndexOf('.')); var currentFilePath = String.Format("{0}_{1:000}.wmo", newFile, wmoGroup); var group = WMOGroupReader.Process(librarian, currentFilePath, wmoRoot, wmoGroup); wmoRoot.Groups[wmoGroup] = group; } //wmoRoot.DumpLiqChunks(); // Parse in the WMO's M2s var curDoodadSet = currentMODF.DoodadSetId; var setIndices = new List <int> { 0 }; if (curDoodadSet > 0) { setIndices.Add(curDoodadSet); } var setDefs = new List <DoodadSet>(setIndices.Count); foreach (var index in setIndices) { if (index >= wmoRoot.DoodadSets.Length) { log.Error("Invalid index {0} into wmoRoot.DoodadSet array with id", index, curDoodadSet); continue; } setDefs.Add(wmoRoot.DoodadSets[index]); } var m2List = new List <M2>(); foreach (var def in setDefs) { var doodadSetOffset = def.FirstInstanceIndex; var doodadSetCount = def.InstanceCount; for (var i = doodadSetOffset; i < (doodadSetOffset + doodadSetCount); i++) { var curDoodadDef = wmoRoot.DoodadDefinitions[i]; if (string.IsNullOrEmpty(curDoodadDef.FilePath)) { log.Error("Encountered Doodad with empty file path"); continue; } var curM2 = M2Reader.ReadM2(librarian, curDoodadDef.FilePath, true); var tempIndices = new List <int>(); for (var j = 0; j < curM2.BoundingTriangles.Length; j++) { var tri = curM2.BoundingTriangles[j]; tempIndices.Add(tri.Index2); tempIndices.Add(tri.Index1); tempIndices.Add(tri.Index0); } var rotatedM2 = TransformWMOM2(curM2, tempIndices, curDoodadDef); m2List.Add(rotatedM2); } } wmoRoot.WMOM2s = m2List.ToArray(); TransformWMO(currentMODF, wmoRoot); var bounds = new BoundingBox(wmoRoot.WmoVertices); wmoRoot.Bounds = bounds; return(wmoRoot); }
/// <summary> /// Adds a WMO to the manager /// </summary> /// <param name="currentMODF">MODF (placement information for this WMO)</param> public void AddWMO(MapObjectDefinition currentMODF) { _fileNames.Add(currentMODF.FilePath); // Parse the WMORoot var wmoRoot = WMORootParser.Process(MpqTerrainManager.MpqManager, currentMODF.FilePath); // Parse the WMOGroups for (var wmoGroup = 0; wmoGroup < wmoRoot.Header.GroupCount; wmoGroup++) { var newFile = wmoRoot.FilePath.Substring(0, wmoRoot.FilePath.LastIndexOf('.')); var currentFilePath = String.Format("{0}_{1:000}.wmo", newFile, wmoGroup); var group = WMOGroupParser.Process(MpqTerrainManager.MpqManager, currentFilePath, wmoRoot, wmoGroup); wmoRoot.Groups[wmoGroup] = group; } //wmoRoot.DumpLiqChunks(); // Parse in the WMO's M2s var curDoodadSet = currentMODF.DoodadSetId; var setIndices = new List <int> { 0 }; if (curDoodadSet > 0) { setIndices.Add(curDoodadSet); } foreach (var index in setIndices) { var doodadSetOffset = wmoRoot.DoodadSets[index].FirstInstanceIndex; var doodadSetCount = wmoRoot.DoodadSets[index].InstanceCount; wmoRoot.WMOM2s = new List <M2.M2>((int)doodadSetCount); for (var i = doodadSetOffset; i < (doodadSetOffset + doodadSetCount); i++) { var curDoodadDef = wmoRoot.DoodadDefinitions[i]; var curM2 = M2ModelParser.Process(MpqTerrainManager.MpqManager, curDoodadDef.FilePath); var tempIndices = new List <int>(); for (var j = 0; j < curM2.BoundingTriangles.Length; j++) { var tri = curM2.BoundingTriangles[j]; tempIndices.Add(tri.Index2); tempIndices.Add(tri.Index1); tempIndices.Add(tri.Index0); } var rotatedM2 = TransformWMOM2(curM2, tempIndices, curDoodadDef); wmoRoot.WMOM2s.Add(rotatedM2); } } TransformWMO(currentMODF, wmoRoot); var bounds = new BoundingBox(wmoRoot.WmoVertices); wmoRoot.Bounds = bounds; WMOs.Add(wmoRoot); }
static void ReadMODF(BinaryReader fileReader, ADTFile adt) { var type = fileReader.ReadUInt32(); var size = fileReader.ReadUInt32(); var endPos = fileReader.BaseStream.Position + size; while (fileReader.BaseStream.Position < endPos) { var objectDef = new MapObjectDefinition(); var nameIndex = fileReader.ReadInt32(); // 4 bytes objectDef.FileName = adt.ObjectFiles[nameIndex]; objectDef.UniqueId = fileReader.ReadUInt32(); // 4 bytes objectDef.Position = fileReader.ReadVector3(); // 12 bytes objectDef.OrientationA = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationB = fileReader.ReadSingle(); // 4 Bytes objectDef.OrientationC = fileReader.ReadSingle(); // 4 Bytes objectDef.Extents = fileReader.ReadBoundingBox(); // 12*2 bytes objectDef.Flags = fileReader.ReadUInt16(); // 2 bytes objectDef.DoodadSet = fileReader.ReadUInt16(); // 2 bytes objectDef.NameSet = fileReader.ReadUInt16(); // 2 bytes fileReader.ReadUInt16(); // padding adt.ObjectDefinitions.Add(objectDef); } }