4

从我 13 岁开始使用 AMOS 3D 开始,我就一直想学习如何编写 3D 图形。现在,10 年后,我终于认为我已经积累了足够的数学知识来尝试一下。

我遵循了各种教程,并将screenX(和screenY,等效地)定义为

screenX = (pointX * cameraX) / distance

(加上偏移和缩放。)

我的问题是距离变量实际指的是什么。我已经看到距离被定义为相机和点之间的 z 差。但是,这并不完全正确,因为 x 和 y 对从相机到该点的实际距离具有与 z 相同的效果。我将距离实现为实际距离,但结果给出了一个有点倾斜的视角,好像它有“太多”的视角。

我的“实际距离”实现大致如下:

distance = new Vector(pointX, pointY, cameraZ - pointZ).magnitude()

使用代码,我在方程中添加了一个额外的变量,一个透视系数,如下所示:

distance = new Vector(pointX * perspectiveCoefficient, 
  pointY * perspectiveCoefficient, cameraZ - pointZ).magnitude()

出于某种原因,这超出了我的范围,我倾向于将透视系数设置为 1/sqrt(2) 以获得最佳结果。

我的 3D 测试立方体位于http://vega.soi.city.ac.uk/~abdv866/3dcubetest/3dtest.svg。(在 Safari 和 FF 中测试。)它会提示您输入透视系数,其中 0 给出不考虑 x/y 距离的透视,而 1 给出同样考虑 x、y 和 z 距离的透视。默认为 1/sqrt(2)。立方体可以使用箭头键围绕 x 和 y 旋转。(任何有兴趣的人,相关代码都在 View.js 文件的 update() 中。)

感谢您对此的任何想法。

4

1 回答 1

5

通常,从该平面后面的眼睛位置在 Z=0 平面上进行投影。投影点是线 (Pt,Eye) 与 Z=0 平面的交点。最后你会得到类似的东西:

screenX = scaling * pointX / (1 + pointZ/eyeDist)
screenY = scaling * pointY / (1 + pointZ/eyeDist)

我假设相机在 (0,0,0) 并且眼睛在 (0,0,-eyeDist)。如果 eyeDist 变为无穷大,则获得平行投影。

于 2009-07-12T15:15:28.243 回答