Операции типа glm::translate()
или glm::roate()
построить матрицу по ее параметрам и умножить входную матрицу на новую матрицу
Это означает, что
rotation = glm::translate(rotation, Position - p );
можно выразить как (псевдокод):
rotation = rotation * translation(Position - p);
Обратите внимание, что умножение матриц должно «читаться» слева направо.(См. Программирование GLSL / Векторные и матричные операции )
Операция translate * rotate
вызывает поворот вокруг начала координат объекта:
![](https://i.stack.imgur.com/20M60.png)
Операция rotate * translate
вызывает вращение вокруг происхождения мира:
![](https://i.stack.imgur.com/of0QY.png)
Матрица 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]);
}