private NavmeshTile CreateTile(Voxelize vox, VoxelMesh mesh, int x, int z, int threadIndex) { if (mesh.tris == null) { throw new ArgumentNullException("mesh.tris"); } if (mesh.verts == null) { throw new ArgumentNullException("mesh.verts"); } if (mesh.tris.Length % 3 != 0) { throw new ArgumentException("Indices array's length must be a multiple of 3 (mesh.tris)"); } if (mesh.verts.Length >= 4095) { if (this.tileXCount * this.tileZCount == 1) { throw new ArgumentException("Too many vertices per tile (more than " + 4095 + ").\n<b>Try enabling tiling in the recast graph settings.</b>\n"); } throw new ArgumentException("Too many vertices per tile (more than " + 4095 + ").\n<b>Try reducing tile size or enabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* Inspector</b>"); } else { NavmeshTile navmeshTile = new NavmeshTile { x = x, z = z, w = 1, d = 1, tris = mesh.tris, bbTree = new BBTree() }; navmeshTile.vertsInGraphSpace = Utility.RemoveDuplicateVertices(mesh.verts, navmeshTile.tris); navmeshTile.verts = (Int3[])navmeshTile.vertsInGraphSpace.Clone(); this.transform.Transform(navmeshTile.verts); uint num = (uint)(this.active.data.graphs.Length + threadIndex); if (num > 255u) { throw new Exception("Graph limit reached. Multithreaded recast calculations cannot be done because a few scratch graph indices are required."); } int num2 = x + z * this.tileXCount; num2 <<= 12; TriangleMeshNode.SetNavmeshHolder((int)num, navmeshTile); object active = this.active; lock (active) { navmeshTile.nodes = base.CreateNodes(navmeshTile.tris, num2, num); } navmeshTile.bbTree.RebuildFrom(navmeshTile.nodes); NavmeshBase.CreateNodeConnections(navmeshTile.nodes); TriangleMeshNode.SetNavmeshHolder((int)num, null); return(navmeshTile); } }
/** Create a tile at tile index \a x, \a z from the mesh. * \version Since version 3.7.6 the implementation is thread safe */ public static NavmeshTile CreateTile(this RecastGraph self, Voxelize vox, VoxelMesh mesh, int x, int z, int threadIndex) { if (mesh.tris == null) { throw new System.ArgumentNullException("mesh.tris"); } if (mesh.verts == null) { throw new System.ArgumentNullException("mesh.verts"); } if (mesh.tris.Length % 3 != 0) { throw new System.ArgumentException("Indices array's length must be a multiple of 3 (mesh.tris)"); } if (mesh.verts.Length >= NavmeshBase.VertexIndexMask) { if (self.tileXCount * self.tileZCount == 1) { throw new System.ArgumentException("Too many vertices per tile (more than " + NavmeshBase.VertexIndexMask + ")." + "\n<b>Try enabling tiling in the recast graph settings.</b>\n"); } else { throw new System.ArgumentException("Too many vertices per tile (more than " + NavmeshBase.VertexIndexMask + ")." + "\n<b>Try reducing tile size or enabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* Inspector</b>"); } } // Create a new navmesh tile and assign its settings var tile = new NavmeshTile { x = x, z = z, w = 1, d = 1, tris = mesh.tris, bbTree = new BBTree(), graph = self, }; tile.vertsInGraphSpace = Utility.RemoveDuplicateVertices(mesh.verts, tile.tris); tile.verts = (Int3[])tile.vertsInGraphSpace.Clone(); self.transform.Transform(tile.verts); // Here we are faking a new graph // The tile is not added to any graphs yet, but to get the position queries from the nodes // to work correctly (not throw exceptions because the tile is not calculated) we fake a new graph // and direct the position queries directly to the tile // The thread index is added to make sure that if multiple threads are calculating tiles at the same time // they will not use the same temporary graph index uint temporaryGraphIndex = (uint)(AstarPath.active.data.graphs.Length + threadIndex); if (temporaryGraphIndex > GraphNode.MaxGraphIndex) { // Multithreaded tile calculations use fake graph indices, see above. throw new System.Exception("Graph limit reached. Multithreaded recast calculations cannot be done because a few scratch graph indices are required."); } TriangleMeshNode.SetNavmeshHolder((int)temporaryGraphIndex, tile); // We need to lock here because creating nodes is not thread safe // and we may be doing this from multiple threads at the same time tile.nodes = new TriangleMeshNode[tile.tris.Length / 3]; lock (AstarPath.active) { self.CreateNodes(tile.nodes, tile.tris, x + z * self.tileXCount, temporaryGraphIndex); } tile.bbTree.RebuildFrom(tile.nodes); NavmeshBase.CreateNodeConnections(tile.nodes); // Remove the fake graph TriangleMeshNode.SetNavmeshHolder((int)temporaryGraphIndex, null); return(tile); }