了解 GLM-openGL 中的相机翻译
understanding camera translation in GLM- openGL
openGL 的 GLM 数学库为 lookAt matrix
的构造提供了此实现。
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
{
vec<3, T, Q> const f(normalize(center - eye));
vec<3, T, Q> const s(normalize(cross(up, f)));
vec<3, T, Q> const u(cross(f, s));
mat<4, 4, T, Q> Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] = f.x;
Result[1][2] = f.y;
Result[2][2] = f.z;
Result[3][0] = -dot(s, eye); //#this
Result[3][1] = -dot(u, eye); //#this
Result[3][2] = -dot(f, eye); //#this
return Result;
}
一切都很好,除了在我用 //#this
标记的最后三行中完成的翻译因素。平移必须针对相机的世界位置 x, y and z
完成,但它是针对相机局部坐标和方向向量的点积完成的,这不可能相等。
考虑一种情况,其中 vector 2*eye
(眼睛是相机的位置)作为 vector center
(中心是目标位置)传递,然后相机的局部 z 轴将与方向重合向量为我们提供相机的平移因子 [0,0,1]
,所以我们基本上只沿着 z-axis
沿着世界移动(因为我们不移动相机,我们会移动世界沿着负方向的 z 轴)这是我们不想要的。我哪里漏掉了重点或者为什么要进行翻译?
glm::lookAt
定义视图矩阵。视图矩阵将顶点坐标从世界 space 转换为视图 space.
eye
、center
和 up
分别是世界 space 中的位置向量,它们定义了相机在世界 space 中的位置和方向。 eye
、center
和 up
定义视图 space。如果你用这个向量设置一个矩阵,那么矩阵将从视图 space 转换为世界 space.
由于视图矩阵必须做相反的事情(世界 space -> 视图 space),视图矩阵是该矩阵的 inverse matrix,它由 eye
、center
和 up
。 glm::lookAt
是在这种特殊情况下计算逆矩阵的优化算法。
注意s
、u
、f
赋值给矩阵的时候是转置的。
逆矩阵的平移是不是矩阵的负平移。逆矩阵的平移必须考虑方向(旋转)。因此必须旋转平移向量。将 (3d) 矢量旋转 3x3 Rotation matrix can be computed by (is the same as) the 3 Dot products 轴矢量和方向矢量。 (s
, u
, f
)定义一个3x3的旋转矩阵,eye
被这个矩阵变换。
代码实际做的是通过转置 (s
, u
, f
) 连接旋转和 -eye
的翻译(非常简化的伪代码):
viewmatrix = transpose(rotation(s, u, f)) * translation(-eye)
一个向量 a 与另一个归一化向量 n 的点积可以被认为是 a 到 n。因此,这里发生的所有事情是 eye
向量被投影到 f
、s
和 u
上,它们是旋转坐标系的基础向量。通过这些投影,我们可以学习x、y和z坐标eye
在f-s-u坐标系中。
openGL 的 GLM 数学库为 lookAt matrix
的构造提供了此实现。
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
{
vec<3, T, Q> const f(normalize(center - eye));
vec<3, T, Q> const s(normalize(cross(up, f)));
vec<3, T, Q> const u(cross(f, s));
mat<4, 4, T, Q> Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] = f.x;
Result[1][2] = f.y;
Result[2][2] = f.z;
Result[3][0] = -dot(s, eye); //#this
Result[3][1] = -dot(u, eye); //#this
Result[3][2] = -dot(f, eye); //#this
return Result;
}
一切都很好,除了在我用 //#this
标记的最后三行中完成的翻译因素。平移必须针对相机的世界位置 x, y and z
完成,但它是针对相机局部坐标和方向向量的点积完成的,这不可能相等。
考虑一种情况,其中 vector 2*eye
(眼睛是相机的位置)作为 vector center
(中心是目标位置)传递,然后相机的局部 z 轴将与方向重合向量为我们提供相机的平移因子 [0,0,1]
,所以我们基本上只沿着 z-axis
沿着世界移动(因为我们不移动相机,我们会移动世界沿着负方向的 z 轴)这是我们不想要的。我哪里漏掉了重点或者为什么要进行翻译?
glm::lookAt
定义视图矩阵。视图矩阵将顶点坐标从世界 space 转换为视图 space.
eye
、center
和 up
分别是世界 space 中的位置向量,它们定义了相机在世界 space 中的位置和方向。 eye
、center
和 up
定义视图 space。如果你用这个向量设置一个矩阵,那么矩阵将从视图 space 转换为世界 space.
由于视图矩阵必须做相反的事情(世界 space -> 视图 space),视图矩阵是该矩阵的 inverse matrix,它由 eye
、center
和 up
。 glm::lookAt
是在这种特殊情况下计算逆矩阵的优化算法。
注意s
、u
、f
赋值给矩阵的时候是转置的。
逆矩阵的平移是不是矩阵的负平移。逆矩阵的平移必须考虑方向(旋转)。因此必须旋转平移向量。将 (3d) 矢量旋转 3x3 Rotation matrix can be computed by (is the same as) the 3 Dot products 轴矢量和方向矢量。 (s
, u
, f
)定义一个3x3的旋转矩阵,eye
被这个矩阵变换。
代码实际做的是通过转置 (s
, u
, f
) 连接旋转和 -eye
的翻译(非常简化的伪代码):
viewmatrix = transpose(rotation(s, u, f)) * translation(-eye)
一个向量 a 与另一个归一化向量 n 的点积可以被认为是 a 到 n。因此,这里发生的所有事情是 eye
向量被投影到 f
、s
和 u
上,它们是旋转坐标系的基础向量。通过这些投影,我们可以学习x、y和z坐标eye
在f-s-u坐标系中。