Краткое руководство по Google Cardboard для iOS

В этом руководстве показано, как использовать Cardboard SDK для iOS для создания собственных возможностей виртуальной реальности (VR).

Вы можете использовать Cardboard SDK, чтобы превратить смартфон в платформу VR. Смартфон может отображать 3D-сцены со стереоскопическим рендерингом, отслеживать движения головы и реагировать на них, а также взаимодействовать с приложениями, определяя, когда пользователь нажимает кнопку просмотра.

Для начала вы воспользуетесь HelloCardboard — демонстрационной игрой, демонстрирующей основные функции Cardboard SDK. В игре пользователи осматривают виртуальный мир, находя и собирая объекты. Он покажет вам, как:

  • Настройте среду разработки
  • Загрузите и создайте демо-приложение
  • Отсканируйте QR-код просмотрщика Cardboard, чтобы сохранить его параметры.
  • Отслеживайте движения головы пользователя
  • Рендеринг стереоскопических изображений, установив правильное искажение для каждого глаза.

Настройте среду разработки

Требования к оборудованию:

Требования к программному обеспечению:

Загрузите и создайте демо-приложение

Cardboard SDK создан с использованием предварительно скомпилированных исходных файлов Protocol Buffers C++. Инструкции по сборке исходных файлов с нуля можно найти здесь .

  1. Клонируйте Cardboard SDK и демонстрационное приложение Hello Cardboard с GitHub, выполнив следующую команду:

    git clone https://github.com/googlevr/cardboard.git
  2. Установите зависимость Protocol Buffers в проект Xcode, выполнив эту команду в корне репозитория:

    pod install
  3. Откройте рабочую область Cardboard ( Cardboard.xcworkspace ) в Xcode.

  4. Измените идентификатор пакета приложения, чтобы вы могли подписать приложение вместе со своей командой.

  5. Перейдите в SDK > Этапы сборки > Связать двоичный файл с библиотеками.

    1. Удалите libPods-sdk.a из списка, выбрав его и нажав кнопку «-».
    2. Добавьте libProtobuf-C++.a в список, нажав кнопку «+» и выбрав его. Если появится сообщение с предложением использовать XCFramework, нажмите «Все равно добавить».
  6. Нажмите «Выполнить» .

Сканируйте QR-код

Чтобы сохранить параметры устройства, отсканируйте QR-код во просмотрщике Cardboard:

Попробуйте демо

В HelloCardboard вы будете искать и собирать геодезические сферы в трехмерном пространстве.

Чтобы найти и собрать сферу:

  1. Двигайте головой в любом направлении, пока не увидите парящую сферу.

  2. Посмотрите прямо на сферу. Это приводит к изменению цвета.

  3. Нажмите кнопку просмотра картона, чтобы «собрать» сферу.

Настройка устройства

Когда пользователь нажимает значок шестеренки для переключения средств просмотра Cardboard, в HelloCardboardOverlayView вызывается метод didTapSwitchButton .

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

Это вызывает CardboardQrCode_scanQrCodeAndSaveDeviceParams , который открывает окно для сканирования QR-кода зрителя. Когда пользователь сканирует QR-код, параметры искажения устройства обновляются.

- (void)switchViewer {
 
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

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

Отслеживание головы

Создать трекер головы

Трекер головы создается один раз в методе viewDidLoad HelloCardboardViewController :

_cardboardHeadTracker = CardboardHeadTracker_create();

Пауза и возобновление отслеживания головы

Методы pauseCardboard и resumeCardboard в классе HelloCardboardViewController приостанавливают и возобновляют трекер головы соответственно. resumeCardboard также устанавливает флаг _updateParams , который приводит к обновлению параметров устройства при следующем вызове отрисовки.

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

Искажение объектива

Каждый раз, когда Cardboard сканирует новый QR-код, следующий код считывает сохраненные параметры и использует их для создания объекта искажения линзы, который применяет правильное искажение линзы к отображаемому контенту:

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

Рендеринг

Рендеринг контента в Cardboard включает в себя следующее:

  • Создание текстур
  • Получение матриц вида и проекции для левого и правого глаза
  • Создание рендерера и настройка сетки искажений
  • Рендеринг каждого кадра

Создание текстур

Содержимое рисуется на текстуре, которая разделена на секции для левого и правого глаза. Эти разделы инициализируются в _leftEyeTexture и _rightEyeTexture соответственно. В примере приложения используется одна текстура для обоих глаз, но также можно создать отдельную текстуру для каждого глаза.

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

Эти текстуры передаются в качестве параметров CardboardDistortionRenderer_renderEyeToDisplay .

Получите матрицы просмотра и проекции для левого и правого глаза.

Сначала извлеките матрицы для левого и правого глаза:

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

Затем получите сетки искажений для каждого глаза и передайте их рендереру искажений:

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

Создайте рендерер и установите правильную сетку искажений.

Средство визуализации необходимо инициализировать только один раз. После создания средства рендеринга установите новую сетку искажений для левого и правого глаза в соответствии со значениями сетки, возвращенными функцией CardboardLensDistortion_getDistortionMesh .

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

Рендеринг контента

Получите текущую ориентацию головы из CardboardHeadTracker_getPose :

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

Используйте текущую ориентацию головы с матрицами вида и проекции, чтобы составить матрицу проекции вида, и используйте их для рендеринга содержимого мира для каждого из глаз:

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

Используйте CardboardDistortionRenderer_renderEyeToDisplay чтобы применить коррекцию искажений к содержимому и отобразить содержимое на экране.

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

В этом руководстве показано, как использовать Cardboard SDK для iOS для создания собственных возможностей виртуальной реальности (VR).

Вы можете использовать Cardboard SDK, чтобы превратить смартфон в платформу VR. Смартфон может отображать 3D-сцены со стереоскопическим рендерингом, отслеживать движения головы и реагировать на них, а также взаимодействовать с приложениями, определяя, когда пользователь нажимает кнопку просмотра.

Для начала вы воспользуетесь HelloCardboard — демонстрационной игрой, демонстрирующей основные функции Cardboard SDK. В игре пользователи осматривают виртуальный мир, находя и собирая объекты. Он покажет вам, как:

  • Настройте среду разработки
  • Загрузите и создайте демо-приложение
  • Отсканируйте QR-код просмотрщика Cardboard, чтобы сохранить его параметры.
  • Отслеживайте движения головы пользователя
  • Рендеринг стереоскопических изображений, установив правильное искажение для каждого глаза.

Настройте среду разработки

Требования к оборудованию:

Требования к программному обеспечению:

Загрузите и создайте демо-приложение

Cardboard SDK создан с использованием предварительно скомпилированных исходных файлов Protocol Buffers C++. Инструкции по сборке исходных файлов с нуля можно найти здесь .

  1. Клонируйте Cardboard SDK и демонстрационное приложение Hello Cardboard с GitHub, выполнив следующую команду:

    git clone https://github.com/googlevr/cardboard.git
  2. Установите зависимость Protocol Buffers в проект Xcode, выполнив эту команду в корне репозитория:

    pod install
  3. Откройте рабочую область Cardboard ( Cardboard.xcworkspace ) в Xcode.

  4. Измените идентификатор пакета приложения, чтобы вы могли подписать приложение вместе со своей командой.

  5. Перейдите в SDK > Этапы сборки > Связать двоичный файл с библиотеками.

    1. Удалите libPods-sdk.a из списка, выбрав его и нажав кнопку «-».
    2. Добавьте libProtobuf-C++.a в список, нажав кнопку «+» и выбрав его. Если появится сообщение с предложением использовать XCFramework, нажмите «Все равно добавить».
  6. Нажмите «Выполнить» .

Сканируйте QR-код

Чтобы сохранить параметры устройства, отсканируйте QR-код во просмотрщике Cardboard:

Попробуйте демо

В HelloCardboard вы будете искать и собирать геодезические сферы в трехмерном пространстве.

Чтобы найти и собрать сферу:

  1. Двигайте головой в любом направлении, пока не увидите парящую сферу.

  2. Посмотрите прямо на сферу. Это приводит к изменению цвета.

  3. Нажмите кнопку просмотра картона, чтобы «собрать» сферу.

Настройка устройства

Когда пользователь нажимает значок шестеренки для переключения средств просмотра Cardboard, в HelloCardboardOverlayView вызывается метод didTapSwitchButton .

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

Это вызывает CardboardQrCode_scanQrCodeAndSaveDeviceParams , который открывает окно для сканирования QR-кода зрителя. Когда пользователь сканирует QR-код, параметры искажения устройства обновляются.

- (void)switchViewer {
 
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

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

Отслеживание головы

Создать трекер головы

Трекер головы создается один раз в методе viewDidLoad HelloCardboardViewController :

_cardboardHeadTracker = CardboardHeadTracker_create();

Пауза и возобновление отслеживания головы

Методы pauseCardboard и resumeCardboard в классе HelloCardboardViewController приостанавливают и возобновляют трекер головы соответственно. resumeCardboard также устанавливает флаг _updateParams , который приводит к обновлению параметров устройства при следующем вызове отрисовки.

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

Искажение объектива

Каждый раз, когда Cardboard сканирует новый QR-код, следующий код считывает сохраненные параметры и использует их для создания объекта искажения линзы, который применяет правильное искажение линзы к отображаемому контенту:

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

Рендеринг

Рендеринг контента в Cardboard включает в себя следующее:

  • Создание текстур
  • Получение матриц вида и проекции для левого и правого глаза
  • Создание рендерера и настройка сетки искажений
  • Рендеринг каждого кадра

Создание текстур

Содержимое рисуется на текстуре, которая разделена на секции для левого и правого глаза. Эти разделы инициализируются в _leftEyeTexture и _rightEyeTexture соответственно. В примере приложения используется одна текстура для обоих глаз, но также можно создать отдельную текстуру для каждого глаза.

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

Эти текстуры передаются в качестве параметров CardboardDistortionRenderer_renderEyeToDisplay .

Получите матрицы просмотра и проекции для левого и правого глаза.

Сначала извлеките матрицы глаз для левого и правого глаза:

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

Затем получите сетки искажений для каждого глаза и передайте их рендереру искажений:

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

Создайте рендерер и установите правильную сетку искажений.

Средство визуализации необходимо инициализировать только один раз. После создания средства рендеринга установите новую сетку искажений для левого и правого глаза в соответствии со значениями сетки, возвращенными функцией CardboardLensDistortion_getDistortionMesh .

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

Рендеринг контента

Получите текущую ориентацию головы из CardboardHeadTracker_getPose :

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

Используйте текущую ориентацию головы с матрицами вида и проекции, чтобы составить матрицу проекции вида, и используйте их для рендеринга содержимого мира для каждого из глаз:

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

Используйте CardboardDistortionRenderer_renderEyeToDisplay чтобы применить коррекцию искажений к содержимому и отобразить содержимое на экране.

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