2016-11-23 65 views
0

我一直在试图将对象放置到房间与spatialunderstandingExample现场拍摄的数据。但是代码对我来说真的不可理解。有没有人使用空间工具实现这个功能?任何帮助?HoloToolkit空间理解和对象放置

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); 
+0

根据您以前的问题(http://stackoverflow.com/questions/40728179/hololens-placing-objects-with-spatial-understanding/40729295#40729295),您已成功替换为您的全息图的默认框自己的,但你正在努力得到它的正确和规模的地方,大小合适,之前我张贴的答案,是正确的? –

+0

我想我没有,但它是一个游戏物体我忘了关。所以我再次回到那里:( – firativerson

+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有一个更新的方法,这将调用每一个团结绘制一个新的帧的时间。在这里调用Draw_PlacementResults。
  5. Draw_PlacementResults循环遍历placementResults工作队列中的每个结果,并调用LineDrawer.cs中的Draw_AnimatedBox
  6. 这就是您如何访问我们在上一个问题中讨论的Draw_Box的调用。

所以,另一个问题是如何修改这个例子来把你自己的模型放在适当的位置。我建议在LevelSolver.cs中进行修改。尝试改变更新(),以这样的:

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从列表添加到队列。我这样做是因为列表被用来在每一帧中绘制一个框。我们希望有一个队列,因为我们要一次实例化一个新的对象,并让Unity引擎管理。找到这行:

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

并将其更改为:

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

做出这样的转变,你将需要解决几个地方之后。删除方法Draw_PlacementResults,它不再被使用。更改调用placementResults.Add的两个位置到placementResults.Enqueue。

+0

这是你的实际代码?在MyProcessPlacementResults()我不能离队放置导致它没有让我,我试图让他们一个个仍然没有工作... – firativerson

+1

是的,它是我的代码,我撕出来一个更大的项目,这是不是基于你的工作了的例子。你是对的,我placementResults是一个实际的队列,我将修改我的答案,试图解决这个问题。 –

+0

谢谢卡梅伦期待它 – firativerson