code_junkie

Projecting a 3D point to a 2D screen coordinate

Nov 14th, 2011
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.79 KB | None | 0 0
  1. public Point Point3DToScreen2D(Point3D point3D,Viewport3D viewPort )
  2. {
  3. double screenX = 0d, screenY = 0d;
  4.  
  5. // Camera is defined in XAML as:
  6. // <Viewport3D.Camera>
  7. // <PerspectiveCamera Position="0,0,800" LookDirection="0,0,-1" />
  8. // </Viewport3D.Camera>
  9.  
  10. PerspectiveCamera cam = viewPort.Camera as PerspectiveCamera;
  11.  
  12. // Translate input point using camera position
  13. double inputX = point3D.X - cam.Position.X;
  14. double inputY = point3D.Y - cam.Position.Y;
  15. double inputZ = point3D.Z - cam.Position.Z;
  16.  
  17. double aspectRatio = viewPort.ActualWidth / viewPort.ActualHeight;
  18.  
  19. // Apply projection to X and Y
  20. screenX = inputX / (-inputZ * Math.Tan(cam.FieldOfView / 2));
  21.  
  22. screenY = (inputY * aspectRatio) / (-inputZ * Math.Tan(cam.FieldOfView / 2));
  23.  
  24. // Convert to screen coordinates
  25. screenX = screenX * viewPort.ActualWidth;
  26.  
  27. screenY = screenY * viewPort.ActualHeight;
  28.  
  29.  
  30. // Additional, currently unused, projection scaling factors
  31. /*
  32. double xScale = 1 / Math.Tan(Math.PI * cam.FieldOfView / 360);
  33. double yScale = aspectRatio * xScale;
  34.  
  35. double zFar = cam.FarPlaneDistance;
  36. double zNear = cam.NearPlaneDistance;
  37.  
  38. double zScale = zFar == Double.PositiveInfinity ? -1 : zFar / (zNear - zFar);
  39. double zOffset = zNear * zScale;
  40.  
  41. */
  42.  
  43. return new Point(screenX, screenY);
  44. }
  45.  
  46. screenY = viewPort.ActualHeight * (1 - screenY);
  47.  
  48. screenY = screenY * viewPort.ActualHeight;
  49.  
  50. screenX = viewPort.ActualWidth * (screenX + 1.0) / 2.0
  51. screenY = viewPort.ActualHeight * (1.0 - ((screenY + 1.0) / 2.0))
  52.  
  53. /// <summary>
  54. /// Takes a 3D point and returns the corresponding 2D point (X,Y) within the viewport.
  55. /// Requires the 3DUtils project available at http://www.codeplex.com/Wiki/View.aspx?ProjectName=3DTools
  56. /// </summary>
  57. /// <param name="point3D">A point in 3D space</param>
  58. /// <param name="viewPort">An instance of Viewport3D</param>
  59. /// <returns>The corresponding 2D point or null if it could not be calculated</returns>
  60. public Point? Point3DToScreen2D(Point3D point3D, Viewport3D viewPort)
  61. {
  62. bool bOK = false;
  63.  
  64. // We need a Viewport3DVisual but we only have a Viewport3D.
  65. Viewport3DVisual vpv =VisualTreeHelper.GetParent(viewPort.Children[0]) as Viewport3DVisual;
  66.  
  67. // Get the world to viewport transform matrix
  68. Matrix3D m = MathUtils.TryWorldToViewportTransform(vpv, out bOK);
  69.  
  70. if (bOK)
  71. {
  72. // Transform the 3D point to 2D
  73. Point3D transformedPoint = m.Transform(point3D);
  74.  
  75. Point screen2DPoint = new Point(transformedPoint.X, transformedPoint.Y);
  76.  
  77. return new Nullable<Point>(screen2DPoint);
  78. }
  79. else
  80. {
  81. return null;
  82. }
  83. }
  84.  
  85. y
  86. |
  87. |
  88. +------x
  89.  
  90. +-------x
  91. |
  92. |
  93. |
  94. y
  95.  
  96. void CompositionTarget_Rendering(object sender, EventArgs e)
  97. {
  98. UpdateWireframe();
  99. }
  100.  
  101. void UpdateWireframe()
  102. {
  103. GeometryModel3D model = cube.Content as GeometryModel3D;
  104.  
  105. canvas.Children.Clear();
  106.  
  107. if (model != null)
  108. {
  109. GeneralTransform3DTo2D transform = cube.TransformToAncestor(viewport);
  110. MeshGeometry3D geometry = model.Geometry as MeshGeometry3D;
  111.  
  112. for (int i = 0; i < geometry.TriangleIndices.Count;)
  113. {
  114. Polygon p = new Polygon();
  115. p.Stroke = Brushes.Blue;
  116. p.StrokeThickness = 0.25;
  117. p.Points.Add(transform.Transform(geometry.Positions[geometry.TriangleIndices[i++]]));
  118. p.Points.Add(transform.Transform(geometry.Positions[geometry.TriangleIndices[i++]]));
  119. p.Points.Add(transform.Transform(geometry.Positions[geometry.TriangleIndices[i++]]));
  120. canvas.Children.Add(p);
  121. }
  122. }
  123. }
Add Comment
Please, Sign In to add comment