不确定是在这里发布还是在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)
点旋转。我做错了什么?
答案 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指出我正确的方向!