Commit 708d3dee authored by BlackAngle233's avatar BlackAngle233
Browse files

update final design

parent 1444629e
fileFormatVersion: 2
guid: 0f957098502a6f947819cc2c69b1fe65
timeCreated: 1574059483
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Transform utility.</para>
/// <para xml:lang="zh">Transform工具。</para>
/// </summary>
public static class TransformUtil
{
/// <summary>
/// <para xml:lang="en">Calculate and set <see cref="Camera"/> transform using <see cref="Camera"/> <paramref name="pose"/>, to express the relation of <see cref="Camera"/> and <see cref="WorldRootController"/> in 3D space which is known in <see cref="Camera"/> <paramref name="pose"/>.</para>
/// <para xml:lang="zh">已知<see cref="Camera"/>与<see cref="WorldRootController"/>的相对关系,通过<see cref="Camera"/>的<paramref name="pose"/>计算并设置<see cref="Camera"/>的Transform,以便在三维空间中将这个关系表达出来。</para>
/// </summary>
public static void SetCameraPoseOnCamera(Transform camera, WorldRootController controller, Matrix44F pose, Matrix4x4 displayCompensation, bool manualHorizontalFlip = false)
{
SetPoseOnTransform(camera.transform, controller.transform, pose, displayCompensation, true, true, manualHorizontalFlip);
}
/// <summary>
/// <para xml:lang="en">Calculate and set <see cref="WorldRootController"/> transform using <see cref="Camera"/> <paramref name="pose"/>, to express the relation of <see cref="Camera"/> and <see cref="WorldRootController"/> in 3D space which is known in <see cref="Camera"/> <paramref name="pose"/>.</para>
/// <para xml:lang="zh">已知<see cref="Camera"/>与<see cref="WorldRootController"/>的相对关系,通过<see cref="Camera"/>的<paramref name="pose"/>计算并设置<see cref="WorldRootController"/>的Transform,以便在三维空间中将这个关系表达出来。</para>
/// </summary>
public static void SetCameraPoseOnWorldRoot(Transform camera, WorldRootController controller, Matrix44F pose, Matrix4x4 displayCompensation, bool manualHorizontalFlip = false)
{
SetPoseOnTransform(controller.transform, camera.transform, pose, displayCompensation, true, false, manualHorizontalFlip);
}
/// <summary>
/// <para xml:lang="en">Calculate and set <see cref="Camera"/> transform using <see cref="Target"/> <paramref name="pose"/>, to express the relation of <see cref="Camera"/> and <see cref="Target"/> in 3D space which is known in <see cref="Target"/> <paramref name="pose"/>.</para>
/// <para xml:lang="zh">已知<see cref="Camera"/>与<see cref="Target"/>的相对关系,通过<see cref="Target"/>的<paramref name="pose"/>计算并设置<see cref="Camera"/>的Transform,以便在三维空间中将这个关系表达出来。</para>
/// </summary>
public static void SetTargetPoseOnCamera(Transform camera, TargetController controller, Matrix44F pose, Matrix4x4 displayCompensation, bool manualHorizontalFlip = false)
{
SetPoseOnTransform(camera.transform, controller.transform, pose, displayCompensation, false, true, manualHorizontalFlip);
}
/// <summary>
/// <para xml:lang="en">Calculate and set <see cref="Target"/> transform using <see cref="Target"/> <paramref name="pose"/>, to express the relation of <see cref="Camera"/> and <see cref="Target"/> in 3D space which is known in <see cref="Target"/> <paramref name="pose"/>.</para>
/// <para xml:lang="zh">已知<see cref="Camera"/>与<see cref="Target"/>的相对关系,通过<see cref="Target"/>的<paramref name="pose"/>计算并设置<see cref="Target"/>的Transform,以便在三维空间中将这个关系表达出来。</para>
/// </summary>
public static void SetTargetPoseOnTarget(Transform camera, TargetController controller, Matrix44F pose, Matrix4x4 displayCompensation, bool manualHorizontalFlip = false)
{
SetPoseOnTransform(controller.transform, camera.transform, pose, displayCompensation, false, false, manualHorizontalFlip);
}
/// <summary>
/// <para xml:lang="en">Set transform <paramref name="t"/> using the matrix <paramref name="mat"/> in EasyAR coordinates.</para>
/// <para xml:lang="zh">使用EasyAR坐标系矩阵<paramref name="mat"/>设置transform <paramref name="t"/>。</para>
/// </summary>
public static void SetMatrixOnTransform(Transform t, Matrix4x4 mat, bool keepScale)
{
Vector3 scaleKept = Vector3.zero;
if (keepScale)
{
scaleKept = t.localScale;
}
//Notice: assume no reflection
var scale = new Vector3 { x = Mathf.Sqrt(mat.GetColumn(0).sqrMagnitude), y = Mathf.Sqrt(mat.GetColumn(1).sqrMagnitude), z = Mathf.Sqrt(mat.GetColumn(2).sqrMagnitude) };
var m = new Matrix4x4();
m.SetColumn(0, mat.GetColumn(0) / scale.x);
m.SetColumn(1, mat.GetColumn(1) / scale.y);
m.SetColumn(2, mat.GetColumn(2) / scale.z);
m.SetColumn(3, mat.GetColumn(3));
var q = new Quaternion
{
w = Mathf.Sqrt(Mathf.Max(0, 1 + m[0, 0] + m[1, 1] + m[2, 2])) / 2,
x = Mathf.Sqrt(Mathf.Max(0, 1 + m[0, 0] - m[1, 1] - m[2, 2])) / 2,
y = Mathf.Sqrt(Mathf.Max(0, 1 - m[0, 0] + m[1, 1] - m[2, 2])) / 2,
z = Mathf.Sqrt(Mathf.Max(0, 1 - m[0, 0] - m[1, 1] + m[2, 2])) / 2
};
q.x *= Mathf.Sign(q.x * (m[2, 1] - m[1, 2]));
q.y *= Mathf.Sign(q.y * (m[0, 2] - m[2, 0]));
q.z *= Mathf.Sign(q.z * (m[1, 0] - m[0, 1]));
var translation = m.GetColumn(3);
t.localRotation = new Quaternion { w = q.w, x = -q.x, y = -q.y, z = q.z };
t.localPosition = new Vector3 { x = translation.x, y = translation.y, z = -translation.z };
t.localScale = scale;
if (keepScale)
{
t.localScale = scaleKept;
}
}
/// <summary>
/// <para xml:lang="en">Calculate and set the transform <paramref name="t"/> of one object using <paramref name="pose"/> and the other object's transform <paramref name="centerT"/>, to express the relation of the two objects in 3D space which is known in <paramref name="pose"/>.</para>
/// <para xml:lang="zh">已知两个物体的的相对关系,通过<paramref name="pose"/>以及一个物体的transform <paramref name="centerT"/>计算并设置另一个物体的transform <paramref name="t"/>,以便在三维空间中将这个关系表达出来。</para>
/// </summary>
public static void SetPoseOnTransform(Transform t, Transform centerT, Matrix44F pose, Matrix4x4 displayCompensation, bool isCamera, bool onCamera, bool manualHorizontalFlip = false)
{
Matrix4x4 translateMatrix = Matrix4x4.identity;
translateMatrix.m22 = -1;
var translateTransform = translateMatrix * Matrix4x4.TRS(centerT.position, centerT.rotation, Vector3.one) * translateMatrix;
var willSetPose = pose.ToUnityMatrix();
if (onCamera)
{
Matrix4x4 cameraTransform;
if (isCamera)
{
cameraTransform = willSetPose;
}
else
{
cameraTransform = willSetPose.inverse;
}
willSetPose = cameraTransform * displayCompensation.inverse;
}
else
{
Matrix4x4 targetTransform;
if (isCamera)
{
targetTransform = willSetPose.inverse;
}
else
{
targetTransform = willSetPose;
}
willSetPose = displayCompensation * targetTransform;
}
if (manualHorizontalFlip)
{
Matrix4x4 hFlipTranslateMatrix = Matrix4x4.identity;
hFlipTranslateMatrix.m00 = -1;
willSetPose = hFlipTranslateMatrix * willSetPose * hFlipTranslateMatrix;
}
willSetPose = translateTransform * willSetPose;
SetMatrixOnTransform(t, willSetPose, true);
}
}
}
fileFormatVersion: 2
guid: 48dae2d32eb412c429fe1157818de10c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 3ad7007cfa898bc438fac395c6cc43d5
folderAsset: yes
timeCreated: 1594182787
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
///<remarks>
/// +-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .-- .--+
/// | .
/// . +---------------------------------------------------------------+ |
/// | | | .
/// . | + -> ObjectTracker - - - - + | |
/// | v ' ' | .
/// . +--> i2FAdapter --> fbFrameFork - - > ImageTracker - - - + ' | |
/// | | ' ' | .
/// v | v v | |
/// FrameSource --> (FrameRecorder) --> iFrameThrottler --> iFrameFork --> i2OAdapter ------------------------------------> oFrameJoin --> oFrameFork --> oFrameBuffer ~~> o
/// ' ^ ^
/// ' ' '
/// + - - - - - - - - - - - - - - - - - > SparseSpatialMap - + '
/// ' '
/// + - - - - - - - - - - - - - - - - - > SurfaceTracker - - - -+
/// '
/// + - - - - - - - - - - - - - - - - - > DenseSpatialMap ~ ~ > o
/// '
/// + - - - - - - - - - - - - - - - - - > CloudRecognizer ~ ~ > o
///</remarks>
/// <summary>
/// <para xml:lang="en">Assembly of AR components. It implements one typical assemble strategy for all EasyAR Sense components. Inherit this class and override some methods can make a more customized assembly.</para>
/// <para xml:lang="zh">AR组件的组装体。它实现了一种对所有EasyAR Sense组件的典型组装。继承这个类并重载部分可以实现更定制化的组装。</para>
/// </summary>
[Serializable]
public class ARAssembly : IDisposable
{
/// <summary>
/// <para xml:lang="en"><see cref="UnityEngine.Camera"/> in the virtual world in reflection of real world camera device, its projection matrix and transform will be set to reflect the real world camera.</para>
/// <para xml:lang="en">It will be set to <see cref="Camera.main"/> when assembling if <see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>.</para>
/// <para xml:lang="zh">现实环境中相机设备在虚拟世界中对应的<see cref="UnityEngine.Camera"/>,其投影矩阵和位置都将于真实相机对应。</para>
/// <para xml:lang="zh">如果<see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>,在组装时会设为<see cref="Camera.main"/>。</para>
/// </summary>
public Camera Camera;
/// <summary>
/// <para xml:lang="en"><see cref="Transform"/> of root node of all <see cref="UnityEngine.Camera"/>s used for AR rendering.</para>
/// <para xml:lang="en">It will be set to <see cref="Camera"/> <see cref="Transform"/> when assembling if <see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>.</para>
/// <para xml:lang="zh">用于AR渲染的所有<see cref="UnityEngine.Camera"/>的根节点的<see cref="Transform"/>。</para>
/// <para xml:lang="zh">如果<see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>,在组装时会设为<see cref="Camera"/>的<see cref="Transform"/>。</para>
/// </summary>
public Transform CameraRoot;
/// <summary>
/// <para xml:lang="en"><see cref="RenderCameraController"/> list.</para>
/// <para xml:lang="en">It will be set to the list of <see cref="RenderCameraController"/> get from children of the <see cref="ARSession"/> <see cref="GameObject"/> when assembling if <see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>.</para>
/// <para xml:lang="zh"><see cref="RenderCameraController"/>的列表。</para>
/// <para xml:lang="zh">如果<see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>,在组装时会从<see cref="ARSession"/>的<see cref="GameObject"/>的所有子节点中寻找并获取<see cref="RenderCameraController"/>。</para>
/// </summary>
public List<RenderCameraController> RenderCameras = new List<RenderCameraController>();
/// <summary>
/// <para xml:lang="en">Frame source.</para>
/// <para xml:lang="en">It will be set to <see cref="easyar.FrameSource"/> get from children of the <see cref="ARSession"/> <see cref="GameObject"/> when assembling if <see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>.</para>
/// <para xml:lang="zh">Frame数据源。</para>
/// <para xml:lang="zh">如果<see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>,在组装时会从<see cref="ARSession"/>的<see cref="GameObject"/>的所有子节点中寻找并获取<see cref="easyar.FrameSource"/>。</para>
/// </summary>
public FrameSource FrameSource;
/// <summary>
/// <para xml:lang="en">Frame recorder.</para>
/// <para xml:lang="en">It will be set to <see cref="easyar.FrameSource"/> get from children of the <see cref="ARSession"/> <see cref="GameObject"/> when assembling if <see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>.</para>
/// <para xml:lang="zh">输入帧录制器。</para>
/// <para xml:lang="zh">如果<see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>,在组装时会从<see cref="ARSession"/>的<see cref="GameObject"/>的所有子节点中寻找并获取<see cref="easyar.FrameSource"/>。</para>
/// </summary>
public FrameRecorder FrameRecorder;
/// <summary>
/// <para xml:lang="en"><see cref="FrameFilter"/> list.</para>
/// <para xml:lang="en">It will be set to the list of <see cref="FrameFilter"/> get from children of the <see cref="ARSession"/> <see cref="GameObject"/> when assembling if <see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>.</para>
/// <para xml:lang="zh"><see cref="FrameFilter"/>的列表。</para>
/// <para xml:lang="zh">如果<see cref="ARSession.AssembleMode"/> == <see cref="AssembleMode.Auto"/>,在组装时会从<see cref="ARSession"/>的<see cref="GameObject"/>的所有子节点中寻找并获取<see cref="FrameFilter"/>。</para>
/// </summary>
public List<FrameFilter> FrameFilters = new List<FrameFilter>();
protected InputFrameThrottler iFrameThrottler;
protected InputFrameFork iFrameFork;
protected InputFrameToOutputFrameAdapter i2OAdapter;
protected InputFrameToFeedbackFrameAdapter i2FAdapter;
protected FeedbackFrameFork fbFrameFork;
protected OutputFrameJoin oFrameJoin;
protected OutputFrameFork oFrameFork;
protected OutputFrameBuffer oFrameBuffer;
private FramePlayer framePlayer;
private int extraBufferCapacity;
~ARAssembly()
{
DisposeAll();
}
/// <summary>
/// <para xml:lang="en">Assemble mode.</para>
/// <para xml:lang="zh">组装模式。</para>
/// </summary>
public enum AssembleMode
{
/// <summary>
/// <para xml:lang="en">Auto assemble, components will be get from the children nodes.</para>
/// <para xml:lang="zh">自动组装,此模式会自动获取子节点的组件进行装配。</para>
/// </summary>
Auto,
/// <summary>
/// <para xml:lang="en">Manual assemble.</para>
/// <para xml:lang="zh">手动组装。</para>
/// </summary>
Manual,
}
/// <summary>
/// <para xml:lang="en">The assembly can be used.</para>
/// <para xml:lang="zh">组装体可以使用。</para>
/// </summary>
public bool Ready { get; private set; }
/// <summary>
/// <para xml:lang="en">If <see cref="WorldRootController"/> is required by the assembly.</para>
/// <para xml:lang="zh">组装体是否需要<see cref="WorldRootController"/>。</para>
/// </summary>
public bool RequireWorldCenter { get; private set; }
/// <summary>
/// <para xml:lang="en">Output frame.</para>
/// <para xml:lang="zh">输出帧。</para>
/// </summary>
public Optional<OutputFrame> OutputFrame
{
get
{
if (!Ready)
{
return null;
}
return oFrameBuffer.peek();
}
}
/// <summary>
/// <para xml:lang="en">Extra device buffer capacity. When you hold a OutputFrame/InputFrame or image from InputFrame for more than one render frame, you should increase this value by one.</para>
/// <para xml:lang="zh">额外需要的设备缓冲容量。如果需要保留OutputFrame/InputFrame或InputFrame中的image超过渲染的一帧,需要增加1。</para>
/// </summary>
public int ExtraBufferCapacity
{
get
{
return extraBufferCapacity;
}
set
{
extraBufferCapacity = value;
ResetBufferCapacity();
}
}
/// <summary>
/// <para xml:lang="en">Internal use only. Display information used by the assembly.</para>
/// <para xml:lang="zh">内部使用。Assembly使用的显示设备信息。</para>
/// </summary>
public IDisplay Display
{
get
{
if (framePlayer && framePlayer.Display != null)
{
return framePlayer.Display;
}
return EasyARController.Instance.Display;
}
}
/// <summary>
/// <para xml:lang="en">Dispose resources.</para>
/// <para xml:lang="zh">销毁资源。</para>
/// </summary>
public virtual void Dispose()
{
DisposeAll();
GC.SuppressFinalize(this);
}
/// <summary>
/// <para xml:lang="en">Assemble AR components.</para>
/// <para xml:lang="zh">组装AR组件。</para>
/// </summary>
public virtual void Assemble(ARSession session)
{
if (session.AssembleMode == AssembleMode.Auto)
{
Camera = Camera.main;
CameraRoot = Camera.transform;
RenderCameras = new List<RenderCameraController>(session.GetComponentsInChildren<RenderCameraController>());
FrameSource = session.GetComponentInChildren<FrameSource>();
FrameRecorder = session.GetComponentInChildren<FrameRecorder>();
FrameFilters = new List<FrameFilter>(session.GetComponentsInChildren<FrameFilter>());
}
foreach (var renderCamera in RenderCameras) { renderCamera.OnAssemble(session); }
if (FrameSource) { FrameSource.OnAssemble(session); }
if (FrameSource && FrameSource is FramePlayer) { framePlayer = FrameSource as FramePlayer; }
if (FrameRecorder) { FrameRecorder.OnAssemble(session); }
foreach (var filter in FrameFilters) { filter.OnAssemble(session); }
try
{
Assemble();
}
catch (Exception ex)
{
Debug.LogError("Fail to Assemble: " + ex.Message);
}
}
/// <summary>
/// <para xml:lang="en">Break the assembly. The assembly cannot be used once broken.</para>
/// <para xml:lang="zh">破坏AR组件体。一旦破坏将无法再使用。</para>
/// </summary>
public void Break()
{
Ready = false;
}
/// <summary>
/// <para xml:lang="en">Pause output.</para>
/// <para xml:lang="zh">暂停输出。</para>
/// </summary>
public void Pause()
{
if (!Ready)
{
return;
}
oFrameBuffer.pause();
}
/// <summary>
/// <para xml:lang="en">Resume output.</para>
/// <para xml:lang="zh">继续输出。</para>
/// </summary>
public void Resume()
{
if (!Ready)
{
return;
}
oFrameBuffer.resume();
}
/// <summary>
/// <para xml:lang="en">Reset buffer capacity.</para>
/// <para xml:lang="zh">重置缓冲的容量。</para>
/// </summary>
public void ResetBufferCapacity()
{
if (FrameSource is CameraSource)
{
var cameraSource = FrameSource as CameraSource;
cameraSource.BufferCapacity = GetBufferRequirement();
}
}
/// <summary>
/// <para xml:lang="en">Get buffer requirement.</para>
/// <para xml:lang="zh">获取当前需要的缓冲容量。</para>
/// </summary>
protected int GetBufferRequirement()
{
int count = 1; // for OutputFrameBuffer.peek
if (FrameSource != null) { count += 1; }
if (FrameRecorder != null) { count += FrameRecorder.BufferRequirement; }
if (iFrameThrottler != null) { count += iFrameThrottler.bufferRequirement(); }
if (i2FAdapter != null) { count += i2FAdapter.bufferRequirement(); }
if (oFrameBuffer != null) { count += oFrameBuffer.bufferRequirement(); }
foreach (var filter in FrameFilters)
{
if (filter != null) { count += filter.BufferRequirement; }
}
count += extraBufferCapacity;
return count;
}
/// <summary>
/// <para xml:lang="en">Get <see cref="FrameFilter"/> number of certain type.</para>
/// <para xml:lang="zh">获取指定<see cref="FrameFilter"/>的数量。</para>
/// </summary>
protected int GetFrameFilterCount<T>()
{
if (FrameFilters == null)
{
return 0;
}
int count = 0;
foreach (var filter in FrameFilters)
{
if (filter is T)
{
count++;
}
}
return count;
}
private void Assemble()
{
// throttler
iFrameThrottler = InputFrameThrottler.create();
// fork input
iFrameFork = InputFrameFork.create(2 + GetFrameFilterCount<FrameFilter.IInputFrameSink>());
iFrameThrottler.output().connect(iFrameFork.input());
var iFrameForkIndex = 0;
i2OAdapter = InputFrameToOutputFrameAdapter.create();
iFrameFork.output(iFrameForkIndex).connect(i2OAdapter.input());
iFrameForkIndex++;
i2FAdapter = InputFrameToFeedbackFrameAdapter.create();
iFrameFork.output(iFrameForkIndex).connect(i2FAdapter.input());
iFrameForkIndex++;
foreach (var filter in FrameFilters)
{
if (filter is FrameFilter.IInputFrameSink)
{
FrameFilter.IInputFrameSink unit = filter as FrameFilter.IInputFrameSink;
var sink = unit.InputFrameSink();
if (sink != null)
{
iFrameFork.output(iFrameForkIndex).connect(unit.InputFrameSink());
}
if (filter is FrameFilter.IInputFrameSinkDelayConnect)
{
var delayUnit = filter as FrameFilter.IInputFrameSinkDelayConnect;
delayUnit.ConnectedTo(iFrameFork.output(iFrameForkIndex), ResetBufferCapacity);
}
iFrameForkIndex++;
}
}
// feedback
fbFrameFork = FeedbackFrameFork.create(GetFrameFilterCount<FrameFilter.IFeedbackFrameSink>());
i2FAdapter.output().connect(fbFrameFork.input());
var fbFrameForkIndex = 0;
foreach (var filter in FrameFilters)
{
if (filter is FrameFilter.IFeedbackFrameSink)
{
FrameFilter.IFeedbackFrameSink unit = filter as FrameFilter.IFeedbackFrameSink;
fbFrameFork.output(fbFrameForkIndex).connect(unit.FeedbackFrameSink());
fbFrameForkIndex++;
}
}
// join
oFrameJoin = OutputFrameJoin.create(1 + GetFrameFilterCount<FrameFilter.IOutputFrameSource>());
var joinIndex = 0;
foreach (var filter in FrameFilters)
{
if (filter is FrameFilter.IOutputFrameSource)
{
FrameFilter.IOutputFrameSource unit = filter as FrameFilter.IOutputFrameSource;
unit.OutputFrameSource().connect(oFrameJoin.input(joinIndex));
joinIndex++;
}
}
i2OAdapter.output().connect(oFrameJoin.input(joinIndex));
// fork output for feedback
oFrameFork = OutputFrameFork.create(2);
oFrameJoin.output().connect(oFrameFork.input());
oFrameBuffer = OutputFrameBuffer.create();
oFrameFork.output(0).connect(oFrameBuffer.input());
oFrameFork.output(1).connect(i2FAdapter.sideInput());
// signal throttler
oFrameBuffer.signalOutput().connect(iFrameThrottler.signalInput());
var inputFrameSink = iFrameThrottler.input();
// connect recorder
if (FrameRecorder)
{
FrameRecorder.Output().connect(inputFrameSink);
inputFrameSink = FrameRecorder.Input();
}
// connect source
if (FrameSource != null)
{
FrameSource.Connect(inputFrameSink);
}
// set BufferCapacity
ResetBufferCapacity();
if (FrameSource.HasSpatialInformation)
{
RequireWorldCenter = true;
}
foreach (var filter in FrameFilters)
{
if (filter is SurfaceTrackerFrameFilter)
{
if (RequireWorldCenter)
{
throw new InvalidOperationException(typeof(SurfaceTracker) + " + VIOCameraDevice is not supported");
}
RequireWorldCenter = true;
}
}
Ready = true;
}
private void DisposeAll()
{
if (iFrameThrottler != null) { iFrameThrottler.Dispose(); }
if (iFrameFork != null) { iFrameFork.Dispose(); }
if (i2OAdapter != null) { i2OAdapter.Dispose(); }
if (i2FAdapter != null) { i2FAdapter.Dispose(); }
if (fbFrameFork != null) { fbFrameFork.Dispose(); }
if (oFrameJoin != null) { oFrameJoin.Dispose(); }
if (oFrameFork != null) { oFrameFork.Dispose(); }
if (oFrameBuffer != null) { oFrameBuffer.Dispose(); }
Ready = false;
}
}
}
fileFormatVersion: 2
guid: 4060caa2b429a6145a92aae9186b2db2
timeCreated: 1575531133
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls AR session in the scene. One session contains a set of components assembled as <see cref="ARAssembly"/> and controls data flow in the whole life cycle. This class is the entrance of AR, it is possible to create a new session class and replace this one in the scene to implement fully different AR workflow.</para>
/// <para xml:lang="zh">在场景中控制AR会话的<see cref="MonoBehaviour"/>。一个会话包含一组组装成<see cref="ARAssembly"/>的组件,并控制整个生命周期的数据流。这个类是AR的入口,如果要实现完全不同的AR工作流可以创建一个新的会话类并在场景中替换这个类。</para>
/// </summary>
public class ARSession : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">AR center mode. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">AR中心模式。可随时修改,立即生效。</para>
/// </summary>
public ARCenterMode CenterMode;
/// <summary>
/// <para xml:lang="en">AR center <see cref="Target"/> when <see cref="CenterMode"/> == <see cref="ARCenterMode.FirstTarget"/> or <see cref="CenterMode"/> == <see cref="ARCenterMode.SpecificTarget"/>. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh"><see cref="CenterMode"/> == <see cref="ARCenterMode.FirstTarget"/> 或 <see cref="CenterMode"/> == <see cref="ARCenterMode.SpecificTarget"/>时的AR中心<see cref="Target"/>。可随时修改,立即生效。</para>
/// </summary>
public TargetController CenterTarget;
/// <summary>
/// <para xml:lang="en">AR center <see cref="WorldRootController"/> when <see cref="CenterMode"/> == <see cref="ARCenterMode.WorldRoot"/>. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh"><see cref="CenterMode"/> == <see cref="ARCenterMode.WorldRoot"/>时的AR中心<see cref="WorldRootController"/>。可随时修改,立即生效。</para>
/// </summary>
public WorldRootController WorldRootController;
/// <summary>
/// <para xml:lang="en">Horizontal flip rendering mode for normal camera. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">正常相机的水平镜像渲染模式。可随时修改,立即生效。</para>
/// </summary>
public ARHorizontalFlipMode HorizontalFlipNormal;
/// <summary>
/// <para xml:lang="en">Horizontal flip rendering mode for front camera. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">前置相机的水平镜像渲染模式。可随时修改,立即生效。</para>
/// </summary>
public ARHorizontalFlipMode HorizontalFlipFront = ARHorizontalFlipMode.World;
/// <summary>
/// <para xml:lang="en">Assemble mode used in <see cref="ARAssembly.Assemble(ARSession)"/>.</para>
/// <para xml:lang="zh">在<see cref="ARAssembly.Assemble(ARSession)"/>中使用的组装模式。</para>
/// </summary>
public ARAssembly.AssembleMode AssembleMode;
/// <summary>
/// <para xml:lang="en">Assembly of AR components.</para>
/// <para xml:lang="zh">AR组件的组装体。</para>
/// </summary>
[HideInInspector, SerializeField]
public ARAssembly Assembly = new ARAssembly();
private WorldRootController previousWorldRootController;
private int frameIndex = -1;
private KeyValuePair<bool, bool> frameStatus = new KeyValuePair<bool, bool>();
/// <summary>
/// <para xml:lang="en">Output frame change event delegate.</para>
/// <para xml:lang="zh">输出帧发生改变的委托。</para>
/// </summary>
public delegate void FrameChangeAction(OutputFrame outputFrame, Matrix4x4 displayCompensation);
/// <summary>
/// <para xml:lang="en">Output frame change event. It is triggered when the data itself changes, the frequency is affected by <see cref="FrameSource"/> data change (like <see cref="CameraDevice"/> FPS).</para>
/// <para xml:lang="zh">输出帧发生改变的事件。该事件会在数据本身产生变化的时候发生,频率受<see cref="FrameSource"/>数据变化(比如<see cref="CameraDevice"/>帧率)影响。</para>
/// </summary>
public event FrameChangeAction FrameChange;
/// <summary>
/// <para xml:lang="en">Output frame update event. It has the same frequency as MonoBehaviour Update.</para>
/// <para xml:lang="zh">输出帧更新事件,该更新频率和MonoBehaviour Update频率相同。</para>
/// </summary>
public event Action<OutputFrame> FrameUpdate;
/// <summary>
/// <para xml:lang="en"><see cref="WorldRootController"/> change event</para>
/// <para xml:lang="zh"><see cref="WorldRootController"/>改变的事件。</para>
/// </summary>
public event Action<WorldRootController> WorldRootChanged;
/// <summary>
/// <para xml:lang="en">AR center mode.</para>
/// <para xml:lang="zh">AR中心模式。</para>
/// </summary>
public enum ARCenterMode
{
/// <summary>
/// <para xml:lang="en">The session will use the first tracked <see cref="Target"/> as center.</para>
/// <para xml:lang="en">You can move or rotate the <see cref="Target"/> and the <see cref="UnityEngine.Camera"/> will follow. You cannot manually change the <see cref="UnityEngine.Camera"/>'s transform in this mode. The relative transform from <see cref="Target"/> to <see cref="UnityEngine.Camera"/> is controlled by <see cref="OnFrameUpdate"/> code according to <see cref="ARAssembly.OutputFrame"/> data every frame.</para>
/// <para xml:lang="zh">当前session是以第一个跟踪到的<see cref="Target"/>为中心的。</para>
/// <para xml:lang="zh">你可以移动或旋转<see cref="Target"/>,<see cref="UnityEngine.Camera"/>会跟着动。在这个模式下你将无法手动控制<see cref="UnityEngine.Camera"/>的transform。<see cref="Target"/>和<see cref="UnityEngine.Camera"/>的相对位置关系由<see cref="OnFrameUpdate"/>代码根据每帧<see cref="ARAssembly.OutputFrame"/>数据控制。</para>
/// </summary>
FirstTarget,
/// <summary>
/// <para xml:lang="en">The session is <see cref="UnityEngine.Camera"/> centered.</para>
/// <para xml:lang="en">You can move or rotate the <see cref="UnityEngine.Camera"/> and the <see cref="Target"/> will follow. You cannot manually change the <see cref="Target"/>'s transform in this mode. The relative transform from <see cref="Target"/> to <see cref="UnityEngine.Camera"/> is controlled by <see cref="OnFrameUpdate"/> code according to <see cref="ARAssembly.OutputFrame"/> data every frame.</para>
/// <para xml:lang="zh">当前session是以<see cref="UnityEngine.Camera"/>为中心的。</para>
/// <para xml:lang="zh">你可以移动或旋转<see cref="UnityEngine.Camera"/>,<see cref="Target"/>会跟着动。在这个模式下你将无法手动控制<see cref="Target"/>的transform。<see cref="Target"/>和<see cref="UnityEngine.Camera"/>的相对位置关系由<see cref="OnFrameUpdate"/>代码根据每帧<see cref="ARAssembly.OutputFrame"/>数据控制。</para>
/// </summary>
Camera,
/// <summary>
/// <para xml:lang="en">The session will use the <see cref="Target"/> specified by <see cref="CenterTarget"/> as center.</para>
/// <para xml:lang="en">If the specified <see cref="Target"/> is not found, will fall back to <see cref="UnityEngine.Camera"/> center mode. The relative transform from <see cref="Target"/> to <see cref="UnityEngine.Camera"/> is controlled by <see cref="OnFrameUpdate"/> code according to <see cref="ARAssembly.OutputFrame"/> data every frame.</para>
/// <para xml:lang="zh">当前session是以<see cref="CenterTarget"/>所指定的<see cref="Target"/>为中心的。</para>
/// <para xml:lang="zh">如果这个指定的<see cref="Target"/>没有被跟踪,将会回退到<see cref="UnityEngine.Camera"/>中心模式。<see cref="Target"/>和<see cref="UnityEngine.Camera"/>的相对位置关系由<see cref="OnFrameUpdate"/>代码根据每帧<see cref="ARAssembly.OutputFrame"/>数据控制。</para>
/// </summary>
SpecificTarget,
/// <summary>
/// <para xml:lang="en">The session will use <see cref="WorldRootController"/> as center.</para>
/// <para xml:lang="en">You can move or rotate the <see cref="WorldRootController"/> and the <see cref="UnityEngine.Camera"/> will follow. You cannot manually change the <see cref="UnityEngine.Camera"/>'s transform in this mode. The relative transform from <see cref="WorldRootController"/> to <see cref="UnityEngine.Camera"/> is controlled by <see cref="OnFrameUpdate"/> code according to <see cref="ARAssembly.OutputFrame"/> data every frame.</para>
/// <para xml:lang="zh">当前session是以<see cref="WorldRootController"/>为中心的。</para>
/// <para xml:lang="zh">你可以移动或旋转<see cref="WorldRootController"/>,<see cref="UnityEngine.Camera"/>会跟着动。在这个模式下你将无法手动控制<see cref="UnityEngine.Camera"/>的transform。<see cref="WorldRootController"/>和<see cref="UnityEngine.Camera"/>的相对位置关系由<see cref="OnFrameUpdate"/>代码根据每帧<see cref="ARAssembly.OutputFrame"/>数据控制。</para>
/// </summary>
WorldRoot,
/// <summary>
/// <para xml:lang="en">The session will behave like <see cref="Camera"/> mode, it is a mode designed for docking another AR system, like an AR eyewear SDK which usually has its own control of the <see cref="UnityEngine.Camera"/> and other objects from the system.</para>
/// <para xml:lang="en">Everything from <see cref="ARAssembly.OutputFrame"/> will be treated as camera centered, but the <see cref="UnityEngine.Camera"/> itself may be controlled by another system or code, while the whole system linked together may have another center.</para>
/// <para xml:lang="en">You can move or rotate the <see cref="UnityEngine.Camera"/> and the <see cref="Target"/> will follow. You cannot manually change the <see cref="Target"/>'s transform in this mode. The relative transform from <see cref="Target"/> to <see cref="UnityEngine.Camera"/> is controlled by <see cref="OnFrameUpdate"/> code according to <see cref="ARAssembly.OutputFrame"/> data every frame.</para>
/// <para xml:lang="zh">当前session与<see cref="Camera"/>模式行为相同。它被用来连接另一个AR系统,比如AR眼镜SDK(通常它有自己对<see cref="UnityEngine.Camera"/>和其它物体的控制策略)。</para>
/// <para xml:lang="zh"><see cref="ARAssembly.OutputFrame"/>内所有物体都将被按照camera 中心来调整,但<see cref="UnityEngine.Camera"/>自身可能会由另一个系统或另一段代码来控制,而连接在一起的整个系统可能会有另一个中心。</para>
/// <para xml:lang="zh">你可以移动或旋转<see cref="UnityEngine.Camera"/>,<see cref="Target"/>会跟着动。在这个模式下你将无法手动控制<see cref="Target"/>的transform。<see cref="Target"/>和<see cref="UnityEngine.Camera"/>的相对位置关系由<see cref="OnFrameUpdate"/>代码根据每帧<see cref="ARAssembly.OutputFrame"/>数据控制。</para>
/// </summary>
ExternalControl,
}
/// <summary>
/// <para xml:lang="en">Horizontal flip rendering mode.</para>
/// <para xml:lang="en">In a flip rendering mode, the camera image will be mirrored. And to display to tracked objects in the right way, it will affect the 3D object rendering as well, so there are two different ways of doing horizontal flip. Horizontal flip can only work in object sensing like image or object tracking algorithms.</para>
/// <para xml:lang="zh">水平镜像渲染模式。</para>
/// <para xml:lang="zh">在水平翻转状态下,相机图像将镜像显示,为确保物体跟踪正常,它同时会影响3D物体的渲染,因此提供两种不同的方式。水平翻转只能在物体感知(比如图像跟踪或物体跟踪)算法下工作。</para>
/// </summary>
public enum ARHorizontalFlipMode
{
/// <summary>
/// <para xml:lang="en">No flip.</para>
/// <para xml:lang="zh">不翻转。</para>
/// </summary>
None,
/// <summary>
/// <para xml:lang="en">Render with horizontal flip, the camera image will be flipped in rendering, the camera projection matrix will be changed to do flip rendering. Target scale will not change.</para>
/// <para xml:lang="zh">水平镜像渲染,camera图像会镜像显示,camera投影矩阵会变化进行镜像渲染,target scale不会改变。</para>
/// </summary>
World,
/// <summary>
/// <para xml:lang="en">Render with horizontal flip, the camera image will be flipped in rendering, the target scale will be changed to do flip rendering. Camera projection matrix will not change.</para>
/// <para xml:lang="zh">水平镜像渲染,camera图像会镜像显示,target scale会改变进行镜像渲染,camera投影矩阵不会改变。</para>
/// </summary>
Target,
}
/// <summary>
/// <para xml:lang="en"><see cref="CameraParameters"/> from current frame.</para>
/// <para xml:lang="zh">当前帧的<see cref="CameraParameters"/>。</para>
/// </summary>
public Optional<CameraParameters> FrameCameraParameters { get; private set; }
/// <summary>
/// MonoBehaviour Start
/// </summary>
private void Start()
{
if (!EasyARController.Initialized)
{
return;
}
Assembly.Assemble(this);
if (!WorldRootController) { WorldRootController = FindObjectOfType<WorldRootController>(); }
}
/// <summary>
/// MonoBehaviour Update
/// </summary>
private void Update()
{
if (!Assembly.Ready)
{
OnEmptyFrame();
return;
}
if (WorldRootController != previousWorldRootController)
{
if (WorldRootChanged != null)
{
WorldRootChanged(WorldRootController);
}
previousWorldRootController = WorldRootController;
}
var oFrame = Assembly.OutputFrame;
if (oFrame.OnNone)
{
OnEmptyFrame();
return;
}
using (var outputFrame = oFrame.Value)
using (var iFrame = outputFrame.inputFrame())
{
if (FrameCameraParameters.OnSome)
{
FrameCameraParameters.Value.Dispose();
}
FrameCameraParameters = iFrame.cameraParameters();
var displayCompensation = GetCompensation(FrameCameraParameters.Value);
var index = iFrame.index();
if (frameIndex != index && FrameChange != null)
{
FrameChange(outputFrame, displayCompensation);
}
frameIndex = index;
// update self first, some flags will pass down to other components
OnFrameUpdate(outputFrame, iFrame, displayCompensation);
if (FrameUpdate != null)
{
FrameUpdate(outputFrame);
}
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
private void OnDestroy()
{
Assembly.Dispose();
if (FrameCameraParameters.OnSome)
{
FrameCameraParameters.Value.Dispose();
}
}
/// <summary>
/// <para xml:lang="en">Transforms points from screen coordinate system ([0, 1]^2) to image coordinate system ([0, 1]^2). <paramref name="pointInView"/> should be normalized to [0, 1]^2.</para>
/// <para xml:lang="zh">从屏幕坐标系([0, 1]^2)变换到图像坐标系([0, 1]^2)。<paramref name="pointInView"/> 需要被归一化到[0, 1]^2。</para>
/// </summary>
public Optional<Vector2> ImageCoordinatesFromScreenCoordinates(Vector2 pointInView)
{
if (FrameCameraParameters.OnNone || !Assembly.Camera)
{
return Optional<Vector2>.CreateNone();
}
return FrameCameraParameters.Value.imageCoordinatesFromScreenCoordinates(
Assembly.Camera.aspect, Assembly.Display.Rotation, true, false, new Vec2F(pointInView.x, 1 - pointInView.y)).ToUnityVector();
}
private void OnFrameUpdate(OutputFrame outputFrame, InputFrame inputFrame, Matrix4x4 displayCompensation)
{
// world root
if (Assembly.RequireWorldCenter && !WorldRootController)
{
Debug.Log("WorldRoot not found, create from " + typeof(ARSession));
var gameObject = new GameObject("WorldRoot");
WorldRootController = gameObject.AddComponent<WorldRootController>();
if (WorldRootChanged != null)
{
WorldRootChanged(WorldRootController);
}
previousWorldRootController = WorldRootController;
}
if (!Assembly.RequireWorldCenter && CenterMode == ARCenterMode.WorldRoot)
{
Debug.LogWarning("ARCenterMode.WorldRoot not available for target only tracking");
CenterMode = ARCenterMode.FirstTarget;
}
// horizontal flip
var hflip = HorizontalFlipNormal;
using (var cameraParameters = inputFrame.cameraParameters())
{
if (cameraParameters.cameraDeviceType() == CameraDeviceType.Front)
{
hflip = HorizontalFlipFront;
}
}
var worldHFlip = false;
var targetHFlip = false;
switch (hflip)
{
case ARHorizontalFlipMode.World:
worldHFlip = true;
targetHFlip = false;
break;
case ARHorizontalFlipMode.Target:
worldHFlip = false;
targetHFlip = true;
break;
default:
break;
}
foreach (var renderCamera in Assembly.RenderCameras)
{
renderCamera.SetProjectHFlip(worldHFlip);
renderCamera.SetRenderImageHFilp(worldHFlip || targetHFlip);
}
foreach (var filter in Assembly.FrameFilters)
{
filter.SetHFlip(targetHFlip);
}
// dispatch results
var results = outputFrame.results();
var motionTrackingStatus = Optional<MotionTrackingStatus>.CreateNone();
if (inputFrame.hasSpatialInformation())
{
motionTrackingStatus = inputFrame.trackingStatus();
}
var resultControllers = DispatchResults(results, motionTrackingStatus);
// get camera pose if available
var cameraPose = Optional<Matrix44F>.Empty;
if (Assembly.RequireWorldCenter)
{
if (motionTrackingStatus.OnSome)
{
if (motionTrackingStatus.Value != MotionTrackingStatus.NotTracking)
{
cameraPose = inputFrame.cameraTransform();
}
}
else
{
foreach (var result in resultControllers)
{
if (result.Key.OnNone)
{
cameraPose = result.Value;
break;
}
}
}
}
// get center target pose if available
var centerTargetPose = Optional<Matrix44F>.Empty;
if (CenterMode == ARCenterMode.FirstTarget || CenterMode == ARCenterMode.SpecificTarget)
{
foreach (var result in resultControllers)
{
if (!CenterTarget)
break;
if (result.Key.OnNone)
continue;
if (result.Key == CenterTarget)
{
centerTargetPose = result.Value;
break;
}
}
if (CenterMode == ARCenterMode.FirstTarget && centerTargetPose.OnNone)
{
foreach (var result in resultControllers)
{
if (result.Key.OnNone)
continue;
CenterTarget = result.Key.Value;
centerTargetPose = result.Value;
break;
}
}
}
else
{
CenterTarget = null;
}
// set camera transform first
if (CenterMode == ARCenterMode.FirstTarget || CenterMode == ARCenterMode.SpecificTarget)
{
if (CenterTarget && centerTargetPose.OnSome)
{
TransformUtil.SetTargetPoseOnCamera(Assembly.CameraRoot, CenterTarget, centerTargetPose.Value, displayCompensation, targetHFlip);
}
}
else if (CenterMode == ARCenterMode.WorldRoot)
{
if (WorldRootController && cameraPose.OnSome)
{
TransformUtil.SetCameraPoseOnCamera(Assembly.CameraRoot, WorldRootController, cameraPose.Value, displayCompensation, targetHFlip);
}
}
// set target and world root transform
if (CenterMode == ARCenterMode.Camera)
{
foreach (var result in resultControllers)
{
if (result.Key.OnSome)
{
TransformUtil.SetTargetPoseOnTarget(Assembly.CameraRoot, result.Key.Value, result.Value, displayCompensation, targetHFlip);
}
}
if (WorldRootController && cameraPose.OnSome)
{
TransformUtil.SetCameraPoseOnWorldRoot(Assembly.CameraRoot, WorldRootController, cameraPose.Value, displayCompensation, targetHFlip);
}
}
else if (CenterMode == ARCenterMode.WorldRoot)
{
foreach (var result in resultControllers)
{
if (result.Key.OnSome)
{
TransformUtil.SetTargetPoseOnTarget(Assembly.CameraRoot, result.Key.Value, result.Value, displayCompensation, targetHFlip);
}
}
}
else if (CenterMode == ARCenterMode.FirstTarget || CenterMode == ARCenterMode.SpecificTarget)
{
foreach (var result in resultControllers)
{
if (result.Key.OnSome && result.Key.Value != CenterTarget)
{
TransformUtil.SetTargetPoseOnTarget(Assembly.CameraRoot, result.Key.Value, result.Value, displayCompensation, targetHFlip);
}
}
if (WorldRootController && cameraPose.OnSome)
{
TransformUtil.SetCameraPoseOnWorldRoot(Assembly.CameraRoot, WorldRootController, cameraPose.Value, displayCompensation, targetHFlip);
}
}
else if (CenterMode == ARCenterMode.ExternalControl)
{
foreach (var result in resultControllers)
{
if (result.Key.OnSome)
{
TransformUtil.SetTargetPoseOnTarget(Assembly.CameraRoot, result.Key.Value, result.Value, displayCompensation, targetHFlip);
}
}
}
// dispose results
foreach (var result in results)
{
if (result.OnSome)
{
result.Value.Dispose();
}
}
}
private void OnEmptyFrame()
{
if (frameStatus.Key)
{
if (FrameChange != null)
{
FrameChange(null, Matrix4x4.identity);
}
DispatchResults(null, frameStatus.Value ? MotionTrackingStatus.NotTracking : Optional<MotionTrackingStatus>.CreateNone());
}
if (FrameCameraParameters.OnSome)
{
FrameCameraParameters.Value.Dispose();
FrameCameraParameters = Optional<CameraParameters>.CreateNone();
}
}
private List<KeyValuePair<Optional<TargetController>, Matrix44F>> DispatchResults(Optional<List<Optional<FrameFilterResult>>> results, Optional<MotionTrackingStatus> motionTrackingStatus)
{
var resultControllers = new List<KeyValuePair<Optional<TargetController>, Matrix44F>>();
var joinIndex = 0;
foreach (var filter in Assembly.FrameFilters)
{
if (!filter)
{
Assembly.Break();
}
if (filter is FrameFilter.IOutputFrameSource)
{
var outputFrameSource = filter as FrameFilter.IOutputFrameSource;
var list = outputFrameSource.OnResult(results.OnSome ? results.Value[joinIndex] : null);
if (list != null)
{
resultControllers.AddRange(list);
}
joinIndex++;
}
if (motionTrackingStatus.OnSome && filter is FrameFilter.ISpatialInformationSink)
{
(filter as FrameFilter.ISpatialInformationSink).OnTracking(motionTrackingStatus.Value);
}
}
if (Assembly.RequireWorldCenter)
{
if (motionTrackingStatus.OnSome)
{
WorldRootController.OnTracking(motionTrackingStatus.Value);
}
else
{
var trackingStatus = MotionTrackingStatus.NotTracking;
foreach (var result in resultControllers)
{
if (result.Key.OnNone)
{
trackingStatus = MotionTrackingStatus.Tracking;
break;
}
}
WorldRootController.OnTracking(trackingStatus);
}
}
frameStatus = new KeyValuePair<bool, bool>(results.OnSome, motionTrackingStatus.OnSome);
return resultControllers;
}
private Matrix4x4 GetCompensation(CameraParameters camParams)
{
var imageRotation = camParams.imageOrientation(Assembly.Display.Rotation) / 180f * Mathf.PI;
Matrix4x4 rotationMatrix = Matrix4x4.identity;
rotationMatrix.m00 = Mathf.Cos(-imageRotation);
rotationMatrix.m01 = -Mathf.Sin(-imageRotation);
rotationMatrix.m10 = Mathf.Sin(-imageRotation);
rotationMatrix.m11 = Mathf.Cos(-imageRotation);
return rotationMatrix;
}
}
}
fileFormatVersion: 2
guid: e61c430477d9c324db3b8fbf8ea02a63
timeCreated: 1562756715
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Abstracts frame filter, used when assemble, to run algorithms using input frame data.</para>
/// <para xml:lang="zh">抽象frame filter,在组装时使用,使用frame输入数据运行算法。</para>
/// </summary>
public abstract class FrameFilter : MonoBehaviour
{
protected bool horizontalFlip;
/// <summary>
/// <para xml:lang="en">Camera buffers occupied in this component.</para>
/// <para xml:lang="zh">当前组件占用camera buffer的数量。</para>
/// </summary>
public abstract int BufferRequirement
{
get;
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Assemble response.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。组装响应方法。</para>
/// </summary>
public virtual void OnAssemble(ARSession session)
{
}
/// <summary>
/// <para xml:lang="en">Set horizontal flip when using <see cref="ARSession.ARHorizontalFlipMode.Target"/> mode.</para>
/// <para xml:lang="zh">在<see cref="ARSession.ARHorizontalFlipMode.Target"/>模式下设置镜像翻转。</para>
/// </summary>
public void SetHFlip(bool hFlip)
{
if (horizontalFlip != hFlip)
{
horizontalFlip = hFlip;
OnHFlipChange(horizontalFlip);
}
}
/// <summary>
/// <para xml:lang="en">Horizontal flip response.</para>
/// <para xml:lang="zh">水平翻转响应方法。</para>
/// </summary>
protected virtual void OnHFlipChange(bool hFlip)
{
}
/// <summary>
/// <para xml:lang="en">Interface for feedback frame input port.</para>
/// <para xml:lang="zh">反馈帧输入端口接口。</para>
/// </summary>
public interface IFeedbackFrameSink
{
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Feedback frame input port.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。反馈帧输入端口。</para>
/// </summary>
FeedbackFrameSink FeedbackFrameSink();
}
/// <summary>
/// <para xml:lang="en">Interface for input frame input port.</para>
/// <para xml:lang="zh">输入帧输入端口接口。</para>
/// </summary>
public interface IInputFrameSink
{
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Input frame input port.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。输入帧输入端口。</para>
/// </summary>
InputFrameSink InputFrameSink();
}
/// <summary>
/// <para xml:lang="en">Interface for input frame input port using delayed connect.</para>
/// <para xml:lang="zh">延迟连接的输入帧输入端口接口。</para>
/// </summary>
public interface IInputFrameSinkDelayConnect
{
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Delay connect to input frame output port, and run <paramref name="action"/> when connect happens.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。延迟连接输入帧输出端口,并在连接时执行<paramref name="action"/>。</para>
/// </summary>
void ConnectedTo(InputFrameSource val, Action action);
}
/// <summary>
/// <para xml:lang="en">Interface for output frame output port.</para>
/// <para xml:lang="zh">输出帧输出端口接口。</para>
/// </summary>
public interface IOutputFrameSource
{
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Output frame output port.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。输出帧输出端口。</para>
/// </summary>
OutputFrameSource OutputFrameSource();
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Process tracking results.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。处理跟踪结果。</para>
/// </summary>
List<KeyValuePair<Optional<TargetController>, Matrix44F>> OnResult(Optional<FrameFilterResult> frameFilterResult);
}
/// <summary>
/// <para xml:lang="en">Interface for spatial information input port.</para>
/// <para xml:lang="zh">空间信息输入端口接口。</para>
/// </summary>
public interface ISpatialInformationSink
{
/// <summary>
/// <para xml:lang="en">Tracking status.</para>
/// <para xml:lang="zh">跟踪状态。</para>
/// </summary>
MotionTrackingStatus TrackingStatus
{
get;
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Process tracking results.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。处理跟踪结果。</para>
/// </summary>
void OnTracking(MotionTrackingStatus status);
}
}
}
fileFormatVersion: 2
guid: 602dbadc81d913a499ed31d4b7ca2e30
timeCreated: 1562756811
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System.Collections;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="InputFramePlayer"/> in the scene, providing a few extensions in the Unity environment. There is no need to use <see cref="InputFramePlayer"/> directly.</para>
/// <para xml:lang="zh">在场景中控制<see cref="InputFramePlayer"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。不需要直接使用<see cref="InputFramePlayer"/>。</para>
/// </summary>
public class FramePlayer : FrameSource
{
/// <summary>
/// <para xml:lang="en">File path type. Set before OnEnable or Start.</para>
/// <para xml:lang="zh">路径类型。可以在OnEnable或Start之前设置。</para>
/// </summary>
public WritablePathType FilePathType;
/// <summary>
/// <para xml:lang="en">File path. Set before OnEnable or Start.</para>
/// <para xml:lang="zh">文件路径。可以在OnEnable或Start之前设置。</para>
/// </summary>
public string FilePath = string.Empty;
private InputFramePlayer player;
private bool isStarted;
private bool isPrepared;
private bool isPaused;
private DisplayEmulator display;
/// <summary>
/// <para xml:lang="en"> Whether the playback is completed.</para>
/// <para xml:lang="zh"> 是否已完成播放。</para>
/// </summary>
public bool IsCompleted
{
get
{
if (isPrepared)
{
return player.isCompleted();
}
return false;
}
}
/// <summary>
/// <para xml:lang="en"> Total expected playback time. The unit is second.</para>
/// <para xml:lang="zh"> 预期的总播放时间。单位为秒。</para>
/// </summary>
public float Length
{
get
{
if (isPrepared)
{
return (float)player.totalTime();
}
return 0;
}
}
/// <summary>
/// <para xml:lang="en"> Current time played.</para>
/// <para xml:lang="zh"> 已经播放的时间。</para>
/// </summary>
public float Time
{
get
{
if (isPrepared)
{
return (float)player.currentTime();
}
return 0;
}
}
public override bool HasSpatialInformation
{
get { return true; }
}
internal IDisplay Display
{
get { return display; }
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
player = InputFramePlayer.create();
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
if (player != null && isStarted && !isPaused)
{
player.resume();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
Play();
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected override void OnDisable()
{
base.OnDisable();
if (player != null)
{
player.pause();
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (player != null)
{
player.Dispose();
}
}
public bool Play()
{
if (isPrepared)
{
isPaused = false;
if (enabled)
{
player.resume();
}
return true;
}
var path = FilePath;
if (FilePathType == WritablePathType.PersistentDataPath)
{
path = Application.persistentDataPath + "/" + path;
}
isPrepared = player.start(path);
isPaused = false;
if (isPrepared)
{
display = new DisplayEmulator();
display.EmulateRotation(player.initalScreenRotation());
}
else
{
GUIPopup.EnqueueMessage(typeof(FramePlayer) + " fail to start with file: " + path, 5);
}
if (enabled)
{
OnEnable();
}
return isPrepared;
}
public void Stop()
{
isPrepared = false;
isPaused = false;
display = null;
OnDisable();
if (player != null)
{
player.stop();
}
}
public void Pause()
{
if (isPrepared)
{
isPaused = true;
player.pause();
}
}
public override void Connect(InputFrameSink val)
{
base.Connect(val);
if (player != null)
{
player.output().connect(val);
}
}
}
}
fileFormatVersion: 2
guid: 1046a0bb047ad0045b78b6fea91459f2
timeCreated: 1593760373
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="InputFrameRecorder"/> in the scene, providing a few extensions in the Unity environment. There is no need to use <see cref="InputFrameRecorder"/> directly.</para>
/// <para xml:lang="en"><see cref="Behaviour.enabled"/> can be used to control record start/stop.</para>
/// <para xml:lang="zh">在场景中控制<see cref="InputFrameRecorder"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。不需要直接使用<see cref="InputFrameRecorder"/>。</para>
/// <para xml:lang="zh"><see cref="Behaviour.enabled"/>可以控制录制开始和结束。</para>
/// </summary>
public class FrameRecorder : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">File path type. Set before OnEnable or Start.</para>
/// <para xml:lang="zh">路径类型。可以在OnEnable或Start之前设置。</para>
/// </summary>
public WritablePathType FilePathType;
/// <summary>
/// <para xml:lang="en">File path. Set before OnEnable or Start.</para>
/// <para xml:lang="zh">文件路径。可以在OnEnable或Start之前设置。</para>
/// </summary>
public string FilePath = string.Empty;
private InputFrameRecorder recorder;
private bool isStarted;
private ARSession arSession;
/// <summary>
/// <para xml:lang="en">Camera buffers occupied in this component.</para>
/// <para xml:lang="zh">当前组件占用camera buffer的数量。</para>
/// </summary>
public int BufferRequirement
{
get
{
return recorder.bufferRequirement();
}
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
recorder = InputFrameRecorder.create();
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (recorder != null && isStarted)
{
var path = FilePath;
if (FilePathType == WritablePathType.PersistentDataPath)
{
path = Application.persistentDataPath + "/" + path;
}
var status = recorder.start(path, arSession.Assembly.Display.Rotation);
if (!status)
{
GUIPopup.EnqueueMessage(typeof(FrameRecorder) + " fail to start with file: " + path, 5);
}
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
if (enabled)
{
OnEnable();
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (recorder == null)
{
return;
}
recorder.stop();
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (recorder != null)
{
recorder.Dispose();
}
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Assemble response.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。组装响应方法。</para>
/// </summary>
public void OnAssemble(ARSession session)
{
arSession = session;
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Assemble response.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。组装响应方法。</para>
/// </summary>
public InputFrameSource Output()
{
return recorder.output();
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Assemble response.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。组装响应方法。</para>
/// </summary>
public InputFrameSink Input()
{
return recorder.input();
}
}
}
fileFormatVersion: 2
guid: b40768300a6291547a6e26ee2c5018cd
timeCreated: 1594131306
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Abstracts frame source, used when assemble, to provide input frame data to the algorithms.</para>
/// <para xml:lang="zh">抽象frame源,在组装时使用,提供算法所需的frame输入数据。</para>
/// </summary>
public abstract class FrameSource : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">Input port connected.</para>
/// <para xml:lang="zh">连接着的输入端口。</para>
/// </summary>
protected InputFrameSink sink;
/// <summary>
/// <para xml:lang="en">Current connected ARSession.</para>
/// <para xml:lang="zh">当前连接的ARSession。</para>
/// </summary>
protected ARSession arSession;
/// <summary>
/// <para xml:lang="en">Whether spatial information can be provided by the source.</para>
/// <para xml:lang="zh">源是否含有空间定位信息。</para>
/// </summary>
public abstract bool HasSpatialInformation
{
get;
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (arSession)
{
arSession.Assembly.Resume();
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (arSession)
{
arSession.Assembly.Pause();
}
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Connect input port.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。连接输入端口。</para>
/// </summary>
public virtual void Connect(InputFrameSink val)
{
sink = val;
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Assemble response.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。组装响应方法。</para>
/// </summary>
public virtual void OnAssemble(ARSession session)
{
arSession = session;
}
}
}
fileFormatVersion: 2
guid: ec0a026cc428e7e4681cb127747385eb
timeCreated: 1562757672
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="Target"/> in the scene, providing a few extensions in the Unity environment.</para>
/// <para xml:lang="zh">在场景中控制<see cref="Target"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。</para>
/// </summary>
public abstract class TargetController : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">Strategy to control the <see cref="GameObject.active"/>. If you are willing to control <see cref="GameObject.active"/> or there are other components controlling <see cref="GameObject.active"/>, make sure to set it to <see cref="ActiveControlStrategy.None"/>.</para>
/// <para xml:lang="zh"><see cref="GameObject.active"/>的控制策略。如果你打算自己控制<see cref="GameObject.active"/>或是有其它组件在控制<see cref="GameObject.active"/>,需要设为<see cref="ActiveControlStrategy.None"/>。</para>
/// </summary>
public ActiveControlStrategy ActiveControl;
/// <summary>
/// <para xml:lang="en">Horizontal flip control, usually for internal use.</para>
/// <para xml:lang="zh">水平翻转控制,一般为内部使用。</para>
/// </summary>
public bool HorizontalFlip;
private bool firstFound;
/// <summary>
/// <para xml:lang="en"><see cref="Target"/> found event.</para>
/// <para xml:lang="zh"><see cref="Target"/>找到的事件。</para>
/// </summary>
public event Action TargetFound;
/// <summary>
/// <para xml:lang="en"><see cref="Target"/> lost event.</para>
/// <para xml:lang="zh"><see cref="Target"/>丢失的事件。</para>
/// </summary>
public event Action TargetLost;
/// <summary>
/// <para xml:lang="en">Strategy to control the <see cref="GameObject.active"/>.</para>
/// <para xml:lang="zh"><see cref="GameObject.active"/>的控制策略。</para>
/// </summary>
public enum ActiveControlStrategy
{
/// <summary>
/// <para xml:lang="en">Active is true when the target is tracked, false when not tracked.</para>
/// <para xml:lang="zh">当没有被识别跟踪时Active为false,当被跟踪识别时Active为true。</para>
/// </summary>
HideWhenNotTracking,
/// <summary>
/// <para xml:lang="en">False before the fist <see cref="TargetFound"/> event, then true.</para>
/// <para xml:lang="zh">在第一次<see cref="TargetFound"/>事件之前Active为false,之后为true。</para>
/// </summary>
HideBeforeFirstFound,
/// <summary>
/// <para xml:lang="en">Do not control <see cref="GameObject.active"/>.</para>
/// <para xml:lang="zh">不控制<see cref="GameObject.active"/>。</para>
/// </summary>
None,
}
/// <summary>
/// <para xml:lang="en">Is the target being tracked at the moment.</para>
/// <para xml:lang="zh">当前target是否被跟踪。</para>
/// </summary>
public bool IsTracked { get; private set; }
/// <summary>
/// <para xml:lang="en">Is the target loaded by a tracker.</para>
/// <para xml:lang="zh">是否被一个trakcer加载。</para>
/// </summary>
public bool IsLoaded { get; protected set; }
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
if (!IsTracked && (ActiveControl == ActiveControlStrategy.HideWhenNotTracking || ActiveControl == ActiveControlStrategy.HideBeforeFirstFound))
{
gameObject.SetActive(false);
}
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Process tracking event.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。处理跟踪事件。</para>
/// </summary>
internal void OnTracking(bool status)
{
if (IsTracked != status)
{
if (status)
{
if (ActiveControl == ActiveControlStrategy.HideWhenNotTracking || (ActiveControl == ActiveControlStrategy.HideBeforeFirstFound && !firstFound))
{
gameObject.SetActive(true);
}
firstFound = true;
if (TargetFound != null)
{
TargetFound();
}
}
else
{
if (ActiveControl == ActiveControlStrategy.HideWhenNotTracking)
{
gameObject.SetActive(false);
}
if (TargetLost != null)
{
TargetLost();
}
}
IsTracked = status;
}
if (IsTracked)
{
OnTracking();
}
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Process tracking event.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。处理跟踪事件。</para>
/// </summary>
protected abstract void OnTracking();
}
}
fileFormatVersion: 2
guid: d158070dfb07b474c90254606b6b3e89
timeCreated: 1566962876
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls the world root in the scene.</para>
/// <para xml:lang="en">The world root is a virtual node, representing the relative node when the camera moves in a motion tracking system. It will be automatically generated to be the origin of the global coordinate system when needed if not manually set in the scene.</para>
/// <para xml:lang="zh">在场景中控制世界根节点的<see cref="MonoBehaviour"/>。</para>
/// <para xml:lang="zh">世界根节点是一个虚拟的节点,它表示在运动跟踪的系统中,camera移动的相对节点。如果场景中没有手动设置这个节点,它将在被需要的时候自动被设置为全局坐标系的原点。</para>
/// </summary>
public class WorldRootController : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">Strategy to control the <see cref="GameObject.active"/>. If you are willing to control <see cref="GameObject.active"/> or there are other components controlling <see cref="GameObject.active"/>, make sure to set it to <see cref="ActiveControlStrategy.None"/>.</para>
/// <para xml:lang="zh"><see cref="GameObject.active"/>的控制策略。如果你打算自己控制<see cref="GameObject.active"/>或是有其它组件在控制<see cref="GameObject.active"/>,需要设为<see cref="ActiveControlStrategy.None"/>。</para>
/// </summary>
public ActiveControlStrategy ActiveControl;
private bool trackingStarted;
/// <summary>
/// <para xml:lang="en">Motion tracking status change event.</para>
/// <para xml:lang="zh">跟踪状态改变的事件。</para>
/// </summary>
public event Action<MotionTrackingStatus> TrackingStatusChanged;
/// <summary>
/// <para xml:lang="en">Strategy to control the <see cref="GameObject.active"/>.</para>
/// <para xml:lang="zh"><see cref="GameObject.active"/>的控制策略。</para>
/// </summary>
public enum ActiveControlStrategy
{
/// <summary>
/// <para xml:lang="en">Active is false when the motion tracking status is not tracking, true otherwise.</para>
/// <para xml:lang="zh">当运动跟踪状态是未跟踪时Active为false,其它情况Active为true。</para>
/// </summary>
HideWhenNotTracking,
/// <summary>
/// <para xml:lang="en">False before the motion tracking status turns to a tracking status, then true.</para>
/// <para xml:lang="zh">在运动跟踪状态第一次不是未跟踪前Active为false,之后为true。</para>
/// </summary>
HideBeforeTrackingStart,
/// <summary>
/// <para xml:lang="en">Do not control <see cref="GameObject.active"/>.</para>
/// <para xml:lang="zh">不控制<see cref="GameObject.active"/>。</para>
/// </summary>
None,
}
/// <summary>
/// <para xml:lang="en">Motion tracking status at the moment.</para>
/// <para xml:lang="zh">当前运动跟踪状态。</para>
/// </summary>
public MotionTrackingStatus TrackingStatus
{
get; private set;
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
if (TrackingStatus == MotionTrackingStatus.NotTracking && (ActiveControl == ActiveControlStrategy.HideBeforeTrackingStart || ActiveControl == ActiveControlStrategy.HideWhenNotTracking))
{
gameObject.SetActive(false);
}
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Process tracking event.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。处理跟踪事件。</para>
/// </summary>
internal void OnTracking(MotionTrackingStatus status)
{
if (TrackingStatus != status)
{
if (ActiveControl == ActiveControlStrategy.HideWhenNotTracking || (ActiveControl == ActiveControlStrategy.HideBeforeTrackingStart && !trackingStarted))
{
gameObject.SetActive(!(status == MotionTrackingStatus.NotTracking));
}
if (!trackingStarted && status != MotionTrackingStatus.NotTracking)
{
trackingStarted = true;
}
if (TrackingStatusChanged != null)
{
TrackingStatusChanged(status);
}
TrackingStatus = status;
}
}
}
}
fileFormatVersion: 2
guid: 8c761ac074d64224388d60d508467aeb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment