Guia de início rápido do Google Cardboard para iOS

Este guia mostra como usar o SDK do Cardboard para iOS para criar suas próprias experiências de realidade virtual (RV).

Você pode usar o SDK do Cardboard para transformar um smartphone em uma plataforma de RV. Um smartphone pode exibir cenas em 3D com renderização estereoscópica, rastrear e reagir aos movimentos da cabeça e interagir com apps detectando quando o usuário pressiona o botão do visualizador.

Para começar, você vai usar o HelloCardboard, um jogo de demonstração que demonstra os principais recursos do SDK do Cardboard. No jogo, os usuários olham ao redor de um mundo virtual para encontrar e coletar objetos. Ele mostra como:

  • Configurar seu ambiente de desenvolvimento
  • Fazer o download e criar o app de demonstração
  • Leia o código QR de um visualizador do Google Cardboard para salvar os parâmetros dele
  • Rastrear os movimentos da cabeça do usuário
  • Renderize imagens estereoscópicas definindo a distorção correta para cada olho

Configurar seu ambiente de desenvolvimento

Requisitos de hardware:

Requisitos de software:

Fazer o download e criar o app de demonstração

O SDK do Cardboard é criado usando arquivos de origem C++ de buffers de protocolo pré-compilados. As etapas para criar os arquivos de origem do zero podem ser encontradas neste link.

  1. Clone o SDK do Cardboard e o app de demonstração Hello Cardboard do GitHub. Para isso, execute este comando:

    git clone https://github.com/googlevr/cardboard.git
  2. Instale a dependência de buffers de protocolo no projeto do Xcode executando este comando na raiz do repositório:

    pod install
  3. Abra o espaço de trabalho do Google Cardboard (Cardboard.xcworkspace) no Xcode.

  4. Mude o ID do pacote do app para assiná-lo com sua equipe.

  5. Acesse SDK > Fases de build > Vincular binário com bibliotecas.

    1. Selecione o libPods-sdk.a da lista e clique no botão "-".
    2. Para adicionar libProtobuf-C++.a à lista, clique no botão "+" e selecione-o. Caso apareça uma mensagem sugerindo o uso de um XCFramework, clique em "Adicionar mesmo assim".
  6. Clique em Run.

Leia o código QR

Para salvar os parâmetros do dispositivo, leia o código QR no visor do Google Cardboard:

Confira a demonstração

No HelloCardboard, você vai procurar e coletar esferas geodésicas no espaço 3D.

Para encontrar e coletar uma esfera:

  1. Mova a cabeça em qualquer direção até ver uma esfera flutuante.

  2. Olhe diretamente para a esfera. Isso faz com que ele mude de cor.

  3. Pressione o botão do visualizador do Google Cardboard para "coletar" a esfera.

Configurar o dispositivo

Quando o usuário toca no ícone de engrenagem para alternar entre os visualizadores do Google Cardboard, o método didTapSwitchButton é chamado em HelloCardboardOverlayView.

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

Isso chama CardboardQrCode_scanQrCodeAndSaveDeviceParams, que abre a janela para ler o código QR do visualizador. Quando o usuário lê o código QR, os parâmetros de distorção do dispositivo são atualizados.

- (void)switchViewer {
  CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

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

Acompanhamento da cabeça

Criar tracker da cabeça

Ele é criado uma vez no método viewDidLoad de HelloCardboardViewController:

_cardboardHeadTracker = CardboardHeadTracker_create();

Pausar e retomar tracker da cabeça

Os métodos pauseCardboard e resumeCardboard na classe HelloCardboardViewController pausam e retomam o rastreador de posições da cabeça, respectivamente. O resumeCardboard também define a flag _updateParams, o que faz com que os parâmetros do dispositivo sejam atualizados na próxima chamada de desenho.

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

Distorção da lente

Toda vez que o Cardboard lê um novo código QR, o código a seguir lê os parâmetros salvos e os usa para criar o objeto de distorção de lente, que aplica a distorção adequada ao conteúdo renderizado:

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

Renderização

A renderização de conteúdo no Cardboard envolve o seguinte:

  • Como criar texturas
  • Como acessar matrizes de visualização e projeção para os olhos esquerdo e direito
  • Como criar o renderizador e definir a malha de distorção
  • Renderização de cada frame

Criar texturas

O conteúdo é desenhado em uma textura, que é dividida em seções para o olho esquerdo e direito. Essas seções são inicializadas em _leftEyeTexture e _rightEyeTexture, respectivamente. O app de exemplo usa uma única textura para os dois olhos, mas também é possível criar uma textura separada para cada um deles.

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

Essas texturas são transmitidas como parâmetros para CardboardDistortionRenderer_renderEyeToDisplay.

Acessar matrizes de visualização e projeção para o olho esquerdo e direito

Primeiro, recupere as matrizes oculares para os olhos esquerdo e direito:

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

Em seguida, extraia as malhas de distorção de cada um dos olhos e as transmita ao renderizador de distorção:

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

Criar o renderizador e definir a malha de distorção correta

O renderizador precisa ser inicializado apenas uma vez. Depois de criar o renderizador, defina a nova malha de distorção para os olhos esquerdo e direito de acordo com os valores da malha retornados pela função CardboardLensDistortion_getDistortionMesh.

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

Renderizar o conteúdo

Recupere a orientação atual da cabeça de CardboardHeadTracker_getPose:

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

Use a orientação atual da cabeça com as matrizes de visualização e projeção para compor uma matriz de projeção de visualização. Use-as para renderizar o conteúdo do mundo para cada um dos olhos:

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

Use CardboardDistortionRenderer_renderEyeToDisplay para aplicar a correção de distorção e renderizar o conteúdo na tela.

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