Wie verwende ich den Gravitationsvektor richtig Szene für Augmented Reality zu verwandeln?

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

  •  23-09-2019
  •  | 
  •  

Frage

Ich versuche, herauszufinden, wie Objekt eine OpenGL angegeben bekommen angezeigt werden korrekt entsprechend der Geräteausrichtung (dh. Nach dem Schwerkraftvektor von dem Beschleunigungsmesser und Position von Kompass).

Das GLGravity Beispielprojekt hat ein Beispiel, das fast wie das ist (trotz Überschrift ignoriert wird), aber es hat einige Probleme. Zum Beispiel springt die Teekanne 180 Grad, da das Gerät Betrachtungswinkel den Horizont durchquert, und es dreht sich auch spuriously wenn Sie das Gerät vom Hoch- ins Quer kippen. Das ist in Ordnung für den Kontext dieses App, wie es nur protzen ein Objekt und es spielt keine Rolle, dass es diese Dinge tut. Aber es bedeutet, dass der Code nur funktioniert nicht, wenn Sie versuchen, das wirkliche Leben zu emulieren eines OpenGL Objekt betrachtet entsprechend der Ausrichtung des Geräts. Was passiert, ist, dass es fast funktioniert, aber die Überschrift Rotation Sie aus dem Kompass anwenden wird „beschädigt“ durch die unechten zusätzliche Rotationen im GLGravity Beispielprojekt gesehen.

Kann jemand bieten Beispielcode, der zeigt, wie richtig für die Ausrichtung des Geräts einzustellen (dh. Schwerkraftvektor) oder das GLGravity Beispiel zu beheben, so dass es nicht falsche Kursänderungen nicht enthalten?

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

Hier ist eine Klarstellung zeigt, wie die Höhe und Neigung zu erhalten, die für gluLookAt Lösung benötigt werden, wie es in meiner letzten Antwort gezeigt:

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

Im Anschluss an Chris Vorschlag auf: Ich bin nicht sicher, ob ich das alles richtig aufgrund unterschiedlicher Konventionen der Zeilen / Spalten-Reihenfolge und Richtung cw oder ccw habe. Doch der folgende Code ist, was ich kam mit:

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

Wenn ich diesen Code ausführen, hat die Teekanne Verhalten anscheinend „verbessert“ zum Beispiel. Position nicht länger dreht 180 Grad, wenn die Vorrichtung Bildschirm (im Hochformat) aufgeschlagen wird, nach vorn / zurück durch aufrecht. Allerdings macht es immer noch große Sprünge in der Position, wenn das Gerät (im Querformat) aufgeschlagen wird vor / zurück. etwas ist so nicht richtig. Er schlägt vor, dass die obige Berechnung der aktuellen Position ist falsch ...

Keine korrekte Lösung

Andere Tipps

Ich fand schließlich eine Lösung, die funktioniert. : -)

Ich ließ die Rotationsmatrix Ansatz und stattdessen gluLookAt angenommen. Um diese Arbeit zu machen, müssen Sie das Gerät „Elevation“ kennen (Betrachtungswinkel relativ zum Horizont dh. 0 am Horizont, +90 Overhead), und die Kamera „Neigung“ (wie weit das Gerät aus der Vertikalen seinem x / y-Ebene, dh . 0, wenn vertikal / Porträt, +/- 90 als horizontal / Querformat), die beide von den Geräteschwerkraftvektorkomponenten erhalten werden.

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;

Dann bewerben Sie nur die gluLookAt Transformation und drehen auch die Szene entsprechend der Geräteüberschrift.

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

versuchen, das Objekt in Abhängigkeit von rotierenden iphone Beschleunigungswerten.

float angle = -atan2(accelX, accelY);

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

Wo Centerpoint® der Mittelpunkt ist das Objekt.

oo, schön.

GLGravity scheint alles richtig, außer für die Gier zu bekommen. Hier ist, was ich versuchen würde. Tun Sie alles GLGravity tut, und dann das:

Projekt ein Vektor in der Richtung, die Sie wollen die Teekanne zu Gesicht, mit dem Kompass oder was auch immer Sie dies wünschen. Dann multiplizieren ein „Vorwärts“ Vektor durch die aktuelle Rotationsmatrix Teekanne, die Sie geben die Richtung die Teekanne is gegenüber. Abflachen der beiden Vektoren zu der horizontalen Ebene und nehmen die Winkel zwischen ihnen.

Dieser Winkel ist Ihre Korrekturgier. Dann einfach glRotatef durch.

Unabhängig davon, ob die 3GS Kompass ist zuverlässig und robust genug für diese Arbeit ist eine andere Sache. Normale Kompasse funktionieren nicht, wenn der Norden Vektor, um ihr Gesicht senkrecht steht. Aber ich habe gerade versucht, das Karten-App auf 3GS meinem Kollegen ist und wie es scheint, zu bewältigen, so vielleicht sie eine mechanische Lösung da drin hat. Zu wissen, was das Gerät die Ergebnisse helfen interpretieren tatsächlich tun es gibt.

Stellen Sie sicher, dass Ihre App an den Nord- und Südpol zu testen, wenn Sie fertig sind. : -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top