Повернуть сетку на основе ее локальных координат

У меня есть самолет в 3D-мире, и его ориентация сохраняется любым способом (например, тангаж, рыскание и крен). Теперь, когда я хочу, чтобы самолет повернул налево, но glRotatef не выполняет свою работу, поскольку придерживается глобальных координат и не заботится о вращении плоскости, и простое изменение рыскания также не помогает, так как это тоже не относительно плоскостей фактическое вращение и будет означать «влево» только тогда, когда самолет летит прямо к горизонту. То, что мне нужно, было бы так:

    float pitch = 10 , yaw = 20, roll = 30;        //some initial values
Turn(&pitch, &yaw, &roll ,  5, 0 , 0 )   //calculate new pitch, yaw and roll as if
//the plane had turned 5 degrees to the right (relative to its current orientation and roll!)
//pitch, yaw and roll are updated to reflect the new orientation.

Многие люди предлагают использовать кватернионы, но я понятия не имею, как реализовать их в функции Turn (один рабочий пример — Blitz3D, у которого есть функция «RotateEntity» для глобального вращения, такого как glRotatef и «TurnEntity» для вращения, основанного на ориентации) Я думаю, что внутренняя функция работает так:

  • преобразовать высоту, рыскать, катиться к кватерниону, как EulerToQuat в
    OpenGL + SDL вращение вокруг локальной оси
  • выполнить локальное вращение с использованием математики кватернионов (источник не найден)
  • превратить Quaternion обратно в рыскание, крен, тангаж (источник не найден)

0

Решение

Я наконец-то решил проблему, переключившись на ношение матрицы для каждого корабля. Высота тона, рыскание и крен рассчитываются только при необходимости, что редко бывает. В заключение, glRotatef делает работу — вам нужно только применить его к уже повернутой матрице — и сохранить результат, чтобы изменение не пропало.

Следующий код — моя реализация структуры корабля, которая содержит x, y, z, Matrix [16], dx, dy, dz. (Обратите внимание, что все массивы кораблей должны быть инициализированы с помощью IdentityMatrix):

//*************************** Turn Ship **********************************
void TurnShip(long nr,float yaw, float pitch=0,float roll=0) {
//Turns ship by pitch, yaw and roll degrees.
glMatrixMode(GL_MODELVIEW);

glLoadMatrixf(&ship[nr].Matrix[0]);
glRotatef(yaw,0,1,0);
glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);

glLoadMatrixf(&ship[nr].Matrix[0]);
glRotatef(pitch,1,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);

glLoadMatrixf(&ship[nr].Matrix[0]);
glRotatef(roll,0,0,1);
glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);
}

Функция загружает матрицу кораблей, хранящуюся в простом массиве с плавающей точкой, манипулирует ею и затем сохраняет ее обратно в массив. В графическом разделе игры этот массив будет загружен с помощью glLoadMatrixf и, следовательно, будет применен к кораблю без каких-либо хлопот или математики.

//*************************** Accelerate Ship relative to own orientation **
void AccelerateShip(long nr,float speedx,float speedy, float speedz)
{   //use speedz to move object "forward".
ship[nr].dx+= speedx*ship[nr].Matrix[0];   //accelerate sidewards (x-vector)
ship[nr].dy+= speedx*ship[nr].Matrix[1];  //accelerate sidewards (x-vector)
ship[nr].dz+= speedx*ship[nr].Matrix[2]; //accelerate sidewards (x-vector)

ship[nr].dx+= speedy*ship[nr].Matrix[4];   //accelerate upwards (y-vector)
ship[nr].dy+= speedy*ship[nr].Matrix[5];  //accelerate upwards (y-vector)
ship[nr].dz+= speedy*ship[nr].Matrix[6]; //accelerate upwards (y-vector)

ship[nr].dx+= speedz*ship[nr].Matrix[8];   //accelerate forward (z-vector)
ship[nr].dy+= speedz*ship[nr].Matrix[9];  //accelerate forward (z-vector)
ship[nr].dz+= speedz*ship[nr].Matrix[10]; //accelerate forward (z-vector)
}

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

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]