1

位置、上、および方向のベクトルを保持するカメラ構造があります。iPhone の加速度計から取得した重力ベクトルに基づいて、これらのベクトルを更新したいと思います。私が目指している効果は、電話の上部があなたから離れて傾いているとき、カメラは地面の方を向くということです。つまり、シーン/ジオメトリは重力ベクトルの方向に従い、カメラは電話自体の方向に従います。

カメラベクトルから構築した行列に重力ベクトルから構築した行列を掛けて、新しい上方向ベクトルと方向ベクトルを引き出すことができると思いましたが、取得できないため、プロセスを完全に理解していないと思いますそれが機能します。助けていただければ幸いです。ありがとう!

4

4 に答える 4

1

Apple のサンプル GLGravity アプリケーションは、私があなたのリクエストを読み間違えていない限り、まさにあなたが望んでいることを実行すると思います。

于 2009-07-13T14:36:59.490 に答える
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.0f) に注意してください。これは 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軸に沿ってカメラを回転させる方法は次のとおりです( 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 フレームワークには、まだその部分をコーディングしていない場合に備えて、コンパスから値を読み取るために必要なコードが含まれています。

幸運を。

于 2009-07-13T10:22:11.543 に答える
0

本当に必要なのは、加速度値に基づく新しい射影行列です。ウーロン茶はそれを行うためにこのクレイジーな数学を提供します(私のものではありません)。

/*
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
于 2009-09-18T13:26:44.883 に答える
0

私はこのようなことに非常に慣れていないので、用心してください、しかし...

上記のブロックのコードと彼の説明を見て、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ように呼び出すことになります:

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

私が言ったように、私はこれに慣れていないので、これは正しく見えないかもしれませんが、そう思われます...あなたが説明しているように、加速度計を追加してvertAngleを制御するつもりなので、加速度コードを配線すると、ここに投稿することを忘れないようにします。

また、他の誰かが光を加えることができる何かを私が見逃している場合は、それを聞いてみたい.

ありがとう、

ジョン

于 2009-07-30T23:40:12.950 に答える