简单的测试代码
glm::mat4 m = glm::rotate(glm::mat4(1.0f), 0.78f, glm::vec3(0,1,0));
while (true) {
glm::vec3 axis = glm::normalize(glm::vec3(m[0])); // right vector
PRINT_VEC("{0:.3f} {1:.3f} {2:.3f}", axis.x, axis.y, axis.z);
m = glm::rotate(m, glm::radians(5.f), axis); // 5 degrees each iteration
}
Run Code Online (Sandbox Code Playgroud)
因此,假设我有一个模型矩阵,它从恒等式绕 y 轴旋转 0.78 弧度,那么每一帧我都会围绕局部右向量旋转,该向量是矩阵的第一列(假设是右手系统)。由于右向量是我旋转的轴,因此我希望它是恒定的,但事实并非如此。我不明白为什么glm::rotate还要改变旋转轴。
输出变化相当大,所以我不认为这是浮点精度错误。
0.657 -0.424 -0.623
0.643 -0.482 -0.595
0.626 -0.539 -0.563
0.608 -0.593 -0.527
0.588 -0.646 -0.487
0.566 -0.696 -0.442
0.543 -0.742 -0.393
0.518 -0.785 -0.339
0.491 -0.824 -0.281
0.464 -0.858 -0.219
0.435 -0.887 -0.153
0.406 -0.910 -0.084
0.377 -0.926 -0.012
0.347 -0.936 0.063
0.319 -0.937 0.140
0.292 -0.931 0.218
0.267 -0.917 0.296
0.244 -0.895 0.374
0.224 -0.864 0.450
0.208 -0.826 0.524
Run Code Online (Sandbox Code Playgroud)
m[0]并不是真正的“局部右向量”。它是世界坐标中的正确向量。局部坐标中的正确向量是vec3(1,0,0),您应该使用它来实现所需的旋转:
glm::mat4 m = glm::rotate(glm::mat4(1.0f), 0.78f, glm::vec3(0,1,0));
while (true) {
glm::vec3 axis = glm::normalize(glm::vec3(m[0])); // right vector
PRINT_VEC("{0:.3f} {1:.3f} {2:.3f}", axis.x, axis.y, axis.z);
m = glm::rotate(m, glm::radians(5.f), glm::vec3(1,0,0)); // 5 degrees each iteration
}
Run Code Online (Sandbox Code Playgroud)
印刷:
0.711 0.000 -0.703
0.711 0.000 -0.703
0.711 0.000 -0.703
...
Run Code Online (Sandbox Code Playgroud)
请注意,GLM 变换函数(例如 )glm::rotate应用右侧的变换;IE
m = m * glm::rotate(glm::mat4(1.0f), glm::radians(5.f), axis);
Run Code Online (Sandbox Code Playgroud)
他们期望轴位于变换前的坐标系中——即本地坐标系。相反,您的代码将向量转换vec3(1,0,0)为世界坐标系,然后围绕具有这些数字坐标的局部向量应用局部旋转,结果是一个任意向量。
事实上,您可以使用axis世界空间来执行相同的旋转。但是,您需要在左侧手动相乘:
m = glm::rotate(glm::mat4(1.0f), glm::radians(5.f), axis) * m;
Run Code Online (Sandbox Code Playgroud)
这给出了与上面第一个版本相同的结果。
编辑:使用正确与不正确的代码呈现的列向量: