Vuforia功能记录(一)------ 动态加载dataset

为了方便AR开发交流,博主建立了一个群 :891555732,欢迎一起讨论


2018.10.25更新

当项目中有两个Model Target时如果在初始就激活Model target程序集,如下所示

Vuforia功能记录(一)------ 动态加载dataset_第1张图片

这样运行动态加载的话是无法识别的,哪怕只激活其中一个也无法识别,而且没有轮廓图

将上面的全部取消勾选,更改动态加载成功识别完整代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Vuforia;

public class DataSetHandle : MonoBehaviour {
    public static void LoadDataSet(string dataSetName)
    {
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
        IEnumerable datasets = objectTracker.GetDataSets();

        objectTracker.Stop();
        foreach (var tb in datasets)
        {
            objectTracker.DeactivateDataSet(tb);
        }
        DataSet dataSet = objectTracker.CreateDataSet();
        if (dataSet.Load(dataSetName))
        {
            //这里必须要停止跟踪才能激活DataSet
            objectTracker.ActivateDataSet(dataSet);
        }
        objectTracker.Start();
    }
    public static Transform ConfigTrackable(string trackedName, string trackComName, GameObject modelPre, Transform recogParent)
    {
        IEnumerable tbs = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();
        foreach (TrackableBehaviour tb in tbs)
        {
            if (tb.TrackableName == trackedName)
            {
                tb.transform.parent = recogParent;
                tb.gameObject.name = trackedName;
                //动态添加识别组件
                tb.gameObject.AddComponent(Type.GetType(trackComName));

                tb.gameObject.AddComponent();

                GameObject augmentation = Instantiate(modelPre, tb.transform);
                if (tb.CurrentStatus == TrackableBehaviour.Status.TRACKED)
                    augmentation.gameObject.SetActive(true);
                else
                    augmentation.gameObject.SetActive(false);
                return augmentation.transform;
            }
        }
        return null;
    }
    ///   
    /// 关闭指定识别数据集  
    ///   
    /// 数据集名称或绝对路径  
    public static void DeactivateDateset(string datasetName)
    {
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();

        IEnumerable activeDataSets = objectTracker.GetActiveDataSets();

        List activeDataSetsToBeRemoved = activeDataSets.ToList();

        List dataSetsToBeActive = new List();

        foreach (DataSet ads in activeDataSetsToBeRemoved)
        {
            objectTracker.DeactivateDataSet(ads);
            if (!ads.Path.Contains(datasetName))
            {
                dataSetsToBeActive.Add(ads);
            }
            else
            {
                objectTracker.DestroyDataSet(ads, false);
                var trackables = ads.GetTrackables();
                foreach (var item in trackables)
                {
                    TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(item, true);
                }
            }
        }
        objectTracker.Stop();
        foreach (DataSet ds in dataSetsToBeActive)
        {
            objectTracker.ActivateDataSet(ds);
        }
        objectTracker.Start();
    }
    //通过名称切换ModelTarget
    public void SwitchTargetByName(string activateThisDataset)
    {
        TrackerManager trackerManager = (TrackerManager)TrackerManager.Instance;
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();

        IEnumerable datasets = objectTracker.GetDataSets();
        IEnumerable activeDataSets = objectTracker.GetActiveDataSets();
        List activeDataSetsToBeRemoved = activeDataSets.ToList();

        //循环遍历所有活动数据集并停用它们。
        foreach (DataSet ads in activeDataSetsToBeRemoved)
        {
            objectTracker.DeactivateDataSet(ads);
        }

        //当ObjectTracker同时工作时,不应该交换数据集。
        //所以,先停止跟踪器。
        objectTracker.Stop();
        //然后,查找新的数据集,如果有一个数据集,激活它。
        foreach (DataSet ds in datasets)
        {
            if (ds.Path.Contains(activateThisDataset))
            {
                objectTracker.ActivateDataSet(ds);
            }
        }
        //最后,启动对象跟踪器。
        objectTracker.Start();
    }
    //此函数将加载并激活指定的数据集。它不会被取消激活
    //任何东西,所以确保没有其他模型目标数据集是主动的以避免问题。
    public void ActivateTarget(string loadThisDataset)
    {
        TrackerManager trackerManager = (TrackerManager)TrackerManager.Instance;
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();

        //Stop the tracker.
        objectTracker.Stop();

        //创建一个新的数据集对象。
        DataSet dataset = objectTracker.CreateDataSet();

        //如果数据集存在,加载并激活它。
        if (DataSet.Exists(loadThisDataset))
        {
            dataset.Load(loadThisDataset);
            objectTracker.ActivateDataSet(dataset);
        }

        //Start the object tracker.
        objectTracker.Start();
    }
}

 


参考链接:

  • vuforia动态加载dataset和imageTarget:https://blog.csdn.net/Pineapplle/article/details/49449343#
  • API 动态加载,动态更改识别数量等:https://blog.csdn.net/su9257/article/details/74608114

第一个链接简单明了,我首先采用了第一个链接加载程序集并初始化模型,第二个链接功能齐全,但是是Resources加载程序集,移动平台首先还得先将资源放在Application.persistentDataPath + "/" + "DataDirectory"+"/"目录下,不实用,两者结合非常nice

代码如下:

using System.Collections.Generic;
using UnityEngine;
using Vuforia;
using System.Linq;

public class TrackableSetting : MonoBehaviour
{
    public static TrackableSetting Instance;
    public void Awake()
    {
        Instance = this;
    }
    public void LoadDataSet(string dataSetName)
    {
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
        IEnumerable datasets = objectTracker.GetDataSets();
        foreach (var tb in datasets)
        {
            objectTracker.DeactivateDataSet(tb);
        }
        DataSet dataSet = objectTracker.CreateDataSet();
        if (dataSet.Load(dataSetName))
        {
            objectTracker.Stop();//这里必须要停止跟踪才能激活DataSet
            objectTracker.ActivateDataSet(dataSet);
            objectTracker.Start();
        }
    }
    public Transform ConfigTrackable(string trackedName,GameObject modelPre,Transform recogParent)
    {
        IEnumerable tbs = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();
        foreach (TrackableBehaviour tb in tbs)
        {
            if (tb.TrackableName == trackedName)
            {
                tb.transform.parent = recogParent;
                tb.gameObject.name = trackedName;
                //下面这两句不能少,需要给它加上这两个组件
                tb.gameObject.AddComponent();
                tb.gameObject.AddComponent();


                GameObject augmentation = Instantiate(modelPre, tb.transform);
                if(tb.CurrentStatus == TrackableBehaviour.Status.TRACKED)
                     augmentation.gameObject.SetActive(true);
                else
                      augmentation.gameObject.SetActive(false);
                return augmentation.transform;
            }
        }
        return null;
    }
    ///   
    /// 关闭指定识别数据集  
    ///   
    /// 数据集名称或绝对路径  
    public virtual void DeactivateDateset(string datasetName)
    {
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
        IEnumerable datasets = objectTracker.GetDataSets();


        IEnumerable activeDataSets = objectTracker.GetActiveDataSets();


        List activeDataSetsToBeRemoved = activeDataSets.ToList();


        List dataSetsToBeActive = new List();


        foreach (DataSet ads in activeDataSetsToBeRemoved)
        {
            objectTracker.DeactivateDataSet(ads);
            if (!ads.Path.Contains(datasetName))
            {
                dataSetsToBeActive.Add(ads);
            }
            else
            {
                objectTracker.DestroyDataSet(ads, false);
                var trackables = ads.GetTrackables();
                foreach (var item in trackables)
                {
                    TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(item, true);
                }
            }
        }
        objectTracker.Stop();
        foreach (DataSet ds in dataSetsToBeActive)
        {
            objectTracker.ActivateDataSet(ds);
        }
        objectTracker.Start();
    }
}



 

问题总结:

 

 ①.第一篇参考博文大家会看到地下评论说ObjectTracker objectTracker = TrackerManager.Instance.GetTracker(); 这句执行的时候返回的是空指针,我也遇上了这个问题,我是其他场景跳转到vuforia识别场景,在start执行方法LoadDataSet,然而当我在update打印

        Debug.Log(TrackerManager.Instance);

输出如下: 

                                               Vuforia功能记录(一)------ 动态加载dataset_第2张图片

发现是start函数都执行完后才有值,因此在Update函数中用个参数来判断不为空即执行,完美解决

        if(!isInit && TrackerManager.Instance != null)
        {
            isInit = true;
            TrackableSetting.Instance.LoadDataSet("Saturn_5");
            //TODO 动态生成,要
            Model = TrackableSetting.Instance.ConfigTrackable("Saturn_5", ModelPre[0],transform); //生成模型
            if (Model != null)
            {
                modelTarget = Model.parent.GetComponent();
                modelTarget.GuideViewMode = ModelTargetBehaviour.GuideViewDisplayMode.GuideView2D;
            }
        }

②.移除特定的程序集时出现问题:

                                                      Vuforia功能记录(一)------ 动态加载dataset_第3张图片                      

      解决方案参考链接:https://blog.csdn.net/aiyan1111111/article/details/52814017

      原来时我虽然Destroy了程序集,但是并没有将程序集里面的识别对象从 TrackerManager.Instance.GetStateManager()中移除,而第二篇博文中那位老兄应该是没有Destroy物体只是Deactive程序集而已,才没有出现我这个问题,总之增加了如下代码:

var trackables = ads.GetTrackables();
foreach (var item in trackables)
{
     TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(item, true);
}

完整代码已经在上面TrackableSetting脚本更新


 

 

你可能感兴趣的:(AR,AR之道)