Jetpack XR용 ARCore로 앵커 만들기

적용 가능한 XR 기기
이 가이드에서는 이러한 유형의 XR 기기를 위한 환경을 빌드하는 방법을 설명합니다.
XR 헤드셋
유선 XR 안경

앵커 는 실제 세계의 위치와 방향을 설명합니다. 객체를 앵커에 연결하면 객체가 실제 세계에 현실적으로 배치된 것처럼 보이고 앱이 매 프레임마다 로직을 실행하지 않아도 되므로 전원을 절약할 수 있습니다.

세션 액세스

Jetpack XR용 ARCore Session을 통해 앵커를 만듭니다. Jetpack Compose for XR을 사용하여 공간 UI를 개선하는 경우 Jetpack Compose for XR에서 세션에 액세스합니다. Jetpack SceneCore 라이브러리의 공간화된 항목 으로 작업하는 경우 Jetpack XR Runtime에서 세션에 액세스합니다.

세션 구성

앵커를 만들고 로드하는 데 세션을 구성할 필요는 없습니다. 하지만 앵커 지속성은 XR 세션에서 기본적으로 사용 설정되지 않습니다. 로컬 스토리지에서 앵커를 유지하고 로드하려면 세션을 구성하고 AnchorPersistenceMode.LOCAL 모드를 설정합니다.

val newConfig = Config.Builder(session.config)
    .setAnchorPersistence(AnchorPersistenceMode.LOCAL)
    .build()
when (val result = session.configure(newConfig)) {
    is SessionConfigureSuccess -> TODO(/* Success! */)
    else ->
        TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}

공간의 위치에 콘텐츠 앵커링

앵커는 기존 Anchorable을 기준으로 해석하거나 세계에 고정할 수 있는 Pose를 사용하여 만들어집니다. Anchorable은 앵커를 연결할 수 있는 Trackable입니다.

Anchorable을 기준으로 앵커 만들기

Plane과 같은 Anchorable을 기준으로 앵커를 만들면 앵커가 공간을 이동할 때 연결된 Anchorable을 따릅니다.

val anchor = plane.createAnchor(pose)

세계에 고정된 앵커 만들기

세계에 고정된 앵커를 만들려면 Anchorable에 연결하지 마세요. 이러한 유형의 앵커는 공간에 떠 있는 점에만 사용하세요. 세션의 움직일 수 없는 객체의 위치 추정치는 시간이 지남에 따라 변경되기 때문입니다.

val anchor = Anchor.create(session, pose)

앵커에 항목 연결

이 위치에서 모델을 렌더링하려면 create a GltfModel을 만들고 상위를 AnchorSpace로 설정합니다.

AnchorSpace.create(session, anchor).apply {
    parent = session.scene.activitySpace
    addChild(entity)
}

TrackingState 이해

Trackable에는 사용하기 전에 확인해야 하는 TrackingState가 있습니다. TrackableStateTrackingTrackablePose는 시스템에서 적극적으로 업데이트됩니다. PausedTrackable은 나중에 Tracking이 될 수 있지만 Stopped된 은 절대 Tracking이 되지 않습니다.

세션 전반에서 앵커 유지

유지되지 않은 앵커는 세션이 소멸된 후 사라집니다. 앵커를 유지하면 앱이 비공개 앱 데이터에서 앵커의 위치를 기억합니다. 이 앵커는 후속 세션에서 검색할 수 있으며 세계의 동일한 위치에 앵커링됩니다.

앵커를 유지하려면 여기에 표시된 대로 Anchor.persist()를 사용합니다.

val uuid = anchor.persist()

앱은 향후 세션에서 UUID를 사용하여 앵커를 검색할 수 있습니다.

when (val result = Anchor.load(session, uuid)) {
    is AnchorCreateSuccess -> {
        // Loading was successful. The anchor is stored in result.anchor.
    }
    else -> {
        // handle failure
    }
}

더 이상 앵커가 필요하지 않으면 unpersist()를 호출합니다. 이렇게 하면 앱의 스토리지에서 앵커가 삭제되고 지정된 UUID를 Anchor.load() 호출에 사용할 수 없게 됩니다.

Anchor.unpersist(session, uuid)

앱은 앱의 스토리지에 아직 있는 유지된 모든 앵커의 목록을 요청할 수도 있습니다.

val uuids = Anchor.getPersistedAnchorUuids(session)