在 3D 中组合旋转
Posted
技术标签:
【中文标题】在 3D 中组合旋转【英文标题】:Combine rotations in 3D 【发布时间】:2016-11-29 21:55:12 【问题描述】:我正在尝试使用 openGL(C++) 实现 3D 旋转, 我真的厌倦了寻找一种方法来围绕全局(X,Y,Z)而不是本地旋转任何对象。
我发现了这个简单的概念:
-
获取要旋转的对象的本地到世界变换矩阵。
使用此矩阵的逆矩阵将世界轴转换为局部坐标。
使用转换后的轴来计算旋转,就像您在代码中所做的那样。
所以我做了类似的东西:
//set the rotation matrix ti identity matrix
transformedModel->rotationMatrix = glm::rotate(glm::mat4(1.0f), float(0), glm::vec3(1, 1, 1) ); //rotation matrix = identity matrix
//X-axis
glm::vec4 axis = glm::inverse(transformedModel->rotationMatrix) * glm::vec4(1,0,0,0);
axis = glm::normalize(axis);
transformedModel->rotationMatrix = glm::rotate(transformedModel->rotationMatrix, glm::radians(rotation.x), glm::vec3(axis.x, axis.y, axis.z));
//Y-axis
glm::vec4 axis2 = glm::inverse(transformedModel->rotationMatrix) * glm::vec4(0,1,0,0);
transformedModel->rotationMatrix = glm::rotate(transformedModel->rotationMatrix, glm::radians(rotation.y), glm::vec3(axis2.x, axis2.y, axis2.z));
axis2 = glm::normalize(axis2);
//Z-axis
glm::vec4 axis3 = glm::inverse(transformedModel->rotationMatrix) * glm::vec4(0,0,1,0);
axis3 = glm::normalize(axis3);
transformedModel->rotationMatrix = glm::rotate(transformedModel->rotationMatrix, glm::radians(rotation.z), glm::vec3(axis3.x, axis3.y, axis3.z));
updateModelMatrix(transformedModel);
在特殊情况下它完全不能正常工作! 任何人都可以帮助我获得最简单的正确方法吗?
【问题讨论】:
如果要在全局系统中旋转,只需将旋转矩阵乘以原始矩阵的左边即可。向右相乘会导致局部系统中的旋转(假设为列向量)。 对不起,原始矩阵是什么意思?我的模型矩阵 = 平移矩阵 * 旋转矩阵 * 缩放矩阵;其中旋转 = Rx * Ry * Rz;然后我发送到顶点着色器:MVP = projectionviewmodelMatrix; 然后将其更改为modelMatrix = RotationMatrix * TranslationMatrix * ScalingMatrix
。这将在全局坐标系中旋转。这是你想要的吗?
不,假设我将我的对象绕 X 轴旋转 90,然后如果我相对于我绕 Y 轴旋转它,我会发现它相对于它绕 Y 轴旋转,即 Z-轴给我!
然后做Rz * Ry * Rx
。
【参考方案1】:
首先,确定旋转对象的点。这通常是对象的中心。我们称之为旋转点。
现在,对于对象中的每个顶点,我们将执行以下操作:
1) 将顶点平移到原点。这可以通过从顶点减去旋转点来完成。例如,如果旋转点是 (5, 10, 20),我们将从顶点的 x 坐标减去 5,从顶点的 y 坐标减去 10,从顶点的 z 坐标减去 20。
2) 使用 3x3 旋转矩阵执行旋转。
3) 将顶点平移回旋转点。我们撤消第一步,将 5、10 和 20 添加到顶点坐标。
我发现这比使用转换矩阵更简单,但效率可能较低。
【讨论】:
我不喜欢处理顶点,只想发送一个矩阵到顶点着色器以应用于所有顶点以上是关于在 3D 中组合旋转的主要内容,如果未能解决你的问题,请参考以下文章