Правильно поверните 3D-объект по 3 осям в JavaFX

Таким образом, метод, который я использовал до сих пор для вращения объектов в JavaFX, заключался в том, что я разделил его на 3 группы, каждая из которых была привязана к одной оси и привязана к ней следующим образом:

    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);

и делал setAngle() каждый раз, когда мне нужно было повернуть объект. Это работало очень хорошо только для курса и вращения, пока я не решил, что мне нужен еще и шаг. Теперь во многих учебниках по OpenGL и тому подобное говорится, что вращательные матрицы или кватернионы лучше всего подходят для такого типа поворотов, но в javadoc отсутствуют какие-либо полезные данные, касающиеся этого.

Пример: что происходит, когда я поворачиваю объект на 180 градусов по оси Y (и что должно было произойти в прозрачном синем цвете) введите описание изображения здесь Я что-то пропустил? Вся помощь будет оценена по достоинству.


person Moff Kalast    schedule 09.05.2015    source источник


Ответы (2)


Есть причина, по которой все эти уроки указывают на матрицы вращения: в 3D вы не можете выполнять одновременные вращения одно за другим, вам нужно выполнять их одновременно. Поскольку JavaFX использует только один угол и одну ось, вы должны обеспечить способ преобразования трех поворотов по трем осям всего в один угол и одну ось.

Некоторое время назад я рассмотрел всю математику этих операций в своем блоге напишите об использовании Leap Motion, чтобы получить три вращения руки (тангаж, рыскание, вращение) для вращения 3D-модели.

Итак, в основном, из трех вращений: шаг (вокруг оси X), рыскание (вокруг оси Y) и крен (вокруг оси Z) у вас есть эти матрицы:

Матрицы

и если вы объедините их, у вас будет одна матрица:

Матрица

Без дополнительных пояснений угол и компоненты унитарной оси вращения могут быть вычислены из:

собственные значения

Что можно записать как:

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));                    
    }
}

где alf — крен, bet — тангаж, а gam — рыскание.

Полный проект можно найти здесь.

person José Pereda    schedule 10.05.2015
comment
Еще один потрясающий ответ! Спасибо за это, я действительно попал в блокпост в этом вопросе. - person Moff Kalast; 10.05.2015
comment
К сожалению, у меня все еще есть проблемы с определением итоговых углов рыскания, крена и тангажа относительно сцены stackoverflow.com/questions/30817123/ - person Moff Kalast; 14.06.2015
comment
Я видел ваш новый вопрос, я постараюсь взглянуть на него - person José Pereda; 14.06.2015
comment
большое спасибо за очень четкий ответ! это действительно помогает мне. - person user2407334; 29.06.2017
comment
Почему ваши матрицы отличаются от матриц здесь? en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations - person shinzou; 15.08.2017
comment
@kuhaku Хороший вопрос. Я думаю, они могли отредактировать это? Я проверил это несколько лет назад, и знак был противоположным. В любом случае, это легко проверить и отрегулировать, основываясь на ваших данных об углах рыскания, тангажа и крена. - person José Pereda; 15.08.2017
comment
Может быть полезно указать, что повороты (и умножение матриц) не коммутируют. То есть порядок последовательных вращений имеет значение. Любые два или более поворота вокруг разных осей эквивалентны одному повороту вокруг составной оси. Однако составной ответ будет другим, если вы измените порядок вращения. Расчет Хосе предназначен для конкретного произведения трех матриц, то есть поворотов в определенном порядке. Я считаю, что это A=AzAyAx, который сначала будет вращаться вокруг оси x, во-вторых, y и в-третьих - person J.E.Tkaczyk; 17.01.2018

Могу предложить решение. Но это немного нецивилизованно и может быть обескураживающей практикой.

Node[] my3dModel = get3DModel();//the method creates a mesh (I suppose that you used Interactive mesh, but it's not important here)
Pane paneForMyModel = new Pane();
paneForMyModel.getChildren.addAll(my3dModel);//you add your model to this pane
//and now
paneForMyModel.getTransforms().add(new Rotate(angle, axis));
person Felipe Bonadykov    schedule 29.05.2019