שימוש בעוגנים גיאו-מרחביים כדי למקם תוכן מהעולם האמיתי ב-Android NDK

עוגנים גיאו-מרחביים הם סוג של עוגן שמאפשר למקם תוכן בתלת-ממד בעולם האמיתי.

סוגים של עוגנים גיאו-מרחביים

יש שלושה סוגים של עוגנים גיאו-מרחביים, שכל אחד מהם מטפל בגובה באופן שונה:

  1. עוגנים של WGS84:
    עוגנים של WGS84 מאפשרים לך למקם תוכן תלת-ממדי בכל קו רוחב נתון, קו אורך וגובה.

  2. עוגנים בפני השטח:
    עוגנים של פני השטח מאפשרים לך להציב תוכן רק באמצעות קווי רוחב ו קו אורך עם גובה ביחס לפני השטח במיקום הזה. הגובה נקבע ביחס לקרקע או לקומה, כפי שהיא ידועה מאת VPS.

  3. עוגנים על הגג:
    מודעות עוגן לחלק העליון של הגג מאפשרות לך למקם תוכן רק לפי קווי רוחב קו אורך ביחס לגג של בניין באותו מיקום. הגובה נקבע ביחס לחלק העליון של המבנה, כפי שהוא ידוע מאת Streetscape Geometry. ברירת המחדל של ההגדרה הזו היא גובה פני השטח כשהיא לא מוצבת על מבנה.

WGS84 פני השטח גג רכב
מיקום אופקי קו רוחב, קו אורך קו רוחב, קו אורך קו רוחב, קו אורך
מיקום אנכי ביחס לגובה של WGS84 ביחס לגובה פני השטח, שנקבע על ידי מפות Google ביחס לרמת הגג, שנקבעת על ידי מפות Google
האם נדרש פתרון לשרת? לא כן כן

דרישות מוקדמות

לפני שממשיכים, חשוב לוודא שאתם מפעילים את Geospatial API.

מיקום עוגנים גיאו-מרחביים

לכל סוג עוגן יש ממשקי API ייעודיים שמאפשרים ליצור אותם. למידע נוסף, ראו סוגים של עוגנים גיאו-מרחביים.

יצירת עוגן מבדיקת היט

אפשר גם ליצור עוגן גיאו-מרחבי מתוצאת בדיקת התאמה. משתמשים ב-Pose מההיט-בדיקה וממירים אותו ל-ArGeospatialPose. משתמשים בו כדי למקם כל אחד מ-3 סוגי העוגנים שמתוארים.

איך מקבלים מיקום גיאו-מרחבי מ-AR Pose

התכונה ArEarth_getGeospatialPose() מספקת דרך נוספת לקבוע את קו הרוחב וקו האורך על ידי המרה של מיקום AR למיקום גיאו-מרחבי.

קבלת AR Pose ממיקום גיאו-מרחבי

הפונקציה ArEarth_getPose() ממירה מיקום אופקי, גובה וסיבוב קווטרניון שצוינו בכדור הארץ ביחס למסגרת קואורדינטות מזרח-מעלה-דרום לתנוחת AR לתנוחת AR ביחס לקואורדינטה בעולם של GL.

בחירת השיטה שמתאימה לתרחיש לדוגמה שלכם

לכל שיטה ליצירת עוגן יש יתרונות וחסרונות שחשוב לזכור:

  • כשמשתמשים בגיאומטריה של Streetscape, להשתמש במבחן היט כדי לצרף תוכן לבניין.
  • יש עדיפות לעוגנים של פני שטח או גג על פני עוגנים WGS84 כי הם משתמשים בערכי גובה שנקבעים על ידי מפות Google.

קביעת קו הרוחב וקו האורך של מיקום

יש שלוש דרכים לחישוב קו הרוחב וקו האורך של מיקום:

  • אפשר להשתמש בתכונה יוצר גיאו-מרחבי כדי להציג את העולם ולהרחיב אותו באמצעות תוכן תלת-ממדי בלי להגיע למיקום פיזי. כך תוכלו למקם ב-Unity Editor תוכן תלת-ממדי חזותי באמצעות מפות Google. המערכת תחשב באופן אוטומטי את קו הרוחב, קו האורך, הסיבוב והגובה של התוכן.
  • שימוש במפות Google
  • משתמשים ב-Google Earth. שימו לב שהשגת הקואורדינטות האלה באמצעות Google Earth, בניגוד למפות Google, תעניק לכם מרווח שגיאה של עד כמה מטרים.
  • מעבר למיקום הפיזי

שימוש במפות Google

כדי לקבל את קו הרוחב וקו האורך של מיקום באמצעות מפות Google:

  1. נכנסים למפות Google במחשב.

  2. עוברים אל שכבות > עוד.

  3. משנים את ההגדרה סוג המפה ללוויין ומבטלים את הסימון של התיבה תצוגת כדור הארץ בפינה הימנית התחתונה של המסך.

    פעולה זו תאלץ נקודת מבט דו-ממדית ויבטלו שגיאות אפשריות שעלולות להגיע מתצוגה תלת-ממדית זוויתית.

  4. במפה, לוחצים לחיצה ימנית על המיקום ובוחרים את קו האורך/קו הרוחב כדי להעתיק אותו ללוח.

שימוש ב-Google Earth

אפשר לחשב את קו הרוחב וקו האורך של מיקום ב-Google Earth על ידי לחיצה על מיקום בממשק המשתמש וקריאת הנתונים מהפרטים של הסמן.

כדי לקבל את קו הרוחב וקו האורך של מיקום באמצעות Google Earth:

  1. נכנסים ל-Google Earth במחשב.

  2. עוברים לתפריט ההמבורגר ובוחרים באפשרות סגנון מפה.

  3. מעבירים את המתג בניינים בתלת-ממד למצב מושבת.

  4. אחרי שמעבירים את המתג בניינים בתלת-ממד למצב מושבת, לוחצים על סמל הסיכה כדי להוסיף סמן במיקום שנבחר.

  5. מציינים פרויקט שיכלול את הסמן ולוחצים על שמירה.

  6. בשדה כותרת של הסמן, מזינים שם לסמן.

  7. לוחצים על החץ חזרה בחלונית הפרויקט ובוחרים בתפריט פעולות נוספות.

  8. בתפריט, בוחרים באפשרות ייצוא כקובץ KML.

קובץ ה-KLM מדווח על קו הרוחב, קו האורך והגובה של הסמן בתג <coordinates>, והוא מופרד בפסיקים, באופן הבא:

<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>

אין להשתמש בקווי אורך ורוחב מתגי <LookAt>, שמציינים את מיקום המצלמה ולא את המיקום.

מעבר למיקום הפיזי

אפשר לחשב את הגובה של מיקום מסוים על ידי הגעה אליו פיזית וביצוע תצפית מקומית.

מקבלים את הקוואטרניון של הסיבוב

ArGeospatialPose_getEastUpSouthQuaternion() מחלצת את הכיוון ממיקום גיאו-מרחבי ומפיקה פלט של קווטרניון שמייצג את מטריצת הסיבוב שהופכת וקטור מהיעד למערכת הקואורדינטות 'מזרח למעלה-דרום' (EUS). X+ מצביע מזרחה, Y+ נקודות למעלה ו-Z+ נקודות דרום. הערכים נכתבים לפי הסדר {x, y, z, w}.

עוגנים של WGS84

עוגן WGS84 הוא סוג של עוגן שמאפשר למקם תוכן תלת-ממדי בכל גובה, קו אורך ורוחב. לצורך ההצבה של המשחק בעולם האמיתי, הוא מסתמך על תנוחה וכיוון. המיקום מורכב מקווי רוחב, קו אורך וגובה, המוגדרים במערכת הקואורדינטות WGS84. הכיוון מורכב מסיבוב של קווטרניון.

הגובה מדווח במטרים מעל האליפסואיד WGS84, כך שגובה הקרקע לא מאפס. האפליקציה שלך אחראית לספק את הקואורדינטות האלה בכל עוגן שנוצר.

מיקום עוגן של WGS84 בעולם האמיתי

קביעת הגובה של מיקום

יש כמה דרכים לקבוע את הגובה של מיקום להצבת עוגנים:

  • אם מיקום העוגן נמצא פיזית ליד המשתמש, ניתן להשתמש בגובה שדומה לגובה המכשיר של המשתמש.
  • אחרי שמציינים את קו הרוחב וקו האורך, משתמשים ב-Heightion API כדי להציג גובה על סמך המפרט של EGM96. צריך להמיר את גובה EGM96 של Maps API ל-WGS84 לצורך השוואה מול הגובה ArGeospatialPose. ראו GeoidEval שכולל גם שורת פקודה וגם ממשק HTML. הממשק API של מפות Google מדווח על קווי אורך ורוחב בהתאם למפרט WGS84.
  • אפשר לקבל את קו הרוחב, קו האורך והגובה של מיקום מ-Google Earth. כך מקבלים מרווח שגיאה של עד כמה מטרים. שימוש בקווי רוחב, קו אורך וגובה מתוך התגים <coordinates>, ולא באמצעות התגים <LookAt> בקובץ ה-KML.
  • אם עוגן קיים נמצא בקרבת מקום וגם אם אתם לא בשיפוע תלול, אפשר להשתמש בגובה מה-ArGeospatialPose של המצלמה בלי להשתמש במקור אחר, כמו ה-API של מפות Google.

יצירת העוגן

אחרי שרואים את קו הרוחב, קו האורך, הגובה וקווטרניון הסיבוב, משתמשים ב-ArEarth_acquireNewAnchor() כדי לעגן תוכן לקואורדינטות גיאוגרפיות שציינתם.

float eus_quaternion_4[4] = {qx, qy, qz, qw};
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArAnchor* earth_anchor = NULL;
    ArStatus status = ArEarth_acquireNewAnchor(ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude,
        eus_quaternion_4, &earth_anchor);

    // Attach content to the anchor specified by geodetic location and
    // pose.
  }
}

מודעות עוגן לפני השטח

עוגן הוא סוג של עוגן שמאפשר להציב אובייקטים ב-AR רק באמצעות קווי רוחב ואורך, תוך שימוש במידע מ-VPS כדי למצוא את הגובה המדויק מעל פני הקרקע.

במקום להזין את הגובה הרצוי, אתם מציינים את הגובה מעל פני השטח. כאשר הערך הוא אפס, העוגן יהיה מיושר עם פני השטח.

הגדרת מצב איתור מטוס

חיפוש המטוס הוא אופציונלי ולא נדרש כדי להשתמש בעוגנים. הערה: נעשה שימוש רק במישורים אופקיים. מישורים אופקיים יעזרו ליישור דינמי של עוגנים על פני השטח.

אפשר לבחור איך האפליקציה תזהה מטוסים באמצעות ArPlaneFindingMode.

יצירת עוגן באמצעות פני השטח באמצעות ה-API האסינכרוני החדש

כדי ליצור ולהציב עוגן שטח, קוראים לפונקציה ArEarth_resolveAnchorOnTerrainAsync().

העוגן לא יהיה מוכן מיד ויהיה צריך לפתור אותו. לאחר פתרון הבעיה, הבעיה תהיה זמינה בArResolveAnchorOnTerrainFuture.

בודקים את מצב העוגן של פני השטח באמצעות ArResolveAnchorOnTerrainFuture_getResultTerrainAnchorState(). כדי לקבל את העוגן שטופל, משתמשים ב-ArResolveAnchorOnTerrainFuture_acquireResultAnchor().

float eus_quaternion_4[4] = {qx, qy, qz, qw};
void* context = NULL;
ArResolveAnchorOnTerrainCallback callback = NULL;
ArResolveAnchorOnTerrainFuture* future = NULL;
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArStatus status = ArEarth_resolveAnchorOnTerrainAsync(
        ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude_above_terrain, eus_quaternion_4,
        context, callback, &future);
  }
}

מה יהיה העתיד?

העתיד ישויך אל ArFutureState.

מדינה תיאור
AR_FUTURE_STATE_PENDING הפעולה עדיין בהמתנה.
AR_FUTURE_STATE_DONE הפעולה הושלמה והתוצאה זמינה.
AR_FUTURE_STATE_CANCELLED הפעולה בוטלה.

בדיקת מצב העוגן של פני השטח של התוצאה העתידית

ArTerrainAnchorState שייך לפעולה האסינכרונית והוא חלק מהתוצאה העתידית הסופית.

switch (terrain_anchor_state) {
  case AR_TERRAIN_ANCHOR_STATE_SUCCESS:
    // A resolving task for this anchor has been successfully resolved.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the
    // Geospatial API.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/c/group/ar-anchor#:~:text=from%20this%20error.-,AR_TERRAIN_ANCHOR_STATE_ERROR_NOT_AUTHORIZED,-The%20authorization%20provided
    // for troubleshooting steps.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_INTERNAL:
    // The Terrain anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

דיבלים לגגות

תמונה ראשית (Hero) של דיבלים לגגות

עוגנים לגגות הם סוג של עוגנים ודומים מאוד לעוגנים בפני השטח שלמעלה. ההבדל הוא שאתם תספקו את הגובה מעל הגג ולא את הגובה מעל פני השטח.

יצירת עוגן על הגג באמצעות ה-API האסינכרוני החדש

העוגן לא יהיה מוכן מיד ויהיה צריך לפתור אותו.

כדי ליצור ולהציב עוגן על הגג, קוראים לפונקציה ArEarth_resolveAnchorOnRooftopAsync(). בדומה לעוגנים של פני השטח, תהיה לך גם גישה ל-ArFutureState של העתיד. לאחר מכן אפשר לבדוק את התוצאה העתידית כדי לגשת אל ArRooftopAnchorState.

משתמשים ב-ArEarth_resolveAnchorOnRooftopAsync() כדי ליצור ArResolveAnchorOnRooftopFuture.

בודקים את מצב העוגן על הגג באמצעות ArResolveAnchorOnRooftopFuture_getResultRooftopAnchorState().

כדי לקבל את העוגן שטופל, משתמשים ב-ArResolveAnchorOnRooftopFuture_acquireResultAnchor().

float eus_quaternion_4[4] = {qx, qy, qz, qw};
void* context = NULL;
ArResolveAnchorOnRooftopCallback callback = NULL;
ArResolveAnchorOnRooftopFuture* future = NULL;
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArStatus status = ArEarth_resolveAnchorOnRooftopAsync(
        ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude_above_rooftop, eus_quaternion_4,
        context, callback, &future);
  }
}

מה יהיה העתיד?

לעתיד משויך ArFutureState. אתם יכולים לעיין בטבלה שלמעלה.

בדיקת מצב העוגן בגג של התוצאה העתידית

ArRooftopAnchorState שייך לפעולה האסינכרונית והוא חלק מהתוצאה העתידית הסופית.

switch (rooftop_anchor_state) {
  case AR_ROOFTOP_ANCHOR_STATE_SUCCESS:
    // A resolving task for this anchor has been successfully resolved.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the
    // Geospatial API.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/c/group/ar-anchor#:~:text=from%20this%20error.-,AR_ROOFTOP_ANCHOR_STATE_ERROR_NOT_AUTHORIZED,-The%20authorization%20provided
    // for troubleshooting steps.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_INTERNAL:
    // The Rooftop anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

המאמרים הבאים