/// <summary> /// Marks tiles that should be built according to how much their geometry affects the navigation mesh and the bounding boxes specified for building /// </summary> private void MarkTiles(NavigationMeshInputBuilder inputBuilder, ref NavigationMeshBuildSettings buildSettings, ref NavigationAgentSettings agentSettings, HashSet <Point> tilesToBuild) { // Extend bounding box for agent size BoundingBox boundingBoxToCheck = inputBuilder.BoundingBox; NavigationMeshBuildUtils.ExtendBoundingBox(ref boundingBoxToCheck, new Vector3(agentSettings.Radius)); List <Point> newTileList = NavigationMeshBuildUtils.GetOverlappingTiles(buildSettings, boundingBoxToCheck); foreach (Point p in newTileList) { tilesToBuild.Add(p); } }
private NavigationMeshTile BuildTile(Point tileCoordinate, NavigationMeshBuildSettings buildSettings, NavigationAgentSettings agentSettings, ICollection <BoundingBox> boundingBoxes, Vector3[] inputVertices, int[] inputIndices, long buildTimeStamp) { NavigationMeshTile meshTile = null; // Include bounding boxes in tile height range BoundingBox tileBoundingBox = NavigationMeshBuildUtils.CalculateTileBoundingBox(buildSettings, tileCoordinate); float minimumHeight = float.MaxValue; float maximumHeight = float.MinValue; bool shouldBuildTile = false; foreach (var boundingBox in boundingBoxes) { if (boundingBox.Intersects(ref tileBoundingBox)) { maximumHeight = Math.Max(maximumHeight, boundingBox.Maximum.Y); minimumHeight = Math.Min(minimumHeight, boundingBox.Minimum.Y); shouldBuildTile = true; } } NavigationMeshBuildUtils.SnapBoundingBoxToCellHeight(buildSettings, ref tileBoundingBox); // Skip tiles that do not overlap with any bounding box if (shouldBuildTile) { // Set tile's minimum and maximum height tileBoundingBox.Minimum.Y = minimumHeight; tileBoundingBox.Maximum.Y = maximumHeight; unsafe { IntPtr builder = Navigation.CreateBuilder(); // Turn build settings into native structure format Navigation.BuildSettings internalBuildSettings = new Navigation.BuildSettings { // Tile settings BoundingBox = tileBoundingBox, TilePosition = tileCoordinate, TileSize = buildSettings.TileSize, // General build settings CellHeight = buildSettings.CellHeight, CellSize = buildSettings.CellSize, RegionMinArea = buildSettings.MinRegionArea, RegionMergeArea = buildSettings.RegionMergeArea, EdgeMaxLen = buildSettings.MaxEdgeLen, EdgeMaxError = buildSettings.MaxEdgeError, DetailSampleDist = buildSettings.DetailSamplingDistance, DetailSampleMaxError = buildSettings.MaxDetailSamplingError, // Agent settings AgentHeight = agentSettings.Height, AgentRadius = agentSettings.Radius, AgentMaxClimb = agentSettings.MaxClimb, AgentMaxSlope = agentSettings.MaxSlope.Degrees, }; Navigation.SetSettings(builder, new IntPtr(&internalBuildSettings)); IntPtr buildResultPtr = Navigation.Build(builder, inputVertices, inputVertices.Length, inputIndices, inputIndices.Length); Navigation.GeneratedData *generatedDataPtr = (Navigation.GeneratedData *)buildResultPtr; if (generatedDataPtr->Success && generatedDataPtr->NavmeshDataLength > 0) { meshTile = new NavigationMeshTile(); // Copy the generated navigationMesh data meshTile.Data = new byte[generatedDataPtr->NavmeshDataLength + sizeof(long)]; Marshal.Copy(generatedDataPtr->NavmeshData, meshTile.Data, 0, generatedDataPtr->NavmeshDataLength); // Append time stamp byte[] timeStamp = BitConverter.GetBytes(buildTimeStamp); for (int i = 0; i < timeStamp.Length; i++) { meshTile.Data[meshTile.Data.Length - sizeof(long) + i] = timeStamp[i]; } List <Vector3> outputVerts = new List <Vector3>(); if (generatedDataPtr->NumNavmeshVertices > 0) { Vector3 *navmeshVerts = (Vector3 *)generatedDataPtr->NavmeshVertices; for (int j = 0; j < generatedDataPtr->NumNavmeshVertices; j++) { outputVerts.Add(navmeshVerts[j]); } } Navigation.DestroyBuilder(builder); } } } return(meshTile); }