public void IsInsideFOVTest9() { float x = -2; float y = 2; for (double i = 0; i < Math.PI * 2; i += Math.PI / 20) { Vector2 viewPoint = new Vector2(x - 1, y); LineF lookLine = new LineF(new Vector2(x + 1, y), (float)i, 1f); LineF line = new LineF(new Vector2(x, y + 0.5f), new Vector2(x, y - 0.5f)); Assert.IsTrue(line.IsInsideFOV(viewPoint, lookLine)); } }
private static bool _isPortalValid(IPortal previous, IPortal next, Vector2 viewPos) { //skip this portal if it isn't linked if (!Portal.IsValid(next)) { return false; } //or it's the exit portal if (previous != null && next == previous.Linked) { return false; } //or if the portal is one sided and the view point is on the wrong side Vector2[] pv2 = Portal.GetWorldVerts(next); LineF portalLine = new LineF(pv2); if (next.OneSided) { if (portalLine.GetSideOf(pv2[0] + next.WorldTransform.GetRight()) != portalLine.GetSideOf(viewPos)) { return false; } } //or if this portal isn't inside the fov of the exit portal if (previous != null) { LineF portalEnterLine = new LineF(Portal.GetWorldVerts(previous.Linked)); if (!portalEnterLine.IsInsideFOV(viewPos, portalLine)) { return false; } } return true; }
public void IsInsideFOVTest7() { float x = 0; float y = 0; for (double i = 0; i < Math.PI * 2; i += Math.PI / 20) { Scene scene = new Scene(); FloatPortal p0 = new FloatPortal(scene); Entity node = new Entity(scene); Transform2.SetPosition(node, new Vector2(x, y)); Transform2.SetRotation(node, (float)(i + Math.PI / 4)); p0.SetParent(node); PortalCommon.UpdateWorldTransform(scene); Vector2 viewPoint = new Vector2(x + (float)Math.Cos(i), y + (float)Math.Sin(i)); Vector2 lookPoint = new Vector2(x + (float)Math.Cos(i) * 2, y + (float)Math.Sin(i) * 2); LineF line = new LineF(Vector2Ext.Transform(Portal.GetVerts(p0), p0.GetWorldTransform().GetMatrix())); Assert.IsFalse(line.IsInsideFOV(viewPoint, lookPoint)); } }
private static bool CalculatePortalViews(IPortal portal, IPortal portalEnter, IList<IPortal> portals, Matrix4 viewMatrix, Vector2 viewPos, Vector2 viewPosPrevious, PortalView portalView, Matrix4 portalMatrix, List<Func<bool>> actionList) { const float AREA_EPSILON = 0.0001f; Clipper c = new Clipper(); //The clipper must be set to strictly simple. Otherwise polygons might have duplicate vertices which causes poly2tri to generate incorrect results. c.StrictlySimple = true; if (!_isPortalValid(portalEnter, portal, viewPos)) { return false; } Vector2[] fov = Vector2Ext.Transform(Portal.GetFov(portal, viewPos, 500, 3), portalMatrix); if (MathExt.GetArea(fov) < AREA_EPSILON) { return false; } List<IntPoint> pathFov = ClipperConvert.ToIntPoint(fov); var viewNew = new List<List<IntPoint>>(); c.AddPath(pathFov, PolyType.ptSubject, true); c.AddPaths(portalView.Paths, PolyType.ptClip, true); c.Execute(ClipType.ctIntersection, viewNew); c.Clear(); if (viewNew.Count <= 0) { return false; } c.AddPaths(viewNew, PolyType.ptSubject, true); foreach (IPortal other in portals) { if (other == portal) { continue; } if (!_isPortalValid(portalEnter, other, viewPos)) { continue; } //Skip this portal if it's inside the current portal's FOV. LineF portalLine = new LineF(Portal.GetWorldVerts(portal)); LineF portalOtherLine = new LineF(Portal.GetWorldVerts(other)); if (portalLine.IsInsideFOV(viewPos, portalOtherLine)) { continue; } Vector2[] otherFov = Vector2Ext.Transform(Portal.GetFov(other, viewPos, 500, 3), portalMatrix); if (MathExt.GetArea(otherFov) < AREA_EPSILON) { continue; } otherFov = MathExt.SetWinding(otherFov, true); List<IntPoint> otherPathFov = ClipperConvert.ToIntPoint(otherFov); c.AddPath(otherPathFov, PolyType.ptClip, true); } var viewNewer = new List<List<IntPoint>>(); c.Execute(ClipType.ctDifference, viewNewer, PolyFillType.pftNonZero, PolyFillType.pftNonZero); c.Clear(); if (viewNewer.Count <= 0) { return false; } Vector2 viewPosNew = Vector2Ext.Transform(viewPos, Portal.GetLinkedMatrix(portal, portal.Linked)); Vector2 viewPosPreviousNew = Vector2Ext.Transform(viewPosPrevious, Portal.GetLinkedMatrix(portal, portal.Linked)); Matrix4 portalMatrixNew = Portal.GetLinkedMatrix(portal.Linked, portal) * portalMatrix; Matrix4 viewMatrixNew = portalMatrixNew * viewMatrix; LineF[] lines = Portal.GetFovLines(portal, viewPos, 500); lines[0] = lines[0].Transform(portalMatrix); lines[1] = lines[1].Transform(portalMatrix); LineF[] linesPrevious = Portal.GetFovLines(portal, viewPosPrevious, 500); linesPrevious[0] = linesPrevious[0].Transform(portalMatrix); linesPrevious[1] = linesPrevious[1].Transform(portalMatrix); LineF portalWorldLine = new LineF(Portal.GetWorldVerts(portal)); portalWorldLine = portalWorldLine.Transform(portalMatrix); PortalView portalViewNew = new PortalView(portalView, viewMatrixNew, viewNewer, lines, linesPrevious, portalWorldLine); foreach (IPortal p in portals) { actionList.Add(() => CalculatePortalViews(p, portal, portals, viewMatrix, viewPosNew, viewPosPreviousNew, portalViewNew, portalMatrixNew, actionList) ); } return true; }