// NavMesh generator private List <VertexPositionColor> LoadNavMeshTestData(H32Loader h32) { // TODO - configure nav dir - determine filename using worldid xml DateTime TIMER; var floorLineVertices = new List <VertexPositionColor>(); bool generate = true; //false; bool loadFromFile = false; //true;//true; bool saveToFile = false; //true; //NavMeshBuilder.OPTION_PARALLEL_THREADS = 1; //NavMeshBuilder.OPTION_REMOVE_SMALL_GRAPHS = false; CompiledNavMeshSet compiledMeshSet = null; if (generate) { TIMER = DateTime.Now; h32.LoadIntoGeoSpace(m_geoSpace); Debug.WriteLine("h32.LoadIntoGeoSpace TIME: " + (DateTime.Now - TIMER)); TIMER = DateTime.Now; m_geoSpace.BuildTree(); m_geoSpace.Validate(); Debug.WriteLine("BuildTree TIME: " + (DateTime.Now - TIMER)); float startX = 90; //133-120; //340 - 20; float endX = 200; //133+20; //360 + 20; float startY = 103 - 20; //220 - 20; float endY = 120; // 103+20; //240 + 20; int top = 400; int bot = 0; float step = 1f; var navMeshBuilder = new NavMeshBuilder(startX, startY, bot, endX, endY, top, step); TIMER = DateTime.Now; compiledMeshSet = navMeshBuilder.ScanFloor(m_geoSpace); Debug.WriteLine("ScanFloor TIME: " + (DateTime.Now - TIMER)); if (saveToFile) { // File roundtrip test using (var fs = File.OpenWrite("c:\\temp2\\300200000.nav")) compiledMeshSet.Save(fs); } } if (loadFromFile) { using (var fs = File.OpenRead(@"c:\temp2\out\210020000.nav")) //"c:\\temp2\\300200000.nav")) compiledMeshSet = CompiledNavMeshSet.Load(fs); } Debug.WriteLine("Total estimated compiled mesh size in bytes: " + compiledMeshSet.GetEstimatedFileSizeInBytes()); var compiledMesh = //compiledMeshSet.FindSubgraphUnderPointWithSnap(126, 66, 145+2, maxFall: 10); //compiledMeshSet.FindSubgraphUnderPointWithSnap(2484, 2614, 300, maxFall: 20); compiledMeshSet.FindSubgraphUnderPointWithSnap(110, 110, 300, maxFall: 2220); if (compiledMesh == null) { throw new InvalidOperationException("point was not over a floor"); } m_tempCompiledNavMeshSet = compiledMeshSet; // DEBUG MARKERS // floorLineVertices.Add(new VertexPositionColor(new Vector3(126, 65, 144.3f + 3), Color.Lime)); // floorLineVertices.Add(new VertexPositionColor(new Vector3(126, 65, 144.3f), Color.Lime)); // floorLineVertices.Add(new VertexPositionColor(new Vector3(127, 64, 145.09f + 3), Color.Red)); // floorLineVertices.Add(new VertexPositionColor(new Vector3(127, 64, 145.09f), Color.Red)); //============================================= // TESTING COMPILED MESH GETNEIGHBOR //start... // floorLineVertices.Add(new VertexPositionColor(new Vector3(133, 103, 150), Color.White)); // floorLineVertices.Add(new VertexPositionColor(new Vector3(133, 103, 144), Color.White)); /* * var curNode = compiledMesh.FindFloorUnderPoint(132.9f, 102.9f, 149, 20); * Vector3 v = compiledMesh.WorldFromBlockIndex(curNode.blockIndex, 144); * * floorLineVertices.Add(new VertexPositionColor(v + new Vector3(0,0,5), Color.Lime)); * floorLineVertices.Add(new VertexPositionColor(v, Color.Lime)); * * curNode = compiledMesh.GetNeighbor(curNode, 0, 1); * v = compiledMesh.WorldFromBlockIndex(curNode.blockIndex, 144); * floorLineVertices.Add(new VertexPositionColor(v + new Vector3(0, 0, 5), Color.Cyan)); * floorLineVertices.Add(new VertexPositionColor(v, Color.Lime)); * * curNode = compiledMesh.GetNeighbor(curNode, 0, 1); * v = compiledMesh.WorldFromBlockIndex(curNode.blockIndex, 144); * floorLineVertices.Add(new VertexPositionColor(v + new Vector3(0, 0, 5), Color.Yellow)); * floorLineVertices.Add(new VertexPositionColor(v, Color.Lime)); * * curNode = compiledMesh.GetNeighbor(curNode, 1, 1); * v = compiledMesh.WorldFromBlockIndex(curNode.blockIndex, 144); * floorLineVertices.Add(new VertexPositionColor(v + new Vector3(0, 0, 5), Color.White)); * floorLineVertices.Add(new VertexPositionColor(v, Color.Lime)); */ // END TEST //============================================= //============================================= // TEST A* //TestAStar(compiledMesh, new Vector3(141, 21, 145), new Vector3(140, 28, 144), 10, floorLineVertices); //TestAStar(compiledMesh, new Vector3(155, 56, 144), new Vector3(169, 23, 144), 10, floorLineVertices); // TestAStar(compiledMesh, new Vector3(130, 101, 145), new Vector3(125, 106, 147), 10, floorLineVertices); // END A* //============================================= TIMER = DateTime.Now; for (int bY = 0; bY < compiledMesh.BlockHeight; bY++) { for (int bX = 0; bX < compiledMesh.BlockWidth; bX++) { float x = compiledMesh.X1 + bX * compiledMesh.Step; float y = compiledMesh.Y1 + bY * compiledMesh.Step; compiledMesh.ForeachHeightAtXY(bX, bY, (directionFlags, z) => { /*Color xcolor = Color.Lime; * * //if (bX == 28 && bY == 0) Debugger.Break(); * * if (y > 221 && y < 223 && x > 346 && x < 348) * xcolor = Color.White; * else if (y > 221 && y < 223 && x > 347 && x < 349) * xcolor = Color.Blue; * else if (y >= 221 && y <= 223 && x >= 346 && x <= 348) * xcolor = Color.Red;*/ // DRAW ELEVATION MARKER /* floorLineVertices.Add(new VertexPositionColor(new Vector3(x - 0.1f, y, z), xcolor)); * floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y + 0.1f, z), xcolor)); * * floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y + 0.1f, z), xcolor)); * floorLineVertices.Add(new VertexPositionColor(new Vector3(x + 0.1f, y, z), xcolor)); * * floorLineVertices.Add(new VertexPositionColor(new Vector3(x + 0.1f, y, z), xcolor)); * floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y - 0.1f, z), xcolor)); * * floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y - 0.1f, z), xcolor)); * floorLineVertices.Add(new VertexPositionColor(new Vector3(x - 0.1f, y, z), xcolor)); */ // EDGE CONNECTIONS // draw lines through the compass points... float halfstep = compiledMesh.Step; float n; n = compiledMesh.GetEdge(bX, bY, z, directionFlags, NavMeshUtil.DIRECTION_LEFT); if (n >= 0) { var test = Color.Orange; if (Math.Abs(z - n) >= 0.9f) { test = Color.Red; } floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y, z), test)); floorLineVertices.Add(new VertexPositionColor(new Vector3(x - halfstep, y, n), test)); } n = compiledMesh.GetEdge(bX, bY, z, directionFlags, NavMeshUtil.DIRECTION_TL); if (n >= 0) { var test = Color.Orange; if (Math.Abs(z - n) / (new Vector2(x, y) - new Vector2(x - halfstep, y + halfstep)).Length() >= 1.4f) { test = Color.Magenta; } floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y, z), test)); floorLineVertices.Add(new VertexPositionColor(new Vector3(x - halfstep, y + halfstep, n), test)); } n = compiledMesh.GetEdge(bX, bY, z, directionFlags, NavMeshUtil.DIRECTION_TOP); if (n >= 0) { var test = Color.Orange; if (Math.Abs(z - n) >= 0.9f) { test = Color.Red; } floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y, z), test)); floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y + halfstep, n), test)); } n = compiledMesh.GetEdge(bX, bY, z, directionFlags, NavMeshUtil.DIRECTION_TR); if (n >= 0) { var test = Color.Orange; if (Math.Abs(z - n) / (new Vector2(x, y) - new Vector2(x + halfstep, y + halfstep)).Length() >= 1.4f) { test = Color.Purple; } floorLineVertices.Add(new VertexPositionColor(new Vector3(x, y, z), test)); floorLineVertices.Add(new VertexPositionColor(new Vector3(x + halfstep, y + halfstep, n), test)); } }); } } Debug.WriteLine("MESH ASSEMBLY TIME: " + (DateTime.Now - TIMER)); return(floorLineVertices); }
// generates navmesh data for the selected levels. public static void GenerateAllNav(WorldIdXmlLoader worldIdXmlLoader, DirManager meshesDir, DirManager levelsDir, string levelId, bool skipExistingNav, string outputPath) { int curFolderIndex = -1; foreach (var pairs in worldIdXmlLoader.FolderNamesById) { curFolderIndex++; string clientLevelId = pairs.Key; string levelFolder = pairs.Value; if (!string.IsNullOrEmpty(levelId) && levelId != clientLevelId) { // skip excluded continue; } string outputNavFilename = Path.Combine(outputPath, clientLevelId + ".nav"); if (skipExistingNav && File.Exists(outputNavFilename)) { Console.WriteLine($" ** Skipping (already exists): {clientLevelId} - {levelFolder}"); continue; } Console.WriteLine($" Loading meshes for {clientLevelId} - {levelFolder}"); var LEVEL_TIME = DateTime.Now; var TIMER = DateTime.Now; var geoSpace = new GeoSpace(); // brushes var brushlst = LevelLoadHelper.CreateBrushLstLoader(levelsDir, Path.Combine(levelFolder, "brush.lst")); if (brushlst != null) { var cgfMap = LevelLoadHelper.CreateBrushLstCgfLoaderMap(meshesDir, brushlst); foreach (var brush in brushlst.brushEntries) { CgfLoader cgf; if (!cgfMap.TryGetValue(brush.meshIdx, out cgf)) { continue; } Matrix brushMatrix = LevelLoadHelper.GetBrushMatrix(brush); AddCgfToWorld(cgf, ref brushMatrix, brush.position, geoSpace); } } // objects var ctx = LevelLoadHelper.LoadObjectsLst(meshesDir, levelsDir, levelFolder); if (ctx != null) { foreach (var o in ctx.objects) { CgfLoader cgf; if (!ctx.cgfMap.TryGetValue(o.ObjectId, out cgf)) { continue; } var xform = LevelLoadHelper.GetObjectMatrix(o); AddCgfToWorld(cgf, ref xform, o.Position, geoSpace); } } // terrain bool loadedH32 = false; string h32path = Path.Combine(levelFolder, @"terrain\land_map.h32"); if (levelsDir.Exists(h32path)) { using (var landMapStream = levelsDir.OpenFile(h32path)) new H32Loader(landMapStream).LoadIntoGeoSpace(geoSpace); loadedH32 = true; } Console.WriteLine(" Data load time: " + (DateTime.Now - TIMER)); if (brushlst == null && ctx == null && !loadedH32) { Console.WriteLine(" ** Skipping (no level data found)"); continue; } // build geo TIMER = DateTime.Now; geoSpace.BuildTree(); geoSpace.Validate(); Console.WriteLine(" Geo build time: " + (DateTime.Now - TIMER)); // get size of level for scanning var bb = geoSpace.GetBoundingBox(); float startX = Math.Max(0, bb.Min.X); float endX = bb.Max.X; float startY = Math.Max(0, bb.Min.Y); float endY = bb.Max.Y; int top = (int)Math.Ceiling(bb.Max.Z); int bot = Math.Max(0, (int)bb.Min.Z); // TODO - print bounding box // TODO - save log file if (endX <= startX || endY <= startY || top < bot) { throw new InvalidOperationException( $"unexpected level size for {clientLevelId} {levelFolder} bb: {bb}"); } // compile mesh TIMER = DateTime.Now; float step = 1f; var navMeshBuilder = new NavMeshBuilder(startX, startY, bot, endX, endY, top, step); CompiledNavMeshSet compiledMeshSet = navMeshBuilder.ScanFloor(geoSpace); Console.WriteLine(" Raycast time: " + (DateTime.Now - TIMER)); // save to file using (var fs = File.OpenWrite(outputNavFilename)) compiledMeshSet.Save(fs); Console.WriteLine($" Level {clientLevelId} finished in {DateTime.Now - LEVEL_TIME}"); } }
// NavMesh generator private List <VertexPositionColor> LoadNavMeshTestData(H32Loader h32) { // TODO - configure nav dir - determine filename using worldid xml DateTime TIMER; bool generate = false; bool loadFromFile = true; bool saveToFile = false;//true; //NavMeshBuilder.OPTION_PARALLEL_THREADS = 1; //NavMeshBuilder.OPTION_REMOVE_SMALL_GRAPHS = false; CompiledNavMeshSet compiledMeshSet = null; if (generate) { TIMER = DateTime.Now; h32.LoadIntoGeoSpace(m_geoSpace); Debug.WriteLine("h32.LoadIntoGeoSpace TIME: " + (DateTime.Now - TIMER)); TIMER = DateTime.Now; m_geoSpace.BuildTree(); m_geoSpace.Validate(); Debug.WriteLine("BuildTree TIME: " + (DateTime.Now - TIMER)); float startX = 90; //133-120; //340 - 20; float endX = 200; //133+20; //360 + 20; float startY = 103 - 20; //220 - 20; float endY = 120; // 103+20; //240 + 20; int top = 400; int bot = 0; float step = 1f; var navMeshBuilder = new NavMeshBuilder(startX, startY, bot, endX, endY, top, step); TIMER = DateTime.Now; compiledMeshSet = navMeshBuilder.ScanFloor(m_geoSpace); Debug.WriteLine("ScanFloor TIME: " + (DateTime.Now - TIMER)); if (saveToFile) { // File roundtrip test using (var fs = File.OpenWrite("c:\\temp2\\300200000.nav")) compiledMeshSet.Save(fs); } } if (loadFromFile) { using (var fs = File.OpenRead(@"c:\temp2\out\210020000.nav")) //"c:\\temp2\\300200000.nav")) compiledMeshSet = CompiledNavMeshSet.Load(fs); } Debug.WriteLine("Total estimated compiled mesh size in bytes: " + compiledMeshSet.GetEstimatedFileSizeInBytes()); var compiledMesh = //compiledMeshSet.FindSubgraphUnderPointWithSnap(126, 66, 145+2, maxFall: 10); //compiledMeshSet.FindSubgraphUnderPointWithSnap(2484, 2614, 300, maxFall: 20); compiledMeshSet.FindSubgraphUnderPointWithSnap(110, 110, 300, maxFall: 2220); if (compiledMesh == null) { throw new InvalidOperationException("point was not over a floor"); } m_tempCompiledNavMeshSet = compiledMeshSet; TIMER = DateTime.Now; var floorLineVertices = RenderFloorLines(compiledMesh, Vector3.Zero, 0); Debug.WriteLine("MESH ASSEMBLY TIME: " + (DateTime.Now - TIMER)); return(floorLineVertices); }