public bool HasCollision(RayX ray) { bool hasCollision = false; m_collisionMeshTree.DoActionOnIntersectingMeshes(ray.GetBoundingBox(), (Vector3[] points) => { for (int i = 0; i < points.Length; i += 3) { float t = ray.IntersectsTriangle(points[i], points[i + 1], points[i + 2]); if (t <= ray.Limit) { hasCollision = true; return(false); // stop } } return(true); }); return(hasCollision); }
// scans the geospace and collects points where it finds a floor. public CompiledNavMeshSet ScanFloor(GeoSpace geoSpace) { var timer = DateTime.Now; // collect the heights at each cell. Parallel.For(0, m_blockHeight, new ParallelOptions { MaxDegreeOfParallelism = OPTION_PARALLEL_THREADS }, (blockY) => { float y = m_y1 + blockY * m_step; int blockX = 0; for (float x = m_x1; x < m_x2; x += m_step, blockX++) { float curTop = m_z2; while (curTop > m_z1) { var v0 = new Vector3(x, y, curTop); var ray = new RayX(v0, new Vector3(0, 0, -1), (curTop - m_z1)); float best = (curTop - m_z1); // descend from top to find vertical hits. geoSpace.DoActionOnIntersectingMeshes(ray.GetBoundingBox(), (Vector3[] points) => { for (int i = 0; i < points.Length; i += 3) { float d = ray.IntersectsTriangle(points[i], points[i + 1], points[i + 2]); if (d < best) { best = d; } } return(true); // process all }); // no more hits? if (best >= (curTop - m_z1)) { break; } float z = curTop - best; // round-trip the height value //z = NavMeshUtil.DecodeHeight(m_z1, m_z2, NavMeshUtil.EncodeHeight(m_z1, m_z2, z)); // add the floor if there is enough room above it. if (!geoSpace.HasCollision( new RayX(new Vector3(x, y, z + 0.01f), // raise z to avoid colliding with start point new Vector3(0, 0, 1), // look up m_requiredSpaceAboveFloor))) { AddFloorPoint(x, y, z); } curTop -= best + 1; // +1 to move down to skip some solid space } } }); Debug.WriteLine("ScanFloor time: " + (DateTime.Now - timer)); // for each floor in each cell, determine neighbor connections. timer = DateTime.Now; ComputeDirectionFlags(geoSpace); Debug.WriteLine("ComputeDirectionFlags time: " + (DateTime.Now - timer)); // make a temporary map of each vertex to its neighboring vertices. // this is used for subgraph calculation. timer = DateTime.Now; Dictionary <EdgeVertex, List <EdgeVertex> > edges = GatherEdgeVertices(); Debug.WriteLine("GATHER EDGES time: " + (DateTime.Now - timer)); /* // PRINT ALL EDGES * foreach (var kvp in edges) * { * Debug.WriteLine(kvp.Key); * foreach (var v in kvp.Value) * { * Debug.WriteLine(" " + v); * } * }*/ // TODO - why the need to remove steep edges? they should have been excluded when // computing directions already... // // remove steep edges... modifies edges (and floordata), do this before // // computing subgraphs. // //timer = DateTime.Now; // //RemoveSteepEdges(edges); // //Debug.WriteLine("RemoveSteepEdges time: " + (DateTime.Now - timer)); // separate the subgraphs timer = DateTime.Now; List <HashSet <EdgeVertex> > subgraphs = ComputeSubgraphs(edges); Debug.WriteLine("ComputeSubgraphs time: " + (DateTime.Now - timer)); // FILTERING // filter subgraphs by size if (OPTION_REMOVE_SMALL_GRAPHS) { timer = DateTime.Now; subgraphs = subgraphs.Where(vertices => vertices.Count >= 100).ToList(); Debug.WriteLine("RemoveSmallSubgraphs time: " + (DateTime.Now - timer)); } else { Debug.WriteLine("NOTE: not removing small graphs"); } // POST FILTERING // by now, the gathered subgraph edges may not match the original direction flags, // due to slope checks, height checks, etc... // so, update the direction flags so they reflect the current gathered subgraphs. // it is possible this step could hide bugs, but overall is necessary... timer = DateTime.Now; FixDirectionFlagsToMatchSubgraphs(edges, subgraphs); Debug.WriteLine("FIX DIRECTION FLAGS time: " + (DateTime.Now - timer)); // VALIDATION ValidateAllSubgraphVerticesExistInFloorData(subgraphs); ValidateEdgesAtBoundsAreBlocked(subgraphs); timer = DateTime.Now; var compiledMeshes = new List <CompiledNavMesh>(); foreach (var sg in subgraphs) { compiledMeshes.Add(Build(sg)); } var compiledNavMeshSet = new CompiledNavMeshSet(compiledMeshes); Debug.WriteLine("Compile time: " + (DateTime.Now - timer)); return(compiledNavMeshSet); }