using System; using System.Collections.Generic; namespace Oni.Akira { internal class Room { private Polygon floorPolygon; private RoomBspNode bspTree; private BoundingBox boundingBox; private RoomGrid grid; private Plane floorPlane; private float height; private readonly List adjacencies = new List(); public BoundingBox BoundingBox { get { return boundingBox; } set { boundingBox = value; } } public RoomBspNode BspTree { get { return bspTree; } set { bspTree = value; } } public RoomGrid Grid { get { return grid; } set { grid = value; } } public Polygon FloorPolygon { get { return floorPolygon; } set { floorPolygon = value; } } public Plane FloorPlane { get { return floorPlane; } set { floorPlane = value; } } public bool IsStairs => floorPlane.Normal.Y < 0.999f; public float Height { get { return height; } set { height = value; } } public List Ajacencies => adjacencies; public bool Contains(Vector3 point) { if (!boundingBox.Contains(point)) return false; bool front = false; RoomBspNode node = bspTree; while (node != null) { front = (node.Plane.DotCoordinate(point) >= MathHelper.Eps); node = front ? node.FrontChild : node.BackChild; } return !front; } public bool Intersect(BoundingBox bbox) { if (!boundingBox.Intersects(bbox)) return false; bool front = false; RoomBspNode node = bspTree; while (node != null) { int intersects = node.Plane.Intersects(bbox); if (intersects == 0) return true; front = intersects > 0; node = front ? node.FrontChild : node.BackChild; } return !front; } public List GetFloorPolygons() { var polys = new List(); if (floorPolygon != null) { polys.Add(floorPolygon.Points.ToArray()); return polys; } var min = new Vector2(boundingBox.Min.X, boundingBox.Min.Z); var max = new Vector2(boundingBox.Max.X, boundingBox.Max.Z); var root = new Polygon2(new[] { new Vector2(min.X, min.Y), new Vector2(max.X, min.Y), new Vector2(max.X, max.Y), new Vector2(min.X, max.Y) }); var cutter = new Polygon2Clipper(bspTree); foreach (Polygon2 polygon in cutter.Clip(root)) { var points = new Vector3[polygon.Length]; for (int i = 0; i < points.Length; i++) { var point = polygon[i]; points[i].X = point.X; points[i].Y = (-floorPlane.D - floorPlane.Normal.Z * point.Y - floorPlane.Normal.X * point.X) / floorPlane.Normal.Y; points[i].Z = point.Y; } Array.Reverse(points); polys.Add(points); } return polys; } } }