我也对全局/局部轮换问题感到不安,我不能把手放在上面。我使用openGL和LWJGL使用a lwjgl book实现游戏。我正在将JOML库用于向量和矩阵。
modelview矩阵的构造如下。根据书,这本来是没有本地轮换的,我自己添加了它们。这个想法是每个对象都有一个全局和局部旋转。这些旋转分别进行计算,然后在左侧/右侧乘以模型视图矩阵。
public Matrix4f getModelViewMatrix(Object obj, Matrix4f viewMatrix) {
Vector3f rotation = obj.getRot();
Vector3f localRot = obj.getLocalRot();
Matrix4f localRotMat = new Matrix4f().identity();
Matrix4f worldRotMat = new Matrix4f().identity();
localRotMat.rotateLocalX((float)Math.toRadians(localRot.x)).
rotateLocalY((float)Math.toRadians(localRot.y)).
rotateLocalZ((float)Math.toRadians(localRot.z));
worldRotMat.rotateX((float)Math.toRadians(-rotation.x)).
rotateY((float)Math.toRadians(-rotation.y)).
rotateZ((float)Math.toRadians(-rotation.z));
modelViewMatrix.identity().translate(obj.getPos());
modelViewMatrix.mulLocal(localRotMat);
modelViewMatrix.mul(worldRotMat);
modelViewMatrix.scale(obj.getScale());
Matrix4f viewCurr = new Matrix4f(viewMatrix);
return viewCurr.mul(modelViewMatrix);
}
这仍然会导致围绕“错误”轴的局部旋转。我已经看过使用四元数的实现,并阅读了有关万向节锁定之类的信息,但对我来说答案要么非常具体,要么太笼统。此外,如果我不需要使用四元数实现,那就太好了,因为我可能必须重构很多代码。
对象类的相关代码:
// Object class
private final Vector3f rot;
private final Vector3f localRot;
public Object() {
pos = new Vector3f(0, 0, 0);
scale = 1;
rot = new Vector3f(0, 0, 0);
localRot = new Vector3f(0, 0, 0);
}
// getters and setters for above
有人可以解释对模型视图矩阵的旋转计算有什么问题吗?
编辑:我可以像下面那样重写代码,这与@GeestWagen的提示更加一致。但是,我对象的“局部旋转”仍显示为全局,因此确实确实好像对它应用了两次“相同”旋转。但是,现在我被困住了,因为我找不到关于这些功能的更多文档(rotateLocal / rotate)。
modelViewMatrix.identity().translate(obj.getPos()).
rotateLocalX((float)Math.toRadians(-localRot.x)).
rotateLocalY((float)Math.toRadians(-localRot.y)).
rotateLocalZ((float)Math.toRadians(-localRot.z)).
rotateX((float)Math.toRadians(-rotation.x)).
rotateY((float)Math.toRadians(-rotation.y)).
rotateZ((float)Math.toRadians(-rotation.z)).
scale(obj.getScale());
好的,我终于解决了。这导致我做了更多的研究。我想到的是以下内容:
Vector3f rotation = obj.getRot();
Vector3f localRot = obj.getLocalRot();
Quaternionf rotationQ = new Quaternionf().
rotateAxis((float)Math.toRadians(-localRot.z), new Vector3f(0f, 0f, 1f)).
rotateAxis((float)Math.toRadians(-localRot.y), new Vector3f(0f, 1f, 0f)).
rotateAxis((float)Math.toRadians(-localRot.x), new Vector3f(1f, 0f, 0f)).
premul(new Quaternionf().
rotateX((float)Math.toRadians(-rotation.x)).
rotateY((float)Math.toRadians(-rotation.y)).
rotateZ((float)Math.toRadians(-rotation.z))
);
modelViewMatrix.identity().
translate(obj.getPos()).
rotate(rotationQ).
scale(obj.getScale());
[这是受this和this等启发。令我感到困惑的是,缺乏进行本地[[]]全局轮换的机会。我能找到的大多数东西是any。这将创建一个四元数并将x,y和z轴设置为对象的局部旋转。然后用四元数pre-multiplies将轴设置为对象的整体旋转。然后,将所得的四元数用于modelView矩阵。 因此,要组合局部和全局旋转,四元数似乎是必要的。我以为它是用来确保轴不更改局部旋转(或局部旋转),但在组合两者时也应使用它们。