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

update final design

parent 1444629e
fileFormatVersion: 2
guid: a1f9a37fb6b1dce449890c0306029eec
folderAsset: yes
timeCreated: 1594182817
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.Runtime.InteropServices;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls map mesh blocks generated by <see cref="DenseSpatialMap"/> in the scene.</para>
/// <para xml:lang="zh">在场景中控制<see cref="DenseSpatialMap"/>生成的地图网格块的<see cref="MonoBehaviour"/>。</para>
/// </summary>
public class DenseSpatialMapBlockController : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">Map mesh block information.</para>
/// <para xml:lang="zh">地图网格块信息。</para>
/// </summary>
public BlockInfo Info { get; private set; }
private Mesh mesh;
private Vector3[] vertices;
private Vector3[] normals;
private int[] indexes;
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
mesh = new Mesh();
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (mesh)
{
Destroy(mesh);
}
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void UpdateData(BlockInfo info, SceneMesh easyarMesh)
{
Info = info;
if (Info.numOfVertex == 0)
{
vertices = null;
normals = null;
indexes = null;
gameObject.SetActive(false);
return;
}
gameObject.SetActive(true);
CopyMeshData(easyarMesh);
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.normals = normals;
mesh.SetTriangles(indexes, 0);
var collider = GetComponent<MeshCollider>();
if (collider)
{
collider.sharedMesh = mesh;
}
var filter = GetComponent<MeshFilter>();
if (filter)
{
filter.sharedMesh = mesh;
}
vertices = null;
normals = null;
indexes = null;
}
private void CopyMeshData(SceneMesh easyarMesh)
{
using (var verticesBuffer = easyarMesh.getVerticesIncremental())
using (var normalBuffer = easyarMesh.getNormalsIncremental())
using (var indicesBuffer = easyarMesh.getIndicesIncremental())
{
using (var vb = verticesBuffer.partition(Info.startPointOfVertex * 12, Info.numOfVertex * 12))
{
var vbData = new float[Info.numOfVertex * 3];
Marshal.Copy(vb.data(), vbData, 0, vbData.Length);
vertices = new Vector3[Info.numOfVertex];
for (int i = 0; i < Info.numOfVertex; ++i)
{
var idx = i * 3;
vertices[i] = new Vector3(vbData[idx], vbData[idx + 1], -vbData[idx + 2]);
}
}
using (var nb = easyarMesh.getNormalsIncremental().partition(Info.startPointOfVertex * 12, Info.numOfVertex * 12))
{
var nbData = new float[Info.numOfVertex * 3];
Marshal.Copy(nb.data(), nbData, 0, nbData.Length);
normals = new Vector3[Info.numOfVertex];
for (int i = 0; i < Info.numOfVertex; ++i)
{
var idx = i * 3;
normals[i] = new Vector3(nbData[idx], nbData[idx + 1], -nbData[idx + 2]);
}
}
using (var ib = easyarMesh.getIndicesIncremental().partition(Info.startPointOfIndex * 4, Info.numOfIndex * 4))
{
indexes = new int[Info.numOfIndex - Info.numOfIndex % 3];
Marshal.Copy(ib.data(), indexes, 0, indexes.Length);
for (int i = 2; i < Info.numOfIndex; i += 3)
{
var tmp = indexes[i];
indexes[i] = indexes[i - 1];
indexes[i - 1] = tmp;
}
}
}
}
}
}
fileFormatVersion: 2
guid: 780cd5842a0bd04429004697f975f1e7
MonoImporter:
externalObjects: {}
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 <see cref="DenseSpatialMap"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Builder"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="DenseSpatialMap"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Builder"/>。</para>
/// </summary>
public class DenseSpatialMapBuilderFrameFilter : FrameFilter, FrameFilter.IInputFrameSink, FrameFilter.ISpatialInformationSink
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after Awake if available.</para>
/// <para xml:lang="zh">EasyAR Sense API,如果功能可以使用,可以在Awake之后访问。</para>
/// </summary>
public DenseSpatialMap Builder { get; private set; }
/// <summary>
/// <para xml:lang="en"><see cref="Material"/> for map mesh render.</para>
/// <para xml:lang="zh">用于渲染Map网格的<see cref="Material"/>。</para>
/// </summary>
public Material MapMeshMaterial;
/// <summary>
/// <para xml:lang="en">The max number of mesh blocks to be updated each frame. Decrease this value if the mesh update slows rendering.</para>
/// <para xml:lang="zh">每帧更新网格块的最大数量。如果网格更新使渲染变慢可以降低这个数值。</para>
/// </summary>
public int BlockUpdateLimitation = 5;
private Dictionary<Vector3, DenseSpatialMapBlockController> blocksDict = new Dictionary<Vector3, DenseSpatialMapBlockController>();
private List<DenseSpatialMapBlockController> dirtyBlocks = new List<DenseSpatialMapBlockController>();
private GameObject mapRoot;
private bool isStarted;
private bool renderMesh = true;
private Material mapMaterial;
private DenseSpatialMapDepthRenderer depthRenderer;
/// <summary>
/// <para xml:lang="en">Event when a new mesh block created.</para>
/// <para xml:lang="zh">新网格块创建的事件。</para>
/// </summary>
public event Action<DenseSpatialMapBlockController> MapCreate;
/// <summary>
/// <para xml:lang="en">Event when mesh block updates.</para>
/// <para xml:lang="zh">网格块更新的事件。</para>
/// </summary>
public event Action<List<DenseSpatialMapBlockController>> MapUpdate;
public override int BufferRequirement
{
get { return Builder.bufferRequirement(); }
}
public MotionTrackingStatus TrackingStatus
{
get; private set;
}
/// <summary>
/// <para xml:lang="en">Mesh render on/off.</para>
/// <para xml:lang="zh">是否渲染网格。</para>
/// </summary>
public bool RenderMesh
{
get { return renderMesh; }
set
{
renderMesh = value;
foreach (var block in blocksDict)
{
block.Value.GetComponent<MeshRenderer>().enabled = renderMesh;
if (depthRenderer)
{
depthRenderer.enabled = renderMesh;
}
}
}
}
/// <summary>
/// <para xml:lang="en">Mesh color.</para>
/// <para xml:lang="zh">网格颜色。</para>
/// </summary>
public Color MeshColor
{
get
{
if (mapMaterial)
{
return mapMaterial.color;
}
return Color.black;
}
set
{
if (mapMaterial)
{
mapMaterial.color = value;
}
}
}
/// <summary>
/// <para xml:lang="en">All mesh blocks.</para>
/// <para xml:lang="zh">当前所有网格块。</para>
/// </summary>
public List<DenseSpatialMapBlockController> MeshBlocks
{
get
{
var list = new List<DenseSpatialMapBlockController>();
foreach (var item in blocksDict)
{
list.Add(item.Value);
}
return list;
}
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
if (!DenseSpatialMap.isAvailable())
{
throw new UIPopupException(typeof(DenseSpatialMap) + " not available");
}
mapRoot = new GameObject("DenseSpatialMapRoot");
Builder = DenseSpatialMap.create();
depthRenderer = GetComponent<DenseSpatialMapDepthRenderer>();
mapMaterial = Instantiate(MapMeshMaterial);
if (depthRenderer && depthRenderer.enabled)
{
depthRenderer.MapMeshMaterial = mapMaterial;
}
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (Builder != null && isStarted)
{
Builder.start();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
if (enabled)
{
OnEnable();
}
}
/// <summary>
/// MonoBehaviour Update
/// </summary>
protected virtual void Update()
{
if (dirtyBlocks.Count <= 0)
{
if (Builder.updateSceneMesh(false))
{
using (var mesh = Builder.getMesh())
{
foreach (var blockInfo in mesh.getBlocksInfoIncremental())
{
DenseSpatialMapBlockController oldBlock;
blocksDict.TryGetValue(new Vector3(blockInfo.x, blockInfo.y, blockInfo.z), out oldBlock);
if (oldBlock == null)
{
var go = new GameObject("MeshBlock");
go.AddComponent<MeshCollider>();
go.AddComponent<MeshFilter>();
var renderer = go.AddComponent<MeshRenderer>();
renderer.material = mapMaterial;
renderer.enabled = RenderMesh;
var block = go.AddComponent<DenseSpatialMapBlockController>();
block.UpdateData(blockInfo, mesh);
go.transform.parent = mapRoot.transform;
blocksDict.Add(new Vector3(blockInfo.x, blockInfo.y, blockInfo.z), block);
dirtyBlocks.Add(block);
if (MapCreate != null)
{
MapCreate(block);
}
}
else if (oldBlock.Info.version != blockInfo.version)
{
oldBlock.UpdateData(blockInfo, mesh);
if (!dirtyBlocks.Contains(oldBlock))
{
dirtyBlocks.Add(oldBlock);
}
}
}
}
}
}
else
{
var count = Math.Min(dirtyBlocks.Count, BlockUpdateLimitation);
var blocks = dirtyBlocks.GetRange(0, count);
foreach (var block in blocks)
{
block.UpdateMesh();
}
dirtyBlocks.RemoveRange(0, count);
if (MapUpdate != null)
{
MapUpdate(blocks);
}
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (Builder != null)
{
Builder.stop();
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (Builder != null)
{
Builder.Dispose();
}
if (mapRoot)
{
Destroy(mapRoot);
}
if (mapMaterial)
{
Destroy(mapMaterial);
}
}
public InputFrameSink InputFrameSink()
{
if (Builder != null)
{
return Builder.inputFrameSink();
}
return null;
}
public void OnTracking(MotionTrackingStatus status)
{
TrackingStatus = status;
}
public override void OnAssemble(ARSession session)
{
if (depthRenderer)
{
depthRenderer.RenderDepthCamera = session.Assembly.Camera;
}
session.WorldRootChanged += (WorldRootController worldRoot) =>
{
mapRoot.transform.parent = worldRoot.transform;
};
}
}
}
fileFormatVersion: 2
guid: 55c96800d740dfe4aa7fdb044b2aeefb
timeCreated: 1565864520
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"><see cref="MonoBehaviour"/> which controls depth data render <see cref="DenseSpatialMap"/> in the scene.</para>
/// <para xml:lang="zh">在场景中控制<see cref="DenseSpatialMap"/>深度数据渲染的<see cref="MonoBehaviour"/>。</para>
/// </summary>
public class DenseSpatialMapDepthRenderer : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en"><see cref="UnityEngine.Shader"/> to render depth texture.</para>
/// <para xml:lang="zh">用于深度渲染的<see cref="UnityEngine.Shader"/>。</para>
/// </summary>
public Shader Shader;
private RenderTexture depthTexture;
/// <summary>
/// <para xml:lang="en"><see cref="Camera"/> used to render depth texture.</para>
/// <para xml:lang="zh">用于深度渲染的<see cref="Camera"/>。</para>
/// </summary>
public Camera RenderDepthCamera { get; set; }
/// <summary>
/// <para xml:lang="en"><see cref="Material"/> used to render mesh.</para>
/// <para xml:lang="zh">用于渲染网格的<see cref="Material"/>。</para>
/// </summary>
public Material MapMeshMaterial { get; set; }
/// <summary>
/// MonoBehaviour LateUpdate
/// </summary>
private void LateUpdate()
{
if (!RenderDepthCamera || !MapMeshMaterial)
{
return;
}
if (depthTexture && (depthTexture.width != Screen.width || depthTexture.height != Screen.height))
{
Destroy(depthTexture);
}
if (!depthTexture)
{
depthTexture = new RenderTexture(Screen.width, Screen.height, 24);
MapMeshMaterial.SetTexture("_DepthTexture", depthTexture);
}
RenderDepthCamera.targetTexture = depthTexture;
RenderDepthCamera.RenderWithShader(Shader, "Tag");
RenderDepthCamera.targetTexture = null;
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
private void OnDestroy()
{
if (depthTexture)
{
Destroy(depthTexture);
}
}
}
}
fileFormatVersion: 2
guid: 7775e1bb3f737c44db76e864e7235e70
timeCreated: 1577082081
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 System.Linq;
using System.Runtime.InteropServices;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls the map generated from <see cref="SparseSpatialMap"/> in the scene.</para>
/// <para xml:lang="zh">在场景中控制<see cref="SparseSpatialMap"/>生成的的地图的<see cref="MonoBehaviour"/>。</para>
/// </summary>
public class SparseSpatialMapController : MonoBehaviour
{
/// <summary>
/// <para xml:lang="en">Map information. Accessible after MapInfoAvailable event.</para>
/// <para xml:lang="zh">地图信息。可以在MapInfoAvailable event之后访问。</para>
/// </summary>
public SparseSpatialMapInfo MapInfo { get; private set; }
/// <summary>
/// <para xml:lang="en">The <see cref="ParticleSystem"/> used for point cloud rendering.</para>
/// <para xml:lang="zh">渲染点云的<see cref="ParticleSystem"/>。</para>
/// </summary>
public ParticleSystem PointCloudParticleSystem;
/// <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">Map data source.</para>
/// <para xml:lang="zh">Map数据来源。</para>
/// </summary>
public DataSource SourceType;
/// <summary>
/// <para xml:lang="en">MapManager source for map creation. Valid when <see cref="SourceType"/> == <see cref="DataSource.MapManager"/>.</para>
/// <para xml:lang="zh">创建map的MapManager来源。在<see cref="SourceType"/> == <see cref="DataSource.MapManager"/>的时候有效。</para>
/// </summary>
[HideInInspector, SerializeField]
public MapManagerSourceData MapManagerSource = new MapManagerSourceData();
/// <summary>
/// <para xml:lang="en">MapInfo source for map creation. Valid when <see cref="SourceType"/> == <see cref="DataSource.MapInfo"/>.</para>
/// <para xml:lang="zh">创建map的MapInfo来源。在<see cref="SourceType"/> == <see cref="DataSource.MapInfo"/>的时候有效。</para>
/// </summary>
public SparseSpatialMapInfo MapInfoSource;
[HideInInspector, SerializeField]
private bool showPointCloud = true;
[HideInInspector, SerializeField]
private ParticleParameter pointCloudParticleParameter = new ParticleParameter();
[HideInInspector, SerializeField]
private bool mapWorkerHasSet;
[HideInInspector, SerializeField]
private SparseSpatialMapWorkerFrameFilter mapWorker;
private SparseSpatialMapWorkerFrameFilter loader;
private bool localized;
/// <summary>
/// <para xml:lang="en">Event when <see cref="MapInfo"/> can be used.</para>
/// <para xml:lang="zh"><see cref="MapInfo"/> 可以使用的事件。</para>
/// </summary>
public event Action MapInfoAvailable;
/// <summary>
/// <para xml:lang="en">Map localized event.</para>
/// <para xml:lang="zh">Map 定位到的事件。</para>
/// </summary>
public event Action MapLocalized;
/// <summary>
/// <para xml:lang="en">Stop map localization event.</para>
/// <para xml:lang="zh">Map停止定位的事件。</para>
/// </summary>
public event Action MapStopLocalize;
/// <summary>
/// <para xml:lang="en">Map load finish event. The bool value indicates the load success or not. The string value is the error message when fail.</para>
/// <para xml:lang="zh">Map加载完成的事件。bool值表示加载是否成功。string值表示出错时的错误信息。</para>
/// </summary>
public event Action<SparseSpatialMapInfo, bool, string> MapLoad;
/// <summary>
/// <para xml:lang="en">Map unload finish event. The bool value indicates the unload success or not. The string value is the error message when fail.</para>
/// <para xml:lang="zh">Map卸载完成的事件。bool值表示卸载是否成功。string值表示出错时的错误信息。</para>
/// </summary>
public event Action<SparseSpatialMapInfo, bool, string> MapUnload;
/// <summary>
/// <para xml:lang="en">Map finish create and upload event. The bool value indicates success or not. The string value is the error message when fail.</para>
/// <para xml:lang="zh">Map创建上传完成的事件。bool值表示是否成功。string值表示出错时的错误信息。</para>
/// </summary>
public event Action<SparseSpatialMapInfo, bool, string> MapHost;
/// <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">False before the fist <see cref="MapLocalized"/> event, then true.</para>
/// <para xml:lang="zh">在第一次<see cref="MapLocalized"/>事件之前Active为false,之后为true。</para>
/// </summary>
HideBeforeLocalized,
/// <summary>
/// <para xml:lang="en">Active is true when the map is localized, false when not localized.</para>
/// <para xml:lang="zh">当没有被定位到时Active为false,当被定位到时Active为true。</para>
/// </summary>
HideWhenNotLocalizing,
/// <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">Map data source type.</para>
/// <para xml:lang="zh">地图数据来源类型。</para>
/// </summary>
public enum DataSource
{
/// <summary>
/// <para xml:lang="en"><see cref="SparseSpatialMap"/> MapBuilder.</para>
/// <para xml:lang="zh"><see cref="SparseSpatialMap"/> MapBuilder。</para>
/// </summary>
MapBuilder,
/// <summary>
/// <para xml:lang="en"><see cref="SparseSpatialMapManager"/>.</para>
/// <para xml:lang="zh"><see cref="SparseSpatialMapManager"/>。</para>
/// </summary>
MapManager,
/// <summary>
/// <para xml:lang="en"><see cref="SparseSpatialMapInfo"/>.</para>
/// <para xml:lang="zh"><see cref="SparseSpatialMapInfo"/>。</para>
/// </summary>
MapInfo,
}
/// <summary>
/// <para xml:lang="en">The <see cref="SparseSpatialMapWorkerFrameFilter"/> which loads the map after <see cref="MapInfoAvailable"/>. When set to null, the map will be unloaded from MapWorker previously set. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">在<see cref="MapInfoAvailable"/>之后加载target的<see cref="SparseSpatialMapWorkerFrameFilter"/>。如果设为null,map将会被从之前设置的MapWorker中卸载。可随时修改,立即生效。</para>
/// </summary>
public SparseSpatialMapWorkerFrameFilter MapWorker
{
get
{
return mapWorker;
}
set
{
mapWorker = value;
UpdateMapInLocalizer();
}
}
/// <summary>
/// <para xml:lang="en">Parameters for point cloud particles rendering.</para>
/// <para xml:lang="zh">渲染点云粒子的参数。</para>
/// </summary>
public ParticleParameter PointCloudParticleParameter
{
get { return pointCloudParticleParameter; }
set
{
pointCloudParticleParameter = value;
UpdatePointCloud();
}
}
/// <summary>
/// <para xml:lang="en">Point cloud data.</para>
/// <para xml:lang="zh">点云数据。</para>
/// </summary>
public List<Vector3> PointCloud
{
get; private set;
}
/// <summary>
/// <para xml:lang="en">Show or hide point cloud.</para>
/// <para xml:lang="zh">显示或隐藏点云。</para>
/// </summary>
public bool ShowPointCloud
{
get
{
return showPointCloud;
}
set
{
showPointCloud = value;
UpdatePointCloud();
}
}
/// <summary>
/// <para xml:lang="en">Is the map being localized at the moment.</para>
/// <para xml:lang="zh">当前map是否在定位中。</para>
/// </summary>
public bool IsLocalizing
{
get; private set;
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
PointCloud = new List<Vector3>();
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
if (!IsLocalizing && (ActiveControl == ActiveControlStrategy.HideBeforeLocalized || ActiveControl == ActiveControlStrategy.HideWhenNotLocalizing))
{
gameObject.SetActive(false);
}
switch (SourceType)
{
case DataSource.MapBuilder:
LoadMapBuilderInfo();
break;
case DataSource.MapManager:
LoadMapManagerInfo(new MapManagerSourceData()
{
ID = MapManagerSource.ID,
Name = MapManagerSource.Name,
});
break;
case DataSource.MapInfo:
LoadMapInfo(MapInfoSource);
break;
default:
break;
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (mapWorker)
{
mapWorker = null;
UpdateMapInLocalizer();
}
if (MapInfo != null)
{
MapInfo = null;
}
}
/// <summary>
/// <para xml:lang="en">Perform hit test against the point cloud. The results are returned sorted by their distance to the camera in ascending order. <paramref name="pointInView"/> should be normalized to [0, 1]^2.</para>
/// <para xml:lang="zh">在当前点云中进行Hit Test,得到距离相机从近到远一条射线上的n(n>=0)个位置坐标。<paramref name="pointInView"/> 需要被归一化到[0, 1]^2。</para>
/// </summary>
public List<Vector3> HitTest(Vector2 pointInView)
{
var points = new List<Vector3>();
if (!IsLocalizing || !mapWorker || !mapWorker.Session || mapWorker.Localizer == null)
{
return points;
}
var coord = mapWorker.Session.ImageCoordinatesFromScreenCoordinates(pointInView);
if (coord.OnNone)
{
return points;
}
var hitPoints = mapWorker.Localizer.hitTestAgainstPointCloud(coord.Value.ToEasyARVector());
foreach (var p in hitPoints)
{
points.Add(new Vector3(p.data_0, p.data_1, -p.data_2));
}
return points;
}
/// <summary>
/// <para xml:lang="en">Create and upload map. <paramref name="name"/> is the map name and <paramref name="preview"/> is the optional map preview image.</para>
/// <para xml:lang="zh">创建和上传Map。<paramref name="name"/>为地图的名字,<paramref name="preview"/>是可选的map预览图 。</para>
/// </summary>
public void Host(string name, Optional<Image> preview)
{
if (SourceType != DataSource.MapBuilder || MapInfo == null || !string.IsNullOrEmpty(MapInfo.ID) || !mapWorker || mapWorker.Builder == null)
{
throw new Exception("Map Unhostable");
}
mapWorker.HostSparseSpatialMap(this, name, preview, (map, status, error) =>
{
if (MapHost != null)
{
MapHost(map, status, error);
}
});
}
/// <summary>
/// <para xml:lang="en">Usually only for internal assemble use. Process localization event.</para>
/// <para xml:lang="zh">通常只在内部组装时使用。处理定位事件。</para>
/// </summary>
internal void OnLocalization(bool status)
{
if (IsLocalizing != status)
{
if (status)
{
if (ActiveControl == ActiveControlStrategy.HideWhenNotLocalizing || (ActiveControl == ActiveControlStrategy.HideBeforeLocalized && !localized))
{
gameObject.SetActive(true);
}
localized = true;
if (MapLocalized != null)
{
MapLocalized();
}
}
else
{
if (ActiveControl == ActiveControlStrategy.HideWhenNotLocalizing)
{
gameObject.SetActive(false);
}
if (MapStopLocalize != null)
{
MapStopLocalize();
}
}
IsLocalizing = status;
}
}
/// <summary>
/// <para xml:lang="en">Update point cloud data. Internal method.</para>
/// <para xml:lang="zh">更新点云数据。内部方法。</para>
/// </summary>
internal void UpdatePointCloud(Buffer buffer)
{
var bufferFloat = new float[buffer.size() / 4];
if (buffer.size() > 0)
{
Marshal.Copy(buffer.data(), bufferFloat, 0, bufferFloat.Length);
}
PointCloud = Enumerable.Range(0, bufferFloat.Length / 3).Select(k =>
{
return new Vector3(bufferFloat[k * 3], bufferFloat[k * 3 + 1], -bufferFloat[k * 3 + 2]);
}).ToList();
UpdatePointCloud();
}
private void UpdatePointCloud()
{
if (!PointCloudParticleSystem)
{
return;
}
if (!ShowPointCloud || PointCloud == null)
{
PointCloudParticleSystem.Clear();
return;
}
var particles = PointCloud.Select(p =>
{
var particle = new ParticleSystem.Particle();
particle.position = p;
particle.startLifetime = pointCloudParticleParameter.StartLifetime;
particle.remainingLifetime = pointCloudParticleParameter.RemainingLifetime;
particle.startSize = pointCloudParticleParameter.StartSize;
particle.startColor = pointCloudParticleParameter.StartColor;
return particle;
}).ToArray();
PointCloudParticleSystem.SetParticles(particles, particles.Length);
}
private void LoadMapBuilderInfo()
{
MapInfo = new SparseSpatialMapInfo();
if (MapInfoAvailable != null)
{
MapInfoAvailable();
}
UpdateMapInLocalizer();
}
private void LoadMapManagerInfo(MapManagerSourceData source)
{
if (!string.IsNullOrEmpty(source.ID))
{
MapInfo = new SparseSpatialMapInfo() { ID = source.ID, Name = source.Name };
if (MapInfoAvailable != null)
{
MapInfoAvailable();
}
UpdateMapInLocalizer();
}
}
private void LoadMapInfo(SparseSpatialMapInfo source)
{
MapInfo = source;
if (MapInfo != null && MapInfoAvailable != null)
{
MapInfoAvailable();
}
UpdateMapInLocalizer();
}
private void UpdateMapInLocalizer()
{
if (MapInfo == null)
{
return;
}
if ((SourceType == DataSource.MapBuilder && !string.IsNullOrEmpty(MapInfo.ID)) ||
(SourceType != DataSource.MapBuilder && string.IsNullOrEmpty(MapInfo.ID)))
{
return;
}
if (loader && loader != mapWorker)
{
switch (SourceType)
{
case DataSource.MapBuilder:
loader.UnloadSparseSpatialMapBuild(this);
loader = null;
break;
case DataSource.MapManager:
loader.UnloadSparseSpatialMap(this, (map, status, error) =>
{
if (MapUnload != null)
{
MapUnload(map, status, error);
}
});
loader = null;
break;
default:
break;
}
}
if (mapWorker && mapWorker != loader)
{
var worker = mapWorker;
switch (SourceType)
{
case DataSource.MapBuilder:
mapWorker.LoadSparseSpatialMapBuild(this);
loader = mapWorker;
break;
case DataSource.MapManager:
mapWorker.LoadSparseSpatialMap(this, (map, status, error) =>
{
if (worker == mapWorker && !status)
{
loader = null;
}
if (MapLoad != null)
{
MapLoad(map, status, error);
}
});
loader = mapWorker;
break;
default:
break;
}
}
}
/// <summary>
/// <para xml:lang="en">Sparse map information.</para>
/// <para xml:lang="zh">稀疏地图信息。</para>
/// </summary>
public class SparseSpatialMapInfo
{
/// <summary>
/// <para xml:lang="en">Sparse map ID.</para>
/// <para xml:lang="zh">稀疏地图的ID。</para>
/// </summary>
public string ID = string.Empty;
/// <summary>
/// <para xml:lang="en">Sparse map name.</para>
/// <para xml:lang="zh">稀疏地图的名字。</para>
/// </summary>
public string Name = string.Empty;
}
/// <summary>
/// <para xml:lang="en">MapManager source for map creation.</para>
/// <para xml:lang="zh">创建map的MapManager来源。</para>
/// </summary>
[Serializable]
public class MapManagerSourceData
{
/// <summary>
/// <para xml:lang="en">Sparse map ID.</para>
/// <para xml:lang="zh">稀疏地图的ID。</para>
/// </summary>
public string ID = string.Empty;
/// <summary>
/// <para xml:lang="en">Sparse map name.</para>
/// <para xml:lang="zh">稀疏地图的名字。</para>
/// </summary>
public string Name = string.Empty;
}
/// <summary>
/// <para xml:lang="en">Parameters for point cloud particles rendering.</para>
/// <para xml:lang="zh">渲染点云粒子的参数。</para>
/// </summary>
[Serializable]
public class ParticleParameter
{
/// <summary>
/// <para xml:lang="en">Particles start color.</para>
/// <para xml:lang="zh">粒子初始颜色。</para>
/// </summary>
public Color32 StartColor = new Color32(11, 205, 255, 255);
/// <summary>
/// <para xml:lang="en">Particles start size.</para>
/// <para xml:lang="zh">粒子初始大小。</para>
/// </summary>
public float StartSize = 0.015f;
/// <summary>
/// <para xml:lang="en">Particles start life time.</para>
/// <para xml:lang="zh">粒子初始生存时间。</para>
/// </summary>
public float StartLifetime = float.MaxValue;
/// <summary>
/// <para xml:lang="en">Particles remaining life time.</para>
/// <para xml:lang="zh">粒子剩余生存时间。</para>
/// </summary>
public float RemainingLifetime = float.MaxValue;
}
}
}
fileFormatVersion: 2
guid: c36553bfeabdad7429e7c8d56adf0522
timeCreated: 1572516248
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"><see cref="MonoBehaviour"/> which controls <see cref="SparseSpatialMap"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Builder"/>, <see cref="Localizer"/> or <see cref="Manager"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="SparseSpatialMap"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Builder"/>、<see cref="Localizer"/>或<see cref="Manager"/>。</para>
/// </summary>
public class SparseSpatialMapWorkerFrameFilter : FrameFilter, FrameFilter.IInputFrameSink, FrameFilter.IOutputFrameSource, FrameFilter.ISpatialInformationSink
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible when building map after Awake if available.</para>
/// <para xml:lang="en">Use when building a map (<see cref="WorkingMode"/> == <see cref="Mode.Build"/>).</para>
/// <para xml:lang="zh">EasyAR Sense API,在地图构建时,如果功能可以使用,可以在Awake之后访问。</para>
/// <para xml:lang="zh">在地图构建时(<see cref="WorkingMode"/> == <see cref="Mode.Build"/>)使用。</para>
/// </summary>
public SparseSpatialMap Builder { get; private set; }
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after Awake if available.</para>
/// <para xml:lang="en">Use when localizing a map (<see cref="WorkingMode"/> == <see cref="Mode.Localize"/>).</para>
/// <para xml:lang="zh">EasyAR Sense API,如果功能可以使用,可以在Awake之后访问。</para>
/// <para xml:lang="zh">在地图定位时(<see cref="WorkingMode"/> == <see cref="Mode.Localize"/>)使用。</para>
/// </summary>
public SparseSpatialMap Localizer { get; private set; }
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after Awake if available.</para>
/// <para xml:lang="en">Use when building and uploading a map.</para>
/// <para xml:lang="zh">EasyAR Sense API,如果功能可以使用,可以在Awake之后访问。</para>
/// <para xml:lang="zh">在地图构建和上传时使用。</para>
/// </summary>
public SparseSpatialMapManager Manager { get; private set; }
/// <summary>
/// <para xml:lang="en">Map localizer config used before every start (<see cref="OnEnable"/>).</para>
/// <para xml:lang="zh">地图定位配置,在每次启动(<see cref="OnEnable"/>)前使用。</para>
/// </summary>
public MapLocalizerConfig LocalizerConfig = new MapLocalizerConfig();
/// <summary>
/// <para xml:lang="en">Use global service config or not. The global service config can be changed on the inspector after click Unity menu EasyAR -> Change Global Spatial Map Service Config.</para>
/// <para xml:lang="zh">是否使用全局服务器配置。全局配置可以点击Unity菜单EasyAR -> Change Global Spatial Map Service Config可以在属性面板里面进行填写。</para>
/// </summary>
public bool UseGlobalServiceConfig = true;
/// <summary>
/// <para xml:lang="en">Service config when <see cref="UseGlobalServiceConfig"/> == false, only valid for this object.</para>
/// <para xml:lang="zh"><see cref="UseGlobalServiceConfig"/> == false时使用的服务器配置,只对该物体有效。</para>
/// </summary>
[HideInInspector, SerializeField]
public SpatialMapServiceConfig ServiceConfig = new SpatialMapServiceConfig();
internal ARSession Session;
private GameObject mapRoot;
private SparseSpatialMap sparseSpatialMapWorker;
private string localizedMapID = string.Empty;
private Dictionary<string, SparseSpatialMapController> mapControllers = new Dictionary<string, SparseSpatialMapController>();
private bool isStarted;
/// <summary>
/// <para xml:lang="en">Map load finish event. The bool value indicates the load success or not. The string value is the error message when fail.</para>
/// <para xml:lang="zh">Map加载完成的事件。bool值表示加载是否成功。string值表示出错时的错误信息。</para>
/// </summary>
public event Action<SparseSpatialMapController, SparseSpatialMapController.SparseSpatialMapInfo, bool, string> MapLoad;
/// <summary>
/// <para xml:lang="en">Map unload finish event. The bool value indicates the unload success or not. The string value is the error message when fail.</para>
/// <para xml:lang="zh">Map卸载完成的事件。bool值表示卸载是否成功。string值表示出错时的错误信息。</para>
/// </summary>
public event Action<SparseSpatialMapController, SparseSpatialMapController.SparseSpatialMapInfo, bool, string> MapUnload;
/// <summary>
/// <para xml:lang="en">Map create and upload finish event. The bool value indicates the create and upload success or not. The string value is the error message when fail.</para>
/// <para xml:lang="zh">Map创建及上传完成的事件。bool值表示创建及上传是否成功。string值表示出错时的错误信息。</para>
/// </summary>
public event Action<SparseSpatialMapController, SparseSpatialMapController.SparseSpatialMapInfo, bool, string> MapHost;
/// <summary>
/// <para xml:lang="en">Working mode.</para>
/// <para xml:lang="zh">工作模式。</para>
/// </summary>
public enum Mode
{
/// <summary>
/// <para xml:lang="en">Map building mode.</para>
/// <para xml:lang="zh">建图模式。</para>
/// </summary>
Build,
/// <summary>
/// <para xml:lang="en">Map localizing mode.</para>
/// <para xml:lang="zh">定位模式。</para>
/// </summary>
Localize,
}
public override int BufferRequirement
{
get { return sparseSpatialMapWorker.bufferRequirement(); }
}
public MotionTrackingStatus TrackingStatus { get; private set; }
/// <summary>
/// <para xml:lang="en">Current working mode. The working mode start as <see cref="Mode.Build"/> and will change to <see cref="Mode.Localize"/> after a map load.</para>
/// <para xml:lang="zh">当前工作模式。工作模式启动为<see cref="Mode.Build"/>,会在加载地图之后变成<see cref="Mode.Localize"/>。</para>
/// </summary>
public Mode WorkingMode { get; private set; }
/// <summary>
/// <para xml:lang="en">The map being localized.</para>
/// <para xml:lang="zh">当前被定为的地图。</para>
/// </summary>
public SparseSpatialMapController LocalizedMap { get; private set; }
/// <summary>
/// <para xml:lang="en">The map controller for map building. To visualize the map building, <see cref="SparseSpatialMapController.SourceType"/> of one <see cref="SparseSpatialMapController"/> should be set to <see cref="SparseSpatialMapController.DataSource.MapBuilder"/> and the map should be loaded before building start.</para>
/// <para xml:lang="zh">用于建图的map controller。如果想可视化地查看建图过程,需要在建图开始之前设置一个即将被加载的<see cref="SparseSpatialMapController"/>的<see cref="SparseSpatialMapController.SourceType"/>为<see cref="SparseSpatialMapController.DataSource.MapBuilder"/>。</para>
/// </summary>
public SparseSpatialMapController BuilderMapController { get; private set; }
/// <summary>
/// <para xml:lang="en"><see cref="SparseSpatialMapController"/> that has been loaded.</para>
/// <para xml:lang="zh">已加载的<see cref="SparseSpatialMapController"/>。</para>
/// </summary>
public List<SparseSpatialMapController> MapControllers
{
get
{
List<SparseSpatialMapController> list = new List<SparseSpatialMapController>();
foreach (var value in mapControllers.Values)
{
list.Add(value);
}
return list;
}
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
if (!SparseSpatialMap.isAvailable())
{
throw new UIPopupException(typeof(SparseSpatialMap) + " not available");
}
if (!SparseSpatialMapManager.isAvailable())
{
throw new UIPopupException(typeof(SparseSpatialMapManager) + " not available");
}
mapRoot = new GameObject("SparseSpatialMapRoot");
sparseSpatialMapWorker = SparseSpatialMap.create();
Builder = sparseSpatialMapWorker;
Localizer = sparseSpatialMapWorker;
Manager = SparseSpatialMapManager.create();
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (sparseSpatialMapWorker != null && isStarted)
{
using (var config = new SparseSpatialMapConfig())
{
config.setLocalizationMode(LocalizerConfig.LocalizationMode);
sparseSpatialMapWorker.setConfig(config);
}
sparseSpatialMapWorker.start();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
if (enabled)
{
OnEnable();
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (sparseSpatialMapWorker != null)
{
sparseSpatialMapWorker.stop();
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (sparseSpatialMapWorker != null)
{
sparseSpatialMapWorker.Dispose();
}
if (Manager != null)
{
Manager.Dispose();
}
if (mapRoot)
{
Destroy(mapRoot);
}
}
/// <summary>
/// <para xml:lang="en">Load map.</para>
/// <para xml:lang="zh">加载地图。</para>
/// </summary>
public void LoadMap(SparseSpatialMapController map)
{
if (TryGetMapController(map.MapInfo.ID) || BuilderMapController == map)
{
return;
}
map.MapWorker = this;
}
/// <summary>
/// <para xml:lang="en">Unload map.</para>
/// <para xml:lang="zh">卸载地图。</para>
/// </summary>
public void UnloadMap(SparseSpatialMapController map)
{
if (!TryGetMapController(map.MapInfo.ID) && BuilderMapController != map)
{
return;
}
map.MapWorker = null;
}
/// <summary>
/// <para xml:lang="en">Create and upload map.</para>
/// <para xml:lang="zh">创建并上传地图。</para>
/// </summary>
public void HostMap(SparseSpatialMapController map, string name, Optional<Image> preview)
{
map.Host(name, preview);
}
public InputFrameSink InputFrameSink()
{
if (sparseSpatialMapWorker != null)
{
return sparseSpatialMapWorker.inputFrameSink();
}
return null;
}
public OutputFrameSource OutputFrameSource()
{
if (sparseSpatialMapWorker != null)
{
return sparseSpatialMapWorker.outputFrameSource();
}
return null;
}
public void OnTracking(MotionTrackingStatus status)
{
TrackingStatus = status;
}
public override void OnAssemble(ARSession session)
{
Session = session;
session.WorldRootChanged += (WorldRootController worldRoot) =>
{
mapRoot.transform.parent = worldRoot.transform;
};
}
public List<KeyValuePair<Optional<TargetController>, Matrix44F>> OnResult(Optional<FrameFilterResult> frameFilterResult)
{
LocalizedMap = null;
if (WorkingMode == Mode.Build)
{
if (BuilderMapController)
{
if (frameFilterResult.OnSome)
{
LocalizedMap = BuilderMapController;
BuilderMapController.OnLocalization(true);
using (var cloudBuffer = sparseSpatialMapWorker.getPointCloudBuffer())
{
BuilderMapController.UpdatePointCloud(cloudBuffer);
}
}
else
{
BuilderMapController.OnLocalization(false);
}
}
}
else
{
if (BuilderMapController)
{
BuilderMapController.OnLocalization(false);
if (BuilderMapController.PointCloud.Count > 0)
{
BuilderMapController.ShowPointCloud = false;
}
}
string mapID = string.Empty;
if (frameFilterResult.OnSome)
{
var mapResult = frameFilterResult.Value as SparseSpatialMapResult;
if (mapResult.getLocalizationStatus())
{
mapID = mapResult.getLocalizationMapID();
var controller = TryGetMapController(mapID);
if (controller)
{
LocalizedMap = controller;
controller.OnLocalization(true);
if (controller.PointCloud.Count == 0)
{
using (var cloudBuffer = sparseSpatialMapWorker.getPointCloudBuffer())
{
controller.UpdatePointCloud(cloudBuffer);
}
}
TransformUtil.SetMatrixOnTransform(controller.transform, mapResult.getVioPose().Value.ToUnityMatrix().inverse * mapResult.getMapPose().Value.ToUnityMatrix(), true);
}
}
}
if (localizedMapID != mapID && !string.IsNullOrEmpty(localizedMapID))
{
mapControllers[localizedMapID].OnLocalization(false);
}
localizedMapID = mapID;
}
return new List<KeyValuePair<Optional<TargetController>, Matrix44F>>();
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void LoadSparseSpatialMap(SparseSpatialMapController controller, Action<SparseSpatialMapController.SparseSpatialMapInfo, bool, string> callback)
{
SpatialMapServiceConfig config;
if (UseGlobalServiceConfig)
{
config = EasyARController.Settings.GlobalSpatialMapServiceConfig;
}
else
{
config = ServiceConfig;
}
NotifyEmptyConfig(config);
var id = controller.MapInfo.ID;
Manager.load(sparseSpatialMapWorker, id.Trim(), config.APIKey.Trim(), config.APISecret.Trim(), config.SparseSpatialMapAppID.Trim(), EasyARController.Scheduler, (status, error) =>
{
if (MapLoad != null)
{
MapLoad(controller, controller.MapInfo, status, error);
}
if (callback != null)
{
callback(controller.MapInfo, status, error);
}
});
mapControllers[id] = controller;
controller.transform.parent = mapRoot.transform;
WorkingMode = Mode.Localize;
Builder = null;
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void UnloadSparseSpatialMap(SparseSpatialMapController controller, Action<SparseSpatialMapController.SparseSpatialMapInfo, bool, string> callback)
{
var id = controller.MapInfo.ID;
if (mapControllers.Remove(id))
{
controller.OnLocalization(false);
sparseSpatialMapWorker.unloadMap(controller.MapInfo.ID, EasyARController.Scheduler, (Action<bool>)((status) =>
{
if (MapUnload != null)
{
MapUnload(controller, controller.MapInfo, status, string.Empty);
}
if (callback != null)
{
callback(controller.MapInfo, status, string.Empty);
}
}));
}
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void HostSparseSpatialMap(SparseSpatialMapController controller, string name, Optional<Image> preview, Action<SparseSpatialMapController.SparseSpatialMapInfo, bool, string> callback)
{
SpatialMapServiceConfig config;
if (UseGlobalServiceConfig)
{
config = EasyARController.Settings.GlobalSpatialMapServiceConfig;
}
else
{
config = ServiceConfig;
}
NotifyEmptyConfig(config);
Manager.host(sparseSpatialMapWorker, config.APIKey.Trim(), config.APISecret.Trim(), config.SparseSpatialMapAppID.Trim(), name, preview, EasyARController.Scheduler, (status, id, error) =>
{
var mapInfo = new SparseSpatialMapController.SparseSpatialMapInfo() { Name = name, ID = id };
if (MapHost != null)
{
MapHost(controller, mapInfo, status, error);
}
if (callback != null)
{
callback(mapInfo, status, error);
}
});
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void LoadSparseSpatialMapBuild(SparseSpatialMapController controller)
{
UnloadSparseSpatialMapBuild(BuilderMapController);
BuilderMapController = controller;
if (controller && mapRoot)
{
BuilderMapController.transform.parent = mapRoot.transform;
}
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void UnloadSparseSpatialMapBuild(SparseSpatialMapController controller)
{
if (BuilderMapController == controller && controller)
{
BuilderMapController = null;
controller.OnLocalization(false);
}
}
private SparseSpatialMapController TryGetMapController(string id)
{
SparseSpatialMapController controller;
if (mapControllers.TryGetValue(id, out controller))
return controller;
return null;
}
private void NotifyEmptyConfig(SpatialMapServiceConfig config)
{
if (string.IsNullOrEmpty(config.APIKey) ||
string.IsNullOrEmpty(config.APISecret) ||
string.IsNullOrEmpty(config.SparseSpatialMapAppID))
{
throw new UIPopupException(
"Service config (for authentication) NOT set, please set" + Environment.NewLine +
"globally on <EasyAR Settings> Asset or" + Environment.NewLine +
"locally on <SparseSpatialMapWorkerFrameFilter> Component." + Environment.NewLine +
"Get from EasyAR Develop Center (www.easyar.com) -> SpatialMap -> Database Details.");
}
}
/// <summary>
/// <para xml:lang="en">Map localizer config.</para>
/// <para xml:lang="zh">地图定位配置。</para>
/// </summary>
[Serializable]
public class MapLocalizerConfig
{
/// <summary>
/// <para xml:lang="en">Localization mode.</para>
/// <para xml:lang="zh">定位模式。</para>
/// </summary>
public LocalizationMode LocalizationMode;
}
/// <summary>
/// <para xml:lang="en">Service config for <see cref="SparseSpatialMapManager"/>.</para>
/// <para xml:lang="zh"><see cref="SparseSpatialMapManager"/>服务器配置。</para>
/// </summary>
[Serializable]
public class SpatialMapServiceConfig
{
/// <summary>
/// <para xml:lang="en">API Key, go to EasyAR Develop Center (https://www.easyar.com) for details.</para>
/// <para xml:lang="zh">API Key,详见EasyAR开发中心(https://www.easyar.cn)。</para>
/// </summary>
public string APIKey = string.Empty;
/// <summary>
/// <para xml:lang="en">API Secret, go to EasyAR Develop Center (https://www.easyar.com) for details.</para>
/// <para xml:lang="zh">API Secret,详见EasyAR开发中心(https://www.easyar.cn)。</para>
/// </summary>
public string APISecret = string.Empty;
/// <summary>
/// <para xml:lang="en">Spatial Map AppID, go to EasyAR Develop Center (https://www.easyar.com) for details.</para>
/// <para xml:lang="zh">Spatial Map AppID,详见EasyAR开发中心(https://www.easyar.cn)。</para>
/// </summary>
public string SparseSpatialMapAppID = string.Empty;
}
}
}
fileFormatVersion: 2
guid: 02abe2947e3d4cb48ada068cce6a5b87
timeCreated: 1566206836
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"><see cref="MonoBehaviour"/> which controls <see cref="SurfaceTracker"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Tracker"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="SurfaceTracker"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Tracker"/>。</para>
/// </summary>
public class SurfaceTrackerFrameFilter : FrameFilter, FrameFilter.IInputFrameSink, FrameFilter.IOutputFrameSource
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after Awake if available.</para>
/// <para xml:lang="zh">EasyAR Sense API,如果功能可以使用,可以在Awake之后访问。</para>
/// </summary>
public SurfaceTracker Tracker { get; private set; }
private bool isStarted;
public override int BufferRequirement
{
get { return Tracker.bufferRequirement(); }
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
if (!SurfaceTracker.isAvailable())
{
throw new UIPopupException(typeof(SurfaceTracker) + " not available");
}
Tracker = SurfaceTracker.create();
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (Tracker != null && isStarted)
{
Tracker.start();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
if (enabled)
{
OnEnable();
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (Tracker != null)
{
Tracker.stop();
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (Tracker != null)
{
Tracker.Dispose();
}
}
public InputFrameSink InputFrameSink()
{
if (Tracker != null)
{
return Tracker.inputFrameSink();
}
return null;
}
public OutputFrameSource OutputFrameSource()
{
if (Tracker != null)
{
return Tracker.outputFrameSource();
}
return null;
}
public List<KeyValuePair<Optional<TargetController>, Matrix44F>> OnResult(Optional<FrameFilterResult> frameFilterResult)
{
var list = new List<KeyValuePair<Optional<TargetController>, Matrix44F>>();
if (frameFilterResult.OnSome)
{
var result = frameFilterResult.Value as SurfaceTrackerResult;
list.Add(new KeyValuePair<Optional<TargetController>, Matrix44F>(null, result.transform()));
}
return list;
}
}
}
fileFormatVersion: 2
guid: b90773d91e5b8e84f948cf6ee6556db0
timeCreated: 1565767053
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"><see cref="MonoBehaviour"/> which controls VIO camera device (<see cref="MotionTrackerCameraDevice"/>, <see cref="ARKitCameraDevice"/> or <see cref="ARCoreCameraDevice"/>) in the scene, providing a few extensions in the Unity environment. Use <see cref="Device"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制VIO相机设备(<see cref="MotionTrackerCameraDevice"/>、<see cref="ARKitCameraDevice"/>、<see cref="ARCoreCameraDevice"/>)的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Device"/>。</para>
/// </summary>
public class VIOCameraDeviceUnion : CameraSource
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API (Union). Accessible between <see cref="DeviceCreated"/> and <see cref="DeviceClosed"/> event if available.</para>
/// <para xml:lang="zh">EasyAR Sense API (Union),如果功能可以使用,可以在<see cref="DeviceCreated"/>和<see cref="DeviceClosed"/>事件之间访问。</para>
/// </summary>
public DeviceUnion Device { get; private set; }
/// <summary>
/// <para xml:lang="en">Strategy of choosing VIO device.</para>
/// <para xml:lang="zh">选择VIO设备的策略。</para>
/// </summary>
public DeviceChooseStrategy DeviceStrategy;
/// <summary>
/// <para xml:lang="en">Desired motion tracker parameters, used only when <see cref="Device"/> start. Effective only when <see cref="MotionTrackerCameraDevice"/> is used.</para>
/// <para xml:lang="zh">期望的运动跟踪参数,只在<see cref="Device"/>启动时使用。只有在使用<see cref="MotionTrackerCameraDevice"/>时有效。</para>
/// </summary>
public MotionTrackerCameraDeviceParameters DesiredMotionTrackerParameters = new MotionTrackerCameraDeviceParameters();
/// <summary>
/// <para xml:lang="en">Whether to update calibration data from server on <see cref="Start"/>.</para>
/// <para xml:lang="zh">是否在<see cref="Start"/>调用时从服务器获取标定数据更新。</para>
/// </summary>
public bool UpdateCalibrationOnStart = true;
private Action deviceStart;
private Action deviceStop;
private Action deviceClose;
private Action<int> deviceSetBufferCapacity;
private Func<int> deviceGetBufferCapacity;
private Action<InputFrameSink> deviceConnect;
private bool willOpen;
/// <summary>
/// <para xml:lang="en">Event when <see cref="Device"/> created.</para>
/// <para xml:lang="zh"><see cref="Device"/> 创建的事件。</para>
/// </summary>
public event Action DeviceCreated;
/// <summary>
/// <para xml:lang="en">Event when <see cref="Device"/> opened.</para>
/// <para xml:lang="zh"><see cref="Device"/> 打开的事件。</para>
/// </summary>
public event Action DeviceOpened;
/// <summary>
/// <para xml:lang="en">Event when <see cref="Device"/> closed.</para>
/// <para xml:lang="zh"><see cref="Device"/> 关闭的事件。</para>
/// </summary>
public event Action DeviceClosed;
/// <summary>
/// <para xml:lang="en">Strategy of choosing VIO device.</para>
/// <para xml:lang="zh">选择VIO设备的策略。</para>
/// </summary>
public enum DeviceChooseStrategy
{
/// <summary>
/// <para xml:lang="en">Choose VIO device based on system support,in the order of System VIO device (ARKit/ARCore) > EasyAR Motion Tracker.</para>
/// <para xml:lang="zh">根据系统对VIO设备支持情况进行选择,优先顺序为 系统VIO设备 (ARKit/ARCore) > EasyAR Motion Tracker。</para>
/// </summary>
SystemVIOFirst,
/// <summary>
/// <para xml:lang="en">Choose VIO device based on system support,in the order of EasyAR Motion Tracker > System VIO device (ARKit/ARCore)。</para>
/// <para xml:lang="zh">根据系统对VIO设备支持情况进行选择,优先顺序为 EasyAR Motion Tracker > 系统VIO设备 (ARKit/ARCore)。</para>
/// </summary>
EasyARMotionTrackerFirst,
/// <summary>
/// <para xml:lang="en">Choose only System VIO device (ARKit/ARCore), do not use EasyAR Motion Tracker.</para>
/// <para xml:lang="zh">只选择系统VIO设备 (ARKit/ARCore),不使用EasyAR Motion Tracker。</para>
/// </summary>
SystemVIOOnly,
/// <summary>
/// <para xml:lang="en">Choose only EasyAR Motion Tracker, do not use System VIO device (ARKit/ARCore).</para>
/// <para xml:lang="zh">只选择EasyAR Motion Tracker,不使用系统VIO设备 (ARKit/ARCore)。</para>
/// </summary>
EasyARMotionTrackerOnly,
}
public override int BufferCapacity
{
get
{
if (deviceGetBufferCapacity != null)
{
return deviceGetBufferCapacity();
}
return bufferCapacity;
}
set
{
bufferCapacity = value;
if (deviceSetBufferCapacity != null)
{
deviceSetBufferCapacity(value);
}
}
}
public override bool HasSpatialInformation
{
get { return true; }
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
if (deviceStart != null)
{
deviceStart();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected override void Start()
{
if (UpdateCalibrationOnStart && Application.platform == RuntimePlatform.Android)
{
// NOTE:
// This downloader instance will return asynchronously. Latest calibration may not be used in the first time.
// You can setup the download procedure in your own code if latest calibration usage is desired before tracking start.
var downloader = new CalibrationDownloader();
downloader.download(EasyARController.Scheduler, (status, error) =>
{
switch (status)
{
case CalibrationDownloadStatus.Successful:
Debug.Log("Calibration file has been updated.");
break;
case CalibrationDownloadStatus.NotModified:
Debug.Log("Calibration file is up to date.");
break;
default:
Debug.LogError("Error download calibration file, " + status + ": " + error);
break;
}
downloader.Dispose();
});
}
switch (DeviceStrategy)
{
case DeviceChooseStrategy.SystemVIOFirst:
var arcoreFail = CheckARCore();
if (!MotionTrackerCameraDevice.isAvailable() && !ARKitCameraDevice.isAvailable() && !ARCoreCameraDevice.isAvailable())
{
throw new UIPopupException("VIOCameraDevice not available");
}
if (arcoreFail)
{
GUIPopup.EnqueueMessage(typeof(MotionTrackerCameraDevice) + " selected", 3);
}
break;
case DeviceChooseStrategy.EasyARMotionTrackerFirst:
if (!MotionTrackerCameraDevice.isAvailable())
{
CheckARCore();
}
if (!MotionTrackerCameraDevice.isAvailable() && !ARKitCameraDevice.isAvailable() && !ARCoreCameraDevice.isAvailable())
{
throw new UIPopupException("VIOCameraDevice not available");
}
break;
case DeviceChooseStrategy.SystemVIOOnly:
CheckARCore();
if (!ARKitCameraDevice.isAvailable() && Application.platform == RuntimePlatform.IPhonePlayer)
{
throw new UIPopupException(typeof(ARKitCameraDevice) + " not available");
}
else if (!ARCoreCameraDevice.isAvailable() && Application.platform == RuntimePlatform.Android)
{
throw new UIPopupException(typeof(ARCoreCameraDevice) + " not available");
}
else if (!ARKitCameraDevice.isAvailable() && !ARCoreCameraDevice.isAvailable())
{
throw new UIPopupException("System VIO not available");
}
break;
case DeviceChooseStrategy.EasyARMotionTrackerOnly:
if (!MotionTrackerCameraDevice.isAvailable())
{
throw new UIPopupException(typeof(MotionTrackerCameraDevice) + " not available");
}
break;
default:
break;
}
base.Start();
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected override void OnDisable()
{
base.OnDisable();
if (deviceStop != null)
{
deviceStop();
}
}
/// <summary>
/// <para xml:lang="en">Performs ray cast from the user&#39;s device in the direction of given screen point. Intersections with horizontal plane is detected in real time in the current field of view,and return the 3D point nearest to ray on horizontal plane. <paramref name="pointInView"/> should be normalized to [0, 1]^2.</para>
/// <para xml:lang="zh">在当前视野内实时检测到的水平面上进行Hit Test,点击到某个水平面后返回该平面上距离Hit Test射线最近的3D点的位置坐标。<paramref name="pointInView"/> 需要被归一化到[0, 1]^2。</para>
/// </summary>
public List<Vector3> HitTestAgainstHorizontalPlane(Vector2 pointInView)
{
var points = new List<Vector3>();
if (Device == null || Device.Type() != typeof(MotionTrackerCameraDevice) || !arSession)
{
return points;
}
var coord = arSession.ImageCoordinatesFromScreenCoordinates(pointInView);
if (coord.OnNone)
{
return points;
}
var hitPoints = Device.MotionTrackerCameraDevice.hitTestAgainstHorizontalPlane(coord.Value.ToEasyARVector());
foreach (var p in hitPoints)
{
points.Add(new Vector3(p.data_0, p.data_1, -p.data_2));
}
return points;
}
/// <summary>
/// <para xml:lang="en">Perform hit test against the point cloud and return the nearest 3D point. <paramref name="pointInView"/> should be normalized to [0, 1]^2.</para>
/// <para xml:lang="zh">在当前点云中进行Hit Test,得到距离相机从近到远一条射线上的最近的一个3D点位置坐标。<paramref name="pointInView"/> 需要被归一化到[0, 1]^2。</para>
/// </summary>
public List<Vector3> HitTestAgainstPointCloud(Vector2 pointInView)
{
var points = new List<Vector3>();
if (Device == null || Device.Type() != typeof(MotionTrackerCameraDevice) || !arSession)
{
return points;
}
var coord = arSession.ImageCoordinatesFromScreenCoordinates(pointInView);
if (coord.OnNone)
{
return points;
}
var hitPoints = Device.MotionTrackerCameraDevice.hitTestAgainstPointCloud(coord.Value.ToEasyARVector());
foreach (var p in hitPoints)
{
points.Add(new Vector3(p.data_0, p.data_1, -p.data_2));
}
return points;
}
public override void Open()
{
willOpen = true;
CameraDevice.requestPermissions(EasyARController.Scheduler, (Action<PermissionStatus, string>)((status, msg) =>
{
if (!willOpen)
{
return;
}
if (status != PermissionStatus.Granted)
{
Debug.LogError("Camera permission not granted");
return;
}
Close();
switch (DeviceStrategy)
{
case DeviceChooseStrategy.SystemVIOFirst:
if (ARKitCameraDevice.isAvailable())
{
CreateARKitCameraDevice();
}
else if (ARCoreCameraDevice.isAvailable())
{
CreateARCoreCameraDevice();
}
else if (MotionTrackerCameraDevice.isAvailable())
{
CreateMotionTrackerCameraDevice();
}
break;
case DeviceChooseStrategy.EasyARMotionTrackerFirst:
if (MotionTrackerCameraDevice.isAvailable())
{
CreateMotionTrackerCameraDevice();
}
else if (ARKitCameraDevice.isAvailable())
{
CreateARKitCameraDevice();
}
else if (ARCoreCameraDevice.isAvailable())
{
CreateARCoreCameraDevice();
}
break;
case DeviceChooseStrategy.SystemVIOOnly:
if (ARKitCameraDevice.isAvailable())
{
CreateARKitCameraDevice();
}
else if (ARCoreCameraDevice.isAvailable())
{
CreateARCoreCameraDevice();
}
break;
case DeviceChooseStrategy.EasyARMotionTrackerOnly:
if (MotionTrackerCameraDevice.isAvailable())
{
CreateMotionTrackerCameraDevice();
}
break;
default:
break;
}
if (DeviceCreated != null)
{
DeviceCreated();
}
if (bufferCapacity != 0)
{
deviceSetBufferCapacity(bufferCapacity);
}
if (sink != null)
deviceConnect(sink);
if (enabled)
{
OnEnable();
}
if (DeviceOpened != null)
{
DeviceOpened();
}
}));
}
public override void Close()
{
willOpen = false;
if (deviceClose != null)
{
OnDisable();
deviceClose();
if (DeviceClosed != null)
{
DeviceClosed();
}
Device = null;
deviceStart = null;
deviceStop = null;
deviceClose = null;
deviceSetBufferCapacity = null;
deviceGetBufferCapacity = null;
deviceConnect = null;
}
}
public override void Connect(InputFrameSink val)
{
base.Connect(val);
if (deviceConnect != null)
{
deviceConnect(val);
}
}
private void CreateMotionTrackerCameraDevice()
{
var device = new MotionTrackerCameraDevice();
deviceStart = () =>
{
if (DesiredMotionTrackerParameters != null)
{
device.setFrameRateType(DesiredMotionTrackerParameters.FPS);
device.setFocusMode(DesiredMotionTrackerParameters.FocusMode);
device.setFrameResolutionType(DesiredMotionTrackerParameters.Resolution);
}
device.start();
};
deviceStop = () =>
{
device.stop();
};
deviceClose = () =>
{
device.close();
device.Dispose();
};
deviceSetBufferCapacity = (int capacity) =>
{
device.setBufferCapacity(capacity);
};
deviceGetBufferCapacity = () =>
{
return device.bufferCapacity();
};
deviceConnect = (InputFrameSink sink) =>
{
device.inputFrameSource().connect(sink);
};
Device = device;
}
private void CreateARKitCameraDevice()
{
var device = new ARKitCameraDevice();
deviceStart = () =>
{
device.start();
};
deviceStop = () =>
{
device.stop();
};
deviceClose = () =>
{
device.close();
device.Dispose();
};
deviceSetBufferCapacity = (int capacity) =>
{
device.setBufferCapacity(capacity);
};
deviceGetBufferCapacity = () =>
{
return device.bufferCapacity();
};
deviceConnect = (InputFrameSink sink) =>
{
device.inputFrameSource().connect(sink);
};
Device = device;
}
private void CreateARCoreCameraDevice()
{
var device = new ARCoreCameraDevice();
deviceStart = () =>
{
device.start();
};
deviceStop = () =>
{
device.stop();
};
deviceClose = () =>
{
device.close();
device.Dispose();
};
deviceSetBufferCapacity = (int capacity) =>
{
device.setBufferCapacity(capacity);
};
deviceGetBufferCapacity = () =>
{
return device.bufferCapacity();
};
deviceConnect = (InputFrameSink sink) =>
{
device.inputFrameSource().connect(sink);
};
Device = device;
}
private bool CheckARCore()
{
if (Application.platform == RuntimePlatform.Android && EasyARController.ARCoreLoadFailed)
{
GUIPopup.EnqueueMessage("Fail to load ARCore library: arcore_sdk_c.so not found" + Environment.NewLine +
"You can turn off ARCore support on <EasyAR Settings> Asset", 3);
return true;
}
return false;
}
/// <summary>
/// <para xml:lang="en">VIO device Union.</para>
/// <para xml:lang="zh">VIO设备的集合。</para>
/// </summary>
public class DeviceUnion
{
private MotionTrackerCameraDevice motionTrackerCameraDevice;
private ARKitCameraDevice arKitCameraDevice;
private ARCoreCameraDevice arCoreCameraDevice;
public DeviceUnion(MotionTrackerCameraDevice value) { motionTrackerCameraDevice = value; DeviceType = VIODeviceType.EasyARMotionTracker; }
public DeviceUnion(ARKitCameraDevice value) { arKitCameraDevice = value; DeviceType = VIODeviceType.ARKit; }
public DeviceUnion(ARCoreCameraDevice value) { arCoreCameraDevice = value; DeviceType = VIODeviceType.ARCore; }
public enum VIODeviceType
{
EasyARMotionTracker,
ARKit,
ARCore,
}
public VIODeviceType DeviceType { get; private set; }
public MotionTrackerCameraDevice MotionTrackerCameraDevice
{
get { if (DeviceType != VIODeviceType.EasyARMotionTracker) throw new InvalidCastException(); ; return motionTrackerCameraDevice; }
set { motionTrackerCameraDevice = value; DeviceType = VIODeviceType.EasyARMotionTracker; }
}
public ARKitCameraDevice ARKitCameraDevice
{
get { if (DeviceType != VIODeviceType.ARKit) throw new InvalidCastException(); ; return arKitCameraDevice; }
set { arKitCameraDevice = value; DeviceType = VIODeviceType.ARKit; }
}
public ARCoreCameraDevice ARCoreCameraDevice
{
get { if (DeviceType != VIODeviceType.ARCore) throw new InvalidCastException(); return arCoreCameraDevice; }
set { arCoreCameraDevice = value; DeviceType = VIODeviceType.ARCore; }
}
public static explicit operator MotionTrackerCameraDevice(DeviceUnion value) { return value.MotionTrackerCameraDevice; }
public static explicit operator ARKitCameraDevice(DeviceUnion value) { return value.ARKitCameraDevice; }
public static explicit operator ARCoreCameraDevice(DeviceUnion value) { return value.ARCoreCameraDevice; }
public static implicit operator DeviceUnion(MotionTrackerCameraDevice value) { return new DeviceUnion(value); }
public static implicit operator DeviceUnion(ARKitCameraDevice value) { return new DeviceUnion(value); }
public static implicit operator DeviceUnion(ARCoreCameraDevice value) { return new DeviceUnion(value); }
public Type Type()
{
switch (DeviceType)
{
case VIODeviceType.EasyARMotionTracker:
return typeof(MotionTrackerCameraDevice);
case VIODeviceType.ARKit:
return typeof(ARKitCameraDevice);
case VIODeviceType.ARCore:
return typeof(ARCoreCameraDevice);
default: return typeof(void);
}
}
public override string ToString()
{
switch (DeviceType)
{
case VIODeviceType.EasyARMotionTracker:
return motionTrackerCameraDevice.ToString();
case VIODeviceType.ARKit:
return arKitCameraDevice.ToString();
case VIODeviceType.ARCore:
return arCoreCameraDevice.ToString();
default:
return "void";
}
}
}
[Serializable]
public class MotionTrackerCameraDeviceParameters
{
public MotionTrackerCameraDeviceFPS FPS;
public MotionTrackerCameraDeviceFocusMode FocusMode;
public MotionTrackerCameraDeviceResolution Resolution;
}
}
}
fileFormatVersion: 2
guid: c2dc4059a1f1a084e97aa697ce12d692
timeCreated: 1565837417
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 4a1652b606cd7464e86c87917bf2f6c4
folderAsset: yes
DefaultImporter:
externalObjects: {}
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.
//
//================================================================================================================================
Shader "EasyAR/CameraImage_BGR"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
Cull Off
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4x4 _projection;
v2f vert(appdata i)
{
v2f o;
o.vertex = mul(_projection, i.vertex);
if (_ProjectionParams.x < 0) // check if the render target is a texture rather than the screen, https://docs.unity3d.com/Manual/SL-PlatformDifferences.html
{
o.vertex.y = -o.vertex.y;
}
o.texcoord = float2(i.texcoord.x, 1.0 - i.texcoord.y); // Texture2D.LoadRawTextureData follows OpenGL convention and will invert Y-axis for uncompressed data on all platforms
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.texcoord).bgra;
#ifndef UNITY_COLORSPACE_GAMMA
col.xyz = GammaToLinearSpace(col.xyz);
#endif
return col;
}
ENDCG
}
}
}
fileFormatVersion: 2
guid: 1499e61b3897c4a4b9318a56ca931b8a
timeCreated: 1533005558
licenseType: Free
ShaderImporter:
defaultTextures: []
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.
//
//================================================================================================================================
Shader "EasyAR/CameraImage_Gray"
{
Properties
{
_grayTexture("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
Cull Off
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
sampler2D _grayTexture;
float4x4 _projection;
v2f vert(appdata i)
{
v2f o;
o.vertex = mul(_projection, i.vertex);
if (_ProjectionParams.x < 0) // check if the render target is a texture rather than the screen, https://docs.unity3d.com/Manual/SL-PlatformDifferences.html
{
o.vertex.y = -o.vertex.y;
}
o.texcoord = float2(i.texcoord.x, 1.0 - i.texcoord.y); // Texture2D.LoadRawTextureData follows OpenGL convention and will invert Y-axis for uncompressed data on all platforms
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float4 col = float4(tex2D(_grayTexture, i.texcoord).aaa, 1.0);
#ifndef UNITY_COLORSPACE_GAMMA
col.xyz = GammaToLinearSpace(col.xyz);
#endif
return col;
}
ENDCG
}
}
}
fileFormatVersion: 2
guid: 798d6e253a35a144d94205b80c8fd48b
timeCreated: 1534320738
licenseType: Free
ShaderImporter:
defaultTextures: []
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