尝试在DirectX 11中加载Obj文件时,向量下标超出范围

时间:2014-03-07 15:46:23

标签: c++ directx directx-11 vertex

当我尝试加载没有法线或纹理坐标的Obj文件时,我得到的矢量下标超出了范围。如果我加载一个具有法线和纹理坐标的obj文件,那么一切正常。所以我只是问我如何修改我的代码以加载没有法线和纹理坐标的obj文件。

这是我存储VERTEX数据的结构

struct VERTEX
{
    XMFLOAT3 position;
    XMFLOAT3 normal;
    XMFLOAT2 texcoord;
};

这些顶点用于存储

中的数据
std::vector<XMFLOAT3> m_position;
std::vector<XMFLOAT2> m_texCoords;
std::vector<XMFLOAT3> m_normals;
std::vector<VERTEX> m_vertices;
std::vector<DWORD> m_Indices;
VERTEX vertex;

这就是我阅读脸部线条的方法。这一切都运行正常,但我不确定是否可能是因为加载没有法线和纹理坐标的obj文件时我的程序中断的原因。

        else if (strcmp(buffer, "f") == 0)
        {
            int fPosition, fTexCoord, fNormal; //data of a single vertex

            for (int iFace = 0; iFace < 3; iFace++)
            {
                ZeroMemory(&vertex, sizeof(VERTEX));
                file >> fPosition;
                vertex.position = m_position[fPosition - 1];

                if (file.peek() == '/')
                {
                    file.ignore();

                    if (file.peek() != '/')
                    {
                        file >> fTexCoord;
                        vertex.texcoord = m_texCoords[fTexCoord - 1];
                    }

                    if (file.peek() == '/')
                    {
                        file.ignore();
                        file >> fNormal;
                        vertex.normal = m_normals[fNormal -1];
                    }

                    m_vertices.push_back(vertex);
                    m_Indices.push_back(m_vertices.size() - 1);

                }
            }
        }       

最后这就是我设置顶点缓冲区的方法

D3D11_INPUT_ELEMENT_DESC vertlayout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

ID3D11Device* pDevice = m_shader->GetDevice();
ID3DBlob* pVSBlob = m_shader->GetVSBlob();

pDevice->CreateInputLayout(vertlayout, ARRAYSIZE(vertlayout), pVSBlob->GetBufferPointer(),
    pVSBlob->GetBufferSize(), &m_vertexLayout);

D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd)); 
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(VERTEX)* m_vertices.size();
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;

D3D11_SUBRESOURCE_DATA initData;
ZeroMemory(&initData, sizeof(initData));
initData.pSysMem = &m_vertices[0]; //This is where it breaks                                                                  

pDevice->CreateBuffer(&bd, &initData, &m_vertexBuffer);

bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(DWORD)* m_Indices.size();
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
initData.pSysMem = &m_Indices[0]; //and it breaks here too

pDevice->CreateBuffer(&bd, &initData, &m_indexBuffer);  

}

正如评论所说,在initData.pSysMem = &m_vertices[0];initData.pSysMem = &m_Indices[0];的行上,我的程序将会中断,我将得到向量下标超出范围错误。如果我从&amp; m_vertices和&amp; m_Indices中删除[0],它就不会破坏,但不会渲染任何内容。

我只想知道如何让我的obj加载器加载obj文件,这些文件不需要总是包含所有4个顶点,法线,纹理坐标和面。

1 个答案:

答案 0 :(得分:2)

一般

你无法通过猜测找出你的应用崩溃的原因。你不需要。作为程序员,我们有很好的工具来解决这些问题。所以,一般建议:学习使用调试器

具体问题

你的矢量是空的。
当您尝试访问不存在的第一个元素(m_vertices[0]m_Indices[0])时,会出现断言失败(因为您处于调试模式) ;在发布模式下,它将静默触发未定义的行为)。

如何检查

当程序执行在这些行上中断时,请选中“调用堆栈”窗口,以查看您的功能。找到一个在堆栈中最高的函数并单击它。选中“Locals”,“Auto”或“Watch”窗口(菜单“Debug” - &gt;“Windows”)以查看范围内的向量和其他变量的内容。如果需要,放置断点并重新启动应用程序。

如何修复

在程序的早期设置断点,以查看向量为空的原因。逐行移动,逐个功能,使用“Step into”和“Step over”,观察变量,直到你会发现错误来源。

如果在那里有空向量是有效的,你可以创建分支以避免访问它的内容的代码路径:

if(!m_vertices.empty())
{
    // Create buffers with data
} 
else 
{
    // Create empty buffers or report an error
}` 

希望它有所帮助。