Unity에서의 맞춤 카메라 구현 - 외부 프레임 데이터 소스
외부 프레임 데이터 소스(ExternalFrameSource)를 통해 개발자는 특정 헤드셋 장치나 다른 입력 장치를 지원하도록 EasyAR Sense에 맞춤 카메라 구현을 확장할 수 있습니다. 다음 내용은 외부 프레임 데이터 소스의 유형 구조와 인터페이스 정의를 소개합니다.
시작하기 전에
외부 프레임 데이터 소스 유형
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
class FrameSource {
<<abstract>>
}
class ExternalFrameSource {
<<abstract>>
}
class ExternalDeviceFrameSource {
<<abstract>>
}
class ExternalDeviceMotionFrameSource:::EasyAR {
<<abstract>>
}
class ExternalDeviceRotationFrameSource:::EasyAR {
<<abstract>>
}
class ExternalImageStreamFrameSource:::EasyAR {
<<abstract>>
}
ExternalFrameSource --|> FrameSource
ExternalDeviceFrameSource --|> ExternalFrameSource
ExternalDeviceMotionFrameSource --|> ExternalDeviceFrameSource
ExternalDeviceRotationFrameSource --|> ExternalDeviceFrameSource
ExternalImageStreamFrameSource --|> ExternalFrameSource
classDef EasyAR fill:#6e6ce6,stroke:#333,color:#fff
위 그림은 외부 프레임 데이터 소스의 유형 구조를 보여줍니다.
입력 데이터에 따라 외부 프레임 데이터 소스는 크게 두 가지로 나뉩니다.
- 이미지 및 디바이스 모션 데이터 입력 확장
- ExternalDeviceMotionFrameSource를 상속하여 구현합니다. 디바이스와 디바이스 SDK가 6DoF 모션 추적 기능을 제공합니다. 가상 카메라의 transform 및 기타 제어는 디바이스 SDK가 담당합니다.
- ExternalDeviceRotationFrameSource를 상속하여 구현합니다. 디바이스와 디바이스 SDK가 3DoF 회전 추적 기능을 제공합니다. 가상 카메라의 transform 및 기타 제어는 디바이스 SDK가 담당합니다.
- 이미지 입력 확장
- ExternalImageStreamFrameSource를 상속하여 구현합니다. 이미지 입력만 제공합니다. 가상 카메라의 transform 및 기타 제어는 EasyAR이 담당합니다.
이러한 외부 프레임 데이터 소스를 연결할 때 사용할 수 있는 AR 기능은 서로 다릅니다.
- 이미지 및 디바이스 모션 데이터 입력 확장 ExternalDeviceMotionFrameSource
- Mega
- 모션 추적(디바이스 자체 제공)
- Sparse Spatial Map
- Dense Spatial Map
- 이미지 추적(모션 융합 지원)
- 클라우드 이미지 인식
- 객체 추적(모션 융합 지원)
- 이미지 및 디바이스 모션 데이터 입력 확장 ExternalDeviceRotationFrameSource
- Mega
- 이미지 추적(모션 융합 미지원)
- 클라우드 이미지 인식
- 객체 추적(모션 융합 미지원)
- 이미지 입력 확장 ExternalImageStreamFrameSource
- 이미지 추적(모션 융합 미지원)
- 클라우드 이미지 인식
- 객체 추적(모션 융합 미지원)
외부 프레임 데이터 소스 인터페이스 정의
외부 프레임 데이터 소스를 만들 때는 관련 인터페이스를 반드시 구현해야 합니다. 아래에서는 각 인터페이스의 정의와 사용 방법을 설명합니다.
장치 정의
FrameSource.IsHMD:
헤드셋인지 정의
헤드셋 장치에서만 true로 설정합니다.
장치가 헤드셋이면 진단 정보는 화면이 아니라 카메라 앞의 3D 보드에 표시됩니다. 일부 AR 기능은 헤드셋 장치에서 조금 다르게 동작할 수 있습니다.FrameSource.Display:
디스플레이 시스템 정의
현재 디스플레이의 회전 등의 정보를 제공합니다.
기본 디스플레이 정보는 Display.DefaultSystemDisplay 또는 Display.DefaultHMDDisplay를 사용할 수 있습니다.
일반적으로 헤드셋에서는 Display.DefaultHMDDisplay를 사용할 수 있습니다.
사용 가능 여부
- FrameSource.IsAvailable:
사용 가능 여부(Availability)
프레임 소스를 사용할 수 있는지 판단하는 데 사용합니다.
현재 실행 중인 디바이스나 환경에서 프레임 소스를 사용할 수 없다면 이 값은 false여야 합니다.
이 값이 Optional<bool>.Empty라면 FrameSource.CheckAvailability() 코루틴이 호출되며, 코루틴이 끝나기 전에 FrameSource.IsAvailable를 갱신해야 합니다.
사용 가능 여부 인터페이스는 세션 어셈블리 때 사용되며, 사용할 수 없는 컴포넌트는 선택되지 않고 세션 실행 중에도 해당 메서드가 호출되지 않습니다. - FrameSource.CheckAvailability() (선택 사항):
프레임 소스 사용 가능 여부를 확인하는 코루틴
FrameSource.IsAvailable가 Optional<bool>.Empty일 때 호출됩니다. 이 코루틴이 끝나기 전까지 세션의 어셈블리 과정은 차단됩니다.
세션 원점
ExternalDeviceFrameSource.OriginType:
원점 유형- XROrigin: 디바이스 SDK가 Unity.XR.CoreUtils.XROrigin을 원점으로 사용합니다.
- Custom: 디바이스 SDK가 사용자 정의 원점을 사용합니다. ExternalDeviceFrameSource.Origin를 지정해야 합니다.
- None: 디바이스 SDK가 원점을 정의하지 않습니다. 이 경우 원점은 씬에서 자동으로 선택되거나 생성되지만 이동하지는 않습니다. 세션은 SessionOrigin 중심 모드만 지원합니다. 모든 target과 target 아래의 콘텐츠가 Unity 좌표계에서 계속 움직이기 때문에, 애플리케이션 개발자는 가상 오브젝트 배치에 특히 주의해야 합니다. 일부 사용자 콘텐츠(예: 물리 시스템)는 정상적으로 동작하지 않을 수 있습니다. Unity 월드 좌표계에 놓인 오브젝트는 어떤 구성에서도 올바른 위치에 표시될 수 없습니다.
ExternalDeviceFrameSource.Origin:
원점 오브젝트
ExternalDeviceFrameSource.OriginType이 Custom일 때만 자체 원점을 정의하며, 그 외의 경우에는 다시 정의할 필요가 없습니다.
가상 카메라
- FrameSource.Camera:
가상 카메라
카메라는 세션의 제어를 받지 않으며, 카메라의 transform과 투영 행렬, 그리고 이미지 배경 렌더링은 외부 코드가 제어해야 합니다.
이 카메라는 헤드셋에서만 사용되며, 일부 진단 텍스트를 눈앞에 표시하는 데 쓰입니다.
ExternalDeviceFrameSource.OriginType이 XROrigin일 때는 정의할 필요가 없습니다. EasyAR이 Unity XR 프레임워크에서 정의한 카메라를 자동으로 사용합니다.
물리 카메라
- FrameSource.DeviceCameras:
물리 카메라 매개변수
카메라 프레임 데이터를 제공하는 물리 카메라입니다. 카메라 프레임 데이터가 여러 카메라에서 제공된다면 목록에 모든 물리 카메라가 포함되어야 합니다.
FrameSource.CameraFrameStarted가 true일 때 올바른 물리 카메라 매개변수를 가져올 수 있어야 합니다. - FrameSource.CameraFrameStarted:
카메라 프레임 입력 시작 여부
물리 카메라가 준비되어 EasyAR에 데이터를 입력할 수 있으면 true를 반환하고, 물리 카메라가 중지되면 false를 반환합니다. FrameSource.CameraFrameStarted가 false이면 EasyAR은 동작하지 않습니다. FrameSource.CameraFrameStarted가 true이면 FrameSource.DeviceCameras 데이터에 접근할 수 있어야 하고, 카메라 프레임 데이터가 끊김 없이 EasyAR에 입력되어야 합니다. EasyAR이 카메라 프레임 입력이 오랜 시간 연속으로 없음을 감지하면 경고를 표시해, 기능이 응답하지 않을 때 문제를 분리하는 데 도움을 줍니다.
물리 카메라 매개변수는 실제 디바이스 카메라와 같아야 합니다.
- FrameSourceCamera.CameraType:
물리 카메라 유형
일반적으로 전면 카메라가 아닌 경우, 예를 들어 헤드셋에서는 후면 카메라를 선택합니다. - FrameSourceCamera.CameraOrientation:
물리 카메라 이미지가 장치의 자연 방향으로 표시될 때 시계 방향으로 회전해야 하는 각도
범위는 [0, 360)입니다. - FrameSourceCamera.FrameSize:
이미지 크기 - FrameSourceCamera.FrameRateRange:
프레임률 범위
x는 프레임률 범위의 하한, y는 상한을 정의합니다. - DeviceFrameSourceCamera.AxisSystem:
머리/물리 카메라 pose 및 물리 카메라 외부 파라미터에 사용하는 좌표축 시스템
모든 행렬은 같은 좌표축 시스템을 사용해야 합니다. 사용하는 데이터 정의가 알려진 시스템과 맞지 않으면 EasyAR에 전달하기 전에 좌표축 변환을 해야 합니다. - DeviceFrameSourceCamera.Extrinsics:
물리 카메라 외부 파라미터
일반적으로 보정된 행렬입니다. 좌표축은 DeviceFrameSourceCamera.AxisSystem 정의를 따라야 합니다. 외부 파라미터의 좌표축 정의가 실제 pose의 좌표축 정의와 다르거나, 둘 다 DeviceFrameSourceCamera.AxisSystem 정의와 맞지 않으면 이 값을 설정하기 전에 좌표축 변환을 해야 합니다.
세션 시작과 중지
- FrameSource.OnSessionStart(ARSession):
세션 시작 이벤트 처리
세션 어셈블리에서 이 프레임 소스가 선택되었을 때만 유효합니다.
지연 초기화에 사용할 수 있으며, 이 메서드에서 AR 전용 초기화 작업을 수행할 수 있습니다. - FrameSource.OnSessionStop():
세션 중지 이벤트 처리
세션 어셈블리에서 이 프레임 소스가 선택되었을 때만 유효합니다.
이 메서드에서 FrameSource.OnSessionStart(ARSession)와 세션 실행 중에 생성된 리소스를 파괴하고 내부 상태를 복구할 수 있습니다. 세션이 파괴되기 전에는 이 메서드가 반드시 호출됩니다. 프레임 소스가 세션보다 먼저 파괴되면 호출되지 않으며, 세션은 Broken 상태가 됩니다.
입력 프레임
ExternalDeviceMotionFrameSource.HandleCameraFrameData(DeviceFrameSourceCamera, double, Image, CameraParameters, Pose, MotionTrackingStatus):
카메라 프레임 데이터 입력ExternalDeviceRotationFrameSource.HandleCameraFrameData(DeviceFrameSourceCamera, double, Image, CameraParameters, Quaternion):
카메라 프레임 데이터 입력
디바이스 SDK API가 스레드 안전하기만 하다면 어떤 스레드에서든 호출할 수 있습니다.
이 데이터는 물리 카메라 센서가 노출될 때의 데이터와 일치해야 합니다. 30 또는 60fps 데이터를 입력하는 것을 권장합니다. 최소 허용 프레임률은 2이지만 일부 알고리즘의 응답 시간에 영향을 줄 수 있습니다. 가능하면 색상 데이터를 입력하는 것이 좋으며, 이는 Mega의 효과에 도움이 됩니다.
최적의 효율을 위해 원본 YUV 데이터를 공유 메모리로 직접 전달하고, 데이터 포인터를 그대로 EasyAR에 넘기며 데이터 소유권에 주의하도록 데이터 경로 전체를 설계할 수 있습니다.ExternalDeviceMotionFrameSource.HandleRenderFrameData(double, Pose, MotionTrackingStatus):
렌더 프레임 데이터 입력ExternalDeviceRotationFrameSource.HandleRenderFrameData(double, Quaternion):
렌더 프레임 데이터 입력
디바이스 데이터가 준비된 뒤에는 각 렌더 프레임마다 호출해야 하며, 프레임을 건너뛰면 안 됩니다. 이 데이터는 같은 프레임 안에서 현재 Unity 가상 카메라의 데이터와 일치해야 합니다.
- ExternalFrameSource.TryAcquireBuffer(int):
메모리 풀에서 메모리 블록 가져오기 시도
이 메모리 블록은 보통 카메라 프레임의 이미지 데이터를 저장해 EasyAR에 입력하는 데 사용됩니다. - ExternalFrameSource.ReceivedFrameCount:
EasyAR이 가져온 카메라 프레임 수
EasyAR은 이를 사용해 디바이스 카메라 프레임 입력의 상태를 확인합니다. 디버깅 시 사용할 수 있으며, 이 값이 증가를 멈추면 보통 디바이스가 EasyAR에 데이터 입력을 중지했다는 뜻입니다.
Unity 메시지
스크립트에서 다음 메시지를 사용할 때는 반드시 기본 클래스 구현이 호출되도록 주의해야 합니다.
후속 단계
- 외부 입력 프레임 데이터를 읽어 카메라 프레임 데이터와 렌더 프레임 데이터를 확인합니다.
- 이미지 및 디바이스 모션 데이터 입력 확장을 만듭니다.
- 이미지 입력 확장을 만듭니다.