【问题标题】:HoloLens spatial mapping.SpatialSurfaceMesh update problem. C++/winrtHoloLens 空间映射。SpatialSurfaceMesh 更新问题。 C++/winrt
【发布时间】:2020-06-24 16:18:54
【问题描述】:

我正在为我的 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);
        });

}

Generation works, Update does not

Manuel 尝试同样的问题:

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. 使用模板创建一个新项目 “全息 DirectX 11 应用 (UWP) C++/WinRT)”
  2. 添加文件: https://github.com/lpnxDX/HL_MVCE_SpatialSurfaceMeshUpdateProblem.git
  3. 替换 AppView.h 中的 m_main

【问题讨论】:

  • 通过 const ref 将值传递给异步操作肯定是自找麻烦。您应该改为按值传递。这可能与您观察到的问题有关,也可能无关。
  • 没有区别。

标签: hololens c++-winrt hololens-emulator


【解决方案1】:

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

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

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

    surfaceMeshOptions-> IncludeVertexNormals = true;

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

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

【讨论】:

  • 感谢您的回答 1. Observer_ObservedSurfacesChanged 仅在绑定 (1x) 时触发 2. 是的,网格生成正在工作。更新是问题。 3.例子是用c++/cx编写的。毕竟它可能是 c++/winrt 中的一个错误。 4. MVCE: 1. 使用模板“Holographic DirectX 11 App (UWP) C++/WinRT)”创建一个新项目 2. 添加文件:github.com/lpnxDX/HL_MVCE_SpatialSurfaceMeshUpdateProblem.git 3. 替换 AppView.h 中的 m_main
【解决方案2】:

您的代码存在以下问题:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多