C++/WinRT从SpatialSurfaceMesh的IBuffer获取顶点位置遇问题
问题:HoloLens C++/WinRT项目提取SpatialSurfaceMesh顶点数据的错误与异常结果
一、IBuffer转换时的越界访问错误
开发基于C++/WinRT的HoloLens项目时,需从SpatialSurfaceMesh::VertexPositions()返回的IBuffer中提取顶点位置数据。参考全息空间映射示例项目(实现网格IBuffer数据渲染),将示例中的C++/CX版本GetDataFromIBuffer函数转换为C++/WinRT版本:
template <typename t = byte> t* GetDataFromIBuffer(IBuffer container) { if (container == nullptr) { return nullptr; } unsigned int bufferLength = container.Length(); if (!(bufferLength > 0)) { return nullptr; } HRESULT hr = S_OK; Microsoft::WRL::ComPtr<IUnknown> pUnknown = reinterpret_cast<IUnknown*>(&container); Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> spByteAccess; hr = pUnknown.As(&spByteAccess); if (FAILED(hr)) { return nullptr; } byte* pRawData = nullptr; hr = spByteAccess->Buffer(&pRawData); if (FAILED(hr)) { return nullptr; } return reinterpret_cast<t*>(pRawData); }
运行时触发错误:Unhandled exception at 0x00007FF985543848 (ntdll.dll) in Project.exe: RangeChecks instrumentation code detected an out of range array access.,错误发生在Microsoft::WRL::ComPtr<IUnknown> pUnknown = reinterpret_cast<IUnknown*>(&container);行的转换操作中。
尝试另一种实现方式:
byte* GetDataFromIBuffer(IBuffer container) { if (container == nullptr) { return nullptr; } unsigned int bufferLength = container.Length(); if (!(bufferLength > 0)) { return nullptr; } HRESULT hr = S_OK; IUnknown* pUnk = reinterpret_cast<IUnknown*>(&container); Windows::Storage::Streams::IBufferByteAccess * spByteAccess = nullptr; hr = pUnk->QueryInterface(IID_PPV_ARGS(&spByteAccess)); if (FAILED(hr)) { return nullptr; } byte* pRawData = nullptr; hr = spByteAccess->Buffer(&pRawData); if (FAILED(hr)) { return nullptr; } return reinterpret_cast<byte*>(pRawData); }
仍出现相同错误,错误位置变为hr = pUnk->QueryInterface(IID_PPV_ARGS(&spByteAccess));行。
二、修复转换错误后顶点数据不符合空间逻辑
经IInspectable解答后,转换代码不再报错,但获取的顶点位置结果不符合空间逻辑。后续处理代码如下:
auto position = surfaceMesh.second->VertexPositions(); auto stride = position.Stride(); auto scale = surfaceMesh.second->VertexPositionScale(); auto positionCoordinateSystem = surfaceMesh.second->CoordinateSystem(); auto transform = positionCoordinateSystem.TryGetTransformTo(currentCoordinateSystem).Value(); ... // 在循环中: auto rawData = GetDataFromIBuffer(position.Data()); float x = BytesToShort(rawData + i) / scale.x; i += stride; float y = BytesToShort(rawData + i) / scale.y; i += stride; float z = BytesToShort(rawData + i) / scale.z; i += stride * 2; float3 vertex = MultVectByMat({ x, y, z }, transform);
得到的结果存在不合理值,例如z=5,意味着设备检测到自身后方5米处有表面,与实际情况不符。
内容的提问来源于stack exchange,提问作者Nikow
相关产品推荐
相关产品推荐

