Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        // 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);
        }