Как мне применить перевод после поворота без изменения направления перевода?

#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. таким образом, применение преобразований в разных порядках приводит к тому, что конечная матрица отличается