במדריך הזה מוסבר איך להשתמש ב-Cardboard SDK ל-iOS כדי ליצור מכונה וירטואלית משלכם. חוויות מציאות (VR).
אפשר להשתמש ב-Cardboard SDK כדי להפוך סמארטפון לפלטפורמת VR. סמארטפון להציג סצנות תלת ממדיות עם עיבוד סטריאוסקופי, לעקוב אחר תנועות הראש ולהגיב לתנועות כאלה. לקיים אינטראקציה עם אפליקציות על ידי זיהוי מתי המשתמש לוחץ על לחצן הצפייה.
כדי להתחיל, עליך להשתמש ב-HelloCardboard, משחק הדגמה שמדגים את התכונות העיקריות של Cardboard SDK. במשחק, המשתמשים מביטים סביב עולם וירטואלי כדי למצוא ולאסוף אובייקטים. המדריך מסביר איך:
- הגדרת סביבת הפיתוח
- הורדה ויצירה של אפליקציית ההדגמה
- צריך לסרוק את קוד ה-QR של מכשיר Cardboard כדי לשמור את הפרמטרים שלו
- מעקב אחר תנועות הראש של המשתמש
- עיבוד תמונות סטריאוסקופיות על ידי הגדרת העיוות הנכון לכל עין
הגדרת סביבת הפיתוח
דרישות חומרה:
- iPhone עם iOS מגרסה 12.0 ואילך
- מציג קרטון
דרישות התוכנה:
- Xcode 12.5 ואילך
- CocoaPods 1.9 ואילך
הורדה ויצירה של אפליקציית ההדגמה
ה-SDK של Cardboard נבנה באמצעות מאגרי פרוטוקולים שעברו הידור מראש קובצי מקור מסוג C++. אפשר למצוא שלבים לבניית קובצי המקור מההתחלה כאן.
שכפול של Cardboard SDK ואת אפליקציית ההדגמה של Hello Cardboard מ-GitHub על ידי הרצת הפקודה הבאה:
git clone https://github.com/googlevr/cardboard.git
מתקינים את התלות של Protocol Buffers בפרויקט Xcode על ידי הרצת הפקודה הבאה ברמה הבסיסית (root) של המאגר:
pod install
פותחים את סביבת העבודה של Cardboard (
Cardboard.xcworkspace
) ב-Xcode.כדי שתהיה לך אפשרות לחתום על האפליקציה עם הצוות, צריך לשנות את מזהה החבילה של האפליקציה.
עוברים אל SDK > שלבי הבנייה > קישור בינארי עם ספריות
- כדי להסיר את
libPods-sdk.a
מהרשימה, בוחרים בה ולוחצים על הסמל '-' לחצן. - כדי להוסיף את
libProtobuf-C++.a
לרשימה, לוחצים על הסמל '+' ובחירה בו. אם תקפוץ הודעה שמציעה להשתמש ב-XCFramework, לוחצים על Add Anyway (הוספת בכל זאת).
- כדי להסיר את
לוחצים על Run.
סריקת קוד ה-QR
כדי לשמור את הפרמטרים של המכשיר, סורקים את קוד ה-QR במציג Cardboard:
נסה את ההדגמה
ב-HelloCardboard מחפשים ואוספים כדורים גיאודזיים במרחב תלת-ממדי.
כדי למצוא ולאסוף ספירה:
יש להזיז את הראש בכיוון כלשהו עד שרואים ספירה צף.
הביטו ישירות בכדור. כתוצאה מכך, הצבעים משתנים.
כדי לבצע "איסוף", יש ללחוץ על הלחצן של מכשיר Cardboard את כדור הארץ.
הגדרת המכשיר
כשהמשתמש מקיש על סמל גלגל השיניים כדי להחליף את מכשיר הצפייה של Cardboard, הפונקציה didTapSwitchButton
נקראת ב-HelloCardboardOverlayView
.
- (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);