AR Tracked image manager
tracked image manager의 타입은 trackable manager이고, 2D image tracking을 수행한다.
tracked image manager은 환경(카메라로 비춰지는 세상)에서 감지된 각각의 이미지에 대해서 GameObject를 생성한다. 이미지가 감지되기 전에, manager은 reference image library로 컴파일 된 이미지 레퍼런스의 집합을 찾아보라고 지시해야한다. 이것은 reference image library에서만 감지한다.
Reference library
Unity Editor에서 reference image library를 생성할 수 있는지에 대한 지침을 보려면 Tracked Image Subsystem 문서를 보아라.
reference image library는 runtime에 정해질 수 있지만, tracked image manager 컴포넌트가 활성화되었다면 reference image library는 null이면 안된다. 다음 스크립트로 설정할 수 있다.
ARTrackedImageManager manager = ...;
manager.referenceLibrary = myReferenceImageLibrary;
reference image library는 XRReferenceImageLibrary 또는 RuntimeReferenceImageLibrary로 정할 수 있다. XRReferenceImageLibrary는 Editor에서만 생성할 수 있고, runtime 동안에는 수정할 수 없다. RuntimeReferenceImageLibrary는 XRReferenceImageLibrary가 runtime 동안에 나타나는 것이다. Library를 XRReferenceImageLibrary로 정할때, 사용을 위해 image tracking subsystem은 자동적으로 RuntimeReferenceImageLibrary로 변환한다.
실제 image library data는 공급자별로 다르다. 자세한 내용은 provider's documentation을 참고해라.
RuntimeReferenceImageLibrary는 ARTrackedImageManager.CreateRuntimeLibrary 방법과 함깨 XRReferenceImageLibrary로부터 만들수 있다.
XRReferenceImageLibrary serializedLibrary = ...
RuntimeReferenceImageLibrary runtimeLibrary = trackedImageManager.CreateRuntimeLibrary(serializedLibrary);
Responding to detected images
image가 추가되고 업데이트되거나 제거될때 알려주기 위해서 ARTrackedImageManager의 trackedImagesChanged 이벤트를 작성해라.
[SerializeField]
ARTrackedImageManager m_TrackedImageManager;
void OnEnable() => m_TrackedImageManager.trackedImagesChanged += OnChanged;
void OnDisable() => m_TrackedImageManager.trackedImagesChanged -= OnChanged;
void OnChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
foreach (var newImage in eventArgs.added)
{
// Handle added event
}
foreach (var updatedImage in eventArgs.updated)
{
// Handle updated event
}
foreach (var removedImage in eventArgs.removed)
{
// Handle removed event
}
}
tracking quality에 대한 추가적인 정보를 제공할 수 있는 tracking state도 있다. 예를 들어 view의 밖으로 나간 이미지는 제거되지 않았을 수 있지만, tracking state는 바뀔 것이다.
ARTrackedImageManager의 trackable 속성들과 함께 최근에 추적된 이미지들을 get 할 수 있다. 이것은 IEnumerable collection처럼 행동하기 때문에, 다음과 같은 foreach 구문으로 사용할 수 있다.
void ListAllImages()
{
Debug.Log(
$"There are {m_TrackedImageManager.trackables.count} images being tracked.");
foreach (var trackedImage in m_TrackedImageManager.trackables)
{
Debug.Log($"Image: {trackedImage.referenceImage.name} is at " +
$"{trackedImage.transform.position}");
}
}
또는 그것의 Trackableld를 사용하여 특정 이미지에 접근할 수 있다.
ARTrackedImage GetImageAt(TrackableId trackableId)
{
return m_TrackedImageManager.trackables[trackableId];
}
Tracked Image Prefab
ARTrackedImageManager은 Tracked Image Prefab필드를 가진다. 하지만 이것은 콘텐츠를 위한 것이 아니다. ARFoundation은 이미지가 감지된 것을 나타내기 위해서 새로은 GameObject를 생성한다.
Tracked Image Prefab필드가 null이라면, ARFoundation은 간단하게 그것에 대한 ARTrackedImage 컴포넌트를 통해 GameObject를 생성한다. 그러나, 모든 추적된 이미지가 추가적인 컴포넌트를 포함하기를 원한다면 ARFoundation이 각각의 추적된 이미지에 대해서 생성할 수 있도록 Prefab을 제공할 수 있다. 즉, Prefab필드의 목적은 추적된 이미지의 default 행동에 대한 확장이다. 콘텐츠를 world에 배치하는 것은 추천하는 방법이 아니다.
추적된 이미지의 pose로 콘텐츠를 인스턴스화 하고, 자동적으로 해당 포즈로 업데이트하고 싶다면 ARTrackedImage로 콘텐츠를 관리해라.
Adding new reference images at runtime
어떤 subsystems는 runtime동안에 수정할 수 있는 image library를 지원할 것이다. 이 경우에는, subsytem이 MutableRuntimeReferenceImageLibrary인 RuntimeReferenceImagelibrary를 생성한다. 이것을 사용하기 위해서는 RuntimeReferenceImagelibrary를 MutableRuntimeReferenceImageLibrary에 할당해야한다.
[SerializeField]
ARTrackedImageManager m_TrackedImageManager;
void AddImage(Texture2D imageToAdd)
{
if (m_TrackedImageManager.referenceLibrary is MutableRuntimeReferenceImageLibrary mutableLibrary)
{
mutableLibrary.ScheduleAddImageJob(
imageToAdd,
"my new image",
0.5f /* 50 cm */);
}
}
추후에 image를 추가할 수 있는 빈 library를 만들기 위해서, CreateRuntimeLibrary를 인자 없이 호출할 수 있다.
void AddImage(Texture2D imageToAdd)
{
var library = m_TrackedImageManager.CreateRuntimeLibrary();
if (library is MutableRuntimeReferenceImageLibrary mutableLibrary)
{
mutableLibrary.ScheduleAddImageJob(
imageToAdd,
"my new image",
0.5f /* 50 cm */);
}
}
mutable libraries를 특정 tracked image manager가 제공하는지 안하는지를 다음과 같이 descriptor로 확인할 수 있다.
bool DoesSupportMutableImageLibraries()
{
return m_TrackedImageManager.descriptor.supportsMutableLibrary;
}
언제든지 이미지에 mutable library를 추가하는 것을 허용한다. 이미지를 추가하는 것은 계산적으로 expensive할 수 있고, 완료하기 위해서는 많은 프레임을 소요할 것이다. Unity Job System은 이미지를 비동기적으로 처리하는데 사용된다.
이미지를 MutableRuntimeReferenceImageLibrary에 추가하기 위해서, ScheduleAddImageJob 방법을 사용해라. 이것은 job이 완료되었을 때를 결정할 때 사용할 수 있는 JobHandle을 반환한다. 이것을 필요로하지 않는다면 안전하게 무시할 수 있다.
만약 Texture2D를 받아들이기 위해서 extension방법을 사용한다면, 어떤 메모리도 관리할 필요가 없다.
NativeSlice 또는 포인터를 받아들이는 ScheduleAddImageJob의 버전을 사용한다면, 해당 job이 완료되었을때 메모리를 해제할 책임이 있다. 메모리를 해제하는 작업을 예약하여 이것을 수행할 수 있다.
struct DeallocateJob : IJob
{
[DeallocateOnJobCompletion]
public NativeArray<byte> data;
public void Execute() { }
}
void AddImage(NativeArray<byte> grayscaleImageBytes,
int widthInPixels, int heightInPixels,
float widthInMeters)
{
if (m_TrackedImageManager.referenceLibrary is MutableRuntimeReferenceImageLibrary mutableLibrary)
{
var aspectRatio = (float)widthInPixels / (float)heightInPixels;
var sizeInMeters = new Vector2(widthInMeters, widthInMeters * aspectRatio);
var referenceImage = new XRReferenceImage(
// Guid is assigned after image is added
SerializableGuid.empty,
// No texture associated with this reference image
SerializableGuid.empty,
sizeInMeters, "My Image", null);
var jobHandle = mutableLibrary.ScheduleAddImageJob(
grayscaleImageBytes,
new Vector2Int(widthInPixels, heightInPixels),
TextureFormat.R8,
referenceImage);
// Schedule a job that deallocates the image bytes after the image
// is added to the reference image library.
new DeallocateJob { data = grayscaleImageBytes }.Schedule(jobHandle);
}
else
{
// Cannot add the image, so dispose its memory.
grayscaleImageBytes.Dispose();
}
}
다중 이미지를 추가하는 동작은 동시에 처리할 수 있다. MutableRuntimeReferenceImageLibrary가 최근에 image tracking에 사용되었는지는 이 동작에 대해서 상관이 없다.
Creating a manager at runtime
runtime동안, 활성화된 GameObject에 컴포넌트를 추가할 때, Unity는 바로 그것의 OnEnable 함수를 호출한다. 그러나 ARTrackedImageManager은 null이 아닌 reference image library를 필요로한다. ARTrackedImageManager가 가능할 때, reference image library가 null이라면 그것은 자동적으로 자기 자신을 불가능하도록 만들 것이다.
ARTrackedImageManager를 runtime에 추가하기위해서는 그것의 reference image library를 정하고 다시 가능하게하면 된다.
var manager = gameObject.AddComponent<ARTrackedImageManager>();
manager.referenceLibrary = myLibrary;
manager.enabled = true;
Maximum number of moving images
어떤 provider들은 움직이는 이미지들을 추적할 수 있다. 이것은 더 많은 CPU 자원을 필요로하기 때문에 다수의 움직이는 이미지들을 추적하는 것은 동시적으로 할 수 있다. SubsystemDescriptor(ARTRACKedImageManager.descriptor)를 통해 지원을 확인할 수 있다.
Tracked image prefab
이 프리팹은 이미지가 reference image library로부터 감지되었을 때 인스턴스화 된다. manager은 인스턴스화 된GameObject가 ARTrackedImage 컴포넌트를 포함할 것을 확신한다. ARTrackedImage.referenceImage 속성과 함께 ARTrackedImage를 추적하는데 사용된 reference image를 get할 수 있다.
Tracking State
ARTrackedImages에 대하여 세가지 tracking state가 가능하다.
Tracking State | Description |
None | 이미지가 추적되지 않았을때이다. 이것은 아마 이미지가 처음 추적되었을때 초기 상태일 것이다. |
Limited | 이미지가 추적중이지만 잘되지 않을 때이다. 이미지가 추적 대신 제한적으로 간주되는 상황은 기본 AR 프레임워크에 따라 달라진다. 제한된 추적이 발생할 수 있는 예는 다음과 같다. - 카메라에 이미지가 잘 보이지 않을때 - 이미지는 움직이는 이미지로 추적되지 않는다.예를 들어 maxNumberOfMovingImages가 초과된 경우 이 문제가 발생할 수 있다. |
Tracking | 이미지 추적이 잘 되었을 때이다. |
Determining when an image is visible
이미지의 가시성을 결정하는 API는 없다. 일반적으로 tracking state가 Tracking일 때, 이미지가 잘 보이지 않는다면 Limited로 바뀔 가능성이 있다. 하지만, tracking state가 상황 안에 없는 상황이 있을 수도 있다.
만약 이 정보가 중요하다면 ARTrackedImage의 transform과 카메라 뷰의 frustum을 비교해보는 것을 고려해라.
https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.0/manual/tracked-image-manager.html
'Programming > Unity' 카테고리의 다른 글
[유니티] AR Foundation_기본 설정 (macOS) (0) | 2022.01.20 |
---|---|
[유니티] AR Foundation_Plane Detection (2) (0) | 2022.01.14 |
[유니티] AR Foundation_Plane Detection (0) | 2022.01.10 |
[유니티] UI 버튼 작동이 안될때 (0) | 2021.08.23 |
나무 (0) | 2021.08.12 |