private bool LoadTile(int tileX, int tileY) { if (!WDT.HasTile(tileX, tileY)) { return(false); } if (IsTileLoaded(tileX, tileY)) { return(false); } // Generate tile var tile = new ADT(Continent, tileX, tileY, WDT); tile.Read(); tile.Generate(); // Generate renderer var renderer = new ADTRenderer(Controller, tile); renderer.Generate(); renderer.Bind(Controller.Shader); ADTRenderer.Renderers.Add(renderer); return(true); }
public void LoadTileData() { s_Geometry = new Geometry.Geometry(); // First read target tile to verify we have geometry and get bounding box // Read tile s_Tile.Read(); // Generate relevant geometry s_Tile.Generate(); // Append to our geometry s_Geometry.AddADT(s_Tile, false); // Generate the bounding box for the tile // (Because we need to cut the surrounding tiles later) Bounds = Geometry.Geometry.GetBoundingBox(X, Y, s_Geometry.Vertices); // We need to load the surrounding tiles because there sometimes is overlap in geometry to and from different tiles for (var y = Y - 1; y <= Y + 1; y++) { for (var x = X - 1; y <= X + 1; y++) { // Skip target tile as we already added it if (X == x && Y == y) { continue; } // Add a surrounding tile var tile = new ADT(World, x, y); tile.Read(); tile.Generate(); s_Geometry.AddADT(tile, false); } } }
public void Build() { var geo = new Geometry.Geometry(); Source.Read(); geo.AddADT(Source); }
public void TestGameAdt() { MpqManager.Initialize("S:\\WoW"); var test = new ADT("World\\maps\\Northrend\\Northrend_43_29.adt"); test.Read(); Assert.AreEqual(test.MapChunks.Length, 16 * 16); Assert.IsNotNull(test.DoodadHandler.Vertices); Assert.IsNotNull(test.DoodadHandler.Triangles); }
public static ADT GetAdt(string world, int x, int y) { //if (Cache.Adt.TryGetValue(new Tuple<int, int>(x, y), out adt)) // return adt; ADT adt = new ADT(GetAdtPath(world, x, y)); if (adt.HasObjectData) { adt.Read(); } //Cache.Adt.Add(new Tuple<int, int>(x, y), adt); return(adt); }
public static ADT GetAdt(string world, int x, int y) { ADT adt = null; if (Cache.Adt.TryGetValue(new Tuple <int, int>(x, y), out adt)) { return(adt); } adt = new ADT(GetAdtPath(world, x, y)); adt.Read(); Cache.Adt.Add(new Tuple <int, int>(x, y), adt); return(adt); }
static void ReadADT() { //var adt = new ADT("Azeroth", 28, 28); //var adt = new ADT("Kalimdor", 32, 36); var adt = new ADT("PvPZone01", 32, 30); adt.Read(); var geom = new Geometry(); geom.AddADT(adt); geom.SaveWavefrontObject(Path.GetFileNameWithoutExtension(adt.Filename) + ".obj"); }
static void CreateNavmesh() { var geom = new Geometry(); var sw = Stopwatch.StartNew(); var adt = new ADT("Azeroth", 28, 28); adt.Read(); sw.Stop(); Console.WriteLine("Read ADT in {0}", sw.Elapsed); geom.AddADT(adt); sw.Restart(); var bbox = Geometry.GetBoundingBox(28, 28, geom.Vertices); var build = geom.GenerateNavmesh(bbox); sw.Stop(); Console.WriteLine("Generated navmesh in {0}", sw.Elapsed); TestNavmesh(new SharpNav.TiledNavMesh(build)); }
static void ReadADTs() { const string continent = "Azeroth"; var allGeom = new Geometry(); var sw = new Stopwatch(); for (int y = 27; y < 29; y++) { for (int x = 28; x < 30; x++) { Console.Write("Parsing {0} [{1}, {2}]", continent, x, y); sw.Start(); var adt = new ADT(continent, x, y); adt.Read(); sw.Reset(); Console.WriteLine(" (done! {0}ms)", sw.ElapsedMilliseconds); allGeom.AddADT(adt); } } allGeom.SaveWavefrontObject(continent + ".obj"); }
protected override void LoadContent() { _adt = new ADT(_path); _adt.Read(); _terrain = new GeometryDrawer(); _terrain.Initialize(Game, Color.Green, _adt.MapChunks.Select(mc => mc.Vertices), _adt.MapChunks.Select(mc => mc.Triangles)); var firstVert = _adt.MapChunks[0].Vertices[0]; meshDisplay.Game.Camera.Camera.Position = new Vector3(firstVert.Y, firstVert.Z, firstVert.X); if (_adt.DoodadHandler.Triangles != null) { _doodads = new GeometryDrawer(); _doodads.Initialize(Game, Color.Yellow, _adt.DoodadHandler.Vertices, _adt.DoodadHandler.Triangles); } if (_adt.WorldModelHandler.Triangles != null) { _wmos = new GeometryDrawer(); _wmos.Initialize(Game, Color.Red, _adt.WorldModelHandler.Vertices, _adt.WorldModelHandler.Triangles); } if (_adt.LiquidHandler.Triangles != null) { _liquid = new GeometryDrawer(); _liquid.Initialize(Game, Color.Blue, _adt.LiquidHandler.Vertices, _adt.LiquidHandler.Triangles); } _effect = new BasicEffect(GraphicsDevice); _depthState = new DepthStencilState { DepthBufferEnable = true }; }
public byte[] Build(BaseLog log) { Log = log; Geometry = new Geometry { Transform = true }; { var main = new ADT(GetAdtPath(World, X, Y)); main.Read(); Geometry.AddAdt(main); } if (Geometry.Vertices.Count == 0 && Geometry.Triangles.Count == 0) { throw new InvalidOperationException("Can't build tile with empty geometry"); } float[] bbMin, bbMax; CalculateTileBounds(out bbMin, out bbMax); Geometry.CalculateMinMaxHeight(out bbMin[1], out bbMax[1]); // again, we load everything - wasteful but who cares for (int ty = Y - 1; ty <= Y + 1; ty++) { for (int tx = X - 1; tx <= X + 1; tx++) { try { // don't load main tile again if (tx == X && ty == Y) { continue; } var adt = new ADT(GetAdtPath(World, tx, ty)); adt.Read(); Geometry.AddAdt(adt); } catch (FileNotFoundException) { // don't care - no file means no geometry } } } Context = new RecastContext(); Context.SetContextHandler(Log); // get raw geometry - lots of slowness here float[] vertices; int[] triangles; byte[] areas; Geometry.GetRawData(out vertices, out triangles, out areas); Geometry.Triangles.Clear(); Geometry.Vertices.Clear(); // add border bbMin[0] -= Config.BorderSize * Config.CellSize; bbMin[2] -= Config.BorderSize * Config.CellSize; bbMax[0] += Config.BorderSize * Config.CellSize; bbMax[2] += Config.BorderSize * Config.CellSize; Heightfield hf; int width = Config.TileWidth + (Config.BorderSize * 2); if (!Context.CreateHeightfield(out hf, width, width, bbMin, bbMax, Config.CellSize, Config.CellHeight)) { throw new OutOfMemoryException("CreateHeightfield ran out of memory"); } Context.ClearUnwalkableTriangles(Config.WalkableSlopeAngle, ref vertices, ref triangles, areas); Context.RasterizeTriangles(ref vertices, ref triangles, ref areas, hf, Config.WalkableClimb); // Once all geometry is rasterized, we do initial pass of filtering to // remove unwanted overhangs caused by the conservative rasterization // as well as filter spans where the character cannot possibly stand. Context.FilterLowHangingWalkableObstacles(Config.WalkableClimb, hf); Context.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb, hf); Context.FilterWalkableLowHeightSpans(Config.WalkableHeight, hf); // Compact the heightfield so that it is faster to handle from now on. // This will result in more cache coherent data as well as the neighbours // between walkable cells will be calculated. CompactHeightfield chf; if (!Context.BuildCompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, hf, out chf)) { throw new OutOfMemoryException("BuildCompactHeightfield ran out of memory"); } hf.Delete(); // Erode the walkable area by agent radius. if (!Context.ErodeWalkableArea(Config.WalkableRadius, chf)) { throw new OutOfMemoryException("ErodeWalkableArea ran out of memory"); } // Prepare for region partitioning, by calculating distance field along the walkable surface. if (!Context.BuildDistanceField(chf)) { throw new OutOfMemoryException("BuildDistanceField ran out of memory"); } // Partition the walkable surface into simple regions without holes. if (!Context.BuildRegions(chf, Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea)) { throw new OutOfMemoryException("BuildRegionsMonotone ran out of memory"); } // Create contours. ContourSet cset; if (!Context.BuildContours(chf, Config.MaxSimplificationError, Config.MaxEdgeLength, out cset)) { throw new OutOfMemoryException("BuildContours ran out of memory"); } // Build polygon navmesh from the contours. PolyMesh pmesh; if (!Context.BuildPolyMesh(cset, Config.MaxVertsPerPoly, out pmesh)) { throw new OutOfMemoryException("BuildPolyMesh ran out of memory"); } // Build detail mesh. PolyMeshDetail dmesh; if ( !Context.BuildPolyMeshDetail(pmesh, chf, Config.DetailSampleDistance, Config.DetailSampleMaxError, out dmesh)) { throw new OutOfMemoryException("BuildPolyMeshDetail ran out of memory"); } chf.Delete(); cset.Delete(); // Remove padding from the polymesh data. (Remove this odditity) pmesh.RemovePadding(Config.BorderSize); // Set flags according to area types (e.g. Swim for Water) pmesh.MarkAll(); // get original bounds float[] tilebMin, tilebMax; CalculateTileBounds(out tilebMin, out tilebMax); tilebMin[1] = bbMin[1]; tilebMax[1] = bbMax[1]; // build off mesh connections for flightmasters // bMax and bMin are switched here because of the coordinate system transformation var taxis = TaxiHelper.GetNodesInBBox(MapId, tilebMax.ToWoW(), tilebMin.ToWoW()); var connections = new List <OffMeshConnection>(); foreach (var taxi in taxis) { Log.Log(LogCategory.Warning, "Flightmaster \"" + taxi.Name + "\", Id: " + taxi.Id + " Horde: " + taxi.IsHorde + " Alliance: " + taxi.IsAlliance); var data = TaxiHelper.GetTaxiData(taxi); var from = taxi.Location.ToRecast().ToFloatArray(); connections.AddRange(data.To.Select(to => new OffMeshConnection { AreaId = PolyArea.Road, Flags = PolyFlag.FlightMaster, From = from, To = to.Value.Location.ToRecast().ToFloatArray(), Radius = Config.WorldWalkableRadius, Type = ConnectionType.OneWay, UserID = (uint)to.Key })); foreach (var target in data.To) { Log.Log(LogCategory.Warning, "\tPath to: \"" + target.Value.Name + "\" Id: " + target.Value.Id + " Path Id: " + target.Key); } } byte[] tileData; if (!Detour.CreateNavMeshData(out tileData, pmesh, dmesh, X, Y, tilebMin, tilebMax, Config.WorldWalkableHeight, Config.WorldWalkableRadius, Config.WorldWalkableClimb, Config.CellSize, Config.CellHeight, Config.TileWidth, connections.ToArray())) { pmesh.Delete(); dmesh.Delete(); return(null); } pmesh.Delete(); dmesh.Delete(); Cache.Clear(); GC.Collect(); return(tileData); }