Russian Qt Forum
Ноябрь 22, 2024, 18:50 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Определить конечный угол вращения составного объекта  (Прочитано 3327 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Март 19, 2021, 13:47 »

Всем привет еще раз.

Этот вопрос следует из предыдущего поста,
где речь шла об определении проекций вектора гравитации на оси акселерометра.

Но теперь задачка немного другая..

А допустим что акселерометр (условно - некий объект) находится внутри какого-то другого объекта (ну, или лежит на нем).
И у каждого из объектов есть возможность их поворота по трем осям X,Y,Z (см рисунок).

1. Изначально угол поворота акселерометра и его "контейнера" равны нулю, относительно земли (некоей неподвижной системы отсчета).

2. Далее, допустим, что акселерометр крутанули вокруг какой-то оси на какой то угол, например на 30 градусов.

3. Теперь мы повернули и сам контейнер вокруг той же оси на какой-то угол, например 30 градусов.

4. Вопрос, а каким теперь будет угол поворота акселерометра вокруг этой же оси относительно земли?


Очевидно, что в этом частном случае что на картинке - он будет 60 градусов?
Но как быть в общем случае, когда вращение идет в пространстве?

Можно ли просто суммировать углы поворота вокруг осей каждого из объектов (а вдруг их будут больше двух, например,
акселерометр может лежать на черепахе, которая может наклоняться в любую сторону, и сама черепаха стоит на слонах,
которые тоже могут играть в присядки)?

Или же опять нужно что-то городить в матрицами? Если да, то как это делается?  Строит глазки

При этом, как я понимаю, каждый объект имеет свою матрицу и прочие 3-д параметры

 

« Последнее редактирование: Март 19, 2021, 13:52 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Март 19, 2021, 14:01 »

Т.е. грубо говоря, что то вроде:

Код
Entity { // Некий контейнер - большой куб, содержит под-объект - малый куб.
   components: [
       Mesh { source: "qrc:/assets/models/big-cube.obj" },
       Transform {
             // Содержит все 3-д свойства большого куба (матрицы и прочее)
       },
       PhongMaterial { ambient: "green" }
   ]
 
   Entity { // Некий чайлд - малый куб
       components: [
           Mesh { source: "qrc:/assets/models/small-cube.obj" },
           Transform {
                 // Содержит все 3-д свойства малого куба (матрицы и прочее)
           },
           PhongMaterial { ambient: "red" }
       ]
   }
}
 

Так вот, надо как то найти углы поворота малого куба относительно глобальной неподвижной системы координат (или как там она называется),
после того как мы повращали большой куб, а в нем - еще и малый вокруг их локальных координат.
« Последнее редактирование: Март 19, 2021, 14:03 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Март 19, 2021, 14:43 »

Так вот, надо как то найти углы поворота малого куба относительно глобальной неподвижной системы координат (или как там она называется),
"Мир" Улыбающийся

Можно ли просто суммировать углы поворота вокруг осей каждого из объектов
НЕТ, углы Эйлера нельзя суммировать, рез-т неверен (причем подленько,  много частных случаев где работает)

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

И вот тут Вы вступили в бооольшое говно.

1) Извлечения углов я в букваре не помню, может придется искать в инете. Ну это еще цветочки

2) Эта операция неоднозначна. Вот если "из углов сделать матрицу" - все норм, но одна и та же матрица может быть получена из неск комбинаций углов. Любая реализация может выдать "странный" рез-т, типа 10 + 10 = 100. Формально он корректен, вращение получается то же самое, но возникают проблемы с UI и.т.п.

Собсно это то за что и матюкают углы Эйлера (и хвалят кватернионы)
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Март 19, 2021, 15:24 »

Цитата: Igors
Если есть отношение parent-child, то матрица чайлда может уже и включать матрицу парента,

К сожалению, не включает.

Цитата: Igors
Если нет, то просто перемножить матрицы.

Да, спс, я попробовал так:

Код
C++ (Qt)
   QMatrix4x4 m =  matrix1 * matrix2;
   QVector3D gravity(0, -1, 0);
   QVector3D v = m.mapVector(gravity);
   qDebug() << v;
 

но почему то это не работает в случае, если :

0. Начальная позиция - все ок, вектор гравитации вдоль оси Y - QVector3D(0, -1, 0)
1. Потом повернули большой куб вокруг оси X - на 90 град - все ок, теперь вектор гравитации вдоль оси Z - QVector3D(0, 0, -1)
2. Теперь вращаем малый куб вокруг оси Y - и результат не меняется, хотя теперь вектор гравитации должен распределяться между осями X и Z

Может надо еще что-то делать с матрицами, а не только перемножать?

Цитата: Igors
Собсно это то за что и матюкают углы Эйлера (и хвалят кватернионы)

И как их можно использовать? Есть мысли? т.к. у каждого объекта также есть свойство `rotation`, которое является кватернионом.


Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Март 19, 2021, 16:18 »

Я даже картинки приататчил.

И вот код (QML):

Код
import Qt3D.Core 2.0
import Qt3D.Extras 2.15
import Qt3D.Input 2.0
import Qt3D.Render 2.15
 
import QtQuick.Scene3D 2.0
 
Scene3D {
   focus: true
   aspects: ["input", "logic"]
   cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
 
   property alias bigCubeRotationX: bigCuberansform.rotationX
   property alias bigCubeRotationZ: bigCuberansform.rotationZ
   property alias smallCubeRotationY: smallCuberansform.rotationY
 
   function calculateMatrix(bigMatrix, smallMatrix) {
       detector.setupObjectMatrix(bigMatrix, smallMatrix);
   }
 
   Entity {
       components: [
           RenderSettings {
               activeFrameGraph: ForwardRenderer {
                   camera: camera
                   clearColor: "white"
               }
           },
           InputSettings { }
       ]
 
       Camera {
           id: camera
           projectionType: CameraLens.PerspectiveProjection
           fieldOfView: 45
           position: Qt.vector3d(0.0, 1, 3.0)
           upVector: Qt.vector3d(0.0, 1.0, 0.0)
           viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
       }
 
       FirstPersonCameraController {
           camera: camera
           linearSpeed: 10.0
           acceleration: 5.0
           deceleration: 5.0
       }
 
       Entity {
           components: [
               PointLight {},
               Transform { translation: camera.position }
           ]
       }
 
       Entity {
           components: [
               CuboidMesh {
                   xExtent: 1
                   yExtent: 0.2
                   zExtent: 0.5
               },
               Transform {
                   id: bigCuberansform
                   onMatrixChanged: calculateMatrix(bigCuberansform.matrix, smallCuberansform.matrix)
               },
               PhongAlphaMaterial {
                   alpha: 0.8
                   diffuse: "red"
               }
           ]
 
           Entity {
               components: [
                   CuboidMesh {
                       xExtent: 0.5
                       yExtent: 0.1
                       zExtent: 0.2
                   },
                   Transform {
                       id: smallCuberansform
                       onMatrixChanged: calculateMatrix(bigCuberansform.matrix, smallCuberansform.matrix)
                   },
                   PhongAlphaMaterial {
                       alpha: 0.8
                       diffuse: "green"
                   }
               ]
           }
       }
   }
}
 
 

И CPP:

Код
C++ (Qt)
void OrientationDetector::setupObjectMatrix(const QMatrix4x4 &matrix1, const QMatrix4x4 &matrix2)
{
   QMatrix4x4 m =  matrix1 * matrix2;
   QVector3D gravity(0, -1, 0);
   QVector3D v = m.mapVector(gravity);
   qDebug() << v;
}
 

« Последнее редактирование: Март 19, 2021, 16:21 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Март 20, 2021, 12:41 »

Может надо еще что-то делать с матрицами, а не только перемножать?
Могут быть определены доп правила трансформа иерархии (напр "наследовать scale парента или нет" и.т.п). Если их нет - то только умножение

но почему то это не работает в случае, если :
Замечания:

1) Для тестов есть хороший угол 30 градусов (cos = 0.866, sin = 0.5, эти числа легко узнать). А вoт с углами 90 легко заблудиться.

2) Обратите внимание что базис (как направлены оси в мире, Вы нарисовали тройку XYZ) не совпадает с тем что Вы показывали для прибора.

Теперь по картинкам. Первый поворот: локальная ось Y (произведения матриц) теперь направлена "на нас" (или "от нас", здесь не играет роли) в мире. Вектор гравитации в мире (0, -1, 0) "вниз", но в локальной СК это (0, 0, -1).

Второй поворот: а теперь Вы вокруг той же самой локальной оси Y и крутите. Конечно сама она никак не меняется. Др словами второй поворот вокруг самого вектора гравитации

Итого: все работает, никакого "касяка" нет  Улыбающийся

И как их можно использовать? Есть мысли? т.к. у каждого объекта также есть свойство `rotation`, которое является кватернионом.
Ну если Вы хотите получить/иметь именно "углы" - то проблема неизбежна. Поэтому

1) Попробовать "обойти" проблему. Убедитесь что углы совершенно необходимы. В принципе они нужны только для одного: предъявить их юзверю в UI, кватернионы для этого не подходят, матрицы тем более. Если же нужен "просто поворот", то его можно (и нужно) делать матрицей, все равно ее придется делать из углов

2) Найти в инете "matrix to euler angles XYZ" и реализовать. Возможно "прыжки углов" для Вас вовсе не проблема, вращение остается корректным.

Edit: да, и убедитесь что матрицы помножены верно (парент x чайлд)
« Последнее редактирование: Март 20, 2021, 13:26 от Igors » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.096 секунд. Запросов: 25.