private static void PrepareM2Info(MapDoodadDefinition def, M2Model model) { TerrainConstants.TilePositionToWorldPosition(ref def.Position); Matrix scaleMatrix; Matrix.CreateScale(def.Scale, out scaleMatrix); var rotateZ = Matrix.CreateRotationZ(MathHelper.ToRadians(def.OrientationB + 180)); var rotateY = Matrix.CreateRotationY(MathHelper.ToRadians(def.OrientationA)); var rotateX = Matrix.CreateRotationX(MathHelper.ToRadians(def.OrientationC)); var modelToWorld = Matrix.Multiply(scaleMatrix, rotateZ); modelToWorld = Matrix.Multiply(modelToWorld, rotateX); modelToWorld = Matrix.Multiply(modelToWorld, rotateY); def.ModelToWorld = modelToWorld; Matrix worldToModel; Matrix.Invert(ref modelToWorld, out worldToModel); def.WorldToModel = worldToModel; CalculateModelBounds(def, model); }
/// <summary> /// Writes all height maps to the default MapDir /// </summary> public static void ExportMapTiles(WDT wdt) { // Map data should only be stored per map ClearObjectData(); var path = Path.Combine(TerrainDisplayConfig.MapDir, wdt.Entry.Id.ToString()); if (wdt.IsWMOOnly) { // This Map has no Tiles, but the MODF still needs to be written // These maps will be considered to have one tile at {0, 0} with only one MODF written therein var adt = ExtractWMOOnly(wdt); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } using (var file = File.Create(Path.Combine(path, TerrainConstants.GetMapFilename(0, 0)))) { WriteTileInfo(file, adt); } return; } // Read in the ADT data - this includes height and liquid maps, WMO information and M2 information TerrainInfo = ExtractMapTiles(wdt); // Write the processed data to files var count = 0; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } for (var tileX = 0; tileX < TerrainConstants.TilesPerMapSide; tileX++) { for (var tileY = 0; tileY < TerrainConstants.TilesPerMapSide; tileY++) { var adt = TerrainInfo[tileY, tileX]; if (adt == null) { continue; } var filePath = Path.Combine(path, TerrainConstants.GetMapFilename(tileX, tileY)); using (var file = File.Create(filePath)) { WriteTileInfo(file, adt); file.Close(); } count++; } } log.Info("Extracted {0} tiles for {1}.", count, wdt.Entry.Id); }
public static void WriteM2Files() { log.Info("Extracting partial M2 world objects - This might take a few minutes....."); var startTime = DateTime.Now; var wowRootDir = ToolConfig.Instance.GetWoWDir(); var outputDir = ToolConfig.M2Dir; manager = new MpqManager(wowRootDir); var entryList = DBCMapReader.GetMapEntries(); if (entryList == null) { log.Error("Could not retrieve MapEntries."); return; } foreach (var mapEntry in entryList) { //if (mapEntry.Id != (int)MapId.EasternKingdoms) continue; var dir = mapEntry.MapDirName; var wdtDir = Path.Combine(baseDir, dir); var wdtName = dir; var wdt = WDTParser.Process(manager, wdtDir, wdtName); if (wdt == null) { continue; } var regionM2s = ExtractRegionM2s(wdt); var count = 0; var max = regionM2s.HasTiles ? TerrainConstants.TilesPerMapSide : 1; for (var tileY = 0; tileY < max; tileY++) { for (var tileX = 0; tileX < max; tileX++) { //if (tileX != 36) continue; //if (tileY != 49) continue; if (regionM2s.ObjectsByTile[tileX, tileY] == null) { continue; } // Don't bother writing tiles with no models. var tileModels = regionM2s.ObjectsByTile[tileX, tileY]; if (tileModels.Models.Count == 0) { continue; } var path = Path.Combine(outputDir, mapEntry.Id.ToString()); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var file = File.Create(Path.Combine(path, TerrainConstants.GetM2File(tileX, tileY))); WriteTileM2s(file, tileModels); count++; file.Close(); } } log.Info(count); } log.Info("Done ({0})", DateTime.Now - startTime); }
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); // } //} }
public static string GetInputMeshFile(MapId map, int tileX, int tileY) { var tileName = TerrainConstants.GetTileName(tileX, tileY); return(WCellTerrainSettings.RecastInputMeshFolder + (int)map + "/" + tileName + RecastAPI.InputMeshExtension); }
/// <summary> /// Builds the mesh for a single tile. /// NOTE: This sets the Terrain's NavMesh property. /// In order to move between tiles, we need to generate one mesh for the entire map /// </summary> public void BuildMesh(TerrainTile tile) { // let recast build the navmesh and then call our callback var inputFile = GetInputMeshFile(tile.Terrain.MapId, tile.TileX, tile.TileY); var navMeshFile = GetNavMeshFile(tile.Terrain.MapId, tile.TileX, tile.TileY); var exists = DoesNavMeshExist(tile.Terrain.MapId, tile.TileX, tile.TileY); if (!exists) { var directory = new FileInfo(inputFile).Directory; if (directory != null) { Directory.CreateDirectory(directory.FullName); } directory = new FileInfo(navMeshFile).Directory; if (directory != null) { Directory.CreateDirectory(directory.FullName); } // export input mesh to file ExportRecastInputMesh(tile, inputFile); Console.WriteLine("Building new NavMesh..."); } var start = DateTime.Now; var result = RecastAPI.BuildMesh( GenerateTileId(tile), inputFile, navMeshFile, SmashMeshDlgt); if (result == 0) { throw new Exception("Could not build mesh for tile " + TerrainConstants.GetTileName(tile.TileX, tile.TileY) + " in map " + Terrain.MapId); } if (!exists) { Console.WriteLine("Done in {0:0.000}s", (DateTime.Now - start).TotalSeconds); } //// move all vertices above the surface //var mesh = tile.Terrain.NavMesh; //for (var i = 0; i < mesh.Vertices.Length; i++) //{ // var vert = mesh.Vertices[i]; // vert.Z += 0.001f; // var ray = new Ray(vert, Vector3.Down); // see if vertex is above surface // var hit = tile.FindFirstHitTriangle(ray); // if (hit == -1) // { // vert.Z -= 0.001f; // // vertex is below surface // ray = new Ray(vert, Vector3.Up); // find surface right above mesh // hit = tile.FindFirstHitTriangle(ray); // if (hit != -1) // { // // set vertex height equal to terrain // var tri = tile.GetTriangle(hit); // var plane = new Plane(tri.Point1, tri.Point2, tri.Point3); // Intersection.LineSegmentIntersectsPlane(ray.Position, ray.Direction, plane, out mesh.Vertices[i]); // } // } //} }
/// <summary> /// The filename of extracted heightfields /// </summary> public static string GetFileName(MapId map, int tileX, int tileY) { var path = GetMapDirectory(map); return(Path.Combine(path, TerrainConstants.GetTileName(tileX, tileY) + FileExtension)); }