如何围绕特定轴旋转或旋转视图矩阵?
How to rotateX or rotateZ view matrix around specified axis?
我想旋转视图矩阵(我认为这代表相机位置)。
我已经通过 Matrix4f#rotateY 成功地围绕 Y 轴旋转了视图矩阵。
然而,关于 rotateX 这需要目标位置在 (0,0,0) 世界中心,我想围绕指定位置旋转视图矩阵。
我试着像下面这样旋转矩阵:
targetCenter = Vector3f(x, y, z)
viewMatrix
.translate(targetCenter)
.rotateX(rotation)
.translate(targetCenter.mul(-1.0f))
但是,这会使渲染模型两次。
这是绕指定轴旋转视图矩阵的正确方法吗?
编辑
- 我已经根据Draykoon D的回答用Kotlin实现了相机,谢谢
- 我正在使用 JOML 作为库来操作 Matrix
fun Matrix4f.orbitBy(modelCenter: Vector3f, angleY: Float, angleX: Float, focalLength: Float) {
// Setup both camera's view matrices
val modelCenterCp = Vector3f(modelCenter)
val recenter = Matrix4f().translate(modelCenterCp.mul(-1.0f)) //not needed if world origin
val rotation = Matrix4f()
.rotateY(angleY)
.rotateX(angleX)
val moveBack = Matrix4f().translate(modelCenter) //not needed if world origin
val transfer = moveBack.mul(rotation).mul(recenter) //order from right to left
val eye = Vector3f(0f, modelCenter.y, -focalLength).mulProject(transfer)
val up = Vector3f(0f, 1f, 0f)
this.setLookAt(eye, modelCenter, up)
}
它在您的示例中有效,因为我假设您的目标等于世界原点。
如果你想围绕世界原点旋转,你不需要平移部分。如果它在某个点附近,它将成为强制性的。
我在计算视图矩阵时喜欢使用的是在我的相机中保留 3 个值:
- 相机位置(眼睛)
- 相机目标(中心)
- 相机upVector(向上)
如果你想围绕你的目标点旋转,你需要在你的眼睛和 upVector 上应用你的旋转,完成后你可以使用 mat4 lookAt(eye, center, up)
重新计算 viewMatrix
void orbitBy(float yaw, vec3 rotationCenter) {
mat4 recenter = translate(mat4(1.0), -rotationCenter); //not needed if world origin
mat4 rotation = rotateY(mat4(1.0), yaw); //can be replaced by glm::eulerAngleZXY(yaw, pitch, roll) ...
mat4 moveBack = translate(mat4(1.0, rotationCenter)); //not needed if world origin
mat4 transfo = moveBack * rotation * recenter; //order from right to left
m_eye = transfo * m_eye;
m_up = transfo * m_up;
m_viewMatrix = lookAt(m_eye, m_center, m_up);
}
我更喜欢这种方法,因为它为您提供了更简单的值,这对调试非常有帮助
我想旋转视图矩阵(我认为这代表相机位置)。
我已经通过 Matrix4f#rotateY 成功地围绕 Y 轴旋转了视图矩阵。
然而,关于 rotateX 这需要目标位置在 (0,0,0) 世界中心,我想围绕指定位置旋转视图矩阵。
我试着像下面这样旋转矩阵:
targetCenter = Vector3f(x, y, z)
viewMatrix
.translate(targetCenter)
.rotateX(rotation)
.translate(targetCenter.mul(-1.0f))
但是,这会使渲染模型两次。 这是绕指定轴旋转视图矩阵的正确方法吗?
编辑
- 我已经根据Draykoon D的回答用Kotlin实现了相机,谢谢
- 我正在使用 JOML 作为库来操作 Matrix
fun Matrix4f.orbitBy(modelCenter: Vector3f, angleY: Float, angleX: Float, focalLength: Float) {
// Setup both camera's view matrices
val modelCenterCp = Vector3f(modelCenter)
val recenter = Matrix4f().translate(modelCenterCp.mul(-1.0f)) //not needed if world origin
val rotation = Matrix4f()
.rotateY(angleY)
.rotateX(angleX)
val moveBack = Matrix4f().translate(modelCenter) //not needed if world origin
val transfer = moveBack.mul(rotation).mul(recenter) //order from right to left
val eye = Vector3f(0f, modelCenter.y, -focalLength).mulProject(transfer)
val up = Vector3f(0f, 1f, 0f)
this.setLookAt(eye, modelCenter, up)
}
它在您的示例中有效,因为我假设您的目标等于世界原点。 如果你想围绕世界原点旋转,你不需要平移部分。如果它在某个点附近,它将成为强制性的。
我在计算视图矩阵时喜欢使用的是在我的相机中保留 3 个值:
- 相机位置(眼睛)
- 相机目标(中心)
- 相机upVector(向上)
如果你想围绕你的目标点旋转,你需要在你的眼睛和 upVector 上应用你的旋转,完成后你可以使用 mat4 lookAt(eye, center, up)
void orbitBy(float yaw, vec3 rotationCenter) {
mat4 recenter = translate(mat4(1.0), -rotationCenter); //not needed if world origin
mat4 rotation = rotateY(mat4(1.0), yaw); //can be replaced by glm::eulerAngleZXY(yaw, pitch, roll) ...
mat4 moveBack = translate(mat4(1.0, rotationCenter)); //not needed if world origin
mat4 transfo = moveBack * rotation * recenter; //order from right to left
m_eye = transfo * m_eye;
m_up = transfo * m_up;
m_viewMatrix = lookAt(m_eye, m_center, m_up);
}
我更喜欢这种方法,因为它为您提供了更简单的值,这对调试非常有帮助