From e25e3d7bb69c062d1988e149fd87d51e71619210 Mon Sep 17 00:00:00 2001 From: Mouse Date: Tue, 2 Jul 2019 17:48:00 +0800 Subject: [PATCH] fix math errors --- docs/23-3d-object-picking.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/23-3d-object-picking.md b/docs/23-3d-object-picking.md index f12e98c..8e94031 100644 --- a/docs/23-3d-object-picking.md +++ b/docs/23-3d-object-picking.md @@ -16,7 +16,7 @@ private boolean selected; in float outSelected; ``` -然后,在片元着色器的结尾,我们将修改最终的片元颜色,如果选中,则将蓝色分量设置为$$1$$. +然后,在片元着色器的结尾,我们将修改最终的片元颜色,如果选中,则将蓝色分量设置为$1$. ```glsl if ( outSelected > 0 ) { @@ -132,16 +132,16 @@ this.selectDetector.selectGameItem(gameItems, camera); 实现它的方法类似于上述方法。在之前的方法中,我们得到了摄像机的位置,并根据摄像机当前的方向使用“前向”方向从摄像机生成射线。在此情况下,我们仍需要投射广西,但方向指向一个远离摄像机的点,也就是点击的点。在本例中,我们需要使用点击的坐标来计算方向向量。 -但是,我们如何将视口空间中的$$(x,y)$$坐标变换到世界空间呢?让我们回顾一下如何从模型空间坐标变换到观察空间。为了达到这个目的,所应用的不同坐标变换是: +但是,我们如何将视口空间中的$(x,y)$坐标变换到世界空间呢?让我们回顾一下如何从模型空间坐标变换到观察空间。为了达到这个目的,所应用的不同坐标变换是: * 我们使用模型矩阵将模型坐标变换到世界坐标。 * 我们使用观察矩阵(提供摄像机功能)将世界坐标转换到观察空间坐标。 * 我们通过应用透视投影矩阵将观察坐标变换到齐次裁剪空间(Homogeneous Clip Space)。 -* 最终的屏幕坐标由OpenGL为我们自动计算。在此之前,它传递到归一化的终端空间(通过将$$x,y,z$$坐标除以$$w$$分量),然后传递到$$x,y$$屏幕坐标。 +* 最终的屏幕坐标由OpenGL为我们自动计算。在此之前,它传递到归一化的终端空间(通过将$x,y,z$坐标除以$w$分量),然后传递到$x,y$屏幕坐标。 -所以我们只需要从屏幕坐标$$(x,y)$$到世界坐标,逆路径遍历。 +所以我们只需要从屏幕坐标$(x,y)$到世界坐标,逆路径遍历。 -第一步是将屏幕坐标转换为归一化的终端空间。视口空间中的$$(x,y)$$坐标的范围是$$[0, 屏幕宽度]$$ $$[0, 屏幕高度]$$。屏幕左上角的坐标为$$(0, 0)$$。我们需要将其转换为$$[-1, 1]$$范围内的坐标。 +第一步是将屏幕坐标转换为归一化的终端空间。视口空间中的$(x,y)$坐标的范围是$[0, 屏幕宽度]$ $[0, 屏幕高度]$。屏幕左上角的坐标为$(0, 0)$。我们需要将其转换为$[-1, 1]$范围内的坐标。 ![屏幕坐标到归一化终端空间](_static/23/screen_coordinates.png) @@ -151,17 +151,17 @@ $$x = 2 \cdot screen_x / screenwidth - 1$$ $$y = 1 - 2 * screen_y / screenheight$$ -但是,我们如何计算$$z$$分量呢?答案很简单,我们只需给它分配$$-1$$值,这样广西就可以指向最远的可见距离(请记住,在OpenGL中,$$-1$$指向频幕)。现在我们有了归一化终端空间中的坐标。 +但是,我们如何计算$z$分量呢?答案很简单,我们只需给它分配$-1$值,这样广西就可以指向最远的可见距离(请记住,在OpenGL中,$-1$指向频幕)。现在我们有了归一化终端空间中的坐标。 -为了继续变换,我们需要将它们转换为齐次剪切空间。我们需要有一个$$w$$分量,它使用齐次坐标。虽然这个概念在前几章已经介绍过了,但让我们再回顾它。为了表示一个三维点,我们需要$$x$$,$$y$$和$$z$$分量,但是我们一直在处理一个额外的$$w$$分量。我们需要这个额外的分量来使用矩阵执行不同的变换。有些变化不需要这个额外的分量,但有些变换需要。例如,如果我们只有$$x$$,$$y$$和$$z$$分量,那么变换矩阵就不能工作。因此,我们添加了$$w$$分量,并为它们赋值为$$1$$,这样我们就可以处理4x4矩阵了。 +为了继续变换,我们需要将它们转换为齐次剪切空间。我们需要有一个$w$分量,它使用齐次坐标。虽然这个概念在前几章已经介绍过了,但让我们再回顾它。为了表示一个三维点,我们需要$x$,$y$和$z$分量,但是我们一直在处理一个额外的$w$分量。我们需要这个额外的分量来使用矩阵执行不同的变换。有些变化不需要这个额外的分量,但有些变换需要。例如,如果我们只有$x$,$y$和$z$分量,那么变换矩阵就不能工作。因此,我们添加了$w$分量,并为它们赋值为$1$,这样我们就可以处理4x4矩阵了。 -此外,大多数变换,或者更精确地说,大多数变换矩阵都不会更改$$w$$分量。投影矩阵是一个例外,该矩阵将$$w$$分量更改为与$$z$$分量成比例。 +此外,大多数变换,或者更精确地说,大多数变换矩阵都不会更改$w$分量。投影矩阵是一个例外,该矩阵将$w$分量更改为与$z$分量成比例。 -通过将$$x$$,$$y$$和$$z$$分量处以$$w$$,就可以实现从齐次裁剪空间到归一化的终端坐标的转换。由于这个分量与$$z$$分量成比例,意味着远处的物体被画得更小。在本例中,需要反其道而行之,我们可以忽略这一步,只需要将$$w$$分量设置为$$1$$,并保留其它组件的原始值。 +通过将$x$,$y$和$z$分量处以$w$,就可以实现从齐次裁剪空间到归一化的终端坐标的转换。由于这个分量与$z$分量成比例,意味着远处的物体被画得更小。在本例中,需要反其道而行之,我们可以忽略这一步,只需要将$w$分量设置为$1$,并保留其它组件的原始值。 我们现在需要回到观察空间。这很简单,我们只需要计算投影矩阵的逆矩阵并将它与4个分量向量相乘。完成之后,我们就需要把它们转换成世界空间。同样,我们只需要使用观察矩阵,计算它的逆矩阵然后乘以向量。 -记住,我们只对方向感兴趣,因此,在本例中,我们将$$w$$分量设置为$$0$$。我们还可以将$$z$$组件再次设置为$$-1$$,因为我们希望它指向频幕。一旦这样做并应用逆矩阵,我们就得到了世界空间中的向量。我们计算了射线,可以使用与摄像机选取相同的算法。 +记住,我们只对方向感兴趣,因此,在本例中,我们将$w$分量设置为$0$。我们还可以将$z$组件再次设置为$-1$,因为我们希望它指向频幕。一旦这样做并应用逆矩阵,我们就得到了世界空间中的向量。我们计算了射线,可以使用与摄像机选取相同的算法。 我们创建了一个名为`MouseBoxSelectionDetector`的新类,它实现了上述步骤。此外,我们将投影矩阵移动到`Window`类,所以我们可以在几个地方使用它们。我们还重构了一点`CameraBoxSelectionDetector`,所以`MouseBoxSelectionDetector`可以继承和使用碰撞检测方法。你可以直接查看源代码,因为实现非常简单。