OpenGL ES翻译和旋转

时间:2014-11-26 13:40:58

标签: android opengl-es

不确定是在这里发布还是在GameDev发布,但由于它不是真正的游戏开发我决定在这里问。

我在Android上尝试OpenGL ES 2,现在我有一个简单的设置。我从.obj文件加载一个对象,将其显示在屏幕上,然后我可以使用触摸控制器围绕对象旋转相机。我的viewMatrix设置如下:

double[] dist = {DISTANCE * Math.sin(yawAngle) * Math.abs(Math.cos(pitchRollAngle)),
        DISTANCE * Math.sin(pitchRollAngle),
        DISTANCE * Math.cos(yawAngle) * Math.abs(Math.cos(pitchRollAngle))};

Matrix.setLookAtM(viewMatrix, 0, (float) dist[0], (float) dist[1], (float) dist[2], 0f, 0f, 0f, 0f, 1.0f, 0.0f);

我的投影矩阵就是这样:

Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 100);

我根据触摸事件设置了偏航/俯仰角度。现在这个工作正常,当对象位于屏幕的中心时,我可以像我应该的那样旋转。但是,如果我试图移动对象,比如X轴上的1个单位,就像这样:

float[] modelMatrix = new float[16];
Matrix.setIdentityM(modelMatrix, 0);
Matrix.translateM(modelMatrix, 0, 1, 0, 0);

然后将所有这些相乘:

float[] MVPMatrix = new float[16];
Matrix.multiplyMM(MVPMatrix, 0, modelMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(MVPMatrix, 0, projectionMatrix, 0, MVPMatrix, 0);

物体在其位置旋转,但我希望它围绕(0, 0, 0)点旋转。我做错了什么?

3 个答案:

答案 0 :(得分:1)

我记得在Delphi 2010中遇到类似的问题,当时我不得不在那里使用OpenGL。诀窍是将对象放回< 0,0,0>,应用旋转,然后在绘制帧之前将其放回原始位置。 我无法回忆起我是如何做到的,也不再能够访问该代码,因为它属于我以前的雇主,但这就是我记得的。

答案 1 :(得分:1)

这是关于矩阵乘法的最常见问题之一。在您的情况下,您需要先旋转对象然后翻译它。因此,如果首先转换为X然后旋转,则对象将出现在位置X处,但绕其自身轴旋转。如果先旋转然后再转换X,则对象不会出现在X处,而是通过旋转X本身得到的点。这是一个预期的结果,它是如何工作的。

所以要了解会发生什么:矩阵实际上由3个基本向量和一个中心组成。标识时,基础向量为(1,0,0)(0,1,0)(0,0,1)(0,0,0)。现在,当将该矩阵与一些变换相乘时,基本矢量实际上被变换。结果是矩阵包含自己的坐标系,其中转换似乎是“逻辑的”。这导致旋转矩阵永远不会改变对象的中心。

我知道这太复杂了,但实际上很容易想象效果:就好像矩阵乘法实际上是从第一人称视角看到角色的命令。因此,当你说“前进”(翻译)时,你向前迈出一步,现在“转90度”,你转90度,仍然在同一个位置,现在“再往前走”,你又向前迈了一步,但这是实际上与开始时的方向不一样......

所以你所做的就是说“前进1”,现在转为ANGLE度。这导致物体保持在相同位置并围绕其自身轴旋转。 而你应该做的是说“转向你的目标”(由ANGLE旋转)现在“前进1”,甚至可能“转回-ANGLE”所以你面向你的方向在开始时做了。

我希望这个解释会对你有帮助。

答案 2 :(得分:0)

问题在于这一行:

Matrix.multiplyMM(MVPMatrix, 0, modelMatrix, 0, viewMatrix, 0);

我只是切换了模型和视图矩阵,以便它们相反地相乘,并且它可以工作!像这样:

 Matrix.multiplyMM(MVPMatrix, 0, viewMatrix, 0, modelMatrix, 0);

感谢@Zubaja指出我正确的方向!