public bool HasParent(Frustum parent) { var frustum = this; while(frustum != null) { if (parent == frustum) return true; frustum = frustum.Parent; } return false; }
public void AddNewPolygonList(List<TransparentPolygonReference> p, Transform transform, Frustum frustum, Camera cam) { foreach (var pp in p) { var transformed = new Polygon(); transformed.Vertices.Resize(pp.Polygon.Vertices.Count, () => new Vertex()); transformed.Transform(pp.Polygon, transform); transformed.DoubleSide = pp.Polygon.DoubleSide; if(frustum.IsPolyVisible(transformed, cam)) { addPolygon(ref _root, new BSPFaceRef(transform, pp), transformed); } } }
public void DrawFrustum(Frustum f) { for (var i = 0; i < f.Vertices.Count - 1; i++) { addLine(f.Vertices[i], f.Vertices[i + 1]); } addLine(f.Vertices.Last(), f.Vertices.First()); }
/// <summary> /// The recursion algorithm: go through the rooms with portal-frustum occlusion test. /// </summary> /// <param name="portal">Portal we entered to the room through</param> /// <param name="frus">Frustum that intersects the portal</param> /// <returns>Number of added rooms</returns> public int ProcessRoom(Portal portal, Frustum frus) { var destination = portal.DestRoom; var current = portal.CurrentRoom; if(current == null || !current.Active || destination == null || !destination.Active) { return 0; } var ret = 0; foreach (var p in destination.Portals) { if(p.DestRoom != null && p.DestRoom.Active && p.DestRoom != current) { // The main function of portal renderer. Here comes the check. var genFrus = Frustum.PortalFrustumIntersect(p, frus, this); if(genFrus != null) { ret++; AddRoom(p.DestRoom); ProcessRoom(p, genFrus); } } } return ret; }
public void SplitPrepare(Portal p) { Vertices = p.Vertices; Normal = p.Normal; Normal.MirrorNormal(); Parent = null; }
public static Frustum PortalFrustumIntersect(Portal portal, Frustum emitter, Render render) { if (portal.DestRoom == null) return null; if (portal.Normal.Distance(render.Camera.Position) < SPLIT_EPSILON) // non face or degenerate to the line portal return null; if (portal.DestRoom.Frustum.Count > 0 && emitter.HasParent(portal.DestRoom.Frustum[0])) return null; // Abort infinite loop! var inDist = false; var inFace = false; foreach (var v in portal.Vertices) { if (!inDist && render.Camera.Frustum.Normal.Distance(v) < render.Camera.DistFar) inDist = true; if (!inFace && emitter.Normal.Distance(v) > 0.0) inFace = true; if (inDist && inFace) break; } if (!inDist || !inDist) return null; // Search for the first free room's frustum portal.DestRoom.Frustum.Add(new Frustum()); var currentGen = portal.DestRoom.Frustum.Last(); currentGen.SplitPrepare(portal); // prepare for clipping if (currentGen.SplitByPlane(emitter.Normal)) // splitting by main frustum clip plane { for (var i = 0; i < emitter.Vertices.Count; i++) { if(!currentGen.SplitByPlane(emitter.Planes[i])) { portal.DestRoom.Frustum.RemoveAt(portal.DestRoom.Frustum.Count - 1); return null; } } currentGen.GenClipPlanes(render.Camera); // all is OK, let's generate clip planes currentGen.Parent = emitter; // add parent pointer currentGen.ParentsCount = emitter.ParentsCount + 1; portal.DestRoom.MaxPath = Math.Max(portal.DestRoom.MaxPath, currentGen.ParentsCount); // maximum path to the room return currentGen; } portal.DestRoom.Frustum.RemoveAt(portal.DestRoom.Frustum.Count - 1); return null; }