如何在轮换后应用翻译而不改变翻译方向?

问题描述 投票:0回答:1

我正在尝试将翻译应用到我的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个操作而不让它们相互交互?

c++ glm-math
1个回答
0
投票

事实证明,当我试图恢复更改时,我正在以错误的顺序(旋转前缩放)应用转换。为了避免必须完全恢复变化,您可以设置3个不同的单位矩阵(一个用于平移,一个用于旋转,一个用于缩放)并将单独的正确变换应用于每个矩阵,然后将3个矩阵相乘以得到模型矩阵,顺序很重要:模型=翻译*旋转*缩放这种方式你总是以正确的顺序应用变换,你不必担心3变换相互干扰

© www.soinside.com 2019 - 2024. All rights reserved.