根据3D Programming for Windows(Charles Petzold)第7章中的信息,我试图编写一个辅助函数,将Point3D投影到包含相应屏幕坐标(x,y)的标准2D点:
public Point Point3DToScreen2D(Point3D point3D,Viewport3D viewPort )
{
double screenX = 0d, screenY = 0d;
// Camera is defined in XAML as:
// <Viewport3D.Camera>
// <PerspectiveCamera Position="0,0,800" LookDirection="0,0,-1" />
// </Viewport3D.Camera>
PerspectiveCamera cam = viewPort.Camera as PerspectiveCamera;
// Translate input point using camera position
double inputX = point3D.X - cam.Position.X;
double inputY = point3D.Y - cam.Position.Y;
double inputZ = point3D.Z - cam.Position.Z;
double aspectRatio = viewPort.ActualWidth / viewPort.ActualHeight;
// Apply projection to X and Y
screenX = inputX / (-inputZ * Math.Tan(cam.FieldOfView / 2));
screenY = (inputY * aspectRatio) / (-inputZ * Math.Tan(cam.FieldOfView / 2));
// Convert to screen coordinates
screenX = screenX * viewPort.ActualWidth;
screenY = screenY * viewPort.ActualHeight;
// Additional, currently unused, projection scaling factors
/*
double xScale = 1 / Math.Tan(Math.PI * cam.FieldOfView / 360);
double yScale = aspectRatio * xScale;
double zFar = cam.FarPlaneDistance;
double zNear = cam.NearPlaneDistance;
double zScale = zFar == Double.PositiveInfinity ? -1 : zFar / (zNear - zFar);
double zOffset = zNear * zScale;
*/
return new Point(screenX, screenY);
}
Run Code Online (Sandbox Code Playgroud)
然而,在测试时,此函数返回不正确的屏幕坐标(通过将2D鼠标坐标与简单的3D形状进行比较来检查).由于我缺乏3D编程经验,我很困惑为什么.
块注释部分包含可能必不可少的缩放计算,但是我不确定如何,并且本书继续使用XAML的MatrixCamera.最初,我只是希望得到一个基本的计算工作,无论它与矩阵相比效率如何.
任何人都可以建议需要添加或更改的内容吗?
由于 Windows 坐标是屏幕中的 z(x 交叉 y),所以我会使用类似的东西
screenY = viewPort.ActualHeight * (1 - screenY);
Run Code Online (Sandbox Code Playgroud)
代替
screenY = screenY * viewPort.ActualHeight;
Run Code Online (Sandbox Code Playgroud)
更正 screenY 以适应 Windows。
或者,您可以使用 OpenGL。当您设置视口 x/y/z 范围时,您可以将其保留为“本机”单位,并让 OpenGL 转换为屏幕坐标。
编辑:因为你的原点是中心。我会尝试
screenX = viewPort.ActualWidth * (screenX + 1.0) / 2.0
screenY = viewPort.ActualHeight * (1.0 - ((screenY + 1.0) / 2.0))
Run Code Online (Sandbox Code Playgroud)
屏幕 + 1.0 从 [-1.0, 1.0] 转换为 [0.0, 2.0]。此时,除以 2.0 即可得到 [0.0, 1.0] 进行乘法。为了考虑到 Windows y 从笛卡尔 y 翻转,您可以通过从 1.0 减去前一个屏幕来从 [1.0, 0.0](从左上到左下)转换为 [0.0, 1.0](从上到下)。然后,您可以缩放到实际高度。