Guía de inicio rápido de Google Cardboard para iOS

En esta guía, se muestra cómo usar el SDK de Cardboard para iOS a fin de crear tus propias experiencias de realidad virtual (RV).

Puedes usar el SDK de Cardboard para convertir un smartphone en una plataforma de RV. Un smartphone puede mostrar escenas en 3D con renderización estereoscópica, hacer un seguimiento de los movimientos de la cabeza y reaccionar a ellos, además de interactuar con las apps mediante la detección de cuando el usuario presiona el botón del visor.

Para comenzar, usarás HelloCardboard, un juego de demostración que demuestra las funciones principales del SDK de Cardboard. En el juego, los usuarios buscan en un mundo virtual para buscar y recolectar objetos. Le muestra cómo hacer lo siguiente:

  • Cómo configurar tu entorno de desarrollo
  • Descarga y compila la app de demostración
  • Escanea el código QR de un visor Cardboard para guardar sus parámetros
  • Realiza un seguimiento de los movimientos de la cabeza del usuario
  • Renderiza imágenes estereoscópicas configurando la distorsión correcta para cada ojo

Cómo configurar tu entorno de desarrollo

Requisitos de hardware:

Requisitos de software:

Descarga y compila la app de demostración

El SDK de Cardboard se compila con archivos de origen de Búferes de protocolo C++ precompilados. Los pasos para compilar los archivos de origen desde cero se pueden encontrar aquí.

  1. Clona el SDK de Cardboard y la app de demostración de Hello Cardboard desde GitHub mediante la ejecución del siguiente comando:

    git clone https://github.com/googlevr/cardboard.git
  2. Instala la dependencia de los búferes de protocolo en el proyecto de Xcode. Para ello, ejecuta este comando en la raíz del repositorio:

    pod install
  3. Abre el lugar de trabajo de Cardboard (Cardboard.xcworkspace) en Xcode.

  4. Cambia el ID del paquete de la app para que puedas firmarla con tu equipo.

  5. Navega a SDK > Build Phases > Link Binary With Libraries

    1. Para eliminar libPods-sdk.a de la lista, selecciónala y haz clic en el botón ''
    2. Para agregar libProtobuf-C++.a a la lista, haz clic en el botón &+33; y selecciónalo. Si aparece un mensaje que sugiere usar un XCFramework, haga clic en "Agregar de todos modos"
  6. Haga clic en Ejecutar.

Escanea el código QR

Para guardar los parámetros del dispositivo, escanea el código QR en el visor Cardboard:

Probar la demostración

En HelloCardboard, buscarás y recopilarás esferas geodésicas en un espacio 3D.

Para buscar y recopilar una esfera, sigue estos pasos:

  1. Mueve la cabeza en cualquier dirección hasta que veas una esfera flotante.

  2. Mira directamente la esfera. Esto cambia los colores.

  3. Presiona el botón del visor Cardboard para "recopilar" la esfera.

Configura el dispositivo

Cuando el usuario presiona el ícono de ajustes para cambiar de visor de Cardboard, se llama al método didTapSwitchButton en HelloCardboardOverlayView.

- (void)didTapSwitchButton:(id)sender {
  if ([self.delegate respondsToSelector:@selector(didTapBackButton)]) {
    [self.delegate didChangeViewerProfile];
  }
  self.settingsBackgroundView.hidden = YES;
}

Esto llama a CardboardQrCode_scanQrCodeAndSaveDeviceParams, que abre la ventana para escanear el código QR del usuario. Cuando el usuario escanea el código QR, se actualizan los parámetros de distorsión del dispositivo.

- (void)switchViewer {
  CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

- (void)didChangeViewerProfile {
  [self pauseCardboard];
  [self switchViewer];
  [self resumeCardboard];
}

Seguimiento de cabeza

Crear seguimiento de cabeza

El seguimiento de cabeza se crea una vez en el método viewDidLoad de HelloCardboardViewController:

_cardboardHeadTracker = CardboardHeadTracker_create();

Pausar y reanudar el seguimiento de cabeza

Los métodos pauseCardboard y resumeCardboard de la clase HelloCardboardViewController pausan y reanudan el seguimiento de cabeza, respectivamente. resumeCardboard también establece la marca _updateParams, que hace que los parámetros del dispositivo se actualicen en la próxima llamada de dibujo.

- (void)pauseCardboard {
  self.paused = true;
  CardboardHeadTracker_pause(_cardboardHeadTracker);
}

- (void)resumeCardboard {
  // Parameters may have changed.
  _updateParams = YES;

  // Check for device parameters existence in app storage. If they're missing,
  // we must scan a Cardboard QR code and save the obtained parameters.
  uint8_t *buffer;
  int size;
  CardboardQrCode_getSavedDeviceParams(&buffer, &size);
  if (size == 0) {
    [self switchViewer];
  }
  CardboardQrCode_destroy(buffer);

  CardboardHeadTracker_resume(_cardboardHeadTracker);
  self.paused = false;
}

Distorsión de la lente

Cada vez que Cardboard escanea un código QR nuevo, el siguiente código lee los parámetros guardados y los usa para crear el objeto de distorsión de la lente, que aplica la distorsión de la lente adecuada al contenido procesado:

CardboardQrCode_getSavedDeviceParams(&encodedDeviceParams, &size);

// Create CardboardLensDistortion.
CardboardLensDistortion_destroy(_cardboardLensDistortion);
_cardboardLensDistortion =
    CardboardLensDistortion_create(encodedDeviceParams, size, width, height);

// Initialize HelloCardboardRenderer.
_renderer.reset(new cardboard::hello_cardboard::HelloCardboardRenderer(
      _cardboardLensDistortion, _cardboardHeadTracker, width, height));

Renderización

El procesamiento de contenido en Cardboard implica lo siguiente:

  • Crea texturas
  • Obtener matrices de vistas y proyección para los ojos izquierdo y derecho
  • Cómo crear el procesador y configurar la malla de distorsión
  • Cómo procesar cada fotograma

Cómo crear texturas

El contenido se dibuja sobre una textura, que se divide en secciones para el ojo izquierdo y el derecho. Estas secciones se inicializan en _leftEyeTexture y _rightEyeTexture, respectivamente. La app de muestra usa una única textura para ambos ojos, pero también es posible crear una textura separada para cada ojo.

// Generate texture to render left and right eyes.
glGenTextures(1, &_eyeTexture);
glBindTexture(GL_TEXTURE_2D, _eyeTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

_leftEyeTexture.texture = _eyeTexture;
_leftEyeTexture.left_u = 0;
_leftEyeTexture.right_u = 0.5;
_leftEyeTexture.top_v = 1;
_leftEyeTexture.bottom_v = 0;

_rightEyeTexture.texture = _eyeTexture;
_rightEyeTexture.left_u = 0.5;
_rightEyeTexture.right_u = 1;
_rightEyeTexture.top_v = 1;
_rightEyeTexture.bottom_v = 0;
CheckGLError("Create Eye textures");

Estas texturas se pasan como parámetros a CardboardDistortionRenderer_renderEyeToDisplay.

Obtén matrices de vista y proyección para el ojo izquierdo y derecho

Primero, recupera las matrices oculares de los ojos izquierdo y derecho:

CardboardLensDistortion_getEyeFromHeadMatrix(_lensDistortion, kLeft, _eyeMatrices[kLeft]);
CardboardLensDistortion_getEyeFromHeadMatrix(_lensDistortion, kRight, _eyeMatrices[kRight]);
CardboardLensDistortion_getProjectionMatrix(_lensDistortion, kLeft, kZNear, kZFar,
                                            _projMatrices[kLeft]);
CardboardLensDistortion_getProjectionMatrix(_lensDistortion, kRight, kZNear, kZFar,
                                            _projMatrices[kRight]);

A continuación, obtén las mallas de distorsión para cada ojo y pásalas al procesador de distorsión:

CardboardLensDistortion_getDistortionMesh(_lensDistortion, kLeft, &leftMesh);
CardboardLensDistortion_getDistortionMesh(_lensDistortion, kRight, &rightMesh);

Crea el procesador y configura la malla de distorsión correcta

El procesador solo debe inicializarse una vez. Una vez que se crea el procesador, configura la nueva malla de distorsión para los ojos izquierdo y derecho según los valores de malla que muestra la función CardboardLensDistortion_getDistortionMesh.

_distortionRenderer = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(_distortionRenderer, &leftMesh, kLeft);
CardboardDistortionRenderer_setMesh(_distortionRenderer, &rightMesh, kRight);

Cómo procesar el contenido

Recupera la orientación actual de la cabeza de CardboardHeadTracker_getPose:

CardboardHeadTracker_getPose(_headTracker, targetTime, position, orientation);
_headView =
    GLKMatrix4Multiply(GLKMatrix4MakeTranslation(position[0], position[1], position[2]),
                       GLKMatrix4MakeWithQuaternion(GLKQuaternionMakeWithArray(orientation)));

Usa la orientación de cabeza actual con las matrices de vistas y proyección a fin de componer una matriz de proyección de vista, y úsalas para renderizar el contenido mundial para cada uno de los ojos:

// Draw left eye.
glViewport(0, 0, _width / 2.0, _height);
glScissor(0, 0, _width / 2.0, _height);
DrawWorld(_leftEyeViewPose, GLKMatrix4MakeWithArray(_projMatrices[kLeft]));

// Draw right eye.
glViewport(_width / 2.0, 0, _width / 2.0, _height);
glScissor(_width / 2.0, 0, _width / 2.0, _height);
DrawWorld(_rightEyeViewPose, GLKMatrix4MakeWithArray(_projMatrices[kRight]));

Usa CardboardDistortionRenderer_renderEyeToDisplay para aplicar la corrección de distorsión al contenido y renderizar el contenido en la pantalla.

CardboardDistortionRenderer_renderEyeToDisplay(_distortionRenderer, renderTarget, /*x=*/0,
                                               /*y=*/0, _width, _height, &_leftEyeTexture,
                                               &_rightEyeTexture);