يوضّح لك هذا الدليل كيفية استخدام حزمة تطوير البرامج (SDK) Cardboard لنظام التشغيل Android من أجل إنشاء تجارب الواقع الافتراضي الخاصة بك.
يمكنك استخدام حزمة تطوير البرامج (SDK) في Cardboard لتحويل هاتف ذكي إلى منصة واقع افتراضي. يمكن للهاتف الذكي عرض مشاهد ثلاثية الأبعاد باستخدام العرض المجسّم، وتتبُّع حركات الرأس والاستجابة لها، والتفاعل مع التطبيقات من خلال رصد وقت ضغط المستخدم على زر المشاهدة.
للبدء، عليك استخدام HelloCardboard، وهي لعبة تجريبية توضّح الميزات الأساسية لحزمة تطوير البرامج (SDK) الخاصة بـ Cardboard. في اللعبة، يتجوّل المستخدمون في عالم افتراضي للعثور على كائنات وجمعها. يوضّح لك هذا المثال كيفية:
- إعداد بيئة التطوير
- تنزيل تطبيق العرض التوضيحي وإنشاؤه
- مسح رمز الاستجابة السريعة الخاص بنظّارة Cardboard لحفظ مَعلمات النظّارة
- تتبُّع حركات رأس المستخدم
- عرض صور مجسّمة من خلال ضبط مصفوفة عرض المنظور الصحيحة لكل عين
تستخدم HelloCardboard حزمة تطوير البرامج الأصلية (NDK) لنظام التشغيل Android. كل طريقة أصلية هي:
- مرتبط بشكل فريد بطريقة فئة
HelloCardboardApp
- إنشاء مثيل لهذه الفئة أو حذفه
إعداد بيئة التطوير
متطلبات الأجهزة:
- جهاز Android يعمل بالإصدار 8.0 "Oreo" من نظام التشغيل Android (المستوى 26 من واجهة برمجة التطبيقات) أو إصدار أحدث
- نظّارة Cardboard
متطلبات البرامج:
- الإصدار 2024.1.2 من استوديو Android (تحديث Koala) أو إصدار أحدث
- الإصدار 15.0 من حزمة تطوير البرامج (SDK) لنظام التشغيل Android "Vanilla Ice Cream" (المستوى 35 لواجهة برمجة التطبيقات) أو إصدار أحدث
أحدث إصدار من إطار عمل Android NDK
لمراجعة حِزم SDK المثبَّتة أو تعديلها، انتقِل إلى الإعدادات المفضّلة > المظهر والسلوك.
إعدادات النظام > حزمة تطوير البرامج (SDK) لنظام التشغيل Android في "استوديو Android"
تنزيل تطبيق العرض التوضيحي وإنشاؤه
تم إنشاء حزمة تطوير البرامج (SDK) الخاصة بـ Cardboard باستخدام ملف عنوان Vulkan مسبق التجميع لكل برنامج تظليل. يمكنك الاطّلاع على خطوات إنشاء ملفات العناوين من البداية هنا.
نفِّذ الأمر التالي لاستنساخ حزمة تطوير البرامج (SDK) الخاصة بـ Cardboard وتطبيق HelloCardboard التجريبي من GitHub:
git clone https://github.com/googlevr/cardboard.git
في "استوديو Android"، انقر على فتح مشروع حالي في "استوديو Android" (Open an existing Android Studio Project)، ثم اختَر الدليل الذي تم استنساخ حزمة تطوير البرامج (SDK) لتطبيق Cardboard وتطبيق HelloCardboard التجريبي فيه.
سيظهر الرمز في نافذة "المشروع" في "استوديو Android".
لتجميع حزمة تطوير البرامج (SDK) الخاصة بنظّارة Cardboard، انقر نقرًا مزدوجًا على الخيار assemble ضمن المجلد cardboard/:sdk/Tasks/build في علامة التبويب Gradle (عرض > نوافذ الأدوات > Gradle).
شغِّل تطبيق HelloCardboard التجريبي على هاتفك من خلال النقر على تشغيل > تشغيل... واختَر هدف
hellocardboard-android
.
المسح الضوئي لرمز الاستجابة السريعة
لحفظ مَعلمات الجهاز، امسح رمز الاستجابة السريعة على نظّارة Cardboard ضوئيًا:
إذا ضغط المستخدم على "تخطّي" ولم تكن هناك أي مَعلمات محفوظة سابقًا، سيحفظ Cardboard مَعلمات Google Cardboard الإصدار 1 (الذي تم إطلاقه في مؤتمر Google I/O عام 2014).
تجربة العرض التوضيحي
في HelloCardboard، عليك البحث عن كرات أرضية ثلاثية الأبعاد وجمعها في مساحة ثلاثية الأبعاد.
للعثور على كرة وجمعها، اتّبِع الخطوات التالية:
حرِّك رأسك في أي اتجاه إلى أن يظهر شكل عائم.
انظر مباشرةً إلى الكرة. ويؤدي ذلك إلى تغيير الألوان.
اضغط على زر نظّارة Cardboard "لجمع" الكرة.
ضبط إعدادات الجهاز
عندما ينقر المستخدم على رمز الترس للتبديل بين نظارات Cardboard، يتم استدعاء الطريقة nativeSwitchViewer
. nativeSwitchViewer
، ما يؤدي إلى فتح نافذة لمسح رمز الاستجابة السريعة الخاص بالمشاهد ضوئيًا.CardboardQrCode_scanQrCodeAndSaveDeviceParams
يتم تعديل تشوّه عدسة المشاهد والمعلمات الأخرى مرة واحدة بعد مسح رمز الاستجابة السريعة ضوئيًا.
// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}
تفعيل محاكي x86 في "استوديو Android"
لإنشاء إصدار لمحاكي x86 في "استوديو Android"، عليك إزالة السطر التالي من ملفات
build.gradle
في حزمة تطوير البرامج (SDK)
والعينة:
abiFilters 'armeabi-v7a', 'arm64-v8a'
يؤدي ذلك إلى تفعيل جميع واجهات التطبيق الثنائية (ABI) وزيادة حجم ملف .aar
الذي تم إنشاؤه بشكل كبير. يمكنك الاطّلاع على واجهات التطبيق الثنائية لنظام التشغيل Android
للحصول على مزيد من المعلومات.
تتبُّع حركة الرأس
إنشاء أداة تتبُّع حركة الرأس
يتم إنشاء أداة تتبُّع حركة الرأس مرة واحدة في أداة إنشاء HelloCardboardApp
:
HelloCardboardApp::HelloCardboardApp(JavaVM* vm, jobject obj, jobject asset_mgr_obj) {
Cardboard_initializeAndroid(vm, obj); // Must be called in constructor
head_tracker_ = CardboardHeadTracker_create();
}
عند إنشاء VrActivity
، يتم إنشاء مثيل للفئة HelloCardboardApp
من خلال استدعاء الطريقة nativeOnCreate
:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
nativeApp = nativeOnCreate(getAssets());
//...
}
إيقاف ميزة "تتبُّع حركة الرأس" مؤقتًا واستئنافها
لإيقاف ميزة تتبُّع حركة الرأس مؤقتًا واستئنافها وإيقافها نهائيًا، يجب استدعاء CardboardHeadTracker_pause(head_tracker_)
وCardboardHeadTracker_resume(head_tracker_)
وCardboardHeadTracker_destroy(head_tracker_)
على التوالي. في تطبيق HelloCardboard، نطلق عليها الأسماء nativeOnPause
وnativeOnResume
وnativeOnDestroy
:
// Code to pause head tracker in hello_cardboard_app.cc
void HelloCardboardApp::OnPause() { CardboardHeadTracker_pause(head_tracker_); }
// Call nativeOnPause in VrActivity
@Override
protected void onPause() {
super.onPause();
nativeOnPause(nativeApp);
//...
}
// Code to resume head tracker in hello_cardboard_app.cc
void HelloCardboardApp::onResume() {
CardboardHeadTracker_resume(head_tracker_);
//...
}
// Call nativeOnResume in VrActivity
@Override
protected void onResume() {
super.onResume();
//...
nativeOnResume(nativeApp);
}
// Code to destroy head tracker in hello_cardboard_app.cc
HelloCardboardApp::~HelloCardboardApp() {
CardboardHeadTracker_destroy(head_tracker_);
//...
}
// Call nativeOnDestroy in VrActivity
@Override
protected void onDestroy() {
super.onDestroy();
nativeOnDestroy(nativeApp);
nativeApp = 0;
}
تشوّه العدسة
في كل مرة يمسح فيها Cardboard رمز استجابة سريعة جديدًا، يقرأ الرمز التالي المَعلمات المحفوظة ويستخدمها لإنشاء عنصر تشويه العدسة، الذي يطبّق تشويه العدسة المناسب على المحتوى المعروض:
CardboardQrCode_getSavedDeviceParams(&buffer, &size);
CardboardLensDistortion_destroy(lens_distortion_);
lens_distortion_ = CardboardLensDistortion_create(
buffer, size, screen_width_, screen_height_);
CardboardQrCode_destroy(buffer);
العرض
يتضمّن عرض المحتوى في Cardboard ما يلي:
- إنشاء زخارف
- الحصول على مصفوفات العرض والإسقاط للعين اليسرى واليمنى
- إنشاء أداة العرض وتعيين شبكة التشويه
- عرض كل إطار
إنشاء مواد
يتم عرض كل المحتوى على نسيج مقسّم إلى أقسام للعين اليسرى واليمنى.
يتمّ تهيئة هذين القسمين في _leftEyeTexture
و_rightEyeTexture
على التوالي.
void HelloCardboardApp::GlSetup() {
LOGD("GL SETUP");
if (framebuffer_ != 0) {
GlTeardown();
}
// Create render texture.
glGenTextures(1, &texture_);
glBindTexture(GL_TEXTURE_2D, texture_);
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, screen_width_, screen_height_, 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);
left_eye_texture_description_.texture = texture_;
left_eye_texture_description_.left_u = 0;
left_eye_texture_description_.right_u = 0.5;
left_eye_texture_description_.top_v = 1;
left_eye_texture_description_.bottom_v = 0;
right_eye_texture_description_.texture = texture_;
right_eye_texture_description_.left_u = 0.5;
right_eye_texture_description_.right_u = 1;
right_eye_texture_description_.top_v = 1;
right_eye_texture_description_.bottom_v = 0;
//...
CHECKGLERROR("GlSetup");
}
يتم تمرير هذه الأنسجة كمعلَمات إلى CardboardDistortionRenderer_renderEyeToDisplay
.
الحصول على مصفوفات العرض والإسقاط للعين اليسرى واليمنى
أولاً، استرجِع مصفوفات العينين اليسرى واليمنى:
CardboardLensDistortion_getEyeFromHeadMatrix(
lens_distortion_, kLeft, eye_matrices_[0]);
CardboardLensDistortion_getEyeFromHeadMatrix(
lens_distortion_, kRight, eye_matrices_[1]);
CardboardLensDistortion_getProjectionMatrix(
lens_distortion_, kLeft, kZNear, kZFar, projection_matrices_[0]);
CardboardLensDistortion_getProjectionMatrix(
lens_distortion_, kRight, kZNear, kZFar, projection_matrices_[1]);
بعد ذلك، احصل على شبكات التشويه لكل عين ومرِّرها إلى أداة عرض التشويه:
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);
إنشاء أداة العرض وضبط شبكة التشويه الصحيحة
يجب إعداد أداة العرض مرة واحدة فقط. بعد إنشاء أداة العرض، اضبط شبكة التشويه الجديدة للعينين اليسرى واليمنى وفقًا لقيم الشبكة التي تعرضها الدالة CardboardLensDistortion_getDistortionMesh
.
distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);
عرض المحتوى
بالنسبة إلى كل إطار، استرجِع اتجاه الرأس الحالي من CardboardHeadTracker_getPose
:
CardboardHeadTracker_getPose(head_tracker_, monotonic_time_nano, &out_position[0], &out_orientation[0]);
استخدِم اتجاه الرأس الحالي مع مصفوفات العرض والإسقاط لإنشاء مصفوفة عرض إسقاط لكل عين وعرض المحتوى على الشاشة:
// Draw eyes views
for (int eye = 0; eye < 2; ++eye) {
glViewport(eye == kLeft ? 0 : screen_width_ / 2, 0, screen_width_ / 2,
screen_height_);
Matrix4x4 eye_matrix = GetMatrixFromGlArray(eye_matrices_[eye]);
Matrix4x4 eye_view = eye_matrix * head_view_;
Matrix4x4 projection_matrix =
GetMatrixFromGlArray(projection_matrices_[eye]);
Matrix4x4 modelview_target = eye_view * model_target_;
modelview_projection_target_ = projection_matrix * modelview_target;
modelview_projection_room_ = projection_matrix * eye_view;
// Draw room and target. Replace this to render your own content.
DrawWorld();
}
استخدِم CardboardDistortionRenderer_renderEyeToDisplay
لتطبيق تصحيح التشويش على المحتوى وعرضه على الشاشة.
// Render
CardboardDistortionRenderer_renderEyeToDisplay(
distortion_renderer_, /* target_display = */ 0, /* x = */ 0, /* y = */ 0,
screen_width_, screen_height_, &left_eye_texture_description_,
&right_eye_texture_description_);