ImageTracking_Targets

演示平面图像跟踪功能。

  • 演示创建target的不同方法

  • 演示动态创建target

  • 演示通过ImageTargetData创建target的方法

  • 演示如何加载和卸载target

  • 演示如何使用不同中心模式(center mode)

  • 演示如何使用不同的水平翻转模式

用法

../../_images/image_26.png
标记1:是否打开Camera。
标记2:按照索引逐个切换Camera。
标记3:切换水平翻转模式。
标记4:切换世界中心模式。
标记5:卸载/加载场景中所有ImageTarget。
标记6:停止跟踪/开始跟踪。
标记7:显示系统状态和操作提示。

详解

场景中的target

如果你需要替换sample中的图像,需要确保选择一个纹理丰富的 .jpg 或 .png 文件。建议阅读 这篇指南 来帮助选择一个可跟踪的图像。

../../_images/image_s1_12.png

Target可以直接在 Unity 编辑器的inspector中配置。

  • Active Control: Targets 及其 children 将在 target 未被跟踪时隐藏。如果你需要在跟踪丢失时保持显示,可以修改这个参数,也可以写自己的处理策略。

  • Source Type: 根据这个参数的数值,targets会从 Image FileTarget Data File 中创建。

  • Path Type: 这里设置为 StreamingAssets ,表示 Path 将使用相对于StreamingAssets的路径。

  • Path: 这个sample中使用图片相对于StreamingAssets的路径。

  • Name: target名字,可以随意输入。

  • Scale: 根据识别图宽度实际的物理大小设置。

  • Tracker: 需要加载ImageTarget的Tracker。

Gizmo将会在target设置有效的时候显示,如有需要也可以在全局配置中关闭。在game view不会显示。game view中namecard的图像是场景中 ImageTarget-namecard 节点下的一个quad。

方块和鸭子的 transform 被调整为底面与识别图对齐。在运行这个场景并跟踪到 target的时候,方块和鸭子会在图像上面显示。

在脚本中创建target -- 从图像创建

可以在脚本中使用图像来创建target。基本上需要做的事情就是把 inspector中的配置在脚本中通过代码做一遍。首先需要创建一个空的 GameObject 并添加 ImageTargetController

private ImageTargetController CreateTargetNode(string targetName)
{
    GameObject go = new GameObject(targetName);
    var targetController = go.AddComponent<ImageTargetController>();
    ...
}

然后像在inspector中一样设置 ImageTargetControllerTrackerSourceTypeImageFileSource.PathTypeImageFileSource.PathImageFileSource.NameImageFileSource.Scale 的值。

var targetController = CreateTargetNode("ImageTarget-argame00");
targetController.Tracker = imageTracker;
targetController.SourceType = ImageTargetController.DataSource.ImageFile;
targetController.ImageFileSource.PathType = PathType.StreamingAssets;
targetController.ImageFileSource.Path = "sightplus/argame00.jpg";
targetController.ImageFileSource.Name = "argame00";
targetController.ImageFileSource.Scale = 0.1f;

在GameObject节点下添加物体,以便在target被跟踪时显示。

GameObject duck02 = Instantiate(Resources.Load("duck02")) as GameObject;
duck02.transform.parent = targetController.gameObject.transform;

在脚本中创建target -- 从列表创建

可以在脚本中通过一个有详细信息的列表创建target。你需要自己定义这个列表的描述。加载json文件的接口已经废弃并在Sense新版本中已经不再被支持。自己定义列表可以在不损失性能的情况下提供定义自己的target描述的灵活性。

类似EasyAR Sense 1.0的json配置的定义可以这样描述,

var imageJosn = JsonUtility.FromJson<ImageJson>(@"
{
    ""images"" :
    [
        {
            ""image"" : ""sightplus/argame01.png"",
            ""name"" : ""argame01""
        },
        {
            ""image"" : ""sightplus/argame02.jpg"",
            ""name"" : ""argame02"",
            ""scale"" : 0.2
        },
        {
            ""image"" : ""sightplus/argame03.jpg"",
            ""name"" : ""argame03"",
            ""scale"" : 1,
            ""uid"" : ""uid string will be ignored""
        }
    ]
}");

只需要通过一个循环来创建target就可以,所有耗时过长会在背景线程中处理。

foreach (var image in imageJosn.images)
{
    targetController = CreateTargetNode("ImageTarget-" + image.name);
    targetController.Tracker = imageTracker;
    targetController.ImageFileSource.PathType = PathType.StreamingAssets;
    targetController.ImageFileSource.Path = image.image;
    targetController.ImageFileSource.Name = image.name;
    targetController.ImageFileSource.Scale = image.scale;

    var duck03 = Instantiate(Resources.Load("duck03")) as GameObject;
    duck03.transform.parent = targetController.gameObject.transform;
}

Target事件

Target事件可以用来处理自定义操作。这个sample使用这些事件来输出一些日志。在使用中可以删除这些日志,也可以添加自己的应用逻辑。

controller.TargetFound += () =>
{
    Debug.LogFormat("Found target {{id = {0}, name = {1}}}", controller.Target.runtimeID(), controller.Target.name());
};
controller.TargetLost += () =>
{
    Debug.LogFormat("Lost target {{id = {0}, name = {1}}}", controller.Target.runtimeID(), controller.Target.name());
};
controller.TargetLoad += (Target target, bool status) =>
{
    Debug.LogFormat("Load target {{id = {0}, name = {1}, size = {2}}} into {3} => {4}", target.runtimeID(), target.name(), controller.Size, controller.Tracker.name, status);
};
controller.TargetUnload += (Target target, bool status) =>
{
    Debug.LogFormat("Unload target {{id = {0}, name = {1}}} => {2}", target.runtimeID(), target.name(), status);
};

加载卸载Target

Target的加载和卸载非常简单。设置 ImageTargetController.Tracker 为 null,target 就会被卸载,而设为某个 tracker,target就会立即被加载进去。

public void UnloadTargets()
{
    foreach (var item in imageTargetControllers)
    {
        item.Key.Tracker = null;
    }
}

public void LoadTargets()
{
    foreach (var item in imageTargetControllers)
    {
        item.Key.Tracker = imageTracker;
    }
}

开关跟踪

ImageTrackerFrameFilter.enabled 可以控制图像跟踪功能的开关。可以在不需要的时候关闭跟踪来节省资源。跟踪关闭的时候不会对camera或其它跟踪功能产生影响。

public void Tracking(bool on)
{
    imageTracker.enabled = on;
}

开关相机

VideoCameraDevice.enabled 可以控制Camera设备的开关。如果camera关闭,跟踪功能将停止收到数据,整个AR链条将停止。

public void EnableCamera(bool enable)
{
    cameraDevice.enabled = enable;
}

中心模式

在物体感知功能中,有三个 ARSession.CenterMode 的模式是有效的。

ARSession.ARCenterMode.Camera 模式中,设备运动时camera不会自动移动。

../../_images/image_s1_2.gif

ARSession.ARCenterMode.FirstTargetARSession.ARCenterMode.SpecificTarget 模式中,camera会在设备运动时自动移动,而target不会动。

../../_images/image_s1_3.gif

为了说明 ARSession.ARCenterMode.FirstTargetARSession.ARCenterMode.SpecificTarget 之间的不同,我们修改了 tracker 配置以同时跟踪两个target。

ARSession.ARCenterMode.FirstTarget 模式中,有target被跟踪时camera会移动,而中心将会是第一个被跟踪到的target,这个target丢失的时候中心会切换到其它target。

../../_images/image_s1_4.gif

在中心target没有变化的时候, ARSession.ARCenterMode.SpecificTarget 模式会一直使用指定的target作为中心,如果这个target丢失,camera将不会移动。

../../_images/image_s1_5.gif

ARSession.CenterMode 可以随时修改并将立即生效。

../../_images/image_s1_6.gif

水平翻转相机图像

ARSession.HorizontalFlipNormalARSession.HorizontalFlipFront 控制了camera图像是如何进行镜像显示的。在camera图像镜像显示的时候,camera投影矩阵或 target scale会同时改变,以确保跟踪行为可以继续。

ARHorizontalFlipMode.None 模式下没有镜像显示。

../../_images/image_s1_71.png

ARHorizontalFlipMode.World 模式下,camera图像会镜像显示,camera投影矩阵会变化进行镜像渲染,target scale不会改变。投影矩阵的改变将对场景中所有物体产生副作用,如果这个效果不是你想要的,可以选择 ARHorizontalFlipMode.Target 模式。

../../_images/image_s1_81.png

ARHorizontalFlipMode.Target 模式下,camera图像会镜像显示,target scale会改变进行镜像渲染,camera投影矩阵不会改变。

../../_images/image_s1_91.png

ARSession.HorizontalFlipNormalARSession.HorizontalFlipFront 可随时修改并将立即生效。

../../_images/image_s1_10.gif