LINUX.ORG.RU

в смысле «вокруг внутренних осей»? имхо, если правильно понимаю чего это за оси, то во всех трех случаях поворачиваются они сами относительно окружающего пространства две из осей относительно третьей (а какой именно - картинки бы увидеть с осями).

arkhnchul ★★
()
Последнее исправление: arkhnchul (всего исправлений: 1)

А в какой именно программе?;-)

Вот есть скажем единичный вектор a, задающий направление полета, единичный вектор b, задающий направление правого крыла, и единичный вектор c, задающий направление киля. Пусть E(alpha,n) - матрица Эйлера, поворачивающая некоторый произвольный вектор вокруг единичного вектора n на угол alpha.

Тогда рысканье на угол alpha приведет к изменению a и b: a'=E(alpha,c)*a, b'=E(alpha,c)*b.

Тангаж на угол alpha приведет к изменению a и с: a'=E(alpha,b)*a, c'=E(alpha,b)*c.

Крен на угол alpha приведет к изменению с и b: с'=E(alpha,a)*c, b'=E(alpha,a)*b.

А вообще это зависит от того, как с-но задается ориентация самолета в программе.

AIv ★★★★★
()
Ответ на: комментарий от AIv

2 Alv

Я примерно так и делаю.

Исходный код программы:

#include <stdio.h>
#include <math.h>
#define VERT_NUM 28
// VERT_NUM - количество вершин объемной модели
typedef struct { double x, y, z; } vector_3d;

struct matrix { double
a11, a12, a13,
a21, a22, a23,
a31, a32, a33; } M = {0}; // Задать матрицу трансформации

#define L 100
// L - масштаб модели самолета
const vector_3d
  A = {1, 0, 0}, B = {0, 1, 0}, C = {0, 0, 1}, // Задать набор базисных векторов
  V[VERT_NUM] = { // Указать набор вершин объемной модели
  {-8*L, 0, L}, // 0
  {-7*L, 0, L}, // 1
  {-7*L, 0, 3*L}, // 2
  {-6*L, 0, 3*L}, // 3
  {-6*L, 0, L}, // 4
  {-L, 0, L}, // 5
  {-L, 0, 7*L}, // 6
  {L, 0, 7*L}, // 7
  {L, 0, L}, // 8
  {4*L, 0, L}, // 9
  {4*L, 0, -L}, // 10
  {L, 0, -L}, // 11
  {L, 0, -7*L}, // 12
  {-L, 0, -7*L}, // 13
  {-L, 0, -L}, // 14
  {-6*L, 0, -L}, // 15
  {-6*L, 0, -3*L}, // 16
  {-7*L, 0, -3*L}, // 17
  {-7*L, 0, -L}, // 18
  {-8*L, 0, -L}, // 19
  {-7*L, 0, 0}, // 20
  {-7*L, 2*L, 0}, // 21
  {-6*L, 2*L, 0}, // 22
  {-6*L, 0, 0}, // 23
  {2*L, 0, 0}, // 24
  {2*L, L, 0}, // 25
  {3*L, L, 0}, // 26
  {3*L, 0, 0} }; // 27

#undef L

#define ZERO_VECTOR {0, 0, 0}

vector_3d
  a = ZERO_VECTOR , b = ZERO_VECTOR , c = ZERO_VECTOR , // Применяются для трансформации базисных векторов
  v[VERT_NUM] = { ZERO_VECTOR } ; // Набор вершин модели после выполнения трансформации

#undef ZERO_VECTOR

/* Прототипы функций программы */

/* Функция для подготовки матрицы поворота.
 *v - единичный вектор оси вращения,
 angle - угол для поворота вокруг данной оси. */
void set_matrix( vector_3d *v, double angle );

/* Данная функция обеспечивает умножение вектора 'v' на матрицу трансформации 'M'. */
void apply_matrix( vector_3d *v );

/* Функция для преобразования координат вершин модели
 в соответствии с новым положением базисных векторов.
 V[] - координаты вершин в исходной системе координат на основе базиса a, b, c;
 v[] - координаты вершин в новой системе координат на основе базиса a", b", c". */
void apply_basis( void );

int main(void) {
  double // Указание поворотного положения самолета, углы в градусах:
  yaw = 35, // рыскание - нос поворачивается влево, вправо;
  pitch = 20, // тангаж - нос поднимается вверх, опускается вниз;
  roll = 30; // крен - поворот вокруг продольной оси по часовой, против часовой стрелки.

  /* Повернуть базис системы координат */

  a = A; b = B; c = C;

  // Повернуть векторы b, c вокруг вектора a на угол roll
  set_matrix( &a, roll );
  apply_matrix( &b );
  apply_matrix( &c );

  // Повернуть векторы a, c' вокруг вектора b' на угол yaw
  set_matrix( &b, yaw );
  apply_matrix( &a );
  apply_matrix( &c );

  // Повернуть векторы a', b' вокруг вектора c" на угол pitch
  set_matrix( &c, pitch );
  apply_matrix( &a );
  apply_matrix( &b );

  // Отобразить на экране координаты базисных векторов a", b", c"
  puts("Обновленные координаты базисных векторов:");
  printf( "a\" ( %lf, %lf, %lf )\n", a.x, a.y, a.z);
  printf( "b\" ( %lf, %lf, %lf )\n", b.x, b.y, b.z);
  printf( "c\" ( %lf, %lf, %lf )\n", c.x, c.y, c.z);

  /* Преобразовать координаты вершин модели
   в соответствии с новым положением базисных векторов. */
  apply_basis();

  return 0;
}

/* Определение функций */

void set_matrix( vector_3d *v, double angle ) {
  double x, y, z, s, c; // s - sine, c - cosine

  // Список вспомогательных переменных
  // c1 = 1 - c; c1xy = c1*x*y; sz = s*z; c1xz = c1*x*z; sy = s*y; c1yz = c1*y*z; sx = s*x;
  double c1, c1xy, sz, c1xz, sy, c1yz, sx;

  // Сохранить координаты вектора *v в локальных переменных функции
  x = v -> x;
  y = v -> y;
  z = v -> z;

  // Преобразовать градусы в радианы
  angle *= M_PI / 180.0;
  s = sin(angle);
  c = cos(angle);

  // Подсчитать значение вспомогательных переменных
  c1 = 1 - c;
  c1xy = c1*x*y;
  sz = s*z;
  c1xz = c1*x*z;
  sy = s*y;
  c1yz = c1*y*z;
  sx = s*x;

  // Заполнить матрицу трансформации значениями
  M.a11 = c + c1*x*x;
  M.a12 = c1xy - sz;
  M.a13 = c1xz + sy;

  M.a21 = c1xy + sz;
  M.a22 = c + c1*y*y;
  M.a23 = c1yz - sx;

  M.a31 = c1xz - sy;
  M.a32 = c1yz + sx;
  M.a33 = c + c1*z*z;
}

void apply_matrix( vector_3d *v ) {
  double x, y, z;

  // Сохранить координаты вектора 'v' в локальных переменных функции
  x = v -> x;
  y = v -> y;
  z = v -> z;

  // Обеспечить умножение вектора 'v' на матрицу 'M'
  v -> x = x*M.a11 + y*M.a12 + z*M.a13;
  v -> y = x*M.a21 + y*M.a22 + z*M.a23;
  v -> z = x*M.a31 + y*M.a32 + z*M.a33;
}

void apply_basis( void ) {
  int i = 0; // Счетчик цикла для перебора всех вершин объемной модели
  // Вспомогательные переменные
  double x=0, y=0, z=0; 
  // Данные переменные используются для сохранения координат векторов a", b", c"
  double ax=0, ay=0, az=0, bx=0, by=0, bz=0, cx=0, cy=0, cz=0;

  // Сохранить координаты векторов a", b", c" в отдельных переменных для удобства рассчетов
  ax = a.x; ay = a.y; az = a.z;
  bx = b.x; by = b.y; bz = b.z;
  cx = c.x; cy = c.y; cz = c.z;

  puts("\nОбновленные координаты вершин модели:");

  for(i = 0; i < VERT_NUM ; i++) {
    // Сохранить значение полей структуры в отдельных переменных
    x = V[i].x;
    y = V[i].y;
    z = V[i].z;

    // Преобразовать координаты отдельной вершины модели в соответствии с обновленным базисом
    v[i].x = x*ax + y*bx + z*cx;
    v[i].y = x*ay + y*by + z*cy;
    v[i].z = x*az + y*bz + z*cz;

    printf( "Вектор № %d ( %lf, %lf, %lf )\n", i, v[i].x, v[i].y, v[i].z);
  }
}

Результат выполнения:

alex@comp:~/program$ cc -Wall program.c -lm
alex@comp:~/program$ ./a.out 
Обновленные координаты базисных векторов:
a" ( 0.769751, 0.565691, -0.295765 )
b" ( -0.280166, 0.715710, 0.639739 )
c" ( 0.573576, -0.409576, 0.709406 )

Обновленные координаты вершин модели:
Вектор № 0 ( -558.443261, -493.510326, 307.552730 )
Вектор № 1 ( -481.468148, -436.941236, 277.976220 )
Вектор № 2 ( -366.752861, -518.856440, 419.857516 )
Вектор № 3 ( -289.777748, -462.287350, 390.281005 )
Вектор № 4 ( -404.493035, -380.372145, 248.399709 )
Вектор № 5 ( -19.617469, -97.526693, 100.517158 )
Вектор № 6 ( 324.528392, -343.272306, 526.161046 )
Вектор № 7 ( 478.478619, -230.134125, 467.008026 )
Вектор № 8 ( 134.332757, 15.611488, 41.364138 )
Вектор № 9 ( 365.258096, 185.318760, -47.365393 )
Вектор № 10 ( 250.542809, 267.233964, -189.246689 )
Вектор № 11 ( 19.617469, 97.526693, -100.517158 )
Вектор № 12 ( -324.528392, 343.272306, -526.161046 )
Вектор № 13 ( -478.478619, 230.134125, -467.008026 )
Вектор № 14 ( -134.332757, -15.611488, -41.364138 )
Вектор № 15 ( -519.208322, -298.456941, 106.518413 )
Вектор № 16 ( -633.923610, -216.541736, -35.362883 )
Вектор № 17 ( -710.898723, -273.110827, -5.786372 )
Вектор № 18 ( -596.183436, -355.026031, 136.094924 )
Вектор № 19 ( -673.158549, -411.595122, 165.671434 )
Вектор № 20 ( -538.825792, -395.983634, 207.035572 )
Вектор № 21 ( -594.859092, -252.841567, 334.983288 )
Вектор № 22 ( -517.883979, -196.272476, 305.406777 )
Вектор № 23 ( -461.850679, -339.414543, 177.459061 )
Вектор № 24 ( 153.950226, 113.138181, -59.153020 )
Вектор № 25 ( 125.933576, 184.709214, 4.820838 )
Вектор № 26 ( 202.908689, 241.278305, -24.755673 )
Вектор № 27 ( 230.925339, 169.707272, -88.729531 )

Deleted
()

Ну если бы был блендер, то я бы создал Empty, привязал бы их к мешу самолета и вращал бы относительно этих Empty.

sid350 ★★★★★
()
Ответ на: 2 Alv от Deleted

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

В чем вопрос то тогда был?

AIv ★★★★★
()
Ответ на: комментарий от AIv

Уточняю свой вопрос

Alv

В чем вопрос то тогда был?

В приведенном мной тексте программы реализован такой алгоритм:

  • Задать ортонормированный базис a (1, 0, 0), b (0, 1, 0), c (0, 0, 1)
  • Добавить к базису 3 последовательных поворота:
    а) повернуть векторы b, c вокруг вектора a на угол крена roll с получением векторов b', c'
    б) повернуть векторы a, c' вокруг вектора b' на угол рысканья yaw с получением векторов a', c"
    в) повернуть векторы a', b' вокруг вектора c" на угол тангажа pitch с получением векторов a", b"
    В результате будет получен ортонормированный базис a", b", c".
  • Преобразовать координаты вершин модели в соответствии с изменившимся базисом. Данное преобразование обеспечивает переход вершин модели с координатами V[VERT_NUM] в набор вершин с координатами v[VERT_NUM].

В процессе визуализации данной модели обнаружил наличие проблемы шарнирного замка (gimbal lock) с блокированием оси.

Список возникших вопросов:

  • правильный ли используется алгоритм для поворота 3D модели в пространстве на основе трех углов?
  • возможно ли избавиться от проблемы шарнирного замка путем изменения порядка следования пунктов а), б), в) ?
  • если невозможно, поможет ли применение кватернионов вращения в качестве замены матрице направляющих косинусов?
Deleted
()
Ответ на: Уточняю свой вопрос от Deleted

возможно ли избавиться от проблемы шарнирного замка путем изменения порядка следования пунктов

нет, полностью избавиться нельзя

поможет ли применение кватернионов вращения в качестве замены матрице направляющих косинусов

да

jtootf ★★★★★
()
Ответ на: Уточняю свой вопрос от Deleted

проблемы шарнирного замка

какая в вашем русском терминология смешная все таки.

велосипед обязателен? может взять glm и заюзать их имплементацию кватерниона?

x0r ★★★★★
()
Ответ на: Уточняю свой вопрос от Deleted

А как Вы преобразуете координаты вершин модели из базиса в базис? Сколько я с матрицей поворота не возякался, ни разу таких проблем не возникало. ИМНО нужно каждую вершину модели крутить аналогичным образом. Т.е. есть исходные координаты вершин (соотвевтсвующие каким то там углам, не важно каким). Есть изменение углов (скажем на шаге). Делаем три матрицы поворота описанным Вами образом, перемножаем их, получаем единую матрицу поворота для всех вершин. Дальше крутим все вершины относительно центра этой матрицей - профит! Все должно работать.

AIv ★★★★★
()
24 сентября 2013 г.

Cypher

Как правильно задать в программе поворот 3D модели самолета вокруг его внутренних осей на основе трех углов: рысканье, тангаж, крен?

Добавил к теме отметку «Решено», так как решил указанную задачу.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.