0

我一直在尝试使用从空间理解示例场景中获取的数据将对象放入房间。但是代码对我来说真的无法理解。有人使用spatialtoolkitexample 实现了这一点吗?有什么帮助吗?

https://github.com/Microsoft/HoloToolkit-Unity/tree/master/Assets/HoloToolkit-Examples/SpatialUnderstanding/SpatialUnderstanding-FeatureOverview/Scripts

所有的脚本都在这里,在 UI 脚本 Query_OnFloor_AwayFromMe() 被调用然后我有点失去对代码的跟踪,直到 linedrawer 脚本中的 draw_box 被调用。在 draw_box 中,我尝试了以下方法将我的全息图带到那里,但没有任何显示。

  mydummy.SetActive(true);
  mydummy.transform.position = new Vector3(center.x,center.y,center.z);
4

1 回答 1

0

我将首先尝试解释此示例中发生的情况。从 UI.cs 中的调用开始到 Query_OnFloor_AwayFromMe()...

  1. 这会调用 LevelSolver.cs。在这个方法中,它创建了一个新的 PlacementQuery 对象并调用 PlaceObjectAsync。
  2. PlaceObjectAsync 通过调用 System.Threading.Tasks.Task.Run 创建一个新线程,调用空间理解的实际工作已经完成。这项工作必须在单独的线程中完成,因为它需要很长时间,因此需要跨多个帧执行,否则您的应用程序将在执行期间锁定。
  3. 在调用新线程 PlaceObject 时,这会实际调用空间理解 (SpatialUnderstandingDllObjectPlacement.Solver_PlaceObject),这是对 C++ HoloToolkit 的调用,这是需要很长时间的调用。当这完成时,结果被添加到基本上是一个工作队列的placementResults。
  4. 在 LevelSolver.cs 中有一个 Update 方法,每次统一绘制新框架时都会调用该方法。这里有一个对 Draw_PlacementResults 的调用。
  5. Draw_PlacementResults 循环遍历放置结果工作队列中的每个结果,并调用 LineDrawer.cs 中的 Draw_AnimatedBox
  6. 这就是我们在上一个问题中讨论的对 Draw_Box 的调用的方式。

所以另一个问题是我如何修改这个例子来放置你自己的模型。我建议在 LevelSolver.cs 中进行修改。尝试将 Update() 更改为如下内容:

private void Update()
{
    // Can't do any of this till we're done with the scanning phase
    if (SpatialUnderstanding.Instance.ScanState != SpatialUnderstanding.ScanStates.Done)
    {
        return;
    }

    // Make sure the solver has been initialized
    if (!IsSolverInitialized &&
        SpatialUnderstanding.Instance.AllowSpatialUnderstanding)
    {
        InitializeSolver();
    }

    // Constraint queries
    if (SpatialUnderstanding.Instance.ScanState == SpatialUnderstanding.ScanStates.Done)
    {
        Update_Queries();
    }

    // Handle async query results
    ProcessPlacementResults();

    MyProcessPlacementResults();
}

这将导致它停止绘制框,而是调用“MyProcessPlacementResults”来处理对结果进行的处理。我会在 LevelSolver.cs 中添加类似这样的方法。(在我借用的代码中,我正在创建一棵树)

private void MyProcessPlacementResults()
{
    if (placementResults.Count > 0)
    {
        var toPlace = placementResults.Dequeue();

        var rotation = Quaternion.LookRotation(toPlace.Result.Forward, Vector3.up);
        CreateTree(toPlace.Result.Position, rotation);

    }
}

这是我用来在正确位置实际实例化树的代码:

private GameObject ThisIsYourCustomModelInMineItWasATree;
private Vector3 TheSizeIPassedToSpatialUnderstanding = new Vector3(1, 1, 1);

public void CreateHologram(Vector3 positionCenter, Quaternion rotation)
{
    ThisIsYourCustomModelInMineItWasATree = GameObject.CreatePrimitive(PrimitiveType.Sphere);

    GameObject newObject = Instantiate(ThisIsYourCustomModelInMineItWasATree, positionCenter, rotation) as GameObject;

    if (newObject != null)
    {
        // Set the parent of the new object the GameObject it was placed on
        newObject.transform.parent = gameObject.transform;

        newObject.transform.localScale = StretchToFit(ThisIsYourCustomModelInMineItWasATree, TheSizeIPassedToSpatialUnderstanding);
        newObject.AddComponent<MeshCollider>();
    }
}

为了完整起见,这里是我用来将其缩放到所需大小的代码:

private Vector3 StretchToFit(GameObject obj, Vector3 desiredSize)
{
    var curBounds = GetBoundsForAllChildren(obj).size;

    return new Vector3(desiredSize.x / curBounds.x / 2, desiredSize.y, desiredSize.z / curBounds.z / 2);
}

private Bounds GetBoundsForAllChildren(GameObject findMyBounds)
{
    Bounds result = new Bounds(Vector3.zero, Vector3.zero);

    foreach (var renderer in findMyBounds.GetComponentsInChildren<Renderer>())
    {
        if (result.extents == Vector3.zero)
        {
            result = renderer.bounds;
        }
        else
        {
            result.Encapsulate(renderer.bounds);
        }
    }

    return result;
}

我还将私有变量placementResults 从列表更改为队列。我这样做是因为 List 用于在每一帧中绘制一个框。我们想要一个队列,因为我们将实例化一个新对象一次并让统一引擎管理它。找到这一行:

private List<PlacementResult> placementResults = new List<PlacementResult>();

并将其更改为:

private Queue<PlacementResult> placementResults = new Queue<PlacementResult>();

进行更改后,您将需要修复几个地方。删除方法 Draw_PlacementResults,反正它不再使用了。将调用placementResults.Add 的两个地方更改为placementResults.Enqueue。

于 2016-11-25T05:24:17.707 回答