簡體   English   中英

Android:OpenGL 2.0使用Matrix.setLookAtM旋轉/移動相機

[英]Android : OpenGL 2.0 Rotation/moving the Camera using Matrix.setLookAtM

所以這是我今天的第二個問題,總之我會很幸運。總之,成為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度,然后出現問題了?

有任何想法嗎?

首先,我建議不要跟蹤look向量,而應跟蹤forward向量,然后在lookAt方法中使用eye+forward生成look向量。 這樣,您可以在移動時完全放松look上的更新,並且無需計算v向量( mRenderer.eyeX += forward.x * SPEED_MOVE; ...)

為了使事情更簡單,我建議您在更改矢量時forwardup歸一化(我將按照在以下方法中所做的考慮)。

現在,旋轉有兩種方法。 無論是使用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)

第二種方法需要一點三角函數:

通常,要計算角度,您可以只調用atan(forward.z/forward.x)並添加一些if語句,因為生成的結果僅在180度角內(我相信您將能夠在網上找到一些答案,以從向量獲得旋轉)。 用於獲得垂直旋轉的up矢量也是如此。 然后,在獲得角度后,您可以輕松地向角度添加一些度數,並使用sincos重新創建向量。 但是有一個陷阱,如果您以這種方式旋轉攝像機,使前臉筆直向上(0,1,0),則需要從up向量獲得第一個旋轉,而從前forward向量獲得第二個旋轉,但是如果您將最大垂直角度的上限設置為+-85度(實際上有很多游戲可以這樣做)。 第二件事是,如果您使用此方法,則您的環境必須支持+ -infinitive,否則如果forward.x == 0則此atan(forward.z/forward.x)將會制動。

還有關於第一種方法的一些補充。 由於我看到您正在嘗試在2D空間中移動,因此應將要與移動速度一起使用的前向矢量normalized(forward.x, 0, forward.z) ,將其歸一化很重要,否則,如果相機傾斜,則移動速度會變慢向上或向下更多。 第二件事是,當您向左/向右旋轉時,您可能希望將向量up強制為(0,1,0)+對右向量進行歸一化,最后從正向和右方向重新創建向上向量。 再一次,您應該設置垂直旋轉的上限(up.z應該大於某個較小的值,例如.01)

原來我的旋轉碼不對

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])));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM