XR_EXT_spatial_anchor
이름 문자열
XR_EXT_spatial_anchor
확장 프로그램 유형
인스턴스 확장 프로그램
등록된 확장 프로그램 번호
763
버전
1
비준 상태
비준됨
확장 프로그램 및 버전 종속 항목
XR_EXT_spatial_entity
도움을 주신 분들
Nihav Jain, Google
Natalie Fleury, Meta
Yuichi Taguchi, Meta
Ron Bessems, Meta
Yin Li, Microsoft
Jimmy Alamparambil, ByteDance
Zhipeng Liu, ByteDance
Jun Yan, ByteDance
개요
이 확장 프로그램은 XR_EXT_spatial_entity를 기반으로 하며 애플리케이션이 공간 앵커를 만들 수 있도록 합니다. 공간 앵커는 사용자의 실제 환경에서 임의의 점이며 런타임에서 추적합니다. 그런 다음 런타임은 다른 모든 공간 및 앵커와 독립적으로 필요에 따라 시간이 지남에 따라 앵커 원점의 위치와 방향을 조정하여 실제 세계에 대한 원래 매핑을 유지해야 합니다should.
XrSpatialContextEXT 내에서 지정된 위치와 방향을 추적하는 앵커는 구성요소가 있는 (또는 '포함하는') 공간 항목으로 표시됩니다.XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
앵커 사용의 이점
XrSpatialContextEXT의 수명 동안 런타임의 사용자 실제 환경 이해가 업데이트됨에 따라 가상 객체가 애플리케이션에서 배치된 위치에서 벗어나는 것처럼 보일 수 있으며, 이는 애플리케이션의 사실성과 사용자 환경의 품질에 영향을 미칩니다. 가상 객체가 배치된 위치에 가까운 앵커를 만들고 항상 앵커를 기준으로 가상 객체를 렌더링하면 애플리케이션은 각 가상 객체가 실제 환경에서 동일한 위치와 방향을 유지하도록 할 수 있습니다can. 또한 특정 참조 공간과 달리 앵커는 시스템 수준의 재중심화에 영향을 받지 않습니다.
런타임 지원
런타임이 공간 앵커를 지원하는 경우 이를 나타내야 합니다(MUST). XR_SPATIAL_CAPABILITY_ANCHOR_EXT에서 xrEnumerateSpatialCapabilitiesEXT를 열거하여 이를 나타내야 합니다.
구성
XrSpatialCapabilityConfigurationAnchorEXT 구조는 다음과 같이 정의됩니다.
typedef struct XrSpatialCapabilityConfigurationAnchorEXT {
XrStructureType type;
const void* next;
XrSpatialCapabilityEXT capability;
uint32_t enabledComponentCount;
const XrSpatialComponentTypeEXT* enabledComponents;
} XrSpatialCapabilityConfigurationAnchorEXT;
회원 설명
type은 이 구조의 XrStructureType입니다.next는NULL이거나 구조 체인의 다음 구조를 가리키는 포인터입니다.capability는 XrSpatialCapabilityEXT입니다 .enabledComponentCount는enabledComponents배열의 요소 수를 설명하는uint32_t입니다.enabledComponents는 XrSpatialComponentTypeEXT 배열을 가리키는 포인터입니다 .
애플리케이션은 XrSpatialContextCreateInfoEXT :: capabilityConfigs에 XrSpatialCapabilityConfigurationAnchorEXT 구조를 가리키는 포인터를 포함하여 XR_SPATIAL_CAPABILITY_ANCHOR_EXT 공간 기능을 사용 설정할 수 있습니다(CAN).
런타임은 해야 합니다(MUST) XR_ERROR_VALIDATION_FAILURE를 반환합니다. capability가 XR_SPATIAL_CAPABILITY_ANCHOR_EXT가 아닌 경우
유효한 사용 (암시적)
-
XR_EXT_spatial_anchor확장 프로그램을 사용하기 전에 XrSpatialCapabilityConfigurationAnchorEXT를 사용 설정해야 합니다(MUST). -
type여야 합니다(MUST)XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT -
nextnext는NULL이거나 구조 체인의 다음 구조를 가리키는 유효한 포인터여야 합니다(MUST). -
capability는 유효한 XrSpatialCapabilityEXT 값이어야 합니다(MUST) -
enabledComponents는enabledComponentCount유효한 XrSpatialComponentTypeEXT 값의 배열을 가리키는 포인터여야 합니다(MUST). -
enabledComponentCount매개변수는 해야 합니다보다 커야 합니다.0
보장된 구성요소
XR_SPATIAL_CAPABILITY_ANCHOR_EXT를 지원하는 런타임은 이 기능으로 생성되거나 검색된 모든 항목의 보장된 구성요소로 다음 공간 구성요소를 제공해야 하며(MUST) xrEnumerateSpatialCapabilityComponentTypesEXT에서 이를 열거해야 합니다(MUST).
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
앵커 구성요소
구성요소 데이터
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT는 앵커의 위치와 방향을 제공하는 데이터에 XrPosef를 사용합니다.
데이터를 쿼리하는 구성요소 목록 구조
XrSpatialComponentAnchorListEXT 구조는 다음과 같이 정의됩니다.
typedef struct XrSpatialComponentAnchorListEXT {
XrStructureType type;
void* next;
uint32_t locationCount;
XrPosef* locations;
} XrSpatialComponentAnchorListEXT;
회원 설명
type은 이 구조의 XrStructureType입니다.next는NULL이거나 구조 체인의 다음 구조를 가리키는 포인터입니다.locationCount는locations배열의 요소 수를 설명하는uint32_t입니다.locations는 XrPosef 배열입니다 .
XrSpatialComponentAnchorListEXT가 XrSpatialComponentDataQueryResultEXT :: `next` 체인에 있지만 `XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT`가 XrSpatialComponentDataQueryConditionEXT :: `componentTypes`에 포함되지 않은 경우 런타임은 xrQuerySpatialComponentDataEXT에서 `XR_ERROR_VALIDATION_FAILURE`를 반환해야 합니다(MUST).XR_ERROR_VALIDATION_FAILUREnextXR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXTcomponentTypes
locationCount가 XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput보다 작은 경우 런타임은 xrQuerySpatialComponentDataEXT에서 XR_ERROR_SIZE_INSUFFICIENT를 반환해야 합니다(MUST).
유효한 사용 (암시적)
- XrSpatialComponentAnchorListEXT를 사용하기 전에
XR_EXT_spatial_anchor확장 프로그램을 사용 설정해야 합니다(MUST). -
type여야 합니다(MUST)XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT -
nextnext는NULL이거나 구조 체인의 다음 구조를 가리키는 유효한 포인터여야 합니다(MUST). -
locations는locationCountXrPosef 구조의 배열을 가리키는 포인터여야 합니다(MUST) -
locationCount매개변수는 해야 합니다보다 큽니다0
구성
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT가 일부 기능의 XrSpatialCapabilityComponentTypesEXT :: componentTypes에 열거된 경우 애플리케이션은 이 구성요소를 지원하는 기능의 XrSpatialCapabilityConfigurationBaseHeaderEXT 파생 구조의 XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents 목록에 열거자를 포함하여 이를 사용 설정할 수 있습니다(CAN).
이 구성요소는 XrSpatialCapabilityConfigurationBaseHeaderEXT :: next 체인에 포함되기 위해 특별한 구성을 필요로 하지 않습니다.
공간 앵커 만들기
xrCreateSpatialAnchorEXT 함수는 다음과 같이 정의됩니다.
XrResult xrCreateSpatialAnchorEXT(
XrSpatialContextEXT spatialContext,
const XrSpatialAnchorCreateInfoEXT* createInfo,
XrSpatialEntityIdEXT* anchorEntityId,
XrSpatialEntityEXT* anchorEntity);
파라미터 설명
spatialContext는 이전에 xrCreateSpatialContextAsyncEXT를 사용하여 만든 XrSpatialContextEXT입니다 .createInfo는 XrSpatialAnchorCreateInfoEXT를 가리키는 포인터입니다 .anchorEntityId는 앵커 항목의 ID가 반환되는XrSpatialEntityIdEXT를 가리키는 포인터입니다.anchorEntity는 앵커 항목의 핸들이 반환되는 XrSpatialEntityEXT를 가리키는 포인터입니다.
애플리케이션은 xrCreateSpatialAnchorEXT를 사용하여 공간 앵커를 만들 수 있습니다(CAN).
앵커의 업데이트된 구성요소 데이터를 가져오려면 스냅샷을 만들 때 anchorEntity에 채워진 값을 XrSpatialUpdateSnapshotCreateInfoEXT :: entities에 전달합니다. 애플리케이션은 can anchorEntityId를 사용하여 XrSpatialComponentDataQueryResultEXT :: entityIds 배열에서 이 앵커를 xrQuerySpatialComponentDataEXT를 사용할 때 고유하게 식별할 수 있습니다 .
`spatialContext`에 `XR_SPATIAL_CAPABILITY_ANCHOR_EXT`가 구성되지 않은 경우 런타임은 `xrCreateSpatialAnchorEXT`에서 `XR_ERROR_VALIDATION_FAILURE`를 반환해야 합니다(MUST). 구성에서 XrSpatialContextEXT를 XR_SPATIAL_CAPABILITY_ANCHOR_EXT 기능에 맞게 구성하는 방법을 확인하세요.
anchorEntity로 표시되는 앵커는 spatialContext의 수명 동안 또는 애플리케이션이 xrDestroySpatialEntityEXT를 호출할 때까지(둘 중 더 빠른 시간 적용)만 유효합니다. 다른 확장 프로그램은 여러 XrSession에서 새로 만든 이 앵커를 유지하거나 프로세스 경계를 넘어 다른 애플리케이션과 공유하는 기능을 제공할 수 있습니다(MAY).
새로 만든 앵커는 삭제될 때까지 상위 공간 컨텍스트에서 검색할 수 있어야 합니다(MUST). 즉, 앵커가 XrSpatialDiscoverySnapshotCreateInfoEXT에 설정된 검색 기준과 일치하는 경우 런타임은 spatialContext에 xrCreateSpatialDiscoverySnapshotAsyncEXT를 사용하여 만든 스냅샷에 anchorEntityId를 포함해야 합니다(must) . 새로 만든 앵커는 다른 공간 컨텍스트에서도 검색할 수 있지만 , 특정 XrSpatialEntityIdEXT는 XrSpatialContextEXT에 고유하므로 다른 XrSpatialEntityIdEXT를 사용합니다.XR_SPATIAL_CAPABILITY_ANCHOR_EXT
유효한 사용 (암시적)
-
XR_EXT_spatial_anchor확장 프로그램을 사용 설정해야 xrCreateSpatialAnchorEXT를 호출할 수 있습니다(MUST). -
spatialContext는 유효한 XrSpatialContextEXT 핸들이어야 합니다(MUST). -
createInfo는 유효한 XrSpatialAnchorCreateInfoEXT 구조를 가리키는 포인터여야 합니다(MUST). -
anchorEntityId는XrSpatialEntityIdEXT값을 가리키는 포인터여야 합니다(MUST). -
anchorEntity는 XrSpatialEntityEXT 핸들을 가리키는 포인터여야 합니다(MUST).
반환 코드
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_POSE_INVALIDXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_TIME_INVALIDXR_ERROR_VALIDATION_FAILUREXR_ERROR_SPATIAL_ANCHOR_ATTACHABLE_COMPONENT_NOT_FOUND_ANDROID(XR_ANDROID_spatial_entity_bound_anchor가 사용 설정된 경우)XR_ERROR_SPATIAL_ENTITY_ID_INVALID_EXT(XR_ANDROID_spatial_entity_bound_anchor가 사용 설정된 경우)
XrSpatialAnchorCreateInfoEXT 구조는 다음과 같이 정의됩니다.
typedef struct XrSpatialAnchorCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
XrPosef pose;
} XrSpatialAnchorCreateInfoEXT;
회원 설명
type은 이 구조의 XrStructureType입니다.next는NULL이거나 구조 체인의 다음 구조를 가리키는 포인터입니다.baseSpace는 XrSpace에서pose가 적용됩니다.time은baseSpace가 있는XrTime(및pose가 적용되는XrTime)입니다.pose는 앵커 항목의 위치입니다.
유효한 사용 (암시적)
-
XR_EXT_spatial_anchor확장 프로그램을 사용하기 전에 XrSpatialAnchorCreateInfoEXT를 사용 설정해야 합니다(MUST). -
type은(는)XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT여야 합니다(MUST). -
nextnext는NULL이거나 구조 체인의 다음 구조를 가리키는 유효한 포인터여야 합니다 . XrSpatialAnchorParentANDROID도 참고하세요. -
baseSpace는 유효한 XrSpace 핸들이어야 합니다(MUST)
앵커 포즈 쿼리
앵커가 생성된 후 런타임은 앵커를 초기화하는 데 사용된 원래 XrSpatialAnchorCreateInfoEXT :: baseSpace와의 관계를 변경하더라도 원래 실제 위치에 최대한 정렬을 유지하기 위해 시간이 지남에 따라 다른 공간을 기준으로 위치와 방향을 조정해야 합니다(SHOULD).
애플리케이션은 앵커의 XrSpatialEntityEXT와 함께 xrCreateSpatialUpdateSnapshotEXT를 사용하여 새 XrSpatialSnapshotEXT를 만든 다음 xrQuerySpatialComponentDataEXT를 사용하여 해당 스냅샷에서 XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT 구성요소를 쿼리할 수 있습니다(CAN). 애플리케이션은 XrSpatialComponentAnchorListEXT를 XrSpatialComponentDataQueryResultEXT :: next에 추가하여 앵커의 최신 위치 데이터를 가져올 수 있습니다(CAN).
런타임은 새로 만든 앵커의 추적 상태를 XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT로 설정할 수 있습니다(MAY) . 애플리케이션은 추적 상태가 XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT인 경우에만 XrSpatialComponentDataQueryResultEXT :: entityStates에 제공된 앵커 항목의 상태와 항목의 앵커 구성요소 데이터를 읽어야 합니다(MUST).
앵커 사용 가이드라인
- 각 앵커의 포즈는 다른 앵커나 공간과 독립적으로 조정됩니다. 별도로 고정된 가상 객체는 서로에 대해 이동하거나 회전할 수 있으며, 이러한 가상 객체가 서로에 대해 제자리에 있어야 하는 경우 공간 계층 구조를 손상시킵니다. 이러한 경우 애플리케이션은 서로에 대해 이동하지 않는 모든 가상 객체에 동일한 앵커를 재사용해야 합니다(SHOULD).
- 애플리케이션은 더 이상 사용되지 않는 앵커의 XrSpatialEntityEXT 핸들을 삭제하여 런타임이 이러한 앵커를 추적하는 데 사용할 수 있는 리소스를 확보해야 합니다(SHOULD).
예제 코드
앵커 기능 구성
다음 예에서는 공간 컨텍스트를 만들 때 앵커 기능을 구성하는 방법을 보여줍니다.
// Create a spatial spatial context
XrSpatialContextEXT spatialContext{};
{
std::vector<XrSpatialComponentTypeEXT> enabledComponents = {
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT,
};
XrSpatialCapabilityConfigurationAnchorEXT anchorConfig{XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT};
anchorConfig.capability = XR_SPATIAL_CAPABILITY_ANCHOR_EXT;
anchorConfig.enabledComponentCount = enabledComponents.size();
anchorConfig.enabledComponents = enabledComponents.data();
std::array<XrSpatialCapabilityConfigurationBaseHeaderEXT*, 1> capabilityConfigs = {
reinterpret_cast<XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&anchorConfig),
};
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;
}
// ...
// Create spatial anchors and get their latest pose in the frame loop.
// ...
CHK_XR(xrDestroySpatialContextEXT(spatialContext));
공간 앵커 만들기 및 위치 가져오기
다음 예에서는 공간 앵커를 만들고 모든 프레임에서 포즈를 가져오는 방법을 보여줍니다.
XrSpatialAnchorCreateInfoEXT createInfo{XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXT};
createInfo.baseSpace = localSpace;
createInfo.time = predictedDisplayTime;
createInfo.pose = {{0, 0, 0, 1}, {1, 1, 1}};
XrSpatialEntityIdEXT spatialAnchorEntityId;
XrSpatialEntityEXT spatialAnchorEntity;
CHK_XR(xrCreateSpatialAnchorEXT(spatialContext, &createInfo, &spatialAnchorEntityId, &spatialAnchorEntity));
auto updateAnchorLocation = [&](XrTime time) {
// We want to get updated data for all components of the entities, so skip specifying componentTypes.
XrSpatialUpdateSnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_UPDATE_SNAPSHOT_CREATE_INFO_EXT};
snapshotCreateInfo.entityCount = 1;
snapshotCreateInfo.entities = &spatialAnchorEntity;
snapshotCreateInfo.baseSpace = localSpace;
snapshotCreateInfo.time = time;
XrSpatialSnapshotEXT snapshot;
CHK_XR(xrCreateSpatialUpdateSnapshotEXT(spatialContext, &snapshotCreateInfo, &snapshot));
// Query for the entities that have the anchor component on them.
std::array<XrSpatialComponentTypeEXT, 1> componentsToQuery {XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT};
XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
queryCond.componentTypeCount = componentsToQuery.size();
queryCond.componentTypes = componentsToQuery.data();
XrSpatialComponentDataQueryResultEXT queryResult{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT};
CHK_XR(xrQuerySpatialComponentDataEXT(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();
// query for the pose data
std::vector<XrPosef> locations(queryResult.entityIdCountOutput);
XrSpatialComponentAnchorListEXT locationList{XR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT};
locationList.locationCount = locations.size();
locationList.locations = locations.data();
queryResult.next = &locationList;
CHK_XR(xrQuerySpatialComponentDataEXT(snapshot, &queryCond, &queryResult));
for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
if (entityStates[i] == XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT) {
// Pose for entity entityIds[i] is locations[i].
}
}
CHK_XR(xrDestroySpatialSnapshotEXT(snapshot));
};
while (1) {
// ...
// For every frame in frame loop
// ...
XrFrameState frameState; // previously returned from xrWaitFrame
const XrTime time = frameState.predictedDisplayTime;
updateAnchorLocation(time);
// ...
// Finish frame loop
// ...
}
CHK_XR(xrDestroySpatialEntityEXT(spatialAnchorEntity));
새 명령어
새 구조
새 열거형 상수
XR_EXT_SPATIAL_ANCHOR_EXTENSION_NAMEXR_EXT_spatial_anchor_SPEC_VERSION-
XR_SPATIAL_CAPABILITY_ANCHOR_EXT
XrSpatialComponentTypeEXT 확장 :
XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT
XrStructureType 확장 :
XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_EXTXR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXTXR_TYPE_SPATIAL_COMPONENT_ANCHOR_LIST_EXT
문제
xrCreateSpatialAnchorEXT가 항목 핸들뿐만 아니라 항목 ID도 출력하는 이유는 무엇인가요?
- 해결됨
- 답변: xrCreateSpatialAnchorEXT 함수는 항목 ID만 출력으로 제공할 수 있으며 애플리케이션은 xrCreateSpatialEntityFromIdEXT를 사용하여 해당 ID의 항목 핸들을 만들 수 있습니다 . 그러나 애플리케이션이 모든 프레임에서 앵커 포즈를 쿼리하는 앵커의 일반적인 사용을 고려할 때 항목 핸들을 입력으로 요구하는 '스냅샷 업데이트'에 사용하기에 적합한 후보가 됩니다. 이 일반적인 사용 사례를 예상하여 xrCreateSpatialAnchorEXT는 애플리케이션을 대신하여 xrCreateSpatialEntityFromIdEXT를 실행하고 xrCreateSpatialUpdateSnapshotEXT와 함께 사용할 항목 핸들을 제공합니다 .
버전 기록
버전 1, 2024-07-10 (Nihav Jain, Google)
- 초기 확장 프로그램 설명