예제 #1
0
        private bool InternalSegmentTest(Vec3 start, Vec3 end, ref Vec3 result, int num_dim)
        {
            Vec3  ray_dir  = end - start;
            float length   = num_dim > 2 ? ray_dir.Normalize() : ray_dir.Normalize2D();
            float length_2 = length * length;

            if (InternalRayTest(start, ray_dir, ref result, num_dim))
            {
                if ((num_dim > 2 ? result.DistanceSqr(start) : result.Distance2DSqr(start)) <= length_2)
                {
                    return(true);
                }

                result = end;
                return(false);
            }

            return(false);
        }
예제 #2
0
파일: Navmesh.cs 프로젝트: panyicast/Nav.D3
        // Aquires DataLock (read); returns true when there is no obstacle
        private bool RayCast(Vec3 from, Cell from_cell, Vec3 to, MovementFlag flags, ref Vec3 intersection, bool test_2d, bool ignore_movement_cost, ref HashSet <Cell> ignored_cells)
        {
            using (new ReadLock(DataLock))
            {
                if (to.IsEmpty)
                {
                    intersection = new Vec3(from);
                    return(false);
                }

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

                if (test_2d ? from_cell.Contains2D(to) : from_cell.Contains(to, 2))
                {
                    intersection = new Vec3(to);
                    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);

                // check if intersection in
                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;
                    }

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

                    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);

                        // ray intersects on connection plane
                        if (shared_aabb != null)
                        {
                            bool accepted = test_2d ? shared_aabb.Contains2D(intersection) :
                                            shared_aabb.Contains(intersection);

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

                return(false);
            }
        }