#c #glm-math
#c #glm-math
Вопрос:
Я пытаюсь применить перевод к матрице модели объекта в моей программе OpenGL, но если я применю перевод после применения масштаба или поворота к матрице модели, я получу результаты, отличные от ожидаемых: применение перевода после масштаба приводит к тому, что перевод умножается на масштаб, применение перевода после поворота приводит к тому, что перевод применяется в другом направлении. Я понимаю, как работают воспроизводимые матрицы и как они изменяют матрицу модели, поэтому я использовал эту реализацию, чтобы отменить изменения перед применением перевода:
void Entity::scale(float scaleFactor) {
this->modelMatrix = glm::scale(this->modelMatrix, glm::vec3(scaleFactor));
this->scaleFactor *= scaleFactor;
}
void Entity::move(glm::vec3 position, glm::mat4 viewMatrix) {
float oldScaleFactor = this->scaleFactor;
float oldRotateFactorX = this->rotateFactorX;
float oldRotateFactorY = this->rotateFactorY;
float oldRotateFactorZ = this->rotateFactorZ;
scale(1 / this->scaleFactor);
rotate(-this->rotateFactorX, -this->rotateFactorY, -this->rotateFactorZ);
this->modelMatrix = glm::translate(modelMatrix, position);
glm::mat4 worldModelMatrix = glm::inverse(viewMatrix) * (viewMatrix * this->modelMatrix);
this->worldPosition.x = worldModelMatrix[3][0];
this->worldPosition.y = worldModelMatrix[3][1];
this->worldPosition.z = worldModelMatrix[3][2];
rotate(oldRotateFactorX, oldRotateFactorY, oldRotateFactorZ);
scale(oldScaleFactor);
}
void Entity::rotate(float x, float y, float z) {
this->rotateFactorX = x;
this->rotateFactorY = y;
this->rotateFactorZ = z;
this->modelMatrix = glm::rotate(this->modelMatrix, glm::radians(x), glm::vec3(1.0f, 0.0f, 0.0f));
this->modelMatrix = glm::rotate(this->modelMatrix, glm::radians(y), glm::vec3(0.0f, 1.0f, 0.0f));
this->modelMatrix = glm::rotate(this->modelMatrix, glm::radians(z), glm::vec3(0.0f, 0.0f, 1.0f));
}
по сути, я отменяю операции масштабирования и поворота перед применением перевода, а затем возвращаю их в прежнее состояние.
Эта реализация работает для масштаба, но не работает для поворота, что приводит к увеличению скорости вращения, которая выходит из-под контроля (что означает, что коэффициент поворота постоянно увеличивается).
Правильно ли я возвращаю поворот? или даже лучше: есть ли лучший способ разделить 3 операции, не заставляя их взаимодействовать друг с другом?
Ответ №1:
Оказывается, я применял преобразования в неправильном порядке (масштабирование перед поворотом) при попытке отменить изменения. Чтобы избежать необходимости полностью отменять изменения, вы можете просто настроить 3 разные идентификационные матрицы (одну для перевода, одну для поворота и одну для масштабирования) и применить правильное преобразование к каждой матрице по отдельности, а затем перемножить 3 матрицы вместе, чтобы получить матрицу модели, порядок важен: модель = перевод * вращение * масштабирование таким образом, вы всегда применяете преобразования в правильном порядке, и вам не нужно беспокоиться о том, что 3 преобразования мешают друг другу
Комментарии:
1. Неплохо. Хотя почему порядок операций имеет значение? Интуитивно понятно, что не должно иметь значения, перемещаются точки до или после масштабирования, нет?
2. проблема в том, что применение преобразований означает умножение матриц, а матричное умножение не является коммутативным (не уверен, называется ли это так на английском). в принципе, если у вас есть матрицы A и B, A * B != B * A. таким образом, применение преобразований в разных порядках приводит к тому, что конечная матрица отличается