Draw infinite world axes

With the following class derived from ViewportLayout you can draw the infinite world axes as shown in the following image:

 

The axes are drawn in 3 overridden methods:

DrawViewportBackground: the part of the axes beyond the far plane

DrawViewport: the part between the camera planes

DrawOverlay: the part nearer than the camera near plane

[Update] The code has been improved to support multiple Viewports. Requires Eyeshot 9 >= 9.0.490 or Eyeshot 10 >= 10.0.859

    internal class MyViewportLayout : devDept.Eyeshot.ViewportLayout
    {
        protected override void DrawViewportBackground(DrawSceneParams data)
        {
            base.DrawViewportBackground(data);

            ComputeNearFarIntersections(data.Viewport);

            var rc = data.RenderContext;
            rc.PushDepthStencilState();

            rc.SetState(depthStencilStateType.DepthTestOff);
            rc.SetShader(shaderType.NoLights);

            // Draw in 2D the parts of the lines beyond the far camera plane

            // X axis 
            DrawLinesBeyondFar(data.Viewport, ptXNear, ptXFar, Color.Red);

            // Y axis 
            DrawLinesBeyondFar(data.Viewport, ptYNear, ptYFar, Color.Green);

            // Z axis 
            DrawLinesBeyondFar(data.Viewport, ptZNear, ptZFar, Color.Blue);

            rc.PopDepthStencilState();
        }

        private void ComputeNearFarIntersections(Viewport viewport)
        {
            Plane farPlane = viewport.Camera.FarPlane;
            Plane nearPlane = viewport.Camera.NearPlane;

            Segment3D sX = new Segment3D(0, 0, 0, 1, 0, 0);
            Segment3D sY = new Segment3D(0, 0, 0, 0, 1, 0);
            Segment3D sZ = new Segment3D(0, 0, 0, 0, 0, 1);

            // Compute the intersections with the camera planes
            sX.IntersectWith(nearPlane, true, out ptXNear);
            sX.IntersectWith(farPlane, true, out ptXFar);

            sY.IntersectWith(nearPlane, true, out ptYNear);
            sY.IntersectWith(farPlane, true, out ptYFar);

            sZ.IntersectWith(nearPlane, true, out ptZNear);
            sZ.IntersectWith(farPlane, true, out ptZFar);
        }

        // Intersections with the camera planes
        Point3D ptXNear, ptXFar, ptYNear, ptYFar, ptZNear, ptZFar;

        protected override void DrawViewport(DrawSceneParams myParams)
        {
            base.DrawViewport(myParams);

            var rc = myParams.RenderContext;

            rc.SetShader(shaderType.NoLights);

            // Draw the 3D lines between the camera planes

            if (ptXNear != null && ptXFar != null)
            {
                rc.SetColorWireframe(Color.Red);
                rc.DrawLines(new Point3D[] {ptXNear, ptXFar});
            }

            if (ptYNear != null && ptYFar != null)
            {
                rc.SetColorWireframe(Color.Green);
                rc.DrawLines(new Point3D[] {ptYNear, ptYFar});
            }

            if (ptZNear != null && ptZFar != null)
            {
                rc.SetColorWireframe(Color.Blue);
                rc.DrawLines(new Point3D[] {ptZNear, ptZFar});
            }

        }

        protected override void DrawOverlay(DrawSceneParams data)
        {
            // Draw in 2D the parts of the lines before the near camera plane
            renderContext.SetShader(shaderType.NoLights);

            for (int i = 0; i < Viewports.Count; i++)
            {
                ComputeNearFarIntersections(Viewports[i]);

                // X axis 
                DrawLinesBeforeNear(Viewports[i], ptXNear, ptXFar, Color.Red);

                // Y axis 
                DrawLinesBeforeNear(Viewports[i], ptYNear, ptYFar, Color.Green);

                // Z axis 
                DrawLinesBeforeNear(Viewports[i], ptZNear, ptZFar, Color.Blue);
            }
        }

        private void DrawLinesBeyondFar(Viewport viewport, Point3D nearPt, Point3D farPt, Color color)
        {
            if (farPt == null || nearPt == null)
                return;

            Vector3D dir = Vector3D.Subtract(farPt, nearPt);
            dir.Normalize();

            if (viewport == null)
                viewport = Viewports[ActiveViewport];

            Point3D pt1 = viewport.WorldToScreen(farPt);
            Point3D pt2 = viewport.WorldToScreen(farPt + dir);
            DrawLine(viewport, pt1, pt2, color, true);
        }

        private void DrawLinesBeforeNear(Viewport viewport, Point3D nearPt, Point3D farPt, Color color)
        {
            if (farPt == null || nearPt == null)
                return;

            Vector3D dir = Vector3D.Subtract(farPt, nearPt);
            dir.Normalize();

            if (viewport == null)
                viewport = Viewports[ActiveViewport];

            var pt1 = viewport.WorldToScreen(nearPt);
            var pt2 = viewport.WorldToScreen(nearPt - dir);
            DrawLine(viewport, pt1, pt2, color, false);
        }

        private void DrawLine(Viewport viewport, Point3D pt1, Point3D pt2, Color color, bool convertToViewport)
        {
            if (pt1 == null || pt2 == null)
                return;

            Segment2D screenLine = new Segment2D(pt1, pt2);

            int[] viewFrame = viewport.GetViewFrame();

            double left = viewFrame[0];
            double right = viewFrame[0] + viewFrame[2];
            double bottom = viewFrame[1];
            double top = viewFrame[1] + viewFrame[3] - 1;
            Point2D lowerLeft = new Point2D(left, bottom);
            Point2D lowerRight = new Point2D(right, bottom);
            Point2D upperLeft = new Point2D(left, top);
            Point2D upperRight = new Point2D(right, top);


            Segment2D[] screenLines = new Segment2D[]
            {
                new Segment2D(lowerLeft, lowerRight),
                new Segment2D(upperLeft, upperRight),
                new Segment2D(lowerLeft, upperLeft),
                new Segment2D(lowerRight, upperRight)
            };

            Point2D ptAxis1 = null, ptAxis2 = null;

            Vector2D dir = Vector2D.Subtract(pt2, pt1);
            dir.Normalize();

            // extend the segment outside the window limits
            screenLine.P1 = screenLine.P0 + dir*(viewport.Size.Width + viewport.Size.Height);

            // Compute the intersection of the screen line against the lower and upper border of the viewport 
            Segment2D.Intersection(screenLine, screenLines[0], out ptAxis1);
            Segment2D.Intersection(screenLine, screenLines[1], out ptAxis2);

            if (ptAxis1 != null)

                screenLine.P1 = ptAxis1;

            if (ptAxis2 != null)

                screenLine.P1 = ptAxis2;

            bool clipAgainstVertical = true;

            // Compute the intersection of the infinite screen line against the left and right border of the viewport 
            Segment2D.Intersection(screenLine, screenLines[2], out ptAxis1);
            Segment2D.Intersection(screenLine, screenLines[3], out ptAxis2);

            if (ptAxis1 != null)

                screenLine.P1 = ptAxis1;

            if (ptAxis2 != null)

                screenLine.P1 = ptAxis2;

            renderContext.SetLineSize(1);
            renderContext.EnableThickLines();
            renderContext.SetColorWireframe(color);

            var tol = 1e-6;

            // Consider some tolerance
            if (screenLine.P0.X >= left - tol && screenLine.P0.X <= right + tol &&
                screenLine.P0.Y >= bottom - tol && screenLine.P0.Y <= top + tol &&
                screenLine.P1.X >= left - tol && screenLine.P1.X <= right + tol &&
                screenLine.P1.Y >= bottom - tol && screenLine.P1.Y <= top + tol)
            {
                if (convertToViewport)
                {
                    // When drawing the lines beyond far inside the DrawViewportBackground, the camera is set to just the Viewport, not to the whole ViewportLayout,
                    // so if we have multiple viewports we must adjust the screen coordinates
                    screenLine.P0 = new Point2D(screenLine.P0.X - left, screenLine.P0.Y - bottom);
                    screenLine.P1 = new Point2D(screenLine.P1.X - left, screenLine.P1.Y - bottom);
                }

                renderContext.DrawLines(new float[]
                {
                    (float) screenLine.P0.X, (float) screenLine.P0.Y, 0,
                    (float) screenLine.P1.X, (float) screenLine.P1.Y, 0
                });
            }
        }
    }

 

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.