0

我正在为我的 HoloLens 项目进行空间映射处理。

以某种方式调用“SpatialSurfaceMesh::TryComputeLatestMeshAsync”会超时返回相同的网格数据。是否有另一个过程涉及更新观察者?

void SpatialMapping::AddOrUpdateSurface(winrt::Windows::Perception::Spatial::SpatialCoordinateSystem const& coordinateSystem)
{
    using namespace winrt::Windows::Perception::Spatial::Surfaces;

    SpatialBoundingBox axisAlignedBoundingBox =
    {
        {  0.f,  0.f, 0.f },
        { 50.f, 50.f, 50.f },
    };
    SpatialBoundingVolume bounds = SpatialBoundingVolume::FromBox(coordinateSystem, axisAlignedBoundingBox);
    m_surfaceObserver.SetBoundingVolume(bounds);

    m_surfaceObserver.ObservedSurfacesChanged(
        winrt::Windows::Foundation::TypedEventHandler
        <SpatialSurfaceObserver, winrt::Windows::Foundation::IInspectable>
        ({ this, &SpatialMapping::Observer_ObservedSurfacesChanged })
    );
}

void SpatialMapping::Observer_ObservedSurfacesChanged(winrt::Windows::Perception::Spatial::Surfaces::SpatialSurfaceObserver const& sender
    , winrt::Windows::Foundation::IInspectable const& object)
{
    {
        using namespace winrt::Windows::Perception::Spatial::Surfaces;

        const auto mapContainingSurfaceCollection = sender.GetObservedSurfaces();

        // Process surface adds and updates?.
        for (const auto& pair : mapContainingSurfaceCollection)
        {
            auto id = pair.Key();
            auto info = pair.Value();
            InsertAsync(id, info);
        }
    }
}

Concurrency::task<void> SpatialMapping::InsertAsync(winrt::guid  /*const&*/ id, winrt::Windows::Perception::Spatial::Surfaces::SpatialSurfaceInfo  /*const&*/ newSurfaceInfo)
{
    using namespace winrt::Windows::Perception::Spatial::Surfaces;

    return concurrency::create_task([this, id, newSurfaceInfo]
        {
            const auto surfaceMesh = newSurfaceInfo.TryComputeLatestMeshAsync(m_maxTrianglesPerCubicMeter, m_surfaceMeshOptions).get();
            std::lock_guard<std::mutex> guard(m_meshCollectionLock);
            m_updatedSurfaces.emplace(id, surfaceMesh);
        });

}

生成有效,更新无效

曼努埃尔尝试同样的问题:

winrt::Windows::Foundation::IAsyncAction SpatialMapping::CollectSurfacesManuel()
{
    const auto mapContainingSurfaceCollection = m_surfaceObserver.GetObservedSurfaces();
    for (const auto& pair : mapContainingSurfaceCollection)
    {
        auto id = pair.Key();
        auto info = pair.Value();
        auto mesh{ co_await info.TryComputeLatestMeshAsync(m_maxTrianglesPerCubicMeter, m_surfaceMeshOptions) };
        {
            std::lock_guard<std::mutex> guard(m_meshCollectionLock);
            m_updatedSurfaces.emplace(id, mesh);
        }
    }
}

MVCE:

  1. 使用模板“Holographic DirectX 11 App (UWP) C++/WinRT)”创建一个新项目
  2. 添加文件: https ://github.com/lpnxDX/HL_MVCE_SpatialSurfaceMeshUpdateProblem.git
  3. 替换 AppView.h 中的 m_main
4

2 回答 2

0

我们做了一些研究,现在对你的问题有一些想法,让我解释一下调查结果

  1. 您的 Observer_ObservedSurfacesChanged 方法是否准确触发?添加输出语句或断点可以帮助您检查它。由于 SurfaceObserver 应该始终可用,通常我们需要在每一帧中检查 surfaceObserver 的可用性,并在必要时重新创建一个新的,示例代码片段请参见此处

  2. 你设置m_surfaceMeshOptions了吗?它在您发布的代码中不可见。如果缺少它,您可以使用以下语句对其进行配置:

    surfaceMeshOptions-> IncludeVertexNormals = true;

  3. Microsoft 提供了Holographic 空间映射示例,展示了如何从 Windows Perception 实时获取空间映射数据。它与您的需求相似,如果您的代码有问题,请缩小问题范围,请尝试在您的设备上检查并运行此示例

  4. 如果经过上述步骤后仍然无法解决问题,能否提供一个 MVCE以便我们定位问题或找到解决方案?小心删除任何与隐私相关的或其他业务功能代码。

于 2020-06-26T09:52:49.160 回答
0

您的代码存在以下问题:

  1. TryComputeLatestMeshAsync 应该从 Observer_ObservedSurfacesChanged 调用而不是从 concurrency::create_task
  2. TryComputeLatestMeshAsync 返回带有矩阵、顶点和索引的网格。索引应在第一次运行时存储到安全位置,以后不会更改。顶点和矩阵应在返回时复制。您不应该保存网格本身,因为它的数据会从各个线程更新。
  3. 不应每帧都调用 ObservedSurfacesChanged。这是长期运行的功能。

也许它还有更多的东西。我建议从前面提到的示例开始。

于 2020-06-26T12:27:15.363 回答