我在世界空间中有几对点,每对都有不同的深度。我想在视图截面的近平面上投射这些点,然后重新计算它们的新世界位置。
注意:我想保持透视效果
为此,我在NDC空间中转换点的位置。我认为NDC空间上具有相同z值的每对点位于同一平面上,与视图方向平行。因此,如果我将z值设置为-1,它们应该位于近平面上。
既然我有新的NDC位置,我需要他们的世界位置,我通过改变深度丢失了w组件,我需要重新计算它。
我找到了这个链接:unproject ndc
其中说:
wclip * inverse(mvp) * vec4(ndc.xyz, 1.0f) = 1.0f
wclip = 1.0f / (inverse(mvp) * vec4(ndc.xyz, 1.0f))
我的完整代码:
glm::vec4 homogeneousClipSpaceLeft = mvp * leftAnchor;
glm::vec4 homogeneousClipSpaceRight = mvp * rightAnchor;
glm::vec3 ndc_left = homogeneousClipSpaceLeft.xyz() / homogeneousClipSpaceLeft.w;
glm::vec3 ndc_right = homogeneousClipSpaceRight.xyz() / homogeneousClipSpaceRight.w;
ndc_left.z = -1.0f;
ndc_right.z = -1.0f;
float clipWLeft = (1.0f / (inverseMVP * glm::vec4(ndc_left, 1.0f)).w);
float clipWRight = (1.0f / (inverseMVP * glm::vec4(ndc_right, 1.0f)).w);
glm::vec3 worldPositionLeft = clipWLeft * inverseMVP * (glm::vec4(ndc_left, 1.0f));
glm::vec3 worldPositionRight = clipWRight * inverseMVP * (glm::vec4(ndc_right, 1.0f));
它应该在实践中起作用,但我得到了奇怪的结果,我从世界空间中的2分开始:
left world position: -116.463 15.6386 -167.327
right world position: 271.014 15.6386 -167.327
left NDC position: -0.59719 0.0790622 -1
right NDC position: 0.722784 0.0790622 -1
final left position: 31.4092 -9.22973 1251.16
final right position: 31.6823 -9.22981 1251.17
mvp
4.83644 0 0 0
0 4.51071 0 0
0 0 -1.0002 -1
-284.584 41.706 1250.66 1252.41
我做错了吗?
你会建议用这种方法将一对点投影到近平面,用透视图吗?
答案 0 :(得分:1)
如果glm::vec3 ndc_left
和glm::vec3 ndc_right
是规范化设备坐标,则下面将坐标投影到标准化设备空间中的近平面:
ndc_left.z = -1.0f;
ndc_right.z = -1.0f;
如果您想在Cartesian coordinates中获取标准化设备空间中某个点的模型位置,则必须通过反转模型视图投影矩阵转换该点并设置x
,{ {1}}和y
组件由结果的z
组件组成。 w
转换不是Homogeneous coordinate:
inverseMVP
请注意,OpenGL Mathematics (GLM)库提供了“unproject”操作。请参阅glm::unProject
。