Come si usa il vettore gravità di trasformare correttamente scena per la realtà aumentata?

StackOverflow https://stackoverflow.com/questions/2541668

  •  23-09-2019
  •  | 
  •  

Domanda

sto provando figura come ottenere un oggetto OpenGL specificato da visualizzare correttamente secondo l'orientamento del dispositivo (es. Secondo il vettore di gravità dalla accelerometro, e voce da bussola).

Il progetto di esempio GLGravity ha un esempio che è quasi come questo (nonostante ignorando titolo), ma ha alcuni difetti. Ad esempio, la teiera salta 180deg come l'angolo di visione dispositivo attraversa l'orizzonte, e ruota anche falsamente se si inclina il dispositivo da verticale in orizzontale. Questo va bene per il contesto di questa applicazione, in quanto mostra appena fuori un oggetto e non importa che fa queste cose. Ma significa che il codice non funziona quando si tenta di emulare la visione vita reale di un oggetto OpenGL in base all'orientamento del dispositivo. Quello che succede è che quasi funziona, ma la rotazione titolo si applica dalla bussola viene "corrotto" dalle rotazioni aggiuntive spuri visto nel progetto di esempio GLGravity.

Qualcuno può fornire il codice di esempio che mostra come regolare correttamente per l'orientamento del dispositivo (ad es. Vettore gravità), o per fissare l'esempio GLGravity in modo che non include intestazione spuria modifiche?

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

//Setup first matrix column as gravity vector
matrix[0][0] = accel[0] / length;
matrix[0][1] = accel[1] / length;
matrix[0][2] = accel[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[1][0] = 0.0;
matrix[1][1] = 1.0;
matrix[1][2] = -accel[1] / accel[2];
length = sqrtf(matrix[1][0] * matrix[1][0] + matrix[1][1] * matrix[1][1] + matrix[1][2] * matrix[1][2]);
matrix[1][0] /= length;
matrix[1][1] /= length;
matrix[1][2] /= length;

//Setup third matrix column as the cross product of the first two
matrix[2][0] = matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1];
matrix[2][1] = matrix[1][0] * matrix[0][2] - matrix[1][2] * matrix[0][0];
matrix[2][2] = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];

//Finally load matrix
glMultMatrixf((GLfloat*)matrix);

Ecco un chiarimento che mostra come ottenere l'elevazione e l'inclinazione che sono necessari per soluzione gluLookAt come indicato nella mia ultima risposta:

// elevation comes from z component (0 = facing horizon)
elevationRadians = asin(gravityVector.z / Vector3DMagnitude(gravityVector));

// tilt is how far screen is from vertical, looking along z axis
tiltRadians = atan2(-gravityVector.y, -gravityVector.x) - M_PI_2;

In seguito il suggerimento di Chris: Non sono sicuro se ho questo tutti corretti causa delle diverse convenzioni di fila ordine / colonna e intestazione senso orario o antiorario. Tuttavia il seguente codice è quello che mi si avvicinò con:

Vector3D forward = Vector3DMake(0.0f, 0.0f, -1.0f);

// Multiply it by current rotation matrix to get teapot direction
Vector3D direction;     
direction.x = matrix[0][0] * forward.x + matrix[1][0] * forward.y + matrix[2][0] * forward.z;
direction.y = matrix[0][1] * forward.x + matrix[1][1] * forward.y + matrix[2][1] * forward.z;
direction.z = matrix[0][2] * forward.x + matrix[1][2] * forward.y + matrix[2][2] * forward.z;

heading = atan2(direction.z, direction.x) * 180 / M_PI;

// Use this heading to adjust the teapot direction back to keep it fixed
// Rotate about vertical axis (Y), as it is a heading adjustment
glRotatef(heading, 0.0, 1.0, 0.0);

Quando ho eseguito questo codice, il comportamento teiera è apparentemente "migliorata", ad esempio. non è più voce gira 180deg quando lo schermo del dispositivo (con orientamento verticale) è lanciato in avanti / indietro attraverso in posizione verticale. Tuttavia, si fa ancora più importanti salti in voce quando il dispositivo (con orientamento orizzontale) è lanciato in avanti / indietro. Quindi qualcosa non va. Si suggerisce che il calcolo di cui sopra del vero titolo è corretto ...

Nessuna soluzione corretta

Altri suggerimenti

ho finalmente trovato una soluzione che funziona. : -)

ho lasciato cadere l'approccio matrice di rotazione, e invece adottato gluLookAt. Per fare questo lavoro è necessario conoscere il dispositivo "elevazione" (angolo di visione rispetto all'orizzonte esempio. 0 all'orizzonte, +90 dall'alto), e della fotocamera "tilt" (quanto il dispositivo è da verticale sua x / y plane ie . 0 quando verticale / verticale, +/- 90 quando orizzontale / verticale), entrambi i quali sono ottenuti dai componenti del dispositivo gravità vettore.

Vector3D eye, scene, up;
CGFloat distanceFromScene = 0.8;
// Adjust eye position for elevation (y/z)
eye.x = 0;
eye.y = distanceFromScene * -sin(elevationRadians); // eye position goes down as elevation angle goes up
eye.z = distanceFromScene * cos(elevationRadians);  // z position is maximum when elevation is zero 
// Lookat point is origin
scene = Vector3DMake(0, 0, 0); // Scene is at origin
// Camera tilt - involves x/y plane only - arbitrary vector length
up.x = sin(tiltRadians);
up.y = cos(tiltRadians);
up.z = 0;

Poi basta applicare la trasformazione gluLookAt, e anche ruotare la scena in base al titolo dispositivo.

// Adjust view for device orientation
gluLookAt(eye.x, eye.y, eye.z, scene.x, scene.y, scene.z, up.x, up.y, up.z);
// Apply device heading to scene
glRotatef(currentHeadingDegrees, 0.0, 1.0, 0.0);

Prova a ruotare l'oggetto a seconda dei valori di accelerazione iphone.

float angle = -atan2(accelX, accelY);

glPushMatrix();     
glTranslatef(centerPoint.x, centerPoint.y, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-centerPoint.x, -centerPoint.y, 0);
glPopMatrix();

Dove Centerpoint è il punto centrale dell'oggetto.

oo, nice.

GLGravity seems to get everything right except for the yaw. Here's what I would try. Do everything GLGravity does, and then this:

Project a vector in the direction you want the teapot to face, using the compass or whatever you so choose. Then multiply a "forward" vector by the teapot's current rotation matrix, which will give you the direction the teapot is facing. Flatten the two vectors to the horizontal plane and take the angle between them.

This angle is your corrective yaw. Then just glRotatef by it.

Whether or not the 3GS's compass is reliable and robust enough for this to work is another thing. Normal compasses don't work when the north vector is perpendicular to their face. But I just tried the Maps app on my workmate's 3GS and it seems to cope, so maybe they have got a mechanical solution in there. Knowing what the device is actually doing will help interpret the results it gives.

Make sure to test your app at the north and south poles once you're done. :-)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top