예제 #1
0
 public PortalView(PortalView parent, Matrix4 viewMatrix, List<List<IntPoint>> path, LineF[] fovLines, LineF[] fovLinesPrevious, LineF portalLine)
 {
     PortalLine = portalLine;
     FovLines = fovLines;
     FovLinesPrevious = fovLinesPrevious;
     Children = new List<PortalView>();
     Parent = parent;
     if (Parent != null)
     {
         Parent.Children.Add(this);
     }
     ViewMatrix = viewMatrix;
     Paths = path;
 }
예제 #2
0
        public static PortalView CalculatePortalViews(IList<IPortal> portals, ICamera2 camera, int depth)
        {
            Debug.Assert(camera != null);
            Debug.Assert(depth >= 0);
            Debug.Assert(portals != null);
            List<IntPoint> view = ClipperConvert.ToIntPoint(CameraExt.GetWorldVerts(camera));
            List<List<IntPoint>> paths = new List<List<IntPoint>>();
            paths.Add(view);
            PortalView portalView = new PortalView(null, CameraExt.GetViewMatrix(camera), view, new LineF[0], new LineF[0]);
            Vector2 camPos = camera.GetWorldTransform().Position;

            List<Func<bool>> actionList = new List<Func<bool>>();

            foreach (IPortal p in portals)
            {
                actionList.Add(() => CalculatePortalViews(p, null, portals, CameraExt.GetViewMatrix(camera), camPos, camPos - camera.GetWorldVelocity().Position / Controller.DrawsPerSecond, portalView, Matrix4.Identity, actionList));
            }

            while (actionList.Count > 0 && depth > 0)
            {
                bool result = actionList.First().Invoke();
                if (result)
                {
                    depth--;
                }
                actionList.RemoveAt(0);
            }

            return portalView;
        }
예제 #3
0
        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;
        }
예제 #4
0
 public PortalView(PortalView parent, Matrix4 viewMatrix, List<IntPoint> path, LineF[] fovLines, LineF[] fovLinesPrevious)
     : this(parent, viewMatrix, new List<List<IntPoint>>(), fovLines, fovLinesPrevious, null)
 {
     Paths.Add(path);
 }
예제 #5
0
파일: Renderer.cs 프로젝트: AyyTee/Aventyr
        /// <summary>Sets scissor region around a portalview.</summary>
        /// <param name="viewMatrix">Camera view matrix, do not use view matrix for the portalview.</param>
        private void SetScissor(PortalView view, Matrix4 viewMatrix)
        {
            Debug.Assert(view != null);
            if (view.Paths == null)
            {
                ResetScissor();
                return;
            }
            Matrix4 ScaleMatrix;
            ScaleMatrix = viewMatrix * Matrix4.CreateTranslation(new Vector3(1, 1, 0));
            ScaleMatrix = ScaleMatrix * Matrix4.CreateScale(new Vector3(CanvasSize.Width / (float)2, CanvasSize.Height / (float)2, 0));

            Vector2 vMin, vMax;
            vMin = ClipperConvert.ToVector2(view.Paths[0][0]);
            vMax = ClipperConvert.ToVector2(view.Paths[0][0]);
            for (int i = 0; i < view.Paths.Count; i++)
            {
                for (int j = 0; j < view.Paths[i].Count; j++)
                {
                    Vector2 vTransform = Vector2Ext.Transform(ClipperConvert.ToVector2(view.Paths[i][j]), ScaleMatrix);
                    vMax = Vector2.ComponentMax(vMax, vTransform);
                    vMin = Vector2.ComponentMin(vMin, vTransform);
                }
            }
            //The -1 and +3 are margins to prevent rounding errors from making the scissor box too small.
            GL.Scissor((int)vMin.X - 1, (int)vMin.Y - 1, (int)(vMax.X - vMin.X) + 3, (int)(vMax.Y - vMin.Y) + 3);
        }