Android:OpenGL 2.0使用Matrix.setLookAtM旋转/移动相机

Bur*_*000 2 android matrix opengl-es-2.0

所以这是我今天的第二个问题,我可能会推动我的运气.简而言之,制作3D第一人称,你可以在那里四处走动.

在我正在使用的My OnDrawFrame中

Matrix.setLookAtM(mViewMatrix, 0, eyeX , eyeY, eyeZ , lookX , lookY , lookZ , upX, upY, upZ);
Run Code Online (Sandbox Code Playgroud)

要向后移动,向后移动,向左移动等我使用这样的东西(转发代码列出)

float v[] = {mRenderer.lookX - mRenderer.eyeX,mRenderer.lookY - mRenderer.eyeY, mRenderer.lookZ - mRenderer.eyeZ};

mRenderer.eyeX += v[0] * SPEED_MOVE;
mRenderer.eyeZ += v[2] * SPEED_MOVE;

mRenderer.lookX +=  v[0] * SPEED_MOVE;
mRenderer.lookZ +=  v[2] * SPEED_MOVE;
Run Code Online (Sandbox Code Playgroud)

这有效

现在我想环顾四周,我试图移植我的iPhone openGL 1.0代码.这是左/右

float v[] = {mRenderer.lookX - mRenderer.eyeX,mRenderer.lookY - mRenderer.eyeY, mRenderer.lookZ - mRenderer.eyeZ};

if (x > mPreviousX )
{
 mRenderer.lookX  +=  ((Math.cos(SPEED_TURN / 2) * v[0]) - (Math.sin(SPEED_TURN / 2) * v[2]));
 mRenderer.lookZ  +=  ((Math.sin(SPEED_TURN / 2) * v[0]) + (Math.cos(SPEED_TURN / 2) * v[2]));
}
else
{
 mRenderer.lookX  -=  (Math.cos(SPEED_TURN / 2) *v[0] - Math.sin(SPEED_TURN / 2) * v[2]);
 mRenderer.lookZ  -=  (Math.sin(SPEED_TURN / 2) *v[0] + Math.cos(SPEED_TURN / 2) * v[2]);
}
Run Code Online (Sandbox Code Playgroud)

这适用于35度,然后去精神?

有任何想法吗?

Mat*_*lak 5

首先,我建议不要追踪look矢量而是追踪forward矢量,然后在lookAt方法中使用eye+forward来生成look矢量.这样你就可以look在移动时完全松开更新,而你不需要计算v向量(mRenderer.eyeX += forward.x * SPEED_MOVE;...)

为了使事情变得更简单,我建议你对矢量进行标准化,forward并且up每当你改变它们时(我会像你在下面的方法中那样考虑).

现在轮换有两种方式.使用rightup向量移动forward(和up)这对于小转弯很有用(我说大约10度并且上限为90度)或者计算当前角度,添加你想要的任何角度并重新创建矢量.

首先提到的旋转方法非常简单:

vector forward = forward
vector up = up
vector right = cross(forward, up) //this one might be the other way around as up, forward :)
//going left or right:
forward = normalized(forward + right*rotationSpeedX)
//going up or down:
forward = normalized(forward + up*rotationSpeedY)
vector right = cross(forward, up) //this one might be the other way around
vector up = normalized(cross(forward, right)) //this one might be the other way around
//tilt left or right:
up = normalized(up + right*rotationZ)
Run Code Online (Sandbox Code Playgroud)

第二种方法需要一点三角学:

通常计算一个角度你可以调用atan(forward.z/forward.x)并添加一些if语句,因为生成的结果只有180度角(我相信你能在网上找到一些答案来从矢量中获得旋转).这同样与up向量获得垂直旋转.然后,你得到的角度后,您可以轻松地只需添加一些度的角度和重建具有矢量sincos.但是有一个问题,如果你以这种方式旋转相机,前方面朝上(0,1,0),你需要从up矢量获得第一次旋转,第二次从forward矢量,但你可以避免所有这一切,如果你将最大垂直角度限制在+ - 85度(并且有很多游戏实际上这样做).第二件事是如果你使用这种方法,你的环境必须支持+ -infinitive,否则这atan(forward.z/forward.x)会制动forward.x == 0.

还有一些关于第一种方法的补充.由于我看到你试图在2D空间中移动,你的前向矢量应该与移动速度一起使用,normalized(forward.x, 0, forward.z)重要的是将其标准化,否则如果相机向上或向下倾斜更多,你将移动得更慢.第二件事是当你向左/向右旋转时,你可能想强制up向量到(0,1,0)+标准化右向量,最后从向前和向右重新创建向上向量.然后,你应该再调整垂直旋转(up.z应该大一些小值,如.01)