Повернуть объект вокруг источника, как он обращен к началу координат в OpenGL с GLM? - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь сделать простую анимацию, в которой объект вращается по всему миру в OpenGL, используя glm lib.Моя идея:

  • Отправить объект в источник

  • Повернуть его

  • Отправить обратно в оригиналposition

  • Заставьте его взглянуть на то, что я хочу

Вот моя реализация:

// Rotates object around point p
void rotate_about(float deltaTime, glm::vec3 p, bool ended) {

    glm::vec3 axis = glm::vec3(0,1,0); //rotation axis
    glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale, scale, scale)); //scale matrix
    glm::mat4 rotation = getMatrix(Right, Up, Front, Position); //builds rotation matrix

    rotation = glm::translate(rotation, p - Position );
    rotation = glm::rotate(rotation, ROTATION_SPEED * deltaTime, axis);
    rotation = glm::translate(rotation, Position - p );

    Matrix = rotation * scale_m;

    //look at point P
    Front = glm::normalize(p - start_Position);
    Right = glm::normalize(glm::cross(WorldUp, Front));
    Up = glm::normalize(glm::cross(Right, Front));

    if (ended == true) { //if last iteration of my animation: saves position
        Position.x = Matrix[3][0];
        Position.y = Matrix[3][1];
        Position.z = Matrix[3][2];  
    }
}

getMatrix () просто возвращаетматрица 4x4 как:

| Right.x Right.y Right.z |
| Up.x    Up.y    Up.z    |
| Front.x Front.y Front.z |
| Pos.x   Pos.y   Pos.z   |

Я использую это изображение как ссылку:

enter image description here

Так как это моя модель простоисчезает, когда я запускаю анимацию.Если я удаляю линии ниже "//look at point P", он вращается вокруг начала координат, но дергается каждый раз, когда моя анимация перезапускается.Я предполагаю, что я теряю или смешиваю информацию, которую я не должен где-то.Как я могу хранить информацию о моих моделях Front / Right / Up, чтобы я мог восстановить матрицу с нуля?

Первое редактирование , это эффект, который я испытываю, когда не пытаюсь заставить мою модель смотреть на точку P, в данном случае на начало координат.Когда я попробую, моя модель исчезнет.Как я могу заставить его посмотреть, где я хочу, и как я могу получить свои модели новые векторы Front / Right / Up после того, как я закончу вращать его?

Run example

Это код, который я запустил в GIF выше

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

РЕШЕНИЕ:

Проблема была в этой части:

rotation = glm::translate(rotation, p - Position ); 
rotation = glm::rotate(rotation, ROTATION_SPEED * deltaTime, axis);
rotation = glm::translate(rotation, Position - p );


if (ended == true) { //if last iteration of my animation: saves position
    Position.x = Matrix[3][0];
    Position.y = Matrix[3][1];
    Position.z = Matrix[3][2];  
}

Обратите внимание, что я использовал расстояние между источником мира и моделью в качестве радиусаперевод.Однако после окончания анимации я обновляю модель Position, которая меняет результат p - Position, то есть радиус орбиты.Когда это происходит, модель «дергается», потому что теряет информацию о вращении.

Я решил ее, используя другую переменную для радиуса орбиты и применив перевод к z-axis модели.Когда перевод применяется к оси x, модель, которая изначально обращена к камере, в конечном итоге сбоку до начала координат.Однако применение перевода на оси z в конечном итоге приведет к тому, что модель будет обращена к исходной точке или назад, в зависимости от сигнала.

0 голосов
/ 12 октября 2018

Операции типа glm::translate() или glm::roate() построить матрицу по ее параметрам и умножить входную матрицу на новую матрицу

Это означает, что

rotation = glm::translate(rotation, Position - p );

можно выразить как (псевдокод):

rotation = rotation * translation(Position - p);

Обратите внимание, что умножение матриц должно «читаться» слева направо.(См. Программирование GLSL / Векторные и матричные операции )

Операция translate * rotate вызывает поворот вокруг начала координат объекта:

Операция rotate * translate вызывает вращение вокруг происхождения мира:

Матрица glm::mat4 rotation (в коде вашего вопроса) - текущая матрица модели вашего объекта.
Содержит положение ( перевод ) и ориентацию объекта.
Вы хотите вращать объект вокругПроисхождение мира.

Для этого вам нужно создать матрицу, которая содержит новое вращение

glm::mat4 new_rot = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, axis);

Затем вы можете рассчитать окончательную матрицу следующим образом:

Matrix = new_rot * rotation * scale_m;

Если вы хотите повернуть объект вокруг точки p и объект всегда должен быть направлен в точку p, то все, что вам нужно, это положение объекта (start_position) и вращениеось.В вашем случае ось вращения является верхним вектором мира.

glm::vec3 WorldUp( 0.0f, 1.0f, 0.0f );
glm::vec3 start_position = ...;
float scale = ...;
glm::vec3 p = ...;

Рассчитать матрицу вращения и новую (повернутую) позицию

glm::mat4 rotate    = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, WorldUp);
glm::vec4 pos_rot_h = rotate * glm::vec4( start_position - p, 1.0f );
glm::vec3 pos_rot   = glm::vec3( pos_rot_h ) + p;

Рассчитать направление, в котором объектдолжен «выглядеть»

glm::vec3 Front    = glm::normalize(p - pos_rot);

Вы можете использовать свою функцию getMatrix для установки текущей матрицы ориентации объекта:

glm::vec3 Right    = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);

Рассчитать матрицу модели:

glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale));
Matrix = pos_look * scale_m;

Окончательный код может выглядеть так:

glm::mat4 getMatrix(const glm::vec3 &X, const glm::vec3 &Y, const glm::vec3 &Z, const glm::vec3 &T)
{
    return glm::mat4(
        glm::vec4( X, 0.0f ),
        glm::vec4( Y, 0.0f ),
        glm::vec4( Z, 0.0f ),
        glm::vec4( T, 1.0f ) );
}

void rotate_about(float deltaTime, glm::vec3 p, bool ended) {

    glm::mat4 rotate    = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, WorldUp);
    glm::vec4 pos_rot_h = rotate * glm::vec4( start_position - p, 1.0f );
    glm::vec3 pos_rot   = glm::vec3( pos_rot_h ) + p;

    glm::vec3 Front    = glm::normalize(p - pos_rot);
    glm::vec3 Right    = glm::normalize(glm::cross(WorldUp, Front));
    glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);

    glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale));
    Matrix = pos_look * scale_m;

    if ( ended == true )
        Position = glm::vec3(Matrix[3]);
}
...