XR_EXT_spatial_marker_tracking

מחרוזת שם

XR_EXT_spatial_marker_tracking

סוג התוסף

תוסף למכונה

מספר השלוחה הרשום

744

גרסה

1

סטטוס האישור

אושר

תלויות של תוספים וגרסאות

XR_EXT_spatial_entity

שותפים ביצירת התוכן

רון בסמס, Meta
ניהב ג'יין, Google
נטלי פלורי, Meta
יויצ'י טגוצ'י, Meta
יין לי, Microsoft
ג'ימי אלמפרמביל, ByteDance
ז'יפנג ליו, ByteDance
ג'ון יאן, ByteDance

סקירה כללית

התוסף הזה מבוסס על XR_EXT_spatial_entity ומאפשר לאפליקציות לזהות סמנים בסביבה שלהן ולעקוב אחריהם. סמנים הם קודים דו-ממדיים שיכולים לכלול קודי QR, קודי Micro QR, סמני ArUco או AprilTags.

סמן למעקב מיוצג כישות מרחבית עם הרכיבים הבאים:

  • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT

תמיכה בסביבת זמן ריצה

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

  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT
  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT
  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT
  • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT

הגדרות אישיות

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

הגדרות של סוגי סמנים

קודי QR

המבנה של XrSpatialCapabilityConfigurationQrCodeEXT מוגדר כך:

typedef struct XrSpatialCapabilityConfigurationQrCodeEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
} XrSpatialCapabilityConfigurationQrCodeEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • capability חייב להיות XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT .
  • ‫enabledComponentCount הוא uint32_t עם מספר הרכיבים ב-enabledComponents .
  • ‫enabledComponents הוא מצביע למערך של רכיבים שצריך להפעיל בשביל היכולת הזו.

אם יש תמיכה בקודי QR, סביבת זמן הריצה חייבת להפעיל מעקב אחרי קודי QR כשמבנה XrSpatialCapabilityConfigurationQrCodeEXT מועבר ב-XrSpatialContextCreateInfoEXT :: capabilityConfigs כשמתבצעת קריאה ל-xrCreateSpatialContextAsyncEXT .

זמן הריצה חייב להחזיר את הערך XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT אם XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT לא מופיע ברשימה של xrEnumerateSpatialCapabilitiesEXT .

שימוש תקין (משתמע)

קודי Micro QR

המבנה של XrSpatialCapabilityConfigurationMicroQrCodeEXT מוגדר כך:

typedef struct XrSpatialCapabilityConfigurationMicroQrCodeEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
} XrSpatialCapabilityConfigurationMicroQrCodeEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • capability חייב להיות XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT .
  • ‫enabledComponentCount הוא uint32_t עם מספר הרכיבים ב-enabledComponents .
  • ‫enabledComponents הוא מצביע למערך של רכיבים שצריך להפעיל בשביל היכולת הזו.

אם יש תמיכה בקודי Micro QR, סביבת זמן הריצה חייבת להפעיל מעקב אחר קודי Micro QR כשמבנה XrSpatialCapabilityConfigurationMicroQrCodeEXT מועבר ב-XrSpatialContextCreateInfoEXT :: capabilityConfigs כשמתבצעת קריאה ל-xrCreateSpatialContextAsyncEXT .

זמן הריצה חייב להחזיר את הערך XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT אם XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT לא מופיע ברשימה של xrEnumerateSpatialCapabilitiesEXT .

שימוש תקין (משתמע)

סמני ArUco

המבנה של XrSpatialCapabilityConfigurationArucoMarkerEXT מוגדר כך:

typedef struct XrSpatialCapabilityConfigurationArucoMarkerEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
    XrSpatialMarkerArucoDictEXT         arUcoDict;
} XrSpatialCapabilityConfigurationArucoMarkerEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • capability חייב להיות XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT .
  • ‫enabledComponentCount הוא uint32_t עם מספר הרכיבים ב-enabledComponents .
  • ‫enabledComponents הוא מצביע למערך של רכיבים שצריך להפעיל בשביל היכולת הזו.
  • ‫arUcoDict הוא מילון הסמנים לזיהוי.

אם יש תמיכה בסמני ArUco, סביבת זמן הריצה חייבת להפעיל מעקב אחר סמני ArUco כשמבנה XrSpatialCapabilityConfigurationArucoMarkerEXT מועבר ב-XrSpatialContextCreateInfoEXT :: capabilityConfigs כשמתבצעת קריאה ל-xrCreateSpatialContextAsyncEXT .

זמן הריצה חייב להחזיר את XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT מ-xrCreateSpatialContextAsyncEXT אם מבנה XrSpatialCapabilityConfigurationArucoMarkerEXT נמצא ב-XrSpatialContextCreateInfoEXT :: capabilityConfigs אבל XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT לא מופיע ברשימה של xrEnumerateSpatialCapabilitiesEXT .

שימוש תקין (משתמע)

הערך של XrSpatialMarkerArucoDictEXT מוגדר כך:

typedef enum XrSpatialMarkerArucoDictEXT {
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_50_EXT = 1,
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT = 2,
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT = 3,
    XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT = 4,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT = 5,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT = 6,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT = 7,
    XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT = 8,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT = 9,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT = 10,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT = 11,
    XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT = 12,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT = 13,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT = 14,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT = 15,
    XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT = 16,
    XR_SPATIAL_MARKER_ARUCO_DICT_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialMarkerArucoDictEXT;

מילון ArUco נתמך שהוגדר מראש:

תיאורי ערכים מספריים

  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_4X4_50_EXT – מילון סמני Aruco בגודל 4 על 4 פיקסלים עם 50 מזהים.
  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_4X4_100_EXT — מילון סמני Aruco בגודל 4 על 4 פיקסלים עם 100 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_250_EXT – מילון סמני Aruco בגודל 4 על 4 פיקסלים עם 250 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_4X4_1000_EXT — מילון סמני Aruco בגודל 4 על 4 פיקסלים עם 1,000 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT — מילון סמני Aruco בגודל 5 על 5 פיקסלים עם 50 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_100_EXT — מילון סמני Aruco בגודל 5 על 5 פיקסלים עם 100 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_250_EXT — מילון סמני Aruco בגודל 5 על 5 פיקסלים עם 250 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_5X5_1000_EXT — מילון סמני Aruco בגודל 5 על 5 פיקסלים עם 1,000 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_50_EXT – מילון של סמני Aruco בגודל 6 על 6 פיקסלים עם 50 מזהים.
  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_6X6_100_EXT – מילון סמני Aruco בגודל 6 על 6 פיקסלים עם 100 מזהים.
  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_6X6_250_EXT – מילון סמני Aruco בגודל 6 על 6 פיקסלים עם 250 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_6X6_1000_EXT — מילון סמני Aruco בגודל 6 על 6 פיקסלים עם 1,000 מזהים.
  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_7X7_50_EXT – מילון סמני Aruco בגודל 7 על 7 פיקסלים עם 50 מזהים.
  • XR_SPATIAL_MARKER_ARUCO_DICT_7X7_100_EXT – מילון של סמני Aruco בגודל 7 על 7 פיקסלים עם 100 מזהים.
  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_7X7_250_EXT – מילון סמני Aruco בגודל 7 על 7 פיקסלים עם 250 מזהים.
  • ‫XR_SPATIAL_MARKER_ARUCO_DICT_7X7_1000_EXT – מילון סמני Aruco בגודל 7 על 7 פיקסלים עם 1,000 מזהים.
AprilTags

המבנה של XrSpatialCapabilityConfigurationAprilTagEXT מוגדר כך:

typedef struct XrSpatialCapabilityConfigurationAprilTagEXT {
    XrStructureType                     type;
    const void*                         next;
    XrSpatialCapabilityEXT              capability;
    uint32_t                            enabledComponentCount;
    const XrSpatialComponentTypeEXT*    enabledComponents;
    XrSpatialMarkerAprilTagDictEXT      aprilDict;
} XrSpatialCapabilityConfigurationAprilTagEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • capability חייב להיות XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT .
  • ‫enabledComponentCount הוא uint32_t עם מספר הרכיבים ב-enabledComponents .
  • ‫enabledComponents הוא מצביע למערך של רכיבים שצריך להפעיל בשביל היכולת הזו.
  • ‫aprilDict הוא מילון הסמנים לזיהוי.

אם יש תמיכה ב-AprilTags, סביבת זמן הריצה חייבת להפעיל מעקב של AprilTag כשמבנה XrSpatialCapabilityConfigurationAprilTagEXT מועבר ב-XrSpatialContextCreateInfoEXT :: capabilityConfigs כשמתבצעת קריאה ל-xrCreateSpatialContextAsyncEXT .

זמן הריצה חייב להחזיר את XR_ERROR_SPATIAL_CAPABILITY_UNSUPPORTED_EXT מ-xrCreateSpatialContextAsyncEXT אם מבנה XrSpatialCapabilityConfigurationAprilTagEXT נמצא ב-XrSpatialContextCreateInfoEXT :: capabilityConfigs אבל XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT לא מופיע ברשימה של xrEnumerateSpatialCapabilitiesEXT .

שימוש תקין (משתמע)

הספירה XrSpatialMarkerAprilTagDictEXT מוגדרת כך:

typedef enum XrSpatialMarkerAprilTagDictEXT {
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_16H5_EXT = 1,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT = 2,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT = 3,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT = 4,
    XR_SPATIAL_MARKER_APRIL_TAG_DICT_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialMarkerAprilTagDictEXT;

מילון AprilTag מוגדר מראש שנתמך:

תיאורי ערכים מספריים

  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_16H5_EXT — 4 על 4 ביטים, מרחק המינג מינימלי בין כל שני קודים = 5, 30 קודים.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_25H9_EXT — 5 על 5 ביטים, מרחק המינג מינימלי בין כל שני קודים = 9, 35 קודים.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H10_EXT — 6 על 6 ביטים, מרחק המינג מינימלי בין כל שני קודים = 10, 2,320 קודים.
  • XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT — 6 על 6 ביטים, מרחק המינג מינימלי בין כל שני קודים = 11, 587 קודים.

הגדרות אופציונליות של סמנים

האפליקציות צריכות להפעיל את xrEnumerateSpatialCapabilityFeaturesEXT כדי לקבל את רשימת התכונות האופציונליות הנתמכות.

במאמר XrSpatialCapabilityFeatureEXT מופיעה רשימה מלאה של כל תכונות היכולות המרחביות שנתמכות על ידי כל תוסף.

גודל הסמן

המבנה של XrSpatialMarkerSizeEXT מוגדר כך:

typedef struct XrSpatialMarkerSizeEXT {
    XrStructureType    type;
    const void*        next;
    float              markerSideLength;
} XrSpatialMarkerSizeEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • ‫markerSideLength הוא הגודל במטרים של כל הסמנים.

אם XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT נספר על ידי xrEnumerateSpatialCapabilityFeaturesEXT עבור יכולת מסוימת, ואם האפליקציה משרשרת את XrSpatialMarkerSizeEXT למבנה ההגדרה המתאים של היכולת הזו, זמן הריצה חייב להניח שלכל הסמנים שזוהו יש רוחב וגובה של markerSideLength . המידע הזה מאפשר לסביבת זמן הריצה להחזיר תנוחה וגודל מדויקים יותר. המבנה הזה חייב להיות מקושר לשרשרת next של XrSpatialCapabilityConfigurationQrCodeEXT,‏ XrSpatialCapabilityConfigurationMicroQrCodeEXT,‏ XrSpatialCapabilityConfigurationArucoMarkerEXT או XrSpatialCapabilityConfigurationAprilTagEXT .

שימוש תקין (משתמע)

אופטימיזציה של סמנים סטטיים

המבנה של XrSpatialMarkerStaticOptimizationEXT מוגדר כך:

typedef struct XrSpatialMarkerStaticOptimizationEXT {
    XrStructureType    type;
    const void*        next;
    XrBool32           optimizeForStaticMarker;
} XrSpatialMarkerStaticOptimizationEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים.
  • optimizeForStaticMarker מציין אם כל הסמנים במרחב לא אמורים לזוז.

אם XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT נספר על ידי xrEnumerateSpatialCapabilityFeaturesEXT עבור יכולת מסוימת, ואם האפליקציה משרשרת את XrSpatialMarkerStaticOptimizationEXT למבנה ההגדרה המתאים של היכולת הזו, זמן הריצה חייב להניח שכל הסמנים שזוהו הם סטטיים אם optimizeForStaticMarker מוגדר ל-XR_TRUE . כך סביבת זמן הריצה יכולה ליצור תנוחה וגודל מדויקים יותר. המבנה הזה חייב להיות מקושר לשרשרת next של XrSpatialCapabilityConfigurationQrCodeEXT,‏ XrSpatialCapabilityConfigurationMicroQrCodeEXT,‏ XrSpatialCapabilityConfigurationArucoMarkerEXT או XrSpatialCapabilityConfigurationAprilTagEXT .

שימוש תקין (משתמע)

רכיבים מובטחים

סביבת זמן ריצה שתומכת ב-XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT,‏ XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT,‏ XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT או XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT חייבת לספק את הרכיבים המרחביים הבאים כרכיבים מובטחים של כל הישויות שזוהו על ידי היכולות האלה, וחייבת למנות אותם ב-xrEnumerateSpatialCapabilityComponentTypesEXT :

  • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT

רכיב הסמן

נתוני רכיבים

המבנה של XrSpatialMarkerDataEXT מוגדר כך:

typedef struct XrSpatialMarkerDataEXT {
    XrSpatialCapabilityEXT    capability;
    uint32_t                  markerId;
    XrSpatialBufferEXT        data;
} XrSpatialMarkerDataEXT;

תיאורי חברים

  • ‫capability הוא ה-XrSpatialCapabilityEXT שזיהה את הסמן.
  • ‫markerId הוא המזהה המקודד מהסמן. בסמני ArUco וב-AprilTag, השדה הזה חייב להיות תקין ולכלול את המזהה המקודד. בקודי QR, הערך בשדה הזה חייב להיות אפס.
  • ‫data הוא מזהה המאגר וסוג המידע הנוסף שכלול בסמן.

‫XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT ו-XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT תומכים בנתונים נוספים. אם capability הוא אחד מהערכים הבאים:

  • אם סביבת זמן הריצה פענחה בהצלחה את הנתונים של הסמן, היא חייבת להגדיר את סוג המאגר data כ-XR_SPATIAL_BUFFER_TYPE_UINT8_EXT או כ-XR_SPATIAL_BUFFER_TYPE_STRING_EXT , בהתאם לנתונים בסמן. בנוסף, סביבת זמן הריצה חייבת להגדיר מזהה מאגר נתונים תקין ב-data, שבו האפליקציה יכולה להשתמש עם הפונקציה המתאימה של xrGetSpatialBuffer* כדי לקבל את הנתונים.
  • אם זמן הריצה עדיין לא פענח את נתוני הסמן, הוא חייב להגדיר את מזהה המאגר data ל-XR_NULL_SPATIAL_BUFFER_ID_EXT ואת סוג המאגר ל-XR_SPATIAL_BUFFER_TYPE_UNKNOWN_EXT .

‫XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT ו-XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT לא תומכים בנתונים נוספים, וזמן הריצה חייב להגדיר את מזהה המאגר של data ל-XR_NULL_SPATIAL_BUFFER_ID_EXT .

שימוש תקין (משתמע)

מבנה רשימת הרכיבים לשליפת נתונים

המבנה של XrSpatialComponentMarkerListEXT מוגדר כך:

typedef struct XrSpatialComponentMarkerListEXT {
    XrStructureType            type;
    void*                      next;
    uint32_t                   markerCount;
    XrSpatialMarkerDataEXT*    markers;
} XrSpatialComponentMarkerListEXT;

תיאורי חברים

  • ‫type הוא ה-XrStructureType של המבנה הזה.
  • ‫next הוא NULL או מצביע למבנה הבא בשרשרת מבנים. מבנים כאלה לא מוגדרים ב-OpenXR או בתוסף הזה.
  • ‫markerCount הוא מספר הרכיבים באיבר markers.
  • ‫markers הוא מערך של XrSpatialMarkerDataEXT .

האפליקציה יכולה לשלוח שאילתה לרכיב הסמן של הישויות המרחביות ב-XrSpatialSnapshotEXT על ידי הוספת XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT ב-XrSpatialComponentDataQueryConditionEXT :: componentTypes והוספת XrSpatialComponentMarkerListEXT לשרשרת המצביעים הבאה של XrSpatialComponentDataQueryResultEXT .

זמן הריצה חייב להחזיר את XR_ERROR_VALIDATION_FAILURE מ-xrQuerySpatialComponentDataEXT אם XrSpatialComponentMarkerListEXT נמצא בשרשרת הבאה של XrSpatialComponentDataQueryResultEXT :: next אבל XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT לא נכלל ב-XrSpatialComponentDataQueryConditionEXT :: componentTypes .

זמן הריצה חייב להחזיר את הערך XR_ERROR_SIZE_INSUFFICIENT מ-xrQuerySpatialComponentDataEXT אם markerCount קטן מ-XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .

שימוש תקין (משתמע)

  • חובה להפעיל את התוסף XR_EXT_spatial_marker_tracking לפני שמשתמשים ב-XrSpatialComponentMarkerListEXT
  • type חייב להיות XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT
  • next חייב להיות NULL או מצביע תקין למבנה הבא בשרשרת מבנים
  • ‫ markers חייב להיות מצביע למערך של מבני markerCount XrSpatialMarkerDataEXT
  • ‫ הפרמטר markerCount חייב להיות גדול מ-0
הגדרות אישיות

אם XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT מופיע ב-XrSpatialCapabilityComponentTypesEXT :: componentTypes עבור יכולת מסוימת, אפליקציה יכולה להפעיל אותה על ידי הכללת הערך ברשימה XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents של המבנה הנגזר XrSpatialCapabilityConfigurationBaseHeaderEXT של היכולת שתומכת ברכיב הזה.

הרכיב הזה לא דורש הגדרה מיוחדת כדי להיכלל בשרשרת XrSpatialCapabilityConfigurationBaseHeaderEXT :: next.

רכיב דו-ממדי מוגבל

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

השדה XrSpatialBounded2DDataEXT :: center חייב להצביע על מרכז הסמן. כשמסתכלים על החלק הקדמי של הסמן, ציר ה-X חייב לפנות ימינה וציר ה-Y חייב לפנות לחלק העליון של הסמן. זמן הריצה חייב לפעול לפי המוסכמה של מערכת הקואורדינטות הימנית, כך שציר ה-Z יוצא מהחלק הקדמי של הסמן. כלומר, סמן עם מיקום {0, 0, 0}, סיבוב {0, 0, 0, 1} (ללא סיבוב) וגודל {1, 1} מתייחס לסמן בגודל 1 מטר על 1 מטר שמרכזו ב-{0, 0, 0} והווקטור הנורמלי של החזית שלו מצביע לכיוון +Z במרחב של הרכיב.

בהמשך מוצג ייצוג של כיוון הסמן.

xr ml marker understanding axis

איור 25. סמן של קוד QR עם ציר

קודי בדיקה

הקודים הבאים חייבים להיות ממוקמים כך שמישור ה-X-Y שלהם נמצא בתוך המסמך וציר ה-Z פונה אל הצופה. ראשית הצירים חייבת להופיע במרכז של כל סמן. ציר ה-X חייב לפנות ימינה, וציר ה-Y חייב לפנות לחלק העליון של המסמך.

ext marker tracking qr

איור 26. קוד QR עם הטקסט "OpenXR"

ext marker tracking apriltag

איור 27. ‫AprilTag XR_SPATIAL_MARKER_APRIL_TAG_DICT_36H11_EXT עם מזהה 42

ext marker tracking aruco

איור 28. סמן ArUco XR_SPATIAL_MARKER_ARUCO_DICT_5X5_50_EXT עם מזהה 43

קוד לדוגמה

הגדרת יכולת המעקב אחרי קודי QR

הקוד לדוגמה הבא מדגים איך להגדיר את יכולת המעקב אחרי קוד QR כשיוצרים הקשר מרחבי.

// Check if marker tracking capability is supported
uint32_t capabilityCount;
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, 0, &capabilityCount, nullptr));
std::vector<XrSpatialCapabilityEXT> capabilities(capabilityCount);
CHK_XR(xrEnumerateSpatialCapabilitiesEXT(instance, systemId, capabilityCount, &capabilityCount, capabilities.data()));

if (std::find(capabilities.begin(), capabilities.end(), XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT) == capabilities.end()) {
  return;
}

uint32_t featureCount = 0;
CHK_XR(xrEnumerateSpatialCapabilityFeaturesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT, 0, &featureCount, nullptr));
std::vector<XrSpatialCapabilityFeatureEXT> capabilityFeatures(featureCount);
CHK_XR(xrEnumerateSpatialCapabilityFeaturesEXT(instance, systemId, XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT, featureCount, &featureCount, capabilityFeatures.data()));

bool supportsFixedMarkerSize = std::find(capabilityFeatures.begin(), capabilityFeatures.end(), XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT) != capabilityFeatures.end();

// Create a spatial context
XrSpatialContextEXT spatialContext{};

// Enable the 2 guaranteed components of the qr code tracking capability
std::vector<XrSpatialComponentTypeEXT> enabledComponents = {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,
};
XrSpatialCapabilityConfigurationQrCodeEXT markerConfiguration{XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_QR_CODE_EXT};
markerConfiguration.capability = XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT;
markerConfiguration.enabledComponentCount = static_cast<uint32_t>(enabledComponents.size());
markerConfiguration.enabledComponents = enabledComponents.data();

// only chained if features.markerSideLength is true.
XrSpatialMarkerSizeEXT markerSize{XR_TYPE_SPATIAL_MARKER_SIZE_EXT};
markerSize.markerSideLength = 0.10f;
if (supportsFixedMarkerSize) {
  markerConfiguration.next = &markerSize;
}


std::array<XrSpatialCapabilityConfigurationBaseHeaderEXT*, 1> capabilityConfigs = {
  reinterpret_cast<XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&markerConfiguration),
};

XrSpatialContextCreateInfoEXT spatialContextCreateInfo{XR_TYPE_SPATIAL_CONTEXT_CREATE_INFO_EXT};
spatialContextCreateInfo.capabilityConfigCount = capabilityConfigs.size();
spatialContextCreateInfo.capabilityConfigs = capabilityConfigs.data();
XrFutureEXT createContextFuture;
CHK_XR(xrCreateSpatialContextAsyncEXT(session, &spatialContextCreateInfo, &createContextFuture));

waitUntilReady(createContextFuture);

XrCreateSpatialContextCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_CONTEXT_COMPLETION_EXT};
CHK_XR(xrCreateSpatialContextCompleteEXT(session, createContextFuture, &completion));
if (completion.futureResult != XR_SUCCESS) {
  return;
}

spatialContext = completion.spatialContext;

// ...
// Discovery entities with the spatial context
// ...

CHK_XR(xrDestroySpatialContextEXT(spatialContext));

חיפוש ישויות מרחביות ושאילתות על נתוני רכיבים

הקוד לדוגמה הבא מדגים איך לגלות ישויות מרחביות בהקשר שמוגדר עם XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT ולשלוח שאילתה לנתוני הרכיבים שלו.

XrFutureEXT future = XR_NULL_FUTURE_EXT;

// We want to look for entities that have the following components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
  XR_SPATIAL_COMPONENT_TYPE_BOUNDED_2D_EXT,
  XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT,
};

auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
  XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
  snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
  snapshotCreateInfo.componentTypes = snapshotComponents.data();
  CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));

  waitUntilReady(future);

  XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT};
  completionInfo.baseSpace = localSpace;
  completionInfo.time = time;
  completionInfo.future = future;

  XrCreateSpatialDiscoverySnapshotCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
  CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
  if (completion.futureResult == XR_SUCCESS) {

    // Query for the bounded2D and marker component data
    XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
    queryCond.componentTypeCount = snapshotComponents.size();
    queryCond.componentTypes = snapshotComponents.data();

    XrSpatialComponentDataQueryResultEXT queryResult{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT};
    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    std::vector<XrSpatialEntityIdEXT> entityIds(queryResult.entityIdCountOutput);
    std::vector<XrSpatialEntityTrackingStateEXT> entityStates(queryResult.entityIdCountOutput);
    queryResult.entityIdCapacityInput = entityIds.size();
    queryResult.entityIds = entityIds.data();
    queryResult.entityStateCapacityInput = entityStates.size();
    queryResult.entityStates = entityStates.data();

    std::vector<XrSpatialBounded2DDataEXT> bounded2D(queryResult.entityIdCountOutput);
    XrSpatialComponentBounded2DListEXT bounded2DList{XR_TYPE_SPATIAL_COMPONENT_BOUNDED_2D_LIST_EXT};
    bounded2DList.boundCount = bounded2D.size();
    bounded2DList.bounds = bounded2D.data();
    queryResult.next = &bounded2DList;

    std::vector<XrSpatialMarkerDataEXT> markers;
    XrSpatialComponentMarkerListEXT markerList{XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT};
    markers.resize(queryResult.entityIdCountOutput);
    markerList.markerCount = markers.size();
    markerList.markers = markers.data();
    bounded2DList.next = &markerList;

    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
      if (entityStates[i] != XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT) {
        continue;
      }

      // 2D bounds for entity entityIds[i] is bounded2D[i].extents centered on bounded2D[i].center.

      if (markers[i].capability == XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT) {
        // Check if marker data has been decoded.
        if (markers[i].data.bufferId != XR_NULL_SPATIAL_BUFFER_ID_EXT) {
          if (markers[i].data.bufferType == XR_SPATIAL_BUFFER_TYPE_STRING_EXT) {
            // Qr Code data can be queried using
            // XrSpatialBufferGetInfoEXT getInfo{XR_TYPE_SPATIAL_BUFFER_GET_INFO_EXT};
            // info.bufferId = markers[i].data.bufferId;
            // xrGetSpatialBufferStringEXT(completion.snapshot, &getInfo, ...)
          } else if (markers[i].data.bufferType == XR_SPATIAL_BUFFER_TYPE_UINT8_EXT) {
            // Qr Code data can be queried using
            // XrSpatialBufferGetInfoEXT getInfo{XR_TYPE_SPATIAL_BUFFER_GET_INFO_EXT};
            // info.bufferId = markers[i].data.bufferId;
            // xrGetSpatialBufferUint8(completion.snapshot, &getInfo, ...)
          }
        }
      }
    }

    CHK_XR(xrDestroySpatialSnapshotEXT(completion.snapshot));
  }
};

while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  // Poll for the XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT event
  XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
  XrResult result = xrPollEvent(instance, &event);
  if (result == XR_SUCCESS) {
      switch (event.type) {
          case XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT: {
              const XrEventDataSpatialDiscoveryRecommendedEXT& eventdata =
                  *reinterpret_cast<XrEventDataSpatialDiscoveryRecommendedEXT*>(&event);
              // Discover spatial entities for the context that we received the "discovery
              // recommended" event for.
              discoverSpatialEntities(eventdata.spatialContext, time);
              break;
          }
      }
  }

  // ...
  // Finish frame loop
  // ...
}

מבנים חדשים

ערכי Enums חדשים

קבועי Enum חדשים

  • XR_EXT_SPATIAL_MARKER_TRACKING_EXTENSION_NAME
  • XR_EXT_spatial_marker_tracking_SPEC_VERSION
  • הרחבה של XrSpatialCapabilityEXT :

    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_APRIL_TAG_EXT
    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_ARUCO_MARKER_EXT
    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_MICRO_QR_CODE_EXT
    • XR_SPATIAL_CAPABILITY_MARKER_TRACKING_QR_CODE_EXT
  • הרחבה של XrSpatialCapabilityFeatureEXT :

    • XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_FIXED_SIZE_MARKERS_EXT
    • XR_SPATIAL_CAPABILITY_FEATURE_MARKER_TRACKING_STATIC_MARKERS_EXT
  • הרחבה של XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_MARKER_EXT
  • הרחבה של XrStructureType :

    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_APRIL_TAG_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ARUCO_MARKER_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_MICRO_QR_CODE_EXT
    • XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_QR_CODE_EXT
    • XR_TYPE_SPATIAL_COMPONENT_MARKER_LIST_EXT
    • XR_TYPE_SPATIAL_MARKER_SIZE_EXT
    • XR_TYPE_SPATIAL_MARKER_STATIC_OPTIMIZATION_EXT

היסטוריית הגרסאות

  • גרסה 1, 29 ביולי 2024 (רון בסמס, Meta)

    • תיאור התוסף הראשוני