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:
- iPhone con iOS 12.0 o versiones posteriores
- Visualizador de Cardboard
Requisitos de software:
- Xcode 12.5 o una versión posterior
- CocoaPods 1.9 o una versión más reciente
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í.
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
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
Abre el lugar de trabajo de Cardboard (
Cardboard.xcworkspace
) en Xcode.Cambia el ID del paquete de la app para que puedas firmarla con tu equipo.
Navega a SDK > Build Phases > Link Binary With Libraries
- Para eliminar
libPods-sdk.a
de la lista, selecciónala y haz clic en el botón '' - 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"
- Para eliminar
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:
Mueve la cabeza en cualquier dirección hasta que veas una esfera flotante.
Mira directamente la esfera. Esto cambia los colores.
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);