c++ 使用Assimp加载的网格显示部分顶点数量?

ctehm74n  于 2023-01-06  发布在  其他
关注(0)|答案(1)|浏览(145)

我使用C++为DirectX 11项目编写了一个网格加载程序,我决定使用assimp,因为我在学习OpenGL时获得了使用API的经验。该加载程序处理较小的网格没有问题,但当顶点数量达到一定阈值时,it completely breaks, displaying only a few vertices (it doesn't show the star on the Cerberus model and its even worse on higher detail meshes).original mesh相反。
一开始我试着:

struct Vertex
{
    struct {
        float x, y, z;
    } position;
    struct {
        float x, y, z;
    } normal;
    struct
    {
        float u, v;
    } TexCoord;
    Vertex(float px, float py, float pz, float nx, float ny, float nz, float u, float v)
        : position{ px, py, pz },normal{nx, ny, nz}, TexCoord{u, v}
    {
    }
    Vertex(){}
};
class Mesh {
    public:
        Mesh(){}
        int Create(const char* filepath);
        inline VertexBuffer* GetVertexBuffer() { return &m_VertexBuffer; }
        inline IndexBuffer* GetIndexBuffer() { return &m_IndexBuffer; }
        inline void DestroyMesh() { m_VertexBuffer.ShutDown(); m_IndexBuffer.ShutDown(); };
    private:
        static BufferLayout layout[];
        std::vector<Vertex> m_vertices;
        std::vector<unsigned int> m_indices;
        VertexBuffer m_VertexBuffer;
        IndexBuffer m_IndexBuffer;
    };
}
int Mesh::Create(const char* filepath)
{
    Assimp::Importer imp;
    const aiScene* pScene = imp.ReadFile(filepath, aiProcess_Triangulate |aiProcess_JoinIdenticalVertices);
        
    const aiMesh* pmesh = pScene->mMeshes[0];
    m_vertices.reserve(pmeshes->mNumVertices);
    m_indices.reserve(pmeshes->mNumFaces * 3);  
    for (unsigned int j = 0; j < pmeshes->mNumVertices; j++)
    {
        m_vertices.push_back(Vertex(
            pmeshes->mVertices[j].x, pmeshes->mVertices[j].y, pmeshes->mVertices[j].z,
            pmeshes->mNormals[j].x, pmeshes->mNormals[j].y, pmeshes->mNormals[j].z,
            pmeshes->mTextureCoords[0][j].x, pmeshes->mTextureCoords[0][j].y
            ));
    }
    for (unsigned int i = 0; i < pmeshes->mNumFaces; i++)
    {
        const auto& face = pmeshes->mFaces[i];
        for (unsigned int j = 0; j < face.mNumIndices; j++)
            m_indices.push_back(face.mIndices[j]);
    }
    m_VertexBuffer.Create(m_vertices.data(), sizeof(Vertex) * pmeshes->mNumVertices, sizeof(Vertex));
    m_IndexBuffer.Create(m_indices.data(), sizeof(unsigned int) * pmeshes->mNumFaces * 3, sizeof(unsigned int));
    imp.FreeScene();
    return 0;
}

顶点缓冲区和索引缓冲区创建方法为:

void VertexBuffer::Create(const void* vertices, unsigned int size, unsigned int stride)
{
    D3D11_BUFFER_DESC bd = {};
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;
    bd.ByteWidth = size;
    D3D11_SUBRESOURCE_DATA sd = {};
    sd.pSysMem = vertices;
    RendererBase::Getd3dDevice()->CreateBuffer(&bd, &sd, &pVertexBuffer);
}
IndexBuffer::Create(const void* indices, unsigned int size, unsigned int stride)
{
        count = size/stride;
    D3D11_BUFFER_DESC bd = {};
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;
    bd.ByteWidth = size;
    D3D11_SUBRESOURCE_DATA sd = {};
    sd.pSysMem = indices;
    RendererBase::Getd3dDevice()->CreateBuffer(&bd, &sd, &pIndexBuffer);
}

我也试过加载文件中的所有模型,并为每个模型创建单独的网格对象,然后绘制每个对象,但我仍然得到了相同的结果。任何帮助都将非常感谢。如果有任何更多的信息或代码片段需要,我总是很乐意提供。

dxpyg8gm

dxpyg8gm1#

我发现了问题,它在我的索引缓冲区类中

class IndexBuffer
{
public:
    IndexBuffer();
    void ShutDown();
    void Bind();
    void UnBind();
    static IndexBuffer* Create(const void* indices, unsigned int size, unsigned int stride);
    void Create(const void* indices, unsigned int size, unsigned int stride);
    inline unsigned int GetCount() { return count; }
private:
    unsigned short count;
    ID3D11Buffer* pIndexBuffer = NULL;
};

count变量是unsigned short,所以索引的数量被限制在65535(所谓的“剪切阈值”),将其改为unsigned int就解决了这个问题。

相关问题