c++ - 如何在不改变平移方向的情况下在旋转后应用平移?
问题描述
我试图在我的 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 个操作而不让它们相互交互?
解决方案
结果我在尝试恢复更改时以错误的顺序(旋转前缩放)应用了转换。为避免将更改全部还原,您只需设置 3 个不同的单位矩阵(一个用于平移,一个用于旋转,一个用于缩放)并分别对每个矩阵应用正确的变换,然后将 3 个矩阵相乘以获得模型矩阵,顺序很重要:模型 = 平移 * 旋转 * 缩放这样您始终以正确的顺序应用变换,您不必担心 3 个变换会相互干扰
推荐阅读
- javascript - 在 getJSON 或 ajax 内设置的变量值在函数外不同步
- python - 安装 Python 包时出错:PATH 中缺少 make 实用程序
- excel - Excel 2016 甚至可以处理所有这些 IF
- php - PHP 购票,每购 10 张门票可享 2 欧元折扣
- awk - 使用 awk 根据分隔符拆分文件的第一行并按原样打印其他行
- php - Jquery 或 PHP 根据重复值突出显示表格行
- c# - asp.net 将第 3 方 dll 部署到 bin 文件夹
- csv - 如何在 Visual Studio 编辑器中查看列对齐的 CSV 文件
- elixir - 使用 ecto 计算关联的模型行
- reactjs - 将 props 传递给 React-Native-Modal