为什么我的四元数不能正常旋转?

好吧,我们不是在讨论OpenGL这个问题,但是这将与OpenGL ES 2.0一起使用。

问题:如何使用以下代码创建和旋转四元数?

我一直在阅读和研究这个问题,但仍然无法完全理解这些概念。 我以为我明白了,但是一旦我开始进行一些计算来旋转四元数,我意识到我甚至无法回到我开始的地方。

所以我们假设我们有一个立方体,它的中心位于(0,0,0)。 我们想在x轴上旋转45度。 我该怎么办? (只有四元数)

假设成功,你如何从’W’获得轮换量? 我知道’1’表示没有旋转,但如果它旋转了173度怎么办?

试图旋转到给定的方向,45度,然后从W获得该值。我觉得我需要将角度转换为rads或其他东西,但不完全确定。 在线教程因人而异。

这是我的代码:

import java.util.Scanner; import Quaternion; public class Main { public static void main(String[] args) { Quaternion q1 = new Quaternion(0, 0, 0, 1); Quaternion q2 = new Quaternion(0, 0, 0, (float) Math.cos(toRAD(45.0f) / 2)); q1 = q2.mul(q1); System.out.println("q1: " + q1.getX() + ", " + q1.getY() + ", " + q1.getZ() + " with " + toANGLE(2.0f * Math.acos(q1.getW()))); } private static double toRAD(float angle) { return angle * (Math.PI / 180.0f); } private static float toANGLE(double rad) { return (float) (rad * (180.0f / Math.PI)); } } 

这是四元数的代码:

 public class Quaternion // Credit goes to 'thebennybox' (http://www.youtube.com/user/thebennybox) { private float x; private float y; private float z; private float w; public Quaternion(float x, float y, float z, float w) { this.x = x; this.y = y; this.z = z; this.w = w; } public float length() { return (float)Math.sqrt(x * x + y * y + z * z + w * w); } public Quaternion normalize() { float length = length(); return new Quaternion(x / length, y / length, z / length, w / length); } public Quaternion conjugate() { return new Quaternion(-x, -y, -z, w); } public Quaternion mul(Quaternion r) { float w_ = w * r.getW() - x * r.getX() - y * r.getY() - z * r.getZ(); float x_ = x * r.getW() + w * r.getX() + y * r.getZ() - z * r.getY(); float y_ = y * r.getW() + w * r.getY() + z * r.getX() - x * r.getZ(); float z_ = z * r.getW() + w * r.getZ() + x * r.getY() - y * r.getX(); return new Quaternion(x_, y_, z_, w_); } public Quaternion mul(Vector3f r) { float w_ = -x * r.getX() - y * r.getY() - z * r.getZ(); float x_ = w * r.getX() + y * r.getZ() - z * r.getY(); float y_ = w * r.getY() + z * r.getX() - x * r.getZ(); float z_ = w * r.getZ() + x * r.getY() - y * r.getX(); return new Quaternion(x_, y_, z_, w_); } public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; } public float getZ() { return z; } public void setZ(float z) { this.z = z; } public float getW() { return w; } public void setW(float w) { this.w = w; } } 

我仍然不能100%确定你的问题是什么,但我会试一试。

问题:

给定四元数表示围绕x,y,z的0度旋转,生成表示围绕x轴旋转45度的新四元数

  • 从表示无旋转的四元数开始,将其命名为q1

q1 =(w1,x1,y1,z1)

q1.w1 = cos(0/2)= 1

q1.x1 = 0 * sin(0/2)= 0

q1.y1 = 0 * sin(0/2)= 0

q1.z1 = 0 * sin(0/2)= 0

所以q1 =(1,0,0,0)

  • 生成围绕X轴45度(PI / 4弧度)的新旋转我们需要一个临时四元数来修改q1。 我们称之为q2。

q2 =(w2,x2,y2,z2)

q2.w2 = cos(PI / 4/2)= cos(PI / 8)

q2.x2 = 1.0 * sin(PI / 4/2)= 1.0 * sin(PI / 8)= sin(PI / 8)

q2.y2 = 0.0 * sin(PI / 4/2)= 0.0

q2.z2 = 0.0 * sin(PI / 4/2)= 0.0

所以q2 =(cos(PI / 8),sin(PI / 8),0,0)

  • 现在最后一步非常重要,您可以通过左侧乘以临时四元数来修改原始四元数

我的意思是:

q1 = q2 * q1

你的乘法函数写得正确,所以问题不存在。 请记住, 四元数乘法不是可交换的 。 那是q2 * q1与q1 * q2不一样!

此时,修改q1以表示围绕X轴的45度旋转。

要以度为单位打印角度,您需要计算2.0 * acos(q1.w) / PI * 180

您的代码错误地计算q1.w/PI * 180以获得以度为单位的角度。

更具体地说,改变

 toANGLE(resQuat.getW()) 

 toANGLE(2.0f * Math.acos(resQuat.getW())) 

我没有看过你的代码,但尝试应用这些概念,看看是否能解决你的问题。