Jetpack XR SDK를 사용하면 Jetpack SceneCore를 사용하여 3D 모델, 3D 동영상, PanelEntity
과 같은 Entity
인스턴스를 만들고 제어하고 관리할 수 있습니다.
Jetpack SceneCore는 3D 개발을 지원하기 위해 두 가지 일반적인 아키텍처 패턴, 즉 장면 그래프와 엔티티-구성요소 시스템 (ECS)을 채택합니다.
장면 그래프를 사용하여 엔티티 만들기 및 제어
3D 공간에서 객체를 만들고 제어하려면 Jetpack SceneCore의 Session API를 사용하여 장면 그래프에 액세스해야 합니다. 장면 그래프는 사용자의 실제 세계와 일치하며 패널 및 3D 모델과 같은 3D 항목을 계층 구조로 구성하고 이러한 항목의 상태를 유지할 수 있습니다.
장면 그래프에 액세스한 후 XR용 Jetpack Compose의 API를 사용하여 장면 그래프 내에 공간 UI (예: SpatialPanel
및 Orbiter
)를 만들 수 있습니다. 3D 모델과 같은 3D 콘텐츠의 경우 세션에 직접 액세스할 수 있습니다. 자세한 내용은 이 페이지의 ActivitySpace 정보를 참고하세요.
항목 구성요소 시스템
항목-구성요소 시스템은 상속보다 컴포지션의 원칙을 따릅니다. 동작 정의 구성요소를 연결하여 항목의 동작을 확장할 수 있으므로 동일한 동작을 여러 유형의 항목에 적용할 수 있습니다. 자세한 내용은 이 페이지의 항목에 공통 동작 추가를 참고하세요.
ActivitySpace 정보
각 Session
에는 Session
와 함께 자동으로 생성되는 ActivitySpace
가 있습니다. ActivitySpace
는 장면 그래프의 최상위 Entity
입니다.
ActivitySpace는 오른손잡이 좌표계 (x축은 오른쪽을, y축은 위쪽을, z축은 원점을 기준으로 뒤쪽을 가리킴)와 실제 세계와 일치하는 단위인 미터로 3차원 공간을 나타냅니다. ActivitySpace
의 원점은 다소 임의적입니다 (사용자가 실제 세계에서 ActivitySpace
의 위치를 재설정할 수 있음). 따라서 원점을 기준으로 하는 대신 콘텐츠를 서로 상대적으로 배치하는 것이 좋습니다.
항목 작업
항목은 SceneCore의 핵심입니다. 사용자가 보고 상호작용하는 대부분의 모든 것은 패널, 3D 모델 등을 나타내는 항목입니다.
ActivitySpace
는 장면 그래프의 최상위 노드이므로 기본적으로 모든 새 항목은 ActivitySpace
에 직접 배치됩니다. setParent
또는 addChild
를 호출하여 장면 그래프를 따라 항목을 재배치할 수 있습니다.
항목에는 위치, 회전, 표시 여부 변경과 같이 모든 항목에 공통적인 사항에 관한 몇 가지 기본 동작이 있습니다. GltfEntity
와 같은 특정 Entity
서브클래스에는 서브클래스를 지원하는 추가 동작이 있습니다.
항목 조작
기본 Entity
클래스에 속한 Entity
속성을 변경하면 변경사항이 모든 하위 요소로 계단식 방식으로 적용됩니다. 예를 들어 상위 요소 Entity
의 Pose
를 조정하면 모든 하위 요소가 동일하게 조정됩니다. 하위 Entity
를 변경해도 상위 요소에는 영향을 미치지 않습니다.
Pose
는 3D 공간 내에서 엔티티의 위치와 회전을 나타냅니다. 위치는 x, y, z 숫자 위치로 구성된 Vector3
입니다. 회전은 Quaternion
로 표현됩니다. Entity
의 위치는 항상 상위 항목을 기준으로 합니다. 즉, 위치가 (0,
0, 0)인 Entity
는 상위 항목의 원점에 배치됩니다.
//place the entity forward 2 meters
val modelPosition = Vector3(0f, 0f, -2f)
//rotate the entity by 180 degrees on the up axis (upside-down)
val newOrientation = Quaternion.fromEulerAngles(0f, 0f, 180f)
//update the position and rotation on the entity
entity.setPose(Pose(newPosition, newOrientation))
Entity
의 공개 상태를 변경하려면 setHidden
를 사용합니다.
//hide the entity
entity.setHidden(true)
전체 도형을 유지하면서 Entity
의 크기를 조절하려면 setScale
를 사용합니다.
//double the size of the entity
entity.setScale(2f)
항목에 공통 동작 추가
다음 구성요소를 사용하여 항목에 일반적인 동작을 추가할 수 있습니다.
MovableComponent
: 사용자가 항목을 이동할 수 있습니다.ResizableComponent
: 사용자가 일관된 UI 패턴으로 항목의 크기를 조절할 수 있습니다.InteractableComponent
: 맞춤 상호작용의 입력 이벤트를 캡처할 수 있습니다.
구성요소를 인스턴스화하려면 Session
클래스의 적절한 생성 메서드를 통해야 합니다. 예를 들어 ResizableComponent
를 만들려면 session.createResizableComponent()
를 호출합니다.
Entity
에 특정 구성요소 동작을 추가하려면 addComponent()
메서드를 사용하세요.
MovableComponent를 사용하여 엔티티를 사용자가 이동할 수 있도록 만들기
MovableComponent
를 사용하면 사용자가 Entity
를 이동할 수 있습니다. 또한 항목을 가로 또는 세로 표면과 같은 표면 유형이나 테이블, 벽, 천장과 같은 특정 시맨틱 표면에 고정할 수 있는지 지정할 수 있습니다. 앵커 옵션을 지정하려면 MovableComponent
를 만들 때 AnchorPlacement
집합을 지정합니다.
다음은 모든 수직 표면과 바닥 및 천장 수평 표면으로만 이동하고 고정할 수 있는 항목의 예입니다.
val anchorPlacement = AnchorPlacement.createForPlanes(
planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE),
planeSemanticFilter = setOf(PlaneType.VERTICAL))
val movableComponent = xrSession.createMovableComponent(
systemMovable = false,
scaleInZ = false,
anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)
ResizableComponent를 사용하여 사용자가 크기를 조절할 수 있는 항목 만들기
ResizableComponent
를 사용하면 사용자가 Entity
의 크기를 조절할 수 있습니다. ResizableComponent
에는 사용자가 Entity
의 크기를 조절하도록 유도하는 시각적 상호작용 신호가 포함되어 있습니다. ResizeableComponent
를 만들 때 최소 또는 최대 크기 (미터)를 지정할 수 있습니다. 너비와 높이가 서로 비례하여 크기가 조절되도록 크기를 조절할 때 고정 가로세로 비율을 지정할 수도 있습니다.
다음은 고정 가로세로 비율로 ResizableComponent
를 사용하는 예입니다.
val resizableComponent = xrSession.createResizableComponent()
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f )
resizableComponent.fixedAspectRatio = 16f / 9f //Specify a 16:9 aspect ratio
entity.addComponent(resizableComponent)
InteractableComponent를 사용하여 사용자 입력 이벤트 캡처
InteractableComponent
를 사용하면 사용자가 Entity
에 참여하거나 마우스를 가져갈 때와 같이 사용자의 입력 이벤트를 캡처할 수 있습니다.
InteractableComponent
를 만들 때 입력 이벤트를 수신할 InputEventListener
를 지정해야 합니다. 사용자가 입력 작업을 실행하면 onInputEvent
메서드가 InputEvent
매개변수에 제공된 특정 입력 정보와 함께 호출됩니다.
InputEvent.action
: 항목에 대한 마우스 오버 또는 탭(ACTION_DOWN)과 같은 입력 유형을 지정합니다.InputEvent.source
: 입력의 출처(예: 손 또는 컨트롤러 입력)를 지정합니다.InputEvent.pointerType
: 입력이 오른손에서 들어왔는지 왼손에서 들어왔는지 지정합니다.
모든 InputEvent
상수의 전체 목록은 참조 문서를 참고하세요.
다음 코드 스니펫은 InteractableComponent
를 사용하여 오른손으로 항목의 크기를 늘리고 왼손으로 줄이는 예를 보여줍니다.
private val executor by lazy { Executors.newSingleThreadExecutor() }
val interactableComponent = xrSession.createInteractableComponent(executor) {
//when the user disengages with the entity with their hands
if (it.source == InputEvent.SOURCE_HANDS && it.action == InputEvent.ACTION_UP) {
// increase size with right hand and decrease with left
if (it.pointerType == InputEvent.POINTER_TYPE_RIGHT){
entity.setScale(1.5f)
} else if (it.pointerType == InputEvent.POINTER_TYPE_LEFT){
entity.setScale(0.5f)
}
}
}
entity.addComponent(interactableComponent)