التشغيل السريع لـ Google Cardboard لنظام التشغيل iOS

يوضح لك هذا الدليل كيفية استخدام حزمة تطوير البرامج (SDK) لـ Cardboard لنظام التشغيل iOS لإنشاء جهازك الافتراضي تجارب الواقع (VR).

يمكنك استخدام حزمة تطوير برامج Cardboard لتحويل هاتف ذكي إلى نظام أساسي للواقع الافتراضي. هاتف ذكي عرض مشاهد ثلاثية الأبعاد بعرض مجسم، وتتبع حركات الرأس والتفاعل معها، تتفاعل مع التطبيقات من خلال اكتشاف وقت ضغط المستخدم على زر العارض.

للبدء، ستستخدم HelloCardboard، وهي لعبة تجريبية توضح الميزات الأساسية لحزمة تطوير البرامج من Cardboard. في هذه اللعبة، ينظر المستخدمون حول عالم افتراضي للعثور على الأخرى. وتوضّح لك كيفية:

  • إعداد بيئة التطوير
  • تنزيل التطبيق التجريبي وإنشاؤه
  • مسح رمز الاستجابة السريعة لعارض Cardboard لحفظ معلماته
  • تتبع حركات رأس المستخدم
  • عرض صور مجسَّمة من خلال ضبط التشوّه الصحيح لكل عين

إعداد بيئة التطوير

متطلبات الأجهزة:

  • هاتف iPhone يعمل بنظام التشغيل iOS 12.0 أو إصدار أحدث
  • عارض Cardboard

متطلبات البرامج:

تنزيل التطبيق التجريبي وإنشاؤه

تم إنشاء حزمة تطوير البرامج (SDK) لـ Cardboard باستخدام مخازن البروتوكولات المجمَّعة مسبقًا ملفات المصدر C++. خطوات إنشاء الملفات المصدر من البداية هنا.

  1. استنسِخ حزمة Card 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، انقر على "Add Anyway".
  6. انقر على تشغيل.

المسح الضوئي لرمز الاستجابة السريعة

لحفظ معلمات الجهاز، امسح رمز الاستجابة السريعة على نظّارة Cardboard:

النسخة التجريبية

في HelloCardboard، ستبحث عن الكرويات الجيوديسية وتجمعها في مساحة ثلاثية الأبعاد.

للعثور على كرة وجمعها:

  1. حرِّك رأسك في أي اتجاه حتى ترى كرة عائمة.

  2. انظر مباشرة إلى الكرة. هذا يتسبب في تغيير ألوانها.

  3. اضغط على زر نظّارة Cardboard من أجل "الجمع" الكرة.

إعداد الجهاز

عندما ينقر المستخدم على رمز الترس لتبديل عارضات Cardboard، يتم تغيير didTapSwitchButton في HelloCardboardOverlayView.

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

يتطلب هذا الاتصال CardboardQrCode_scanQrCodeAndSaveDeviceParams، الذي يفتح نافذة لمسح رمز الاستجابة السريعة للمشاهد. وعندما يمسح المستخدم رمز الاستجابة السريعة ضوئيًا، فإن رمز الاستجابة السريعة يتم تحديث معلَمات التشوّه.

- (void)switchViewer {
  CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

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

تتبُّع حركة الرأس

إنشاء جهاز تتبُّع حركة الرأس

يتم إنشاء أداة تتبُّع حركة الرأس مرة واحدة بطريقة viewDidLoad بالطريقة HelloCardboardViewController:

_cardboardHeadTracker = CardboardHeadTracker_create();

الإيقاف المؤقت واستئناف جهاز تتبُّع الرأس

الطريقتان pauseCardboard وresumeCardboard في إيقاف صف واحد (HelloCardboardViewController) مؤقتًا واستئناف جهاز تتبُّع حركة الرأس على التوالي. يتم أيضًا ضبط العلامة _updateParams من قِبل resumeCardboard، ما يؤدي إلى معلمات الجهاز المراد تحديثها في استدعاء الرسم التالي.

- (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 رمز استجابة سريعة جديدًا، يقرأ الرمز التالي المعلمات المحفوظة. وتستخدمها لإنشاء كائن تشوّه العدسة، ما يؤدي إلى تطبيق التشوّه المناسب في العدسة على المحتوى المعروض:

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