2009-07-13 13 views
1

私は、位置、上方向、および方向ベクトルを保持するカメラ構造を持っています。私はiPhoneの加速度計から得られる重力ベクトルに基づいてこれらのベクトルを更新したいと思います。私が行っている効果は、電話機の上部があなたから離れて傾けられたとき、カメラは地面に向かって見えるということです。言い換えると、シーン/ジオメトリは重力ベクトルの向きに従いますが、カメラは電話機の向きに従います。iPhoneの加速度計からの重力ベクトルでOpenGLでカメラを制御するには

私は、カメラベクトルから構築した行列に重力ベクトルから構築した行列を掛けて、新しい上方向ベクトルと方向ベクトルを引き出すことができると考えましたが、それを働かせることはできません。私は大いに助けていただければ幸いです。ありがとう!

答えて

1

カメラの向きを変更するだけで済みます。あなたは世界の行列を変更する必要はありません、openGLの "gluLookAt()"メソッドは自動的にあなたのためにそれを行います。

カメラクラスを設定している場合は、カメラの上方向ベクトルを設定する関数を作成するだけで、iPhoneのコンパスからfloat/double値(私が想定している)に基づいて計算する必要があります。あなたのカメラのアップデートがlookAt()の位置にあるとき、正しい位置を見るようにカメラを変更する必要があります。

これは、FPSベースのゲームでカメラを回転させたときとは大きく異なります。違いは、Y軸に沿ってではなくX軸に沿ってカメラを回転させたいということです。

キーボードでカメラを左右に動かすためにカメラクラスをどのように回転させたかを見て、コンパスの方向値を使ってカメラクラスを動作させる方法を見てみましょう。

ここ

は、お使いのカメラのクラスが作業しなければならない方法についてのあなたの洞察力を与える可能性があり、私が書いたいくつかのC++コードです:

/* This reshapes the camera using the perspective projection */ 
void Camera::ReshapePerspectiveForPicking(void) 
{ 
    glMatrixMode(GL_PROJECTION); 

    // Sets the clipping volume 
    gluPerspective(m_FieldOfView, (float)m_width/(float)m_height, m_zNear, m_zFar); 

    gluLookAt( camPos.x, camPos.y, camPos.z, 
      camPos.x + camView.x, camPos.y + camView.y, camPos.z + camView.z, 
      0.0f, 1.0f, 0.0f); 

    glMatrixMode(GL_MODELVIEW); 
} 

をメモ(は0.0f、1.0F上の行に、0.0 f)。これがUP方向ベクトルです。 カメラが見下す必要がないので、私のゲームでは静的でした。 コンパスの方向に新しいアップベクトルを作成するだけで、このベクトルを変更するだけです。

以下のメソッドは、特殊なベクターを渡すことによってカメラを時々更新する必要があった単純な方法でした。あなたはおそらくそれを無視することができます、私はあなたがそれから学ぶことができるようにそれを含んでいます。ここで

/* This updates the camera to look at the changed camera position. This uses a passed in camPosition and camView GameMath::Vector */ 
    void Camera::Update(GameMath::Vector camPos, GameMath::Vector camView) 
    { 
     glMatrixMode(GL_PROJECTION); 
     gluLookAt( camPos.x, camPos.y, camPos.z, 
       camPos.x + camView.x, camPos.y + camView.y, camPos.z + camView.z, 
       0.0f, 1.0f,0.0f); 
    } 

は、Y軸に沿ってカメラを回転させるための私の方法は、私はそれを書いた(それはちょっとdodgeyだから--Iは今、このメソッドを書き換えるでしょう(あなたはX軸に沿って回転したい忘れないでください)です数年前)、どのようにそれを行うことができるかを示すだけで十分です。

void Camera::Rotate(void) 
{ 
    if (m_rotateCamera == true) 
    { 
     // Keep the radians within 2 pi, roughly 
     float minimumRadiansRotate = 0.00; 
     float maximumRadiansRotate = 6.2831853072; 
     m_YRotateAngle = GameMath::Wrap(m_YRotateAngle, minimumRadiansRotate, maximumRadiansRotate); 

     m_YRotateAngle += m_rotateSpeed * m_rotateDirection; // Add to the camera's current angle value 
     camView.x = sin(m_YRotateAngle); 
     camView.z = -cos(m_YRotateAngle); 
    } 
} 

これはあなたが何をすべきか理解してもらう必要がありますが、お使いのカメラのクラスは、鉱山におそらく異なっているので、それはあなたがやりたいようにコードの特定の部分を提供するために少し難しいです。

CoreLocationフレームワークには、コードをまだコンパイルしていない場合でもコンパスから値を読み取るために必要なコードが含まれています。

幸運。

+0

これは私が持っているすべては、任意の時点で新しいです(私はあなたが説明しているものを誤解していない限り)コンパスが組み込まれていますが、私は唯一の加速度計で働いている新しいiPhoneのために働くだろうアップベクター。また、新しいアップベクトルはカメラのx軸に対して垂直であることが保証されていないので、カメラの新しい方向を決定するにはどうすればよいですか? –

1

Appleのsample GLGravity applicationは、あなたの要求を間違って読んでいない限り、あなたが望むものを正確に行うと思います。

+0

はい、達成しようとしているのと非常に似ています。だからこそ私は私の研究を始めました。しかし、後で使用するために方向ベクトルを保存しながらこの効果を得ることは、難易度を見つけているところです。ありがとう! –

0

私はコトで開始、私は、このようなものに非常に新しいですので、警戒するが、...

私は上記のBrockのコードと彼の説明を見て、私は回転するカメラを思い付いたと思います奨めx軸とy軸の周りに実際には、私のカメラはz軸まわりで回転しますが、私はそれが別の物語だと考えています(私はちょうど "アップ"ベクトルにx & y加速度計の値を直接フィードして、 ...かなりうまくいく)。

そう...ここに私が思い付いたものです:

float lx = sin(DEGREES_TO_RADIANS(horzAngle)); 
float ly = sin(DEGREES_TO_RADIANS(vertAngle)); 
float lz = -cos(DEGREES_TO_RADIANS(horzAngle)); 

float x; 
float y; 
float z; 

    // get the default camera eye for the object 
    // this will center the object on the screen 
[sprite.camera restore]; 
[sprite.camera eyeX:&x eyeY:&y eyeZ:&z]; 

// add distance calcs 
x = x + (-1 * sprite.distance)*(lx); 
z = z + (-1 * sprite.distance)*(-1); 

[sprite.camera setEyeX:x eyeY:y eyeZ:z]; 
[sprite.camera setCenterX:x + lx centerY:y + ly centerZ:z + lz]; 

これは、それが呼び出してしまいますように、これはカメラのものをラップ...(非常に使いやすい)cocos2dライブラリを使用しています

gluLookAt(eyeX, eyeY, eyeZ, 
      centerX, centerY, centerZ, 
      upX, upY, upZ 
      ); 

私が言ったように、私はこれに新たなんだので、これは右見ていないかもしれませんが、あなたが記述しているよう...私はvertAngleを制御するために、加速度計を追加するつもりのようです。このようgluLookAtだから、私は加速コードが結ばれると、私は試して、ここに投稿することを忘れないでください。

また、他の誰かが光を加えることができないものがあれば、私はそれを聞いてみたいです。あなたが本当に欲しい

おかげで、

ジョン

0

は、加速度値に基づいて、新たな射影行列です。ウーロンはこれを(私ではなく)crazy mathに提供します。

/* 
Oolong Engine for the iPhone/iPod touch 
Copyright (c) 2007-2008 Wolfgang Engel http://code.google.com/p/oolongengine/ 

This software is provided 'as-is', without any express or implied warranty. 
In no event will the authors be held liable for any damages arising from the use of this software. 
Permission is granted to anyone to use this software for any purpose, 
including commercial applications, and to alter it and redistribute it freely, 
subject to the following restrictions: 

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 
3. This notice may not be removed or altered from any source distribution. 
*/ 

#import "Accelerometer.h" 

#define FILTERINGFACTOR 0.1 

@implementation Accel 

- (void) SetupAccelerometer: (float) AcclerometerFrequency 
{ 
     //Configure and start accelerometer 
     [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0/AcclerometerFrequency)]; 
     [[UIAccelerometer sharedAccelerometer] setDelegate:self]; 
} 



- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)Acceleration 
{ 
     // use a basic low-pass filter to only keep the gravity in the accelerometer values 
     _accelerometer[0] = Acceleration.x * FILTERINGFACTOR + _accelerometer[0] * (1.0 - FILTERINGFACTOR); 
     _accelerometer[1] = Acceleration.y * FILTERINGFACTOR + _accelerometer[1] * (1.0 - FILTERINGFACTOR); 
     _accelerometer[2] = Acceleration.z * FILTERINGFACTOR + _accelerometer[2] * (1.0 - FILTERINGFACTOR); 
} 

- (void) GetAccelerometerMatrix:(GLfloat *) matrix 
{ 

     GLfloat length = sqrtf(_accelerometer[0] * _accelerometer[0] + _accelerometer[1] * _accelerometer[1] + _accelerometer[2] * _accelerometer[2]); 

     //Clear matrix to be used to rotate from the current referential to one based on the gravity vector 
     bzero(matrix, sizeof(matrix)); 
     matrix[15] = 1.0f; 
     //matrix[3][3] = 1.0; 

     //Setup first matrix column as gravity vector 
     matrix[0] = _accelerometer[0]/length; 
     matrix[1] = _accelerometer[1]/length; 
     matrix[2] = _accelerometer[2]/length; 

     //Setup second matrix column as an arbitrary vector in the plane perpendicular to the gravity vector {Gx, Gy, Gz} defined by by the equation "Gx * x + Gy * y + Gz * z = 0" in which we arbitrarily set x=0 and y=1 
     matrix[4] = 0.0; 
     matrix[5] = 1.0; 
     matrix[6] = -_accelerometer[1]/_accelerometer[2]; 
     length = sqrtf(matrix[4] * matrix[4] + matrix[5] * matrix[5] + matrix[6] * matrix[6]); 
     matrix[4] /= length; 
     matrix[5] /= length; 
     matrix[6] /= length; 

     //Setup third matrix column as the cross product of the first two 
     matrix[8] = matrix[1] * matrix[6] - matrix[2] * matrix[5]; 
     matrix[9] = matrix[4] * matrix[2] - matrix[6] * matrix[0]; 
     matrix[10] = matrix[0] * matrix[5] - matrix[1] * matrix[4]; 
} 

- (void) GetAccelerometerVector:(double *) AccelValue; 
{ 
     // the vector is read-only, so make a copy of it and do not expose a pointer to it 
     AccelValue[0] = (double)_accelerometer[0]; 
     AccelValue[1] = (double)_accelerometer[1]; 
     AccelValue[2] = (double)_accelerometer[2]; 
} 

@end 
関連する問題