public LiquidChunk(ADT adt, Chunk chunk) { Chunk = chunk; ADT = adt; Read(); }
public void Read(ADT combinedFile) { foreach (var subChunk in Data.Chunks) { switch (subChunk.Name) { case "MVER": combinedFile.MVER = new MVER(subChunk); break; case "MAMP": combinedFile.MAMP = new MAMP(subChunk); break; // case "MFBO": // combinedFile.MFBO = new MFBO(subChunk); // break; case "MHDR": combinedFile.MHDR = new MHDR(subChunk); break; case "MH2O": combinedFile.Liquid = new LiquidChunk(combinedFile, subChunk); break; case "MCNK": combinedFile.AddMapChunk(subChunk); break; default: Console.WriteLine($"Unhandled {subChunk.Name} chunk in model ADT."); break; } } }
public LiquidChunk(ADT adt, Chunk chunk) { ADT = adt; Chunk = chunk; Read(); }
public void Read() { if (Type == ADTType.Normal) { ADTObjects = new ADT(World, X, Y, ADTType.Objects); ADTObjects.Read(); //ADTTextures = new ADT(World, X, Y, ADTType.Textures); //ADTTextures.Read(); } MapChunks = new MapChunk[16 * 16]; int mcIdx = 0; foreach (var subChunk in Data.Chunks) { switch (subChunk.Name) { case "MHDR": MHDR = new MHDR(subChunk); break; case "MMDX": MMDX = new MMDX(subChunk); break; case "MMID": MMID = new MMID(subChunk); ReadDoodads(); break; case "MWMO": MWMO = new MWMO(subChunk); break; case "MWID": MWID = new MWID(subChunk); ReadModels(); break; case "MDDF": MDDF = new MDDF(subChunk); break; case "MODF": MODF = new MODF(subChunk); break; case "MH2O": Liquid = new LiquidChunk(this, subChunk); break; case "MCNK": MapChunks[mcIdx++] = new MapChunk(this, subChunk); break; } } }
public WMORoot(string filename, ADT adt = null) { Filename = filename; ADT = adt; Data = new ChunkData(filename); Read(); }
static void ReadADT() { var adt = new ADT("Azeroth", 32, 48); //var adt = new ADT("Kalimdor", 32, 36); adt.Read(); var geom = new Geometry(); geom.Transform = true; geom.AddADT(adt); geom.SaveWavefrontObject(Path.GetFileNameWithoutExtension(adt.Filename) + ".obj"); WoWMap.Builders.ContinentBuilder b = new WoWMap.Builders.ContinentBuilder("Azeroth", 32, 48,1,1); b.Build(); }
public MapChunk(ADT adt, Chunk chunk, bool isObj0 = false) { ADT = adt; Chunk = chunk; MCNK = new MCNK(chunk); Holes = MCNK.Flags.HasFlag(MCNK.MCNKFlags.HighResolutionHoles) ? HighResHoles : TransformToHighRes(MCNK.Holes); var stream = chunk.GetStream(); stream.Seek(chunk.Offset + MCNK.ChunkHeaderSize, SeekOrigin.Begin); Read(new ChunkData(stream, chunk.Size - MCNK.ChunkHeaderSize)); }
public void AddADT(ADT source) { foreach (var s in new ADT[] { source, source.ADTObjects, /* source.ADTTextures */ }) { foreach (var mc in s.MapChunks) { if (mc.Vertices != null && mc.Vertices.Count() > 0 && mc.Indices != null && mc.Indices.Count > 0) AddGeometry(mc.Vertices, mc.Indices); if (mc.WMOVertices != null && mc.WMOVertices.Count > 0 && mc.WMOIndices != null && mc.WMOIndices.Count > 0) AddGeometry(mc.WMOVertices, mc.WMOIndices); if (mc.DoodadVertices != null && mc.DoodadVertices.Count > 0 && mc.DoodadIndices != null && mc.DoodadIndices.Count > 0) AddGeometry(mc.DoodadVertices, mc.DoodadIndices); } if (s.Liquid != null && s.Liquid.Vertices != null && s.Liquid.Indices != null) AddGeometry(source.Liquid.Vertices, source.Liquid.Indices); } }
public MapChunk(ADT adt, Chunk chunk, bool isObj0 = false) { ADT = adt; Chunk = chunk; var stream = chunk.GetStream(); if (adt.Type == ADTType.Normal) { MCNK = new MCNK(chunk); Holes = MCNK.Flags.HasFlag(MCNK.MCNKFlags.HighResolutionHoles) ? HighResHoles : TransformToHighRes(MCNK.Holes); stream.Seek(chunk.Offset + MCNK.ChunkHeaderSize, SeekOrigin.Begin); SubData = new ChunkData(stream, chunk.Size - MCNK.ChunkHeaderSize); } else SubData = new ChunkData(stream, chunk.Size); Read(); }
public void Read(ADT combinedFile) { var mcnkIdx = 0; foreach (var subChunk in Data.Chunks) { switch (subChunk.Name) { case "MMDX": combinedFile.MMDX = new MMDX(subChunk); break; case "MMID": combinedFile.MMID = new MMID(subChunk); break; case "MWMO": combinedFile.MWMO = new MWMO(subChunk); break; case "MWID": combinedFile.MWID = new MWID(subChunk); break; case "MDDF": combinedFile.MDDF = new MDDF(subChunk); break; case "MODF": combinedFile.MODF = new MODF(subChunk); break; case "MCNK": combinedFile.UpdateMapChunk(subChunk, mcnkIdx++); break; default: Console.WriteLine($"Unhandled {subChunk.Name} chunk in Objects ADT."); break; } } }
public void Read(ADT combinedFile) { var mcnkIdx = 0; foreach (var subChunk in Data.Chunks) { switch (subChunk.Name) { case "MTEX": combinedFile.MTEX = new MTEX(subChunk); break; case "MCNK": combinedFile.UpdateMapChunk(subChunk, mcnkIdx++); break; default: Console.WriteLine($"Unhandled {subChunk.Name} chunk in Textures ADT."); break; } } }
static void ReadADTs() { const string continent = "Azeroth"; var allGeom = new Geometry(); var sw = new Stopwatch(); for (int y = 49; y < 50; y++) { for (int x = 31; x < 33; 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"); }
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)); }
public byte[] Build() { Geometry = new Geometry.Geometry {Transform = true }; { var main = new ADT(World, X, Y); main.Read(); // main.Generate(); Geometry.AddADT(main); } if (Geometry.Vertices.Count == 0 && Geometry.Indices.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(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.SaveWavefrontObject($"{World}_{X}_{Y}.obj"); Geometry.Indices.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.MarkWalkableTriangles(Config.WalkableSlopeAngle, ref vertices, ref triangles,out areas); // 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 connections = new List<OffMeshConnection>(); 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(); GC.Collect(); return tileData; }
public void Merge(ADT adt, Chunk chunk) { ADT = adt; Read(new ChunkData(chunk.GetStream(), chunk.Size)); }