ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java-为什么我的四元数不能正确旋转?

2019-11-22 16:13:17  阅读:270  来源: 互联网

标签:quaternions rotation java


好的,我们不会在这个问题上谈论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()))

除此以外,我没有看过您的代码,但是尝试应用这些概念,看看是否可以解决您的问题.

标签:quaternions,rotation,java
来源: https://codeday.me/bug/20191122/2060996.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有