在 JavaFX 中正确旋转 3 轴上的 3D 对象 [英] Rotate a 3D object on 3 axis in JavaFX properly

查看:27
本文介绍了在 JavaFX 中正确旋转 3 轴上的 3D 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以到目前为止我在 JavaFX 中旋转对象的方法是我将它分成 3 组,每组附加一个旋转并锁定到一个轴,如下所示:

 旋转航向、横滚、俯仰;组 normalrotate、rollrotate、verticalrotate;Heading.setAxis(new Point3D(0,1,0));normalrotate.getTransforms().add(heading);roll.setAxis(new Point3D(0,0,1));rollrotate.getTransforms().add(roll);pitch.setAxis(new Point3D(1,0,0));Verticalrotate.getTransforms().add(pitch);

每次我需要旋转对象时都执行一次 setAngle().在我决定我也需要俯仰之前,这仅适用于航向和滚转非常有效.现在,许多 OpenGL 等教程都说旋转矩阵或四元数最适合这些类型的旋转,但 javadoc 缺乏有关此的任何有用数据.

示例:当我在 y 轴上将对象旋转 180 度时会发生什么(以及在透明蓝色中实际发生的情况)我错过了什么吗?所有帮助将不胜感激.

解决方案

所有这些教程都指向旋转矩阵是有原因的:在 3D 中你不能一个一个地同时执行旋转,你需要一次执行它们.由于JavaFX仅使用一角一轴,因此您必须提供将三个轴上的三个旋转仅转换为一角一轴的方法.

不久前,我在我的博客中介绍了这些操作背后的所有数学原理 找到完整的项目.

So the method that I've used so far to rotate objects in JavaFX was that I layered it in 3 groups, each of them with a Rotate attached and locked to a single axis like so:

    Rotate heading, roll, pitch;
    Group normalrotate, rollrotate, verticalrotate;

    heading.setAxis(new Point3D(0,1,0));
    normalrotate.getTransforms().add(heading);

    roll.setAxis(new Point3D(0,0,1));
    rollrotate.getTransforms().add(roll);

    pitch.setAxis(new Point3D(1,0,0));
    verticalrotate.getTransforms().add(pitch);

and did a setAngle() for each time I needed to rotate the object. This worked very well for only heading and roll until i decided that I need pitch too. Now a lot of tutorials for OpenGL and alike say that rotational matixes or quaternions are best for these type of rotations, but the javadoc lacks any usefull data regaring this.

Example: What happens when I rotate an object by 180 degrees on the y axis (and what should actually have happened in transparent blue) Am I missing something? All help would be appreciated.

解决方案

There's a reason why all those tutorials point to rotational matrices: in 3D you can't perform simultaneous rotations one by one, you need to perform them at once. Since JavaFX only uses one angle and one axis, you have to provide the way to convert three rotations over three axes in just one angle and one axis.

A while ago I went to all the math behind these operations in my blog post about using Leap Motion to get the three rotations of your hand (pitch, yaw, roll) to rotate a 3D model.

So basically, from three rotations: pitch (around its X axis), yaw (around its Y axis) and roll (around its Z axis), you have these matrices:

and if you combine them you have one single matrix:

Without further explanations, the angle and the rotation unitary axis components can be computed from:

Which can be written as:

private void matrixRotateNode(Node n, double alf, double bet, double gam){
    double A11=Math.cos(alf)*Math.cos(gam);
    double A12=Math.cos(bet)*Math.sin(alf)+Math.cos(alf)*Math.sin(bet)*Math.sin(gam);
    double A13=Math.sin(alf)*Math.sin(bet)-Math.cos(alf)*Math.cos(bet)*Math.sin(gam);
    double A21=-Math.cos(gam)*Math.sin(alf);
    double A22=Math.cos(alf)*Math.cos(bet)-Math.sin(alf)*Math.sin(bet)*Math.sin(gam);
    double A23=Math.cos(alf)*Math.sin(bet)+Math.cos(bet)*Math.sin(alf)*Math.sin(gam);
    double A31=Math.sin(gam);
    double A32=-Math.cos(gam)*Math.sin(bet);
    double A33=Math.cos(bet)*Math.cos(gam);

    double d = Math.acos((A11+A22+A33-1d)/2d);
    if(d!=0d){
        double den=2d*Math.sin(d);
        Point3D p= new Point3D((A32-A23)/den,(A13-A31)/den,(A21-A12)/den);
        n.setRotationAxis(p);
        n.setRotate(Math.toDegrees(d));                    
    }
}

where alf is roll, bet is pitch and gam is yaw.

You can find the full project here.

这篇关于在 JavaFX 中正确旋转 3 轴上的 3D 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆