如何从DirectXTK(ToolKit)DirectX :: Model类中获取所有顶点坐标以用于冲突检测

时间:2017-05-22 22:30:50

标签: c++ visual-studio-2015 directx directx-11

我用DirectXToolKit做一些基本的渲染,我希望能够获得每个模型的顶点坐标,以便计算模型之间的碰撞。

目前,我有一些测试代码可以加载模型,但ID3D11Buffer在内部使用CreateFromSDKMESH加载

void Model3D::LoadSDKMESH(ID3D11Device* p_device, ID3D11DeviceContext* device_context, const wchar_t* file_mesh)
{
    mAlpha = 1.0f;
    mTint = DirectX::Colors::White.v;

    mStates.reset(new DirectX::CommonStates(p_device));
    auto fx = new DirectX::EffectFactory(p_device);
    fx->SetDirectory(L"media");
    mFxFactory.reset(fx);
    mBatch.reset(new DirectX::PrimitiveBatch<DirectX::VertexPositionColor>(device_context));

    mBatchEffect.reset(new DirectX::BasicEffect(p_device));
    mBatchEffect->SetVertexColorEnabled(true);
    {
        void const* shaderByteCode;
        size_t byteCodeLength;

        mBatchEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);

        HR(p_device->CreateInputLayout(DirectX::VertexPositionColor::InputElements,
            DirectX::VertexPositionColor::InputElementCount,
            shaderByteCode, byteCodeLength,
            mBatchInputLayout.ReleaseAndGetAddressOf()));
    }

    mModel = DirectX::Model::CreateFromSDKMESH(p_device, file_mesh, *mFxFactory);
}

我知道有一种方法可以从ID3D11Buffer获取顶点,在这里回答: How to read vertices from vertex buffer in Direct3d11

但他们建议不要从GPU内存加载。所以我假设将顶点提前加载到一个单独的容器中会更好。

1 个答案:

答案 0 :(得分:0)

我查看了CreateFromSDKMESH,并且有一些可公开访问的功能,而无需更改XTK

要在加载模型时获取顶点,请将以上问题中的行mModel = DirectX::Model::CreateFromSDKMESH(p_device, file_mesh, *mFxFactory);替换为:

size_t data_size = 0;
std::unique_ptr<uint8_t[]> v_data;
HRESULT hr = DirectX::BinaryReader::ReadEntireFile(file_mesh, v_data, &data_size);
if (FAILED(hr))
{
    DirectX::DebugTrace("CreateFromSDKMESH failed (%08X) loading '%ls'\n", hr, file_mesh);
    throw std::exception("CreateFromSDKMESH");
}
uint8_t* mesh_data = v_data.get();
mModel = DirectX::Model::CreateFromSDKMESH(p_device, v_data.get(), data_size, *mFxFactory, false, false);
mModel->name = file_mesh;
auto v_header = reinterpret_cast<const DXUT::SDKMESH_HEADER*>(mesh_data);
auto vb_array = reinterpret_cast<const DXUT::SDKMESH_VERTEX_BUFFER_HEADER*>(mesh_data + v_header->VertexStreamHeadersOffset);

if(v_header->NumVertexBuffers < 1)
    throw std::exception("Vertex Buffers less than 1");
auto& vertex_header = vb_array[0];
uint64_t buffer_data_offset = v_header->HeaderSize + v_header->NonBufferDataSize;
uint8_t* buffer_data = mesh_data + buffer_data_offset;  
auto verts_pairs = reinterpret_cast<std::pair<Vector3,Vector3>*>(buffer_data + (vertex_header.DataOffset - buffer_data_offset));

在那里,访问坐标应该像

一样简单

float x = verts_pairs[0].first.x; 并且顶点总数存储在

vertex_header.NumVertices

不要忘记加载顶点缓冲区后会被删除,所以你可能想要做类似的事情:

memcpy(vertexBuffer, reinterpret_cast<std::pair<Vector3,Vector3>*>(buffer_data + (vertex_header.DataOffset - buffer_data_offset)), vertexCnt);

此外,顶点缓冲区不会被绘制函数转换,所以你需要自己进行转换

谢谢,