Dieser Artikel wurde maschinell übersetzt.

Touch and Go

Windows Phone Bewegung und 3D Ansichten

Charles Petzold

Charles PetzoldDie neue Motion-Klasse mit Windows Phone 7.1 eingeführt ist ein wunderbares Werkzeug für Programmierer, die müssen wissen, wie das Telefon im dreidimensionalen Raum ausgerichtet ist.Die Motion-Klasse kombiniert Informationen aus den Sensoren (Beschleunigungsmesser, Magnetometer und Gyroskop), glättet die Daten und stellt sie in bequemen Formen zur Verfügung.

Wenn ein Windows Phone-Programm die Ausrichtung des Telefons im 3D-Raum kennt, kann das Telefon ein Portal in eine 3D Welt bereitstellen.Diese Einrichtung hat Anwendungen in Zuordnung, virtual-Reality, augmented-Reality und, natürlich, Spiele, aber wahrscheinlich auch einige Anwendungen, die noch nicht konzipiert worden.Dies ist definitiv ein Bereich, wo Sie Ihre Fantasie so viel wie Ihre Programmierkenntnisse ausüben wollen.

Weg-

Ich möchte konzentrieren sich ausschließlich auf die Erlangung der Orientierung über das Telefon anstatt die Geschwindigkeit oder die Beschleunigung, die auch von der Motion-Klasse verfügbar sind.Der Sensor bietet eine MotionReading-Struktur und die Ausrichtung-Informationen sind in der Haltung-Eigenschaft verfügbar.Das Wort "Haltung" kommt vom Flug-Dynamik, wo gibt es die Ausrichtung eines Flugzeugs im 3D-Raum — Höhe unterscheidet, das ist die Höhe über der Erde.Das Wort wird manchmal auch in der Vektor-Geometrie verwendet.

Diese Haltung-Eigenschaft ist vom Typ AttitudeReading, eine andere Struktur, die fünf Eigenschaften beschreiben dreidimensionale Ausrichtung definiert:

  • Gieren vom Typ Float, ein Winkel im Bogenmaß
  • Stellplatz Typ float, ein Winkel im Bogenmaß
  • Wurf vom Typ Float, ein Winkel im Bogenmaß
  • RotationMatrix vom Typ Matrix, ein 4 × 4-Matrix-Typ definiert in XNA
  • Quaternion des Typs Quaternion, in XNA definiert

Yaw, Pitch und Roll sind auch Begriffe, die in der Flug-Dynamik, und sie sind oft als Euler Winkel bezeichnet.Gieren gibt die Kompassrichtung, die die Nase des Flugzeuges konfrontiert ist, sodass das Flugzeug dreht sich rechts oder Links hat, der Scherung ändert.Stellplatz Änderungen, wie die Nase für einen Aufstieg geht nach oben oder nach unten für einen Tauchgang.Rollenwechsel als Flugzeug Ufer Links und rechts.Um diese bezogen auf das Telefon zu visualisieren, hilft es, "fliegende" auf Ihrem Telefon wie ein fliegender Teppich durch das sitzen auf dem Handy-Bildschirm am oberen Rand des Telefons auf dem vorderen und die drei standard-Tasten auf Ihrer Rückseite vorstellen.

Ein kleines Programm namens YawPitchRoll mit dem herunterladbaren Code für diesen Artikel enthalten könnte auch helfen, diese Winkel zu visualisieren.(Wie alle Programme in diesem Artikel müssen sie Verweise auf die Assemblys Microsoft.Devices.Sensors und Microsoft.Xna.Framework.) Wie im Abbildung 1, das Programm zeigt die Werte für diese drei Winkel in Grad umgewandelt und es symbolisiert auch ihre Werte grafisch.


Abbildung 1 die YawPitchRoll-Anzeige

Gieren wird mit einer einfachen Linie zeigt Norden wie ein Kompass angezeigt, während Pitch und Roll als feste Kugeln, die scheinen angezeigt werden, in Richtung der Erde Rollen.Wenn das Telefon auf eine Ebene Tisch mit dem Bildschirm oben und oben das Telefon zeigt Norden sitzt, haben alle drei Winkel Nullwerte.

Wie Sie oben das Telefon nach oben und unten kippen, können Sie die Tonhöhe von 90 ° ändern, wenn das Telefon aufrecht bis-90 ° wenn oben das Telefon nach unten zeigt.Ebenso können Sie Roll von 90 °-90 ° ändern, durch Kippen des Telefons rechts und Links.

Wenn das Display des Telefons unten steht, verweist der Yaw-Winkel Süd.Tonhöhe nimmt Werte im Bereich von 90 ° c bis 180 ° und von-90 °-180 °.In dem YawPitchRoll-Programm werden diese Werte durch eine hohle, rote Kontur Kugel symbolisiert.Die Werte der Roll weiterhin auf Werte im Bereich von 90 °-90 °.

Rotations-Perspektiven

Obwohl wir unser ganzen Leben in einem dreidimensionalen Universum verbringen, haben viele von uns eine sehr schlechte intuitive Verständnis des dreidimensionalen Drehung.Visualisieren und arbeiten mit Drehungen im dreidimensionalen Raum können daher schwierig sein.Yaw, Pitch und Roll scheinen Rotation im 3D-Raum adäquat zu beschreiben, aber sie erweisen sich als ziemlich umständlich in der praktischen Programmierung.

Viel lieber Programmierer arbeiten mit alternativen Möglichkeiten, 3D Drehung zu beschreiben:

  • Einem einzigen Winkel beschreiben Drehung um ein 3D Vektor (Achse/Winkel-Drehung)
  • Einer Rotationsmatrix (eine Teilmenge einer 3D Matrix-Transformation)
  • Die Quaternion, ein 3D analog der 2D Drehung in der komplexen Zahlenebene

Diese Formen können alle konvertiert werden zwischen einander, wie ich in Kapitel 7 und 8 meines Buches "3D-Programmierung für Windows" zeigen (Microsoft Press, 2008).Die Quaternion ist besonders für glatte Bewegung von einer Orientierung zu einem anderen, weil es sich für lineare Interpolation eignet.

Die Motion-Klasse bietet 3D Drehung mit einer Rotationsmatrix und Quaternion, aber ich konzentriere mich ausschließlich auf die RotationMatrix-Eigenschaft der AttitudeReading-Struktur.Dies ist ein Wert von XNA-Matrix, der eine Norm 4 × 4-Transformationsmatrix ist, aber die Matrix stellt nur Drehung.Es hat keine Skalierung und keine Übersetzung.Die M14, M24, M34, M41, M42 und M43 Felder sind alle 0, und das M44-Feld ist 1.

Bei der Arbeit mit dieser Drehmatrix wird eine Änderung der Perspektive nützlich sein.In der letzten Ausgabe dieser Kolumne beschrieb ich, wie der dreidimensionale Vektor zur Verfügung, der Beschleunigungssensor und Kompass Sensoren relativ ein dreidimensionales Koordinatensystem die Geographie des Telefons auferlegt ist.Müssen jedoch bei der Arbeit mit der Drehmatrix Sie wirklich um zwei verschiedene 3D Koordinatensysteme, eine für das Telefon und das andere für die Erde zu visualisieren:

  • Des Telefons Dreidimensionales Koordinatensystem positive Y-Punkte an die Spitze des Telefons (im Hochformat), kommt in positive X Punkte rechts und positive z aus dem Bildschirm heraus.
  • Im 3D Koordinatensystem der Erde positive y weist im Norden, positive X Punkte Ost und positiven z kommt aus dem Boden.

Wenn das Telefon befindet sich auf einer ebenen Fläche mit dem Schirm oben und zeigen Norden oben, der RotationMatrix-Wert ist die Identität Matrix.Ansonsten, es beschreibt, wie die Erde relativ zum Telefon, gedreht wird das entgegengesetzte ist der Drehung durch die Euler-Winkel beschrieben.

Um dies zu veranschaulichen, habe ich ein kleines Programm namens MotionMatrix.Die Anzeige (gezeigt Abbildung 2) beinhaltet nur die numerischen Werte: Yaw, Pitch und Roll-Werte, die 3 × 3 Umdrehung Matrix Teilmenge der voll-Matrix und Drehung in die Achse/Winkel-Form ausgedrückt.

The MotionMatrix Display
Abbildung 2 die MotionMatrix anzeigen

Beim ersten mit diesem Programm zu spielen Start, ist Ihre sofortige Instinkt wahrscheinlich, das Telefon zu orientieren, so dass alle Euler Winkel NULL sind.Allerdings geht der Vector Achse nach unten am unteren verrückt, da gibt es fast keine Rotation, so dass der Achsenwert fast alles kann.Einfache Rotationen ruhig im Display.Das Bildschirmfoto in Abbildung 2 zeigt oben das Telefon zeigt Nord aber erhöhten ca. 45°.Das ist, was den Pitch-Wert meldet, und die Drehung der Achse/Winkel zeigt ganz in der Nähe der Wert 46 °.

Aber beachten Sie die Drehachse: Es ist ungefähr (– 1, 0, 0), ist die Achse des Koordinatensystems verläuft, die auf der linken Seite des Telefons zeigt.XNA Achse/Winkel Rotationen halten sich an die Rechte-Hand-Regel: zeigen den Daumen Ihrer rechten Hand in Richtung der Achse (das ist, auf der linken Seite des Telefons in diesem Fall).Die Kurve der Finger zeigt dann positive Drehrichtung.Dies bedeutet, dass die Drehung gegenüber der Steigungswinkel.Es sagt uns, dass das Telefon-45 ° gedreht werden muss, mit der Erde ausgerichtet werden.

Die MotionMatrix und XNA

Es erscheint sinnvoll, die Rotationsmatrix von der Motion-Klasse zu verwenden, zum Anzeigen von 3D-Objekten auf das Telefon.Aber anstatt der normalen Ansatz — wo ein 3D-Objekt gedreht im Verhältnis zu der Anzeige, vielleicht mit einer Maus oder Finger — hier würde das Display relativ zu dem 3D Objekt gedreht werden (im Prinzip sowieso).

Um dies auszuprobieren, die ich heruntergeladen habe ein 3D-Modell der ein antikes Telefon aus der archive3d.NET-Website (speziell bit.ly/GSNTi3) und dann im 3ds-Format in das XNA-freundliche FBX Format konvertiert mit einem Konvertierungstool von Autodesk.Ich habe vier Visual Studio-Projekte, die zunehmend bessere Möglichkeiten zur Darstellung dieses Objekts zeigen.(Tatsächlich, ich zappelte um einiges und erst später erstellt diese vier Projekte um diese Tatsache zu verschleiern!) Um Ihren Quellcode, die Downloadzeiten zu verringern, verweisen alle vier Projekte die gleichen 3D Modell-Datei.

Die erste der vier Projekte heißt View3DPhonePlain, die nur eine statische Ansicht des Objekts ist; Abbildung 3 zeigt den entsprechenden Code.Dieses Programm lädt im Modell definiert eine Welttransformation, die skaliert des Modells hin sehr viel, und definiert eine einfache Kamera.(Die scheinbare Überfluß von Feld-Variablen wird in Kürze sinnvoll.)

Abbildung 3 das View3DPhonePlain-Programm

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    Model model;
    Matrix scaleMatrix, worldMatrix, lookatMatrix,
           viewMatrix, projectionMatrix;
    ...
protected override void LoadContent()
    {
        model = this.Content.Load<Model>(“Phone Retro Caesar N170910”);
        foreach (ModelMesh mesh in model.Meshes)
            foreach (BasicEffect effect in mesh.Effects)
                effect.EnableDefaultLighting();
        // World matrix
        scaleMatrix = Matrix.CreateScale(0.0001f);
        worldMatrix = scaleMatrix;
        // View matrix
        lookatMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 10f),
                                                       Vector3.Zero,
                                                       Vector3.Up);
        viewMatrix = lookatMatrix;
        // Projection matrix
        float aspectRatio = 
            graphics.GraphicsDevice.Viewport.AspectRatio;
        projectionMatrix =
            Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                                                aspectRatio,
                                                1f, 100.0f);
    }
    ...
protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        model.Draw(worldMatrix, viewMatrix, projectionMatrix);
        base.Draw(gameTime);
    }
}

In einem 3D grafische System wie XNA unterliegen einer Reihe von Matrix-Transformationen auf dem Weg zur Anzeige Modelle. Die globale Transformation wird zuerst angewendet, und dies das Modell im dreidimensionalen Raum verortet. Die Kamera ist eine Kombination aus zwei Transformationen angewendet in Folge: die Ansichtstransformation entfallen die Lage und Ausrichtung der Kamera, während die Transformation der Projektion Perspektive Effekte behandelt sowie alle Koordinaten zum Clipping normalisiert.

Abbildung 4 zeigt, wie das Modell in der XNA sieht, default Landscape-Modus, und es ist ziemlich viel, wie wir vielleicht erwarten.

The View3DPhonePlain Display
Abbildung 4 die View3DPhonePlain-Anzeige

Der nächste Schritt ist das Projekt mit dem Namen View3DPhoneReoriented. Ich wollte zur Portrait-Modus zu wechseln, so dass die 3D-Koordinaten in XNA verwendet das gleiche wie das 3D Koordinatensystem verwendet, die von den Sensoren waren. Dies ist eine einfache Sache des Hinzufügen von ein paar Anweisungen an den Konstruktor der Game Ableitung:

graphics.IsFullScreen = true;
   graphics.PreferredBackBufferWidth = 480;
   graphics.PreferredBackBufferHeight = 800;

Ich wollte auch das Telefon selbst neu orientieren. Wie bereits erwähnt, ist die 3D-Drehung-Matrix von der Motion-Klasse bereitgestellt die Einheitsmatrix, wenn das Telefon für eine Tabelle mit den Bildschirm oben sitzt und oben Norden zeigen. Wie wollte ich das 3D Telefon angezeigt werden, wenn das Telefon in dieser Position war? Ich wollte an der Spitze des Telefons suchen als ob von oben, so dass ich einfach eine Rotation um die x-Achse die globale Transformation hinzugefügt:

worldMatrix *= Matrix.CreateRotationX(MathHelper.PiOver2);

Das Ergebnis ist in Abbildung 5 dargestellt.

The View3DPhone­Reoriented Display
Abbildung 5 der View3DPhone­umorientiert Display

Die Kamera sieht ein wenig zu nah an das Objekt an dieser Stelle, aber dies störte mich nicht, weil ich wusste, dass wenn ich die Rotationsmatrix eingebaut, ich in der Lage wäre, drehen Sie das Telefon ein wenig um alles im Blick zu erhalten. (Ein scharfsinniger Viewer 3D Licht und Schattierungen bemerken einen konzeptionellen Fehler in der Ansatz, den ich verwende, den aber lassen Sie mich zunächst naiv auf diesem Weg zu latschen und dann mache ich Dinge oben.)

Jetzt wollen wir die Rotationsmatrix von der Motion-Klasse zu übernehmen.

Im Prinzip das 3D-Objekt sollte scheinen im Raum unverändert bleiben, und das Handy bewegen sollten können Sie das Objekt aus verschiedenen Richtungen anzeigen. Natürlich ist die Erfahrung nicht wie im "richtigen Leben", denn Sie können nicht immer das Telefon zu schauen weg von dem Objekt wechseln. Das Objekt ist immer auf dem Display, aber die Ausrichtung der Anzeige im 3D-Raum gibt Ihnen verschiedene Ansichten von ihm.

Um diesen Effekt zu erreichen, müssen wir eine Matrix für das Objekt gelten, die Drehung des Telefons-Koordinatensystem zum Koordinatensystem der Erde, erreicht, wo dieses Objekt im Prinzip vorhanden ist.

Wir sollten in der Lage, diesen Effekt zu erzielen, indem Sie einfach das RotationMatrix-Objekt aus der Motion-Klasse bei der Berechnung der die globale Transformation einschließlich sein. Das View3DPhoneWorldMotion-Projekt tut dies. Es enthält Code zum Erstellen eines Bewegungssensor in seinem Konstruktor, in der OnActivated-Überschreibung zu starten und stoppen sie das Überschreiben von OnDeactivated. Dann zog ich die Berechnung der die globale Transformation auf die Update-Override, wie in Abbildung 6.

Abbildung 6 die Update-Überschreibung in View3DPhoneWorldMotion

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
      ButtonState.Pressed)
        this.Exit();
    worldMatrix = scaleMatrix * 
      Matrix.CreateRotationX(MathHelper.PiOver2);
    if (motion != null && motion.IsDataValid)
        worldMatrix *= motion.CurrentValue.Attitude.RotationMatrix;
    base.Update(gameTime);
}

In diesem Programm wie Sie die Telefon Orientierung im 3D-Raum, bewegen anzeigen Sie das 3D-Objekt aus allen anderen Richtungen. Die Wirkung ist sehr glatt und — ich muss zugeben – sehr cool.

Verlagerung der Rotation

Und doch, je mehr ich spielte mit dieser Version des Programms, je mehr ich fühlte, dass etwas falsch war.

Die Rotationsmatrix auf die globale Transformation anwenden, wird das 3D-Objekt effektiv nicht nur bezogen auf die Kamera, sondern auch relativ zur Lichtquelle gedreht. In einigen Szenarios wäre das richtige. Beispielsweise wenn Sie eine Touch-Schnittstelle implementieren, damit Sie das 3D-Bild mit den Fingern drehen können, wäre die Rotationsmatrix auf die globale Transformation anwenden geeigneter.

Aber für dieses Programm, das Paradigma ist ganz anders. Ich wollte das Display des Telefons zu sein wie eine mobile Kamera, die relativ zu dem 3D Objekt bewegt, und das bedeutet, dass dieses Objekt relativ zur Lichtquelle unverändert bleiben sollten. Die Rotationsmatrix aus der Weg-und/oder Geschwindigkeitsgeber muss Ansichtstransformation anstatt die globale Transformation angewendet werden.

Für die endgültige Version des Programms — genannt View3DPhone­CameraMotion — ich die Berechnung der die globale Transformation der Originalversion wiederhergestellt:

worldMatrix = scaleMatrix;

Sogar anwenden die anfängliche Rotation war ein Fehler, denn es impliziert, dass das Licht von hinten das Telefon und nicht von oben kommt. Die neue Update-Methode zeigt sich an Abbildung 7.

Abbildung 7 die Update-Überschreibung in View3DPhoneCameraMotion

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
      ButtonState.Pressed)
        this.Exit();
    if (motion != null && motion.IsDataValid)
        viewMatrix = Matrix.CreateRotationX(MathHelper.PiOver2) *
                        motion.CurrentValue.Attitude.RotationMatrix *
                        lookatMatrix;
    else
        viewMatrix = Matrix.CreateRotationX(MathHelper.PiOver2) *
                        lookatMatrix;
    base.Update(gameTime);
}

Sie wirklich brauchen, um zu versuchen, dieses Programm auf einem Telefon zu erhalten, die volle Wirkung, aber das Bild im Abbildung 8 zeigt eine mögliche Ansicht.

One View in View3DPhoneCameraMotion
Abbildung 8 eine Ansicht im View3DPhoneCameraMotion

Charles Petzold ist eine langjährige Mitarbeit beim MSDN Magazin und ist derzeit aktualisiert sein klassisches Buch "Programming Windows" (Microsoft Press, 1998) für Windows 8. Seiner Website lautet charlespetzold.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Donn Morse