このガイドでは、iOS 用の Cardboard SDK を使用して独自のバーチャル リアリティ(VR)体験を創出する方法について説明します。
Cardboard SDK を使用して、スマートフォンを VR プラットフォームにすることができます。スマートフォンは、立体画像レンダリングで 3D シーンを表示し、頭の動きを追跡して反応し、ユーザーがボタンを押したことを検知してアプリを操作できます。
まず、HelloCardboard を使用します。これは、Cardboard SDK のコア機能のデモゲームです。このゲームでは、ユーザーは仮想世界を見ながらオブジェクトを見つけて収集します。次の方法について説明します。
- 開発環境をセットアップする
- デモアプリのダウンロードとビルド
- Cardboard ビューアの QR コードをスキャンして、パラメータを保存します
- ユーザーの頭の動きをトラッキングする
- 左右の目の歪みを適切に補正することで、立体画像をレンダリングする
開発環境をセットアップする
ハードウェア要件:
- iOS 12.0 以上を搭載した iPhone
- Cardboard ビューア
ソフトウェア要件:
- Xcode 12.5 以降
- CocoaPods 1.9 以降
デモアプリのダウンロードとビルド
Cardboard SDK は、コンパイル済みのプロトコル バッファ C++ ソースファイルを使用してビルドされています。ソースファイルをゼロからビルドする手順については、こちらをご覧ください。
GitHub から Cardboard SDK と Hello Cardboard デモアプリのクローンを作成し、次のコマンドを実行します。
git clone https://github.com/googlevr/cardboard.git
リポジトリ ルートで次のコマンドを実行して、プロトコル バッファの依存関係を Xcode プロジェクトにインストールします。
pod install
Xcode で Cardboard ワークスペース(
Cardboard.xcworkspace
)を開きます。アプリのバンドル ID を変更して、チームでアプリに署名できるようにします。
[SDK] > [Build Phases] > Link Binary With Libraries に移動します。
libPods-sdk.a
をリストから削除するには、リストを選択して ['-'] ボタンをクリックします。- '+' ボタンをクリックしてリストに
libProtobuf-C++.a
を追加します。XCFramework の使用をおすすめするメッセージがポップアップ表示された場合は、[このまま追加] をクリックします。
[実行] をクリックします。
QR コードをスキャンする
デバイスのパラメータを保存するには、Cardboard ビューアで QR コードをスキャンします。
デモを試す
HelloCardboard で 3D 空間内の測地線球を検索、収集できます。
球を検索、収集するには:
頭が任意の方向に動くと、浮いている球体が表示されます。
球体を直接見ます。これにより、色が変化します。
Cardboard ビューア ボタンを押して球体を「収集」します。
デバイスを設定する
ユーザーが歯車アイコンをタップして 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];
}
ヘッド トラッキング
ヘッドトラッカーを作成する
ヘッドトラッカーは、HelloCardboardViewController
の viewDidLoad
メソッドで 1 回作成されます。
_cardboardHeadTracker = CardboardHeadTracker_create();
ヘッドトラッカーを一時停止、再開する
HelloCardboardViewController
クラスの pauseCardboard
メソッドと resumeCardboard
メソッドは、それぞれヘッドトラッカーを一時停止、再開します。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);
レンダラを作成し、正しい歪みメッシュを設定する
レンダラの初期化が必要なのは 1 回のみです。レンダラを作成したら、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);