旋转后如何应用平移而不改变平移方向?

时间:2019-03-30 12:48:48

标签: 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));
}

基本上,在应用平移之前,我会还原比例并旋转操作,然后将其放回原处。 此实现适用于比例尺,但不适用于旋转,这会导致旋转速度增加而失去控制(这意味着旋转系数不断增加)。 我是否可以正确还原旋转角度?甚至更好:是否有更好的方法来分离这三个操作,而不让它们彼此交互?

1 个答案:

答案 0 :(得分:0)

结果是,当尝试还原更改时,我以错误的顺序(旋转之前缩放)应用了转换。为了避免全部还原更改,您可以只设置3个不同的标识矩阵(一个用于平移,一个用于旋转,一个用于缩放),然后将正确的变换分别应用于每个矩阵,然后将这三个矩阵相乘以得到模型矩阵,顺序很重要: 模型=平移*旋转*比例 这样一来,您始终可以按正确的顺序应用转换,而不必担心3个转换相互干扰