Jak mohu ovládat kameru v OpenGL s vektoru gravitace z iPhone akcelerometr

hlasů
1

I mají strukturu kamery, která drží místě, nahoru a směrových vektorů. Rád bych, aby aktualizaci těchto vektorů na základě vektoru gravitace získám z iPhone akcelerometr. Účinek Jdu je: když je horní část telefonu nakloněna směrem od sebe, kamera se dívá směrem k zemi. Jinými slovy, scéna / geometrie následuje orientace vektoru gravitace, zatímco kamera sleduje orientaci samotný telefon.

Myslel jsem, že bych mohl násobit matici I postavený z vektorů fotoaparát jeden postavený z vektoru gravitace a pak už jen vytáhněte nových nahoru a směrových vektorů, ale nemyslím si, že jsem plně pochopit proces, jak jsem nemůže dostat se do práce. Já bych velice vážíme jakoukoliv pomoc. Dík!

Položena 13/07/2009 v 11:03
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
1

Ty by prostě muset aktualizovat směr, ve kterém je kamera dívá. Nemusíte měnit svět matice, OpenGL „gluLookAt ()“ metoda udělá za vás automaticky zákulisí.

Pokud máte nastavení třídu fotoaparát, jednoduše vytvořit funkci nastavit směr vektoru kamery, které budete potřebovat získat vypočítat na základě float / dvojnásobku (předpokládám) z iPhone kompas. Když vaše aktualizace fotoaparát je to lookAt pozice (), že by se měl změnit na kameru podívat na správném místě.

To není tak příliš neliší od toho, co děláte, když otočíte fotoaparát do FPS založená hra s. Rozdíl je v tom, že chcete otočit kameru po ose X namísto podél osy y.

Podívejte se, jak třída fotoaparát schopen rotace pro pohyb kamery doleva nebo doprava pomocí klávesnice a potom jej upravit pro práci s své hodnoty kompasu.

Zde jsou některé C ++ kód, který jsem napsal, která vám může poskytnout náhled na to, jak vaše třída fotoaparát by měl být práci:

/* 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 );
}

Vezměte na vědomí, na řádek výše (0.0f, 1.0f, 0.0f). To je směr nahoru vektor. Bylo to statické pro mou hru, protože fotoaparát nikdy nepotřeboval dívat dolů. Ty by prostě muset změnit tento vektor by vytvořil nový up vektoru na orientaci kompasu.

Níže uvedená metoda byla prostě alternativní metodou jsme potřebovali občas aktualizovat kameru průchodem speciální vektor. Můžete pravděpodobně ignorovat, prostě jsem to zahrnuty, takže si mohl se z ní poučit.

   /* 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 );
    }

Zde je moje metoda pro otáčení fotoaparátu podél osy Y (Nezapomeňte, že chcete otočit kolem osy X ) --I by přepsat tuto metodu nyní, protože je to docela dodgey (napsal jsem to před lety), ale je to dost, aby vám ukázat, jak se to dá udělat.

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

Je to trochu obtížné, aby vám s určitou část kódu dělat, co chcete dělat, protože vaše třída fotoaparát je pravděpodobně odlišná od dolu, i když to by měl dostat, abyste pochopili, co je třeba udělat.

Rámec CoreLocation obsahuje kousky kódu, budete muset číst hodnoty z kompasu zapouzdřit jste kódované že část dosud.

Hodně štěstí.

Odpovězeno 13/07/2009 v 11:22
zdroj uživatelem

hlasů
1

Myslím, že Apple je vzorek GLGravity aplikace dělá přesně to, co chcete, pokud čtu váš požadavek špatně.

Odpovězeno 13/07/2009 v 15:36
zdroj uživatelem

hlasů
0

musím začít tím, že říkáš, jsem velmi nový této věci, takže se na pozoru, ale ...

Podíval jsem se na kód Brockově výše a jeho vysvětlení, a myslím, že jsem přišel s kamerou rotující kolem oba x a osy y. ve skutečnosti, můj fotoaparát otáčí kolem Z taky, ale myslím, že je jiný příběh (i jen zdroj filtrované hodnoty z hodnot akcelerometru x a y přímo na „up“ vektoru vytvořit iluzi, že moje cíle jsou ovlivněny skutečnou gravitací ... funguje docela dobře).

takže ... tady je to, co jsem přišel s:

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

To je pomocí Cocos2d knihovny (velmi snadné) ... to zabalí věci kamery tak, že skončíš volá gluLookAttakhle:

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

Jak jsem řekl, že jsem se na tento nový, takže to nemusí vypadat správně, ale zdá se, že ... mám v úmyslu přidat akcelerometru k ovládání vertAngle jak popisujete, takže když jsem se dostat zrychlení kód zapojen, Pokusím se zapamatovat, abyste mohl psát, že tady.

Také, pokud jsem něco chybí, že někdo jiný může přidat nějaké světlo, rád bych to slyšet.

dík,

John

Odpovězeno 31/07/2009 v 00:40
zdroj uživatelem

hlasů
0

To, co opravdu chcete, je nový projekční matice na základě hodnot zrychlení. Oolong poskytuje tuto bláznivou matematiku k tomu, že (ne moje).

/*
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
Odpovězeno 18/09/2009 v 14:26
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more