2

所以这是我今天的第二个问题,我可能会碰运气 简而言之,制作一个 3D 第一人称,您可以在其中四处走动和环顾四周。

在我的 OnDrawFrame 我正在使用

Matrix.setLookAtM(mViewMatrix, 0, eyeX , eyeY, eyeZ , lookX , lookY , lookZ , upX, upY, upZ);

要前后移动,向左回避等,我使用类似这样的东西(列出的前向代码)

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;

这有效

现在我想环顾四周,并尝试移植我的 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]);
}

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

有任何想法吗?

4

2 回答 2

5

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

为了使事情变得更简单,我建议您规范化向量forward以及up每当您更改它们时(我会像您在以下方法中所做的那样考虑)。

现在轮换有两种方式。使用rightup向量来移动forward(and 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)

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

通常要计算一个角度,你可以调用atan(forward.z/forward.x)并添加一些if语句,因为生成的结果只有 180 度角(我相信你可以在网上找到一些答案来从矢量旋转)。up用于获取垂直旋转的向量也是如此。然后在获得角度后,您可以轻松地为角度添加一些度数并使用 和 重新创建sin向量cos。但是有一个问题,如果你以这种方式旋转相机,那么你需要从up向量中获得第一个旋转,第二个来自forward矢量,但如果您将最大垂直角度限制在 +- 85 度之类的范围内,则可以避免所有这些(实际上有很多游戏都这样做)。第二件事是,如果您使用这种方法,您的环境必须支持 +-不定式,否则atan(forward.z/forward.x)如果forward.x == 0.

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

于 2013-04-16T11:28:02.133 回答
0

原来我的轮换代码是错误的

if (x > mPreviousX )
{
 mRenderer.lookX  = (float) (mRenderer.eyeX +  ((Math.cos(SPEED_TURN / 2) * v[0]) - (Math.sin(SPEED_TURN / 2) * v[2])));
 mRenderer.lookZ  =  (float) (mRenderer.eyeZ +  ((Math.sin(SPEED_TURN / 2) * v[0]) + (Math.cos(SPEED_TURN / 2) * v[2])));
}
else
{
 mRenderer.lookX  =  (float) (mRenderer.eyeX + ((Math.cos(-SPEED_TURN / 2) * v[0]) - (Math.sin(-SPEED_TURN / 2) * v[2])));
 mRenderer.lookZ  =  (float) (mRenderer.eyeZ + ((Math.sin(-SPEED_TURN / 2) * v[0]) + (Math.cos(-SPEED_TURN / 2) * v[2])));
}
于 2013-04-16T11:48:40.583 回答