可视空间中的 OpenGL 旋转

Posted

技术标签:

【中文标题】可视空间中的 OpenGL 旋转【英文标题】:OpenGL Rotation in Viewing Space 【发布时间】:2020-04-23 04:25:05 【问题描述】:

我想在建模空间中定义一个对象以在查看空间中进行转换。通过单击和拖动鼠标(改变 deltaX 和 deltaY)来控制平移量。这是运行良好的代码: (参考https://gist.github.com/ptbrowne/2048812)

glPushMatrix();
glLoadMatrixd(cam2wld[cameraIndex].matrix());
glTranslated(deltaX, deltaY, 0);
glMultMatrixd(wld2cam[cameraIndex].matrix());
glMultMatrixd(obj2wld.matrix());
glGetDoublev(GL_MODELVIEW_MATRIX, obj2wld.matrix());
glPopMatrix();

我还想相对于相机(屏幕)的 x 轴旋转对象,旋转量取决于鼠标再次拖动。但是,通过从

glTranslated(deltaX, deltaY, 0);

glRotated(deltaX + deltaY, 1, 0, 0);

改为翻译对象。知道如何解决问题吗?谢谢。

【问题讨论】:

旋转总是围绕原点发生。如果你想围绕空间中的任意中心/轴旋转一些东西,那么你必须将它与 resp 结合起来。平移以在旋转之前将该中心移动到原点并在之后恢复平移。也许,这可能有助于理解:SO: Rotate an image in C++ without using OpenCV functions。 (它与 OpenGL 无关,但涉及到一些转换,在 2D 和 3D 中没有区别。) 【参考方案1】:

我假设wld2cam[cameraIndex] 是视图矩阵,cam2wld[cameraIndex] 是逆视图矩阵:

glLoadMatrixd(cam2wld[cameraIndex].matrix());
glRotated(deltaY, 1, 0, 0);
glMultMatrixd(wld2cam[cameraIndex].matrix());

您实际上要做的是围绕视点旋转模型。旋转轴 (1, 0, 0) 是视图空间的 x 轴。如果相机到模型的距离大,角度小,这个旋转看起来就是平移:

您必须为旋转定义一个枢轴。比如世界的起源。在视图空间中世界的起源:

const GLdouble *viewMat = cam2wld[cameraIndex].matrix();
GLdouble pivotX = viewMat[12];
GLdouble pivotY = viewMat[13];
GLdouble pivotZ = viewMat[14];

glLoadMatrixd(cam2wld[cameraIndex].matrix());

glTranslated(pivotX, pivotY, pivotZ);
glRotated(deltaY, 1, 0, 0);
glTranslated(-pivotX, -pivotY, -pivotZ);

glMultMatrixd(wld2cam[cameraIndex].matrix());

如果你想做复杂的矩阵运算,那么我推荐使用像OpenGL Mathematics (GLM)这样的库:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
glm::dmat4 c2w = glm::make_mat4<double>(cam2wld[cameraIndex].matrix());
glm::dmat4 t   = glm::translate(glm::dmat4(1.0), glm::dvec3( deltaX, deltaY, 0.0));
glm::dmat4 w2c = glm::make_mat4<double>(wld2cam[cameraIndex].matrix());
glm::dmat4 o2w = glm::make_mat4<double>(obj2wld.matrix());

glm::dmat final = c2w * t * w2c * o2w;
glLoadMatrixd(glm::value_ptr(final));

【讨论】:

就像你说的,我需要在旋转之前定义枢轴和平移(我忘了提到我希望旋转的中心位于建模空间的中心)。谢谢。

以上是关于可视空间中的 OpenGL 旋转的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 中的可视化问题(glOrtho 和投影)

OpenGL - 将变换应用于 3D 空间中的多边形

✠OpenGL-3-数学基础

在OpenGL中保存旋转矩阵

如何在 OpenGL 窗口模式下扩展鼠标空间

如何在OpenGL中的对象空间坐标中获得近剪裁平面坐标