public bool Contains2D(Vec3 p) { return(AABB.Contains2D(p)); }
// 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); } }