Draw Infinite world axes

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

Capture.PNG

namespace WindowsApplication1 
{ 
    internal class MyViewportLayout : SingleViewportLayout 
    { 
         
        protected override void DrawOverlay(DrawSceneParams myParams) 
        { 
            base.DrawOverlay(myParams); 

            Point3D pt1 = WorldToScreen(0, 0, 0); 

            // X axis 
            Point3D pt2 = WorldToScreen(1, 0, 0); 
            DrawInfiniteLine(pt1, pt2, Color.Red); 

            // Y axis 
            pt2 = WorldToScreen(0, 1, 0); 
            DrawInfiniteLine(pt1, pt2, Color.Green); 

            // Z axis 
            pt2 = WorldToScreen(0, 0, 1); 
            DrawInfiniteLine(pt1, pt2, Color.Blue); 

        } 

        private void DrawInfiniteLine(Point3D pt1, Point3D pt2, Color color) 
        { 
            Viewport viewport = Viewports[ActiveViewport]; 

            Segment2D screenLineX = new Segment2D(pt1, pt2); 

            int[] viewFrame = new int[] 
                                  { 
                                      viewport.Location.X, 
                                      Height - viewport.Location.Y - viewport.Size.Height, 
                                      viewport.Size.Width, 
                                      viewport.Size.Height 
                                  }; 
            int left = viewFrame[0]; 
            int right = viewFrame[0] + viewFrame[2]; 
            int bottom = viewFrame[1]; 
            int 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; 

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

            bool clipAgainstVertical = true; 

            if (ptAxis1 == null || ptAxis2 == null) 
            { 
                // Compute the intersection of the infinite screen line against the left and right border of the viewport 
                clipAgainstVertical = false; 
                Segment2D.IntersectionLine(screenLineX, screenLines[2], out ptAxis1); 
                Segment2D.IntersectionLine(screenLineX, screenLines[3], out ptAxis2); 
            } 

            if (ptAxis1 != null && ptAxis2 != null) 
            { 
                Segment2D myLine = new Segment2D(ptAxis1, ptAxis2); 

                Point2D clippedPt1 = null, clippedPt2 = null; 

                if (ptAxis1.X < ptAxis2.X) 
                { 
                    clippedPt1 = ptAxis1; 
                    clippedPt2 = ptAxis2; 
                } 
                else 
                { 
                    clippedPt2 = ptAxis1; 
                    clippedPt1 = ptAxis2; 
                } 

                // Compute the intersection of the screen line against the other 2 borders of the viewport 
                Point2D clipped; 
                if (Segment2D.Intersection(myLine, screenLines[(clipAgainstVertical) ? 2 : 0], out clipped)) 
                    clippedPt1 = clipped; 

                if (Segment2D.Intersection(myLine, screenLines[(clipAgainstVertical) ? 3 : 1], out clipped)) 
                    clippedPt2 = clipped; 

                renderContext.SetLineSize(1);
                renderContext.EnableThickLines();
                renderContext.SetColorWireframe(color);
                renderContext.DrawLines(new float[]
                {
                    (float) clippedPt1.X, (float) clippedPt1.Y, 0,
                    (float) clippedPt2.X, (float) clippedPt2.Y, 0
                });
} } } }

 

The above method draws the axes in 2D above all the scene geometry. To have the axes in 3D, so that they mix well with the scene and the entities can hide parts of them, we need to use a slightly different approach, drawing in 3D the parts of the axes between the Camera planes and in 2D the parts outside the camera planes: 

Capture.PNG

 

Here is the code (Eyeshot build 8.0.423 or greater is needed):

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

        Plane farPlane  = data.Viewport.Camera.FarPlane;
        Plane nearPlane = data.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);


        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(ptXNear, ptXFar, Color.Red);

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

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

        rc.PopDepthStencilState();
    }

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

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

        var rc = myParams.RenderContext;

        // Save some states
        rc.PushMatrices();
        rc.PushDepthStencilState();

        // Set the matrices to draw in 3D
        rc.SetViewport(myParams.ViewFrame, (float)RenderContextBase.OverlayDepthRange, 1);
        rc.SetMatrices(myParams.Viewport.Camera.ProjectionMatrix, myParams.Viewport.Camera.ModelViewMatrix);
        rc.SetState(depthStencilStateType.DepthTestLEQUAL);
        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});
        }

        // Restore some states
            rc.PopMatrices();
        rc.SetViewport(myParams.ViewFrame, 0, (float)RenderContextBase.OverlayDepthRange);
        rc.PopDepthStencilState();

        // Draw in 2D the parts of the lines before the near camera plane
        rc.SetShader(shaderType.NoLights);

        // X axis 
        DrawLinesBeforeNear(ptXNear, ptXFar, Color.Red);

        // Y axis 
        DrawLinesBeforeNear(ptYNear, ptYFar, Color.Green);

        // Z axis 
        DrawLinesBeforeNear(ptZNear, ptZFar, Color.Blue);

        rc.PopDepthStencilState();
    }

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

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

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

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

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

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

    private void DrawLine(Point3D pt1, Point3D pt2, Color color)
    {
            if (pt1 == null || pt2 == null)
                return;
            Viewport viewport = Viewports[ActiveViewport];

        Segment2D screenLine = new Segment2D(pt1, pt2);

        int[] viewFrame = new int[]
                                {
                                viewport.Location.X,
                                Height - viewport.Location.Y - viewport.Size.Height,
                                viewport.Size.Width,
                                viewport.Size.Height
                                };
        int left = viewFrame[0];
        int right = viewFrame[0] + viewFrame[2];
        int bottom = viewFrame[1];
        int 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 * (Width + 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);

        bool clipAgainstVertical = true;

        if (ptAxis1 == null || ptAxis2 == null)
        {
            // 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;

        else if (ptAxis2 != null)

            screenLine.P1 = ptAxis2;

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

        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.