示例#1
0
文件: Navmesh.cs 项目: rol2728/Dev.D3
        // Aquires DataLock (read)
        private bool RayCast(Vec3 from, Cell from_cell, Vec3 to, MovementFlag flags, bool test_2d, bool ignore_movement_cost, ref HashSet <Cell> ignored_cells)
        {
            using (new ReadLock(DataLock))
            {
                if (to.IsEmpty)
                {
                    return(false);
                }

                if (from_cell == null && !GetCellContaining(from, out from_cell, ignored_cells, false, flags, test_2d, 2))
                {
                    return(false);
                }

                if (test_2d ? from_cell.Contains2D(to) : from_cell.Contains(to, 2))
                {
                    return(true);
                }

                ignored_cells.Add(from_cell);

                Vec3 ray_dir = to - from;
                if (test_2d)
                {
                    ray_dir.Normalize2D();
                }
                else
                {
                    ray_dir.Normalize();
                }

                Vec3 ray_origin = new Vec3(from);

                // raycast through neighbours
                foreach (Cell.Neighbour neighbour in from_cell.Neighbours)
                {
                    if (neighbour.cell.Disabled || (neighbour.connection_flags & flags) != flags || (!ignore_movement_cost && neighbour.cell.MovementCostMult > from_cell.MovementCostMult))
                    {
                        continue;
                    }

                    Cell neighbour_cell = neighbour.cell;

                    if (ignored_cells.Contains(neighbour_cell))
                    {
                        continue;
                    }

                    Vec3 intersection = null;

                    bool ray_test_result = test_2d ? neighbour_cell.AABB.RayTest2D(ray_origin, ray_dir, out intersection) :
                                           neighbour_cell.AABB.RayTest(ray_origin, ray_dir, out intersection);

                    // ray intersects on connection plane
                    if (ray_test_result)
                    {
                        AABB shared_aabb = test_2d ? from_cell.AABB.Intersect2D(neighbour_cell.AABB, true) :
                                           from_cell.AABB.Intersect(neighbour_cell.AABB, true);

                        if (shared_aabb != null)
                        {
                            bool accepted = test_2d ? shared_aabb.Contains2D(intersection) :
                                            shared_aabb.Contains(intersection);

                            if (accepted && RayCast(intersection, neighbour_cell, to, flags, test_2d, ignore_movement_cost, ref ignored_cells))
                            {
                                return(true);
                            }
                        }
                    }
                }

                return(false);
            }
        }