Compartir a través de


Este artículo proviene de un motor de traducción automática.

Tocar y listo

Windows Phone movimiento y vistas 3D

Charles Petzold

Descargar el ejemplo de código

Charles PetzoldLa nueva clase de movimiento introducida con Windows Phone 7.1 es una maravillosa herramienta para programadores que necesitan saber cómo el teléfono se orienta en el espacio tridimensional. La clase de movimiento combina información de los sensores (acelerómetro, magnetómetro y giróscopo) y también suaviza los datos y pone a disposición en forma conveniente.

Cuando un programa de Windows Phone conoce la orientación del teléfono en el espacio 3D, el teléfono puede proporcionar un portal en un mundo 3D. Esta instalación tiene aplicaciones en asignación, realidad virtual, realidad aumentada y por curso, juegos, pero probablemente también algunas aplicaciones que aún no han sido concebidos. Este es definitivamente un área donde usted querrá ejercer su imaginación tanto como sus habilidades de codificación.

Datos de movimiento

Quiero a centrarse exclusivamente en la obtención de la orientación del teléfono en lugar de velocidad o aceleración, que también están disponibles en la clase de movimiento. El sensor proporciona una estructura de MotionReading, y la información de orientación está disponible en la propiedad de actitud. La palabra «actitud» viene de dinámica de vuelo, que indican la orientación de un plano en el espacio 3D — a diferencia de altitud, que es la altura sobre la tierra. La palabra es también utilizada en geometría vectorial.

Esta propiedad de la actitud es de tipo AttitudeReading, otra estructura que define cinco propiedades que describen la orientación tridimensional:

  • Orientación de tipo float, un ángulo expresado en radianes
  • Tono de tipo float, un ángulo expresado en radianes
  • Rollo de tipo float, un ángulo expresado en radianes
  • RotationMatrix de tipo matriz, un tipo de matriz de 4 × 4 definidos en XNA
  • Cuaternión de tipo cuaternión, un tipo definido en XNA

Yaw, Pitch y Roll también son términos utilizados en la dinámica de vuelo, y están a menudo refiere a ellos como ángulos de Euler. Guiñada indica la dirección brújula que la nariz del avión se enfrenta, así como el plano gira derecha o izquierda, cambia la orientación. Cambios de tono, como la nariz sube para un ascenso o durante una inmersión. Rollo de cambios como los bancos de plano izquierdo y derecho. Para visualizar estos en relación con el teléfono, ayuda a imaginar "volador" en su teléfono como una alfombra mágica por sentado en el teléfono la pantalla con la parte superior del teléfono a su frente y los tres botones estándar en su parte trasera.

Un pequeño programa llamado YawPitchRoll incluido con el código descargable para este artículo también puede ayudar a visualizar estos ángulos. (Como todos los programas en este artículo, requiere referencias a los ensamblados Microsoft.Devices.Sensors y Microsoft.Xna.Framework). Como se muestra en la figura 1, el programa muestra los valores de estos tres ángulos convertidos a grados y también simboliza sus valores gráficamente.


Figura 1 la pantalla de YawPitchRoll

Guiñada se muestra con una línea simple hacia el norte como una brújula, Considerando que el Pitch y Roll aparecen como sólidos bolas que parecen rodar hacia la tierra. Cuando el teléfono está sentado en una mesa de nivel con la pantalla hacia arriba y la parte superior del teléfono apuntando al norte, todos los tres ángulos tienen valores cero.

Como se inclina hacia arriba y hacia abajo la parte superior del teléfono, puede cambiar tono de 90 ° cuando el teléfono esté en posición vertical a-90 ° cuando la parte superior del teléfono apunta hacia abajo. Asimismo, puede cambiar rollo de 90 °-90 ° inclinando el teléfono derecho e izquierdo.

Cuando la pantalla del teléfono hacia abajo, el ángulo de guiñada apunta hacia el sur. PITCH toma valores que van desde 90 ° a 180 ° y de-90 °-180 °. En el programa de YawPitchRoll, estos valores son simbolizados por una bola hueca, esbozado por el rojo. Los valores del rollo de seguirán tomando en valores que van desde 90 °-90 °.

Perspectivas rotacionales

Aunque pasamos toda la vida en un universo tridimensional, muchos de nosotros tenemos una muy mala idea intuitiva de rotación tridimensional. En consecuencia, visualizar y trabajar con rotaciones en el espacio 3D pueden ser desafiantes. Yaw, Pitch y Roll parecen describir adecuadamente la rotación en el espacio 3D, pero resultan para ser bastante torpe en la programación de la práctica.

Los programadores prefieren trabajar con formas alternativas de describir la rotación 3D:

  • Un único ángulo describiendo la rotación alrededor de un vector 3D (rotación de eje o ángulo)
  • Una matriz de rotación (un subconjunto de una transformación de matriz 3D)
  • Cuaternión, un análogo de 3D de rotación 2D en el plano complejo

Estas formas pueden todos convertir entre sí, como demuestran en los capítulos 7 y 8 de mi libro "programación 3D para Windows" (Microsoft Press, 2008). Cuaternión es particularmente útil para un movimiento suave de una orientación a otro porque se presta a la interpolación lineal.

La clase de movimiento proporciona la rotación 3D con una matriz de rotación y un cuaternión, pero me centraré exclusivamente en la propiedad RotationMatrix de la estructura AttitudeReading. Este es un valor de matriz de XNA, que es una matriz de transformación de 4 × 4 estándar, pero la matriz representa sólo rotación. Tiene ninguna escala y sin traducción. Los campos M14, M24, M34, M41, M42 y M43 son todas 0, y el campo de M44 es 1.

Cuando se trabaja con esta matriz de rotación, un cambio de perspectiva será útil. En la anterior entrega de esta columna, describí cómo el vector tridimensional de los sensores acelerómetro y brújula es relativo a un sistema de coordenadas 3D impuesto sobre la geografía del teléfono. Sin embargo, cuando se trabaja con la matriz de rotación, realmente necesita visualizar dos 3D coordenadas sistemas diferentes, uno para el teléfono y el otro para la tierra:

  • En el sistema de coordenadas 3D del teléfono, positivo y apunta a la parte superior del teléfono (en el modo de retrato), positivo x puntos positivos y derecho z sale de la pantalla.
  • En sistema de coordenadas 3D de la tierra, Y positivo hacia el norte, puntos positivos x puntos este y z positivo sale de la tierra.

Cuando el teléfono se asienta sobre una superficie plana con la pantalla hacia arriba y la parte superior apuntando al norte, el valor de RotationMatrix es la matriz identidad. De lo contrario, describe cómo la tierra gira en relación con el teléfono, que es el opuesto de la rotación descrita por los ángulos de Euler.

Para ilustrar esto, escribí un pequeño programa llamado MotionMatrix. La pantalla (se muestra en la figura 2) consiste en sólo valores numéricos: la guiñada, cabeceo y alabeo de valores, el subconjunto de matriz de rotación de 3 × 3 de la matriz completa y expresado en forma de ángulo o eje de rotación.

The MotionMatrix Display
Figura 2 en la pantalla de MotionMatrix

Al iniciar por primera vez jugando con este programa, su instinto inmediato es probablemente orientar el teléfono para que todos los ángulos de Euler son cero. Sin embargo, el vector de eje hacia abajo en la parte inferior va loco porque no hay casi ninguna rotación, por lo que el valor del eje puede ser casi cualquier cosa. Rotaciones simples calmar la pantalla. La captura de pantalla en figura 2 muestra la parte superior del teléfono apuntando Norte pero elevada unos 45 °. Eso es lo que informa el valor de tono, y la rotación del eje o ángulo muestra un valor muy cerca de 46 °.

Pero el eje de rotación: es aproximadamente (– 1, 0, 0), que es el eje de coordenadas que apunta a la izquierda del teléfono. Rotaciones de eje/ángulo XNA acaten la regla de derecha: apuntar el dedo pulgar de la mano derecha en la dirección del eje (que es, a la izquierda del teléfono, en este caso). La curva de los dedos, a continuación, muestra la dirección de rotación positiva. Esto significa que la rotación es opuesto al ángulo de inclinación. Nos dice que el teléfono debe estar girado-45 ° esté alineado con la tierra.

El MotionMatrix y XNA

Parece razonable utilizar la matriz de rotación de la clase de movimiento para visualizar objetos 3D en el teléfono. Pero en lugar del enfoque normal — donde se gira un objeto 3D en relación con la pantalla, quizás con un ratón o un dedo — aquí la pantalla podría ser girada con respecto al objeto 3D (conceptualmente, de todos modos).

Para experimentar con esto, he descargado un modelo 3D de un teléfono antiguo de los archive3d. NET Web site (específicamente bit.ly/GSNTi3) y luego convertir el formato 3DS al formato FBX XNA-friendly utilizando una herramienta de conversión de Autodesk. Creé cuatro proyectos de Visual Studio que muestran progresivamente mejores formas de mostrar de este objeto. (En realidad, fracasaron alrededor un poco y sólo más tarde creó estos cuatro proyectos para disimular ese hecho!) Para reducir el código de tiempo de descarga, todos los cuatro proyectos hacen referencia al mismo archivo de modelo 3D.

El primero de los cuatro proyectos se llama View3DPhonePlain, que es sólo una vista estática del objeto; Figura 3 muestra el código correspondiente. Este programa se carga en el modelo, define una transformación del mundo que escala el modelo abajo bastante y define una cámara simple. (La aparente son variables de campo hará sentido poco.)

Figura 3 el programa de View3DPhonePlain

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

En un sistema gráfico 3D como XNA, los modelos son sometidos a una serie de transformaciones de matriz en su camino a la pantalla. La transformación del mundo se aplica primero, y esto sitúa el modelo en el espacio 3D. La cámara es una combinación de dos transformaciones aplicadas en sucesión: la transformación de vista representa la ubicación y orientación de la cámara, mientras que la transformación de proyección maneja efectos de perspectiva y también normaliza todas las coordenadas para el recorte.

Figura 4 muestra cómo el modelo parece en XNA forma predeterminada en modo de paisaje, y es bastante tanto como cabría esperar.

The View3DPhonePlain Display
Figura 4 la pantalla de View3DPhonePlain

El siguiente paso es el proyecto llamado View3DPhoneReoriented. Quería cambiar al modo de retrato, por lo que las coordenadas 3D utilizadas en XNA eran los mismos que el sistema de coordenadas 3D utilizado por los sensores. Esto es una simple cuestión de añadir unas declaraciones al constructor de la derivada de juego:

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

También quería reorientar el propio teléfono. Como he mencionado, la matriz de rotación 3D suministrada por la clase de movimiento es la matriz identidad cuando el teléfono está sentado en una mesa con la pantalla hacia arriba y la parte superior apuntando al norte. ¿Cómo querían que el teléfono 3D que aparecen cuando el teléfono estaba en esa posición? Quería estar buscando en la parte superior del teléfono como si visto desde arriba, así que simplemente agregué una rotación alrededor del eje x a la transformación del mundo:

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

El resultado se muestra en la Figura 5.

The View3DPhone­Reoriented Display
Figura 5: el View3DPhone­reorientado la pantalla

La cámara se ve un poco demasiado cerca al objeto en este punto, pero esto no me molesta porque yo sabía que cuando incorpore la matriz de rotación, sería capaz de girar el teléfono un poco para tenerlo todo a la vista. (Un visor de Obrer@s de luz 3D y sombreado podría notar un error conceptual en el enfoque estoy usando, pero permítanme ingenuamente recogerlo este camino primero y luego voy a arreglar las cosas).

Ahora vamos a incorporar a la matriz de rotación de la clase de movimiento.

Conceptualmente, el objeto 3D debe parecer que permanecen fijos en el espacio, y moviendo el teléfono debe permitirle ver el objeto desde diferentes direcciones. Por supuesto, la experiencia no es como la "vida real" porque nunca se puede mover el teléfono para mirar lejos del objeto. Siempre existe el objeto en la pantalla, pero la orientación de la pantalla en el espacio 3D le ofrece diferentes vistas de la misma.

Para conseguir este efecto, tenemos que aplicar una matriz al objeto de que logre la rotación del sistema de coordenadas del teléfono al sistema de coordenadas de la tierra, donde conceptualmente existe este objeto.

Nosotros deberíamos ser capaces de lograr este efecto simplemente por incluido el objeto de RotationMatrix de la clase de movimiento en el cálculo de la transformación del mundo. Para ello, el proyecto de View3DPhoneWorldMotion. Incluye código para crear un detector de movimiento en su constructor, iniciarlo en la anulación de OnActivated y detenerse en la anulación de OnDeactivated. Luego pasé el cálculo de la transformación del mundo a la anulación de la actualización, como se muestra en la figura 6.

Figura 6 la anulación de la actualización en 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);
}

En este programa, como mover la orientación del teléfono en el espacio 3D, ver el objeto 3D desde todas las direcciones diferentes. El efecto es muy suave y — lo confieso — muy cool.

La rotación de movimiento

Y aún, más jugaba más con esta versión del programa, sentí que algo estaba mal.

Aplicando la matriz de rotación a la transformación del mundo, el objeto 3D se rota efectivamente no sólo en relación con la cámara, sino también en relación con la fuente de luz. En algunos casos, esto sería correcto. Por ejemplo, si implementa una interfaz táctil por lo que puede girar alrededor de la imagen 3D con los dedos, aplicar la matriz de rotación para la transformación del mundo sería apropiado.

Pero para este programa, el paradigma es muy diferente. Quería que la pantalla del teléfono a ser como una cámara móvil que se mueve en relación con el objeto 3D, y eso significa que este objeto debe permanecer fija en relación con la fuente de luz. La matriz de rotación desde el sensor de movimiento debe ser aplicada para la transformación de la vista, en lugar de la transformación del mundo.

Para la versión final del programa, llamado View3DPhone­CameraMotion — ya restaurado el cálculo de la transformación del mundo a la versión original:

worldMatrix = scaleMatrix;

Incluso aplicar la rotación inicial fue un error porque implicaba que la luz venía detrás del teléfono en lugar de hacerlo desde arriba. El nuevo método de actualización se muestra en figura 7.

Figura 7 la anulación de la actualización en 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);
}

Realmente necesita probar este programa en un teléfono para obtener el efecto completo, pero la imagen en figura 8 muestra una vista posible.

One View in View3DPhoneCameraMotionFigura 8 una vista en View3DPhoneCameraMotion

Charles Petzold es un viejo colaborador MSDN Magazine y está actualizando su clásico libro "Programming Windows" (Microsoft Press, 1998) para Windows 8. Su sitio Web es charlespetzold.com.

Gracias al siguiente experto técnico por su ayuda en la revisión de este artículo: Donn Morse