Table of Contents

세션 실행 결과 가져오기

세션 실행 과정에서 장면 내 일부 물체의 트랜스폼이 수정되고, 카메라 화면 등이 수정됩니다. 때로는 이러한 수정만으로는 애플리케이션의 사용 요구를 충족시키지 못할 수 있으며, 세션의 프레임별 실행 결과를 가져와 이 데이터를 추가로 처리해야 할 수 있습니다. 이 문서에서는 이러한 결과 데이터를 가져와 사용하는 방법을 설명합니다.

시작하기 전에

InputFrame 업데이트 가져오기

InputFrameUpdate 이벤트를 사용하여 InputFrame 업데이트를 가져올 수 있습니다. 이 이벤트는 세션의 프레임별 출력 데이터 중 InputFrame이 변경될 때만 트리거됩니다.

[!참고] InputFrameUpdate는 EasyAR이 화면을 렌더링하는 세션에서만 유효합니다. 일반적으로 AR Foundation 또는 헤드셋을 사용할 때는 유효하지 않으며, 이러한 경우 해당 타사 라이브러리에서 제공하는 방법을 사용하여 데이터 업데이트를 가져와야 합니다.

InputFrame을 사용하면 물리적 카메라 이미지, 카메라 매개변수, 타임스탬프, 월드 좌표계에 대한 물리적 카메라의 트랜스폼 및 추적 상태 등을 가져올 수 있습니다. 그러나 카메라 트랜스폼은 세션에 의해 가상 카메라 및 기타 물체에 이미 적용되었으므로 일반적으로 InputFrame을 통해 카메라 트랜스폼을 가져올 필요는 없습니다.

현재 프레임의 물리적 카메라 이미지 가져오기

InputFrame.image() 메서드를 사용하여 Image 유형의 물리적 카메라 이미지 데이터를 가져올 수 있습니다.

예를 들어, 다음 코드는 InputFrame이 업데이트될 때 물리적 카메라 이미지를 가져올 수 있습니다:

Session.InputFrameUpdate += (inputFrame) => {
    using (var image = inputFrame.image())
    {
    }
};

[!주의] Image 유형 데이터 및 이로부터 가져온 기타 class 유형 데이터를 사용할 때는 Dispose()가 올바르게 호출되는지 반드시 확인해야 합니다(위 코드의 using 문이 이를 보장함). 그렇지 않으면 메모리 누수 또는 화면 업데이트 중단 등의 문제가 발생할 수 있습니다.

InputFrame 또는 Image를 다음 프레임까지 유지해야 하는 경우, 유지할 데이터 양에 따라 ARAssembly.ExtraBufferCapacity 값을 증가시켜야 합니다. 그렇지 않으면 버퍼 공간 부족으로 인해 데이터 가져오기에 실패할 수 있습니다.

InputFrame을 유지해야 하는 경우, Clone() 메서드를 호출하여 참조 복사본을 생성하고, 더 이상 필요하지 않을 때 복사본에 대해 Dispose()를 호출해야 합니다.

물리적 카메라의 프레임 속도는 일반적으로 렌더링 프레임 속도보다 낮기 때문에 모든 렌더링 프레임에서 InputFrameUpdate 이벤트를 수신하는 것은 아닙니다. 마찬가지로 물리적 카메라 화면 렌더링도 모든 렌더링 프레임마다 업데이트되지 않습니다. InputFrameUpdate 다음 이벤트가 트리거되기 전까지의 모든 렌더링 프레임의 화면 내용은 현재 InputFrame의 이미지와 일치합니다.

[!참고] InputFrame의 이미지는 현재 프레임의 가상 카메라 배경 화면과 항상 일치하지만, 배경 화면 렌더링 시 크기 조정 및 잘림이 발생할 수 있으므로 가져온 이미지 크기나 비율이 화면에 표시되는 것과 일치하지 않는 것은 정상적인 현상입니다.

또한 InputFrame.image()이 반환하는 이미지 데이터는 CPU에서 읽을 수 있으며 GPU 텍스처가 아닙니다. GPU에서 이미지 데이터를 사용해야 하는 경우 이미지 데이터를 GPU 텍스처로 업로드하거나 CameraImageRenderer.RequestTargetTexture(Action<Camera, RenderTexture>) 인터페이스를 통해 직접 GPU 텍스처를 가져와야 합니다.

[선택 사항] 물리적 카메라 이미지 렌더링 가로채기

ARAssembly.CameraImageRenderer를 사용하여 물리적 카메라 이미지 그리기를 제어할 수 있습니다.

다음 코드는 물리적 카메라 이미지 그리기를 중지할 수 있습니다:

if (Session.Assembly != null && Session.Assembly.CameraImageRenderer.OnSome)
{
    Session.Assembly.CameraImageRenderer.Value.enabled = false;
}

여기서는 먼저 ARAssembly.CameraImageRenderer의 존재 여부를 확인해야 합니다.

[!참고] EasyAR이 화면을 렌더링하는 세션에서만 위의 방법으로 화면 업데이트를 중지할 수 있습니다. 일반적으로 AR Foundation 또는 헤드셋을 사용할 때는 유효하지 않으며, 이러한 경우 해당 타사 라이브러리에서 제공하는 방법을 사용하여 해당 기능을 구현해야 합니다.

물리적 카메라 이미지 그리기를 중지한 후 애플리케이션은 InputFrame을 사용하여 물리적 카메라 이미지 데이터를 가져오고 이 데이터를 사용하여 사용자 정의 그리기를 수행할 수 있습니다.

트랜스폼 업데이트 가져오기

PostSessionUpdate 이벤트를 통해 세션의 프레임별 업데이트 후 장면 내 물체의 트랜스폼 데이터를 가져올 수 있습니다.

[!참고] 일부 기능(예: Mega)의 경우 이미지가 변경되지 않았고 서비스 업데이트를 명시적으로 요청하지 않더라도 AR 계산은 모든 렌더링 프레임에서 실행됩니다. 따라서 모든 트랜스폼 변경 사항을 가져와야 하는 경우 특정 프레임이 아닌 모든 프레임에서 트랜스폼 데이터를 가져와야 합니다.

가상 카메라의 트랜스폼 가져오기

ARAssembly.Camera를 통해 장면 내 카메라의 트랜스폼을 가져올 수 있습니다.

Session.PostSessionUpdate += () =>
{
    var position = Session.Assembly.Camera.transform.position;
    var rotation = Session.Assembly.Camera.transform.rotation;
};

타겟의 트랜스폼 가져오기

사용 중인 특정 타겟 객체를 통해 장면 내 타겟의 트랜스폼을 가져올 수 있습니다. 예를 들어, 이미지 추적의 경우 이 타겟은 ImageTargetController 컴포넌트가 있는 물체입니다.

Session.PostSessionUpdate += () =>
{
    var position = target.transform.position;
    var rotation = target.transform.rotation;
};

[선택 사항] 포즈 가져오기

포즈는 물체의 위치와 방향을 설명하는 데이터 구조로, 일반적으로 position과 rotation 두 부분으로 구성됩니다. AR 애플리케이션에서 포즈는 일반적으로 특정 기준 좌표계에 대한 물리적 카메라 또는 추적 대상의 위치와 방향을 설명하는 데 사용됩니다.

Unity에서는 원시 포즈 데이터를 제공하지 않습니다. 포즈는 일반적으로 장면 내 물체의 움직임을 구동하는 데 사용되며, 이는 세션이 자동으로 수행하는 작업입니다. 콘텐츠 계산 및 렌더링의 경우 트랜스폼만으로도 충분합니다.

[!중요] 아래 방법을 읽기 전에, 장면의 카메라, 추적 대상 등 물체의 트랜스폼 데이터가 이미 요구 사항을 충족하는지 다시 한번 고려해 보십시오. 일반적으로 추가 포즈 데이터는 필요하지 않습니다.

어떤 이유로든 포즈 데이터가 반드시 필요한 경우, PostSessionUpdate 이벤트에서 트랜스폼을 사용하여 필요한 포즈 값을 계산할 수 있습니다. 일반적으로 PostSessionUpdate에서 가져온 타겟과 카메라 간의 상대적 트랜스폼이 포즈입니다.

다음 코드는 카메라와 타겟의 트랜스폼을 가져와 상대적 포즈를 계산하는 방법을 보여줍니다:

Session.PostSessionUpdate += () =>
{
    Pose cameraToWorld = new(Session.Assembly.Camera.transform.position, Session.Assembly.Camera.transform.rotation);
    Pose targetToWorld = new(target.transform.position, target.transform.rotation);
    Pose worldToTarget = new()
    {
        position = Quaternion.Inverse(targetToWorld.rotation) * (-targetToWorld.position),
        rotation = Quaternion.Inverse(targetToWorld.rotation)
    };
    Pose cameraToTarget = cameraToWorld.GetTransformedBy(worldToTarget);
};

[!주의] AR Foundation, 헤드셋 또는 기타 타사 라이브러리를 동시에 사용 중인 경우, 이러한 라이브러리들도 장면 내 카메라의 트랜스폼을 수정할 수 있습니다. 관련 포즈 계산을 수행하기 전에 이러한 라이브러리의 업데이트 로직이 완료되었는지 확인해야 합니다. 그렇지 않으면 계산 결과가 정확하지 않을 수 있습니다. 이러한 시나리오에서도 PostSessionUpdate의 타겟과 origin 간의 상대적 포즈는 정확합니다.

[선택 사항] 트랜스폼 업데이트 가로채기

AR 기능이 실행될 때 Unity의 카메라, 추적 대상 등 물체의 트랜스폼은 일반적으로 세션에 의해 자동으로 업데이트됩니다. 이러한 업데이트 과정은 AR 렌더링의 정확성과 일관성을 보장하므로 이러한 업데이트를 가로챌 수 있는 방법은 없습니다.

그러나 물체의 트랜스폼 업데이트 로직을 사용자 정의해야 하는 경우 PostSessionUpdate 이벤트를 수신하여 구현할 수 있습니다. 이 경우 다소 번거로운 방법이 필요합니다:

  1. 일반적으로 렌더링 콘텐츠를 세션이 제어하는 물체의 하위 노드 또는 추가 컴포넌트로 연결해야 하지만, 물체의 트랜스폼 업데이트를 사용자 정의해야 하는 경우 이러한 물체를 세션이 제어하는 물체 계층 구조에서 제거해야 합니다. 즉, 이러한 물체는 세션이 제어하는 물체의 하위 노드가 아니어야 합니다.
  2. PostSessionUpdate 이벤트에서 사용자 정의 업데이트를 원하는 물체의 트랜스폼을 기록합니다.
  3. 마지막으로, PostSessionUpdate 이벤트에서 세션이 제공하는 데이터를 기반으로 사용자 정의 로직을 사용하여 이러한 물체의 트랜스폼을 업데이트합니다.

[!참고] PostSessionUpdate 이벤트 사용은 필수적입니다. 이 시간 이후에야 세션이 장면 내 물체를 조작하지 않기 때문입니다.

이 방법은 카메라를 수정하는 데 사용할 수 없으며, 카메라의 사용자 정의 업데이트를 처리하려면 더 복잡한 로직이 필요합니다.

또한 이 방법은 물체의 트랜스폼을 사용자 정의 업데이트하는 데만 사용할 수 있으며, 세션이 제어하는 물체의 트랜스폼을 수정하는 데는 사용할 수 없습니다. 세션이 제어하는 물체의 트랜스폼이 외부에서 수정되면 세션은 여전히 다음 프레임 업데이트 시 이러한 수정 사항을 덮어쓰며, 이로 인해 일부 계산의 정확성에 영향을 미칠 수 있습니다.

[!주의] 이 방법을 사용할 때는 물체 트랜스폼의 정확성을 보장해야 합니다. 그렇지 않으면 AR 렌더링 오류가 발생할 수 있습니다.

AR Foundation, 헤드셋 또는 기타 타사 라이브러리를 동시에 사용 중인 경우, 이러한 라이브러리들도 장면 내 물체의 트랜스폼을 수정할 수 있습니다. 이러한 라이브러리의 업데이트 로직과 사용자 정의 로직이 충돌하지 않도록 보장해야 합니다. 그렇지 않으면 예기치 않은 결과가 발생할 수 있습니다.

관련 주제