With the following class derived from ViewportLayout you can draw the infinite world axes as shown in the following image:
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:
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 }); } }
Previous versions of this article: Eyeshot 7
Comments
Please sign in to leave a comment.