ASSIMP网格负载的奇怪问题

问题描述 投票:0回答:1

我在ASSIMP网格加载中遇到了一个奇怪的问题。这就是问题,我有一个复杂的模型obj文件来显示一个字符,该模型有4个子网格,在我的代码中,我封装了网格类以获取相关数据(顶点,索引,法线...),当我将4个网格绘制在一起时(在for圈中),我总是得到错误的结果:

但是如果我一次只加载一个网格(硬编码我的assimp加载类来做到这一点),并且只绘制一个网格,那么我就可以正确绘制网格(但是仅当我加载复杂模型obj时才会出现此问题文件,而不是立方体或平面,我可以加载多个立方体和平面obj文件并将它们绘制在一起):

这是我的ASSIMP加载类代码,我不知道我的问题在哪里,请帮助我:

#include "AssetImport.h"
#include "Mesh.h"
#include "Model.h"
#include "ModelMgr.h"
#include "TextureMgr.h"
#include <string>

using namespace Assimp;

AssetImport::AssetImport()
{
}

AssetImport::~AssetImport()
{
}

int AssetImport::LoadModel(const char *path)
{
    Importer import;
    const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate 
        | aiProcess_FlipUVs 
        | aiProcess_CalcTangentSpace
        | aiProcess_GenNormals);
    if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
    {
        return -1;
    }

    m_prePath = path;
    auto index = m_prePath.lastIndexOf("/");
    if (-1 != index) {
        m_prePath = m_prePath.left(index + 1);
    }

    HandleChildNode(scene, scene->mRootNode);

    return 0;
}

int AssetImport::HandleChildNode(const aiScene *scene, aiNode *node)
{
    unsigned int numChild = node->mNumChildren;
    for (unsigned int a = 0; a < 1; ++a)
    {
        **auto child = node->mChildren[3];// here is the hard code**
        if (child->mNumChildren > 0) {
            HandleChildNode(scene, child);
        }

        if (0) {
            continue;
        }

        // create a new model for a child
        Model *mod = ModelMgr::Instance().CreateNewModel();
        mod->SetModelName(child->mName.C_Str());

        auto numMeshes = child->mNumMeshes;
        for (unsigned int i = 0; i < numMeshes; ++i)
        {
            // create new sub mesh, then you can add it to one model
            Mesh *m = new Mesh;

            auto mesh = scene->mMeshes[child->mMeshes[i]];

            //handle the mesh's materials
            auto mat = scene->mMaterials[mesh->mMaterialIndex];
            HandleMeshMaterial(mat, m);
            // add vertex info
            for (unsigned int j = 0; j < mesh->mNumVertices; ++j)
            {
                auto vert = mesh->mVertices[j];
                Mesh::VertInfo info;

                info.pos = QVector3D(mesh->mVertices[j].x, mesh->mVertices[j].y, mesh->mVertices[j].z);
                info.color = QVector4D(0.8f, 0.8f, 0.8f, 1);
                info.normal = QVector3D(mesh->mNormals[j].x, mesh->mNormals[j].y, mesh->mNormals[j].z);
                if (nullptr != mesh->mTangents)
                {
                    info.tangent = QVector4D(mesh->mTangents[j].x, mesh->mTangents[j].y, mesh->mTangents[j].z, 0);
                }
                if (nullptr != mesh->mBitangents)
                {
                    info.bitangent = QVector4D(mesh->mBitangents[j].x, mesh->mBitangents[j].y, mesh->mBitangents[j].z, 0);
                }
                if (nullptr != mesh->mTextureCoords[0])
                {
                    info.uv1 = QVector2D(mesh->mTextureCoords[0][j].x, mesh->mTextureCoords[0][j].y);
                }

                m->AddVertInfo(info);
            }

            // add index info
            for (unsigned int j = 0; j < mesh->mNumFaces; ++j)
            {
                auto face = mesh->mFaces[j];
                for (unsigned int k = 0; k < face.mNumIndices; ++k)
                {
                    m->AddIndex(face.mIndices[k]);
                }
            }

            m->BindBuffer();
            mod->AddMesh(m);
        }
    }

    return 0;
}

int AssetImport::HandleMeshMaterial(aiMaterial *mat, Mesh *mesh)
{
    auto diffuseTexCount = mat->GetTextureCount(aiTextureType_DIFFUSE);
    auto specularTexCount = mat->GetTextureCount(aiTextureType_SPECULAR);

    for (unsigned int i = 0; i < diffuseTexCount; ++i)
    {
        aiString path;
        mat->GetTexture(aiTextureType_DIFFUSE, i, &path);
        QString strPath = path.C_Str();

        strPath.replace("/", "\\");
        auto index = strPath.lastIndexOf("\\");
        if (-1 != index) {
            strPath = strPath.right(strPath.length() - index - 1);
            strPath.prepend(m_prePath);
        }

        auto texID = TextureMgr::Instance().LoadTexture(strPath.toLocal8Bit());
        mesh->SetDiffuseTexID(texID);
    }

    for (unsigned int i = 0; i < specularTexCount; ++i)
    {
        aiString strPath;
        mat->GetTexture(aiTextureType_SPECULAR, i, &strPath);
    }

    return 0;
}    

这是我的网格物体类(带有绘制功能):

#include "Mesh.h"
#include "TextureMgr.h"
#include "ShaderHelper.h"
#include "PreDef.h"
#include "QMatrix4x4"

Mesh::Mesh()
    :m_vao(0), m_vbo(0), m_vaeo(0), m_instanceBufferId(0), m_tbo1(0)
    , m_drawType(Triangle)
    , m_skyboxTexID(0), m_projTexID(0), m_normalmapTexID(0)
    , m_diffuseTex1ID(0)
{
    initializeOpenGLFunctions();

    m_normalmapTexID = TextureMgr::Instance().LoadTexture("./models/brickwall_normal.jpg");
}

Mesh::~Mesh()
{

}

void Mesh::AddVertex(QVector3D vert)
{
    m_vertices.push_back(vert.x());
    m_vertices.push_back(vert.y());
    m_vertices.push_back(vert.z());
}

const float* Mesh::GetVertices() const
{
    return m_vertices.data();
}

int Mesh::GetVerticesMemSize() const
{
    return m_vertices.size() * sizeof(float);
}

int Mesh::GetVerticesNum() const
{
    return m_vertices.size() / 3;
}

void Mesh::AddColor(QVector4D color)
{
    m_colors.push_back(color.x());
    m_colors.push_back(color.y());
    m_colors.push_back(color.z());
    m_colors.push_back(color.w());
}

const float* Mesh::GetColors() const
{
    return m_colors.data();
}

int Mesh::GetColorsMemSize() const
{
    return m_colors.size() * sizeof(float);
}

void Mesh::AddNormal(QVector3D normal)
{
    m_normals.append(normal.x());
    m_normals.append(normal.y());
    m_normals.append(normal.z());
}

const float* Mesh::GetNormals() const
{
    return m_normals.data();
}

int Mesh::GetNormalsMemSize() const
{
    return m_normals.size() * sizeof(float);
}

int Mesh::GetNormalsNum() const
{
    return m_normals.size() / 3;
}

void Mesh::AddTangent(QVector4D tangent)
{
    m_tangents.append(tangent.x());
    m_tangents.append(tangent.y());
    m_tangents.append(tangent.z());
    m_tangents.append(tangent.w());
}

const float* Mesh::GetTangents() const
{
    return m_tangents.data();
}

int Mesh::GetTangentsMemSize() const
{
    return m_tangents.size() * sizeof(float);
}

int Mesh::GetTangentsNum() const
{
    return m_tangents.size() / 4;
}

void Mesh::AddBitangent(QVector4D binormal)
{
    m_binormals.append(binormal.x());
    m_binormals.append(binormal.y());
    m_binormals.append(binormal.z());
    m_binormals.append(binormal.w());
}

const float* Mesh::GetBitangents() const
{
    return m_binormals.data();
}

int Mesh::GetBitangentsMemSize() const
{
    return m_binormals.size() * sizeof(float);
}

int Mesh::GetBitangentsNum() const
{
    return m_binormals.size() / 4;
}

void Mesh::AddUv1(QVector2D uv)
{
    m_uvs1.append(uv.x());
    m_uvs1.append(uv.y());
}

const float* Mesh::GetUvs1() const
{
    return m_uvs1.data();
}

int Mesh::GetUvs1MemSize() const
{
    return m_uvs1.size() * sizeof(float);
}

int Mesh::GetUvs1Num() const
{
    return m_uvs1.size() / 2;
}

void Mesh::AddVertInfo(const VertInfo &info)
{
    m_vertInfoVec.push_back(info);

    AddVertex(info.pos);
    AddColor(info.color);
    AddNormal(info.normal);
    AddTangent(info.tangent);
    AddBitangent(info.bitangent);
    AddUv1(info.uv1);
}

void Mesh::BindBuffer()
{
    // init the shaders first
    ShaderHelper::Instance();

    BindVertexRelevantBuffer();
}

void Mesh::BindVertexRelevantBuffer()
{
    const GLuint *vertex_indices = GetIndices();

    const GLfloat *vertex_positions = GetVertices();
    const GLfloat *vertex_uvs = GetUvs1();
    const GLfloat *vertex_tangents = GetTangents();
    const GLfloat *vertex_bitangents = GetBitangents();
    const GLfloat *vertex_normals = GetNormals();

    // set element array(index array) buffer
    glGenBuffers(1, &m_vaeo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vaeo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndicesMemSize(), vertex_indices, GL_STATIC_DRAW);

    // set vertex array object
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);
    glVertexArrayElementBuffer(m_vao, m_vaeo);

    glGenBuffers(1, &m_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, GetVerticesMemSize() + GetUvs1MemSize()
        + GetTangentsMemSize() + GetBitangentsMemSize() + GetNormalsMemSize() /*+ 16 * sizeof(GLfloat) * 10*/, NULL, GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, GetVerticesMemSize(), vertex_positions);
    glBufferSubData(GL_ARRAY_BUFFER, GetVerticesMemSize(), GetUvs1MemSize(), vertex_uvs);
    glBufferSubData(GL_ARRAY_BUFFER, GetVerticesMemSize() + GetUvs1MemSize(), GetTangentsMemSize(), vertex_tangents);
    glBufferSubData(GL_ARRAY_BUFFER, GetVerticesMemSize() + GetUvs1MemSize() + GetTangentsMemSize(),
        GetBitangentsMemSize(), vertex_bitangents);
    glBufferSubData(GL_ARRAY_BUFFER, GetVerticesMemSize() + GetUvs1MemSize()
        + GetTangentsMemSize() + GetBitangentsMemSize(),
        GetNormalsMemSize(), vertex_normals);

    GLint positionLoc = 0;
    GLint uvLoc = 1;
    GLint tangentLoc = 2;
    GLint bitangentLoc = 3;
    GLint normalLoc = 4;
    GLint modelMatLoc = -1;

    glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, (0));
    glEnableVertexAttribArray(positionLoc);
    glVertexAttribPointer(uvLoc, 2, GL_FLOAT, GL_FALSE, 0, (void*)(GetVerticesMemSize()));
    glEnableVertexAttribArray(uvLoc);
    glVertexAttribPointer(tangentLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)(GetVerticesMemSize() + GetUvs1MemSize()));
    glEnableVertexAttribArray(tangentLoc);

    glVertexAttribPointer(bitangentLoc, 3, GL_FLOAT, GL_FALSE, 0,
        (void*)(GetVerticesMemSize() + GetUvs1MemSize() + GetTangentsMemSize()));
    glEnableVertexAttribArray(bitangentLoc);

    glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0,
        (void*)(GetVerticesMemSize() + GetUvs1MemSize() + GetTangentsMemSize() + GetBitangentsMemSize()));
    glEnableVertexAttribArray(normalLoc);

    // multi instances model matrix
    if (-1 != modelMatLoc) {
        // generate the new buffer for instances
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glGenBuffers(1, &m_instanceBufferId);
        glBindBuffer(GL_ARRAY_BUFFER, m_instanceBufferId);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16 * 10, nullptr, GL_STATIC_DRAW);

        //      m_instanceBufferId = m_vbo;

        // mat4 type take space of 4 vec4, so we should circle 4 times
        for (int i = 0; i < 4; ++i)
        {
            glVertexAttribPointer(modelMatLoc + i, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 16,
                (void*)(/*GetVerticesMemSize() + GetUvs1MemSize() + GetTangentsMemSize() + GetBitangentsMemSize() + GetNormalsMemSize() +*/ sizeof(GLfloat) * 4 * i));
            glEnableVertexAttribArray(modelMatLoc + i);
            // implement the multi instances
            glVertexAttribDivisor(modelMatLoc + i, 1);
        }

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    // sampler buffer bind
    glGenBuffers(1, &m_tbo1);
    glBindBuffer(GL_TEXTURE_BUFFER, m_tbo1);
    glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 16 * 10, nullptr, GL_STATIC_DRAW);
    GLuint tex1;
    glCreateTextures(GL_TEXTURE_BUFFER, 1, &tex1);
    glTextureBuffer(tex1, GL_RGBA32F, m_tbo1);
    glBindTextureUnit(0, m_tbo1);
    glBindBuffer(GL_TEXTURE_BUFFER, 0);
}

GLuint Mesh::GetVao()
{
    return m_vao;
}

void Mesh::AddIndex(unsigned int index)
{
    m_indices.push_back(index);
}

void Mesh::AddIndexVec(QVector<unsigned int> &indexVec)
{
    m_indices = indexVec;
}

const unsigned int* Mesh::GetIndices() const
{
    return m_indices.data();
}

int Mesh::GetIndicesMemSize() const
{
    return m_indices.size() * sizeof(unsigned int);
}

int Mesh::GetIndicesNum() const
{
    return m_indices.size();
}

GLuint Mesh::GetMultiInstanceModelMatrixOffset() const
{
    return (GetVerticesMemSize() + GetUvs1MemSize() + GetTangentsMemSize()
        + GetBitangentsMemSize() + GetNormalsMemSize());
}

GLuint Mesh::GetInstancesBufferId() const
{
    return m_instanceBufferId;
}

void Mesh::SetDiffuseTexID(GLuint id)
{
    m_diffuseTex1ID = id;
}

void Mesh::AddSpecularTexture(GLuint id)
{
    m_specularTex1ID = id;
}

GLuint Mesh::GetTextureBuffer1() const
{
    return m_tbo1;
}

void Mesh::InitSkybox()
{
    m_skyboxTexID = TextureMgr::Instance().LoadTexture("skybox");
}

void Mesh::InitProjTex()
{
    m_projTexID = TextureMgr::Instance().LoadTexture("./textures/proj.jpg");
}

void Mesh::SetDrawType(eDrawType type)
{
    m_drawType = type;
}

void Mesh::Draw(QMatrix4x4 matVP, QMatrix4x4 matModel, QVector3D camPos, QMatrix4x4 matProj, QMatrix4x4 matView,
    QMatrix4x4 matOrtho)
{

    if (0 != m_diffuseTex1ID)
    {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, m_diffuseTex1ID);
    }

    if (0 != m_normalmapTexID)
    {
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, m_normalmapTexID);
    }


    if (0 != m_skyboxTexID) {
        glBindTexture(GL_TEXTURE_CUBE_MAP, m_skyboxTexID);
        matModel.translate(camPos);
        matModel.scale(10000);
        glCullFace(GL_FRONT);
        glDepthMask(0);
        ShaderHelper::Instance().SetShaderType(ShaderHelper::Skybox);
    }
    else if (0 != m_projTexID) {
        glActiveTexture(GL_TEXTURE10);
        glBindTexture(GL_TEXTURE_2D, m_projTexID);
        ShaderHelper::Instance().SetShaderType(ShaderHelper::Decal);
    }
    glBindVertexArray(GetVao());
    matVP = matVP * matModel;
    ShaderHelper::Instance().SetMVPMatrix(matVP);
    ShaderHelper::Instance().SetWorldMatrix(matModel);
    ShaderHelper::Instance().SetCamWorldPos(camPos);
    ShaderHelper::Instance().SetProjMat(matProj);
    ShaderHelper::Instance().SetViewMat(matView);
    ShaderHelper::Instance().SetOrthoMat(matOrtho);

    // Draw element(with indices)
    if (Triangle == m_drawType)
    {
        glDrawElements(GL_TRIANGLES, GetIndicesNum(), GL_UNSIGNED_INT, 0);
    } 
    else if (Point == m_drawType)
    {
        glDrawArrays(GL_POINTS, 0, GetVerticesNum());
    }

    if (0 != m_skyboxTexID) {
        glCullFace(GL_BACK);
        glDepthMask(1);
    }
    glBindVertexArray(0);
}    

这里是主要绘制功能:

void OpenWidget::paintGL()
{
    static int i = 0;
    if (0 == i){
        ++i;
        CreateOffScreenFrameBufferTexture();
    }

    glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        return;
    }
    paintClearAndReset();

    QMatrix4x4 matVP = m_cam->GetVPMatrix();
    QMatrix4x4 matProj = m_cam->GetProjectionMatrix();
    QMatrix4x4 matOrtho = m_cam->GetOrthographicMatrix();
    QMatrix4x4 matView = m_cam->GetViewMatrix();
    QVector3D camPos = m_cam->GetCamPos().toVector3D();

    auto modelNum = ModelMgr::Instance().GetModelNum();
    for (unsigned int i = 0; i < modelNum; ++i)
    {
        Model *mod = ModelMgr::Instance().GetModel(i);
        SwitchShader(ShaderHelper::Default);

        QMatrix4x4 matModel = mod->GetWorldMat();
        mod->Draw(matVP, matModel, camPos, matProj, matView, matOrtho);

        if (modelNum - 1 == i) {
            Model *pBox = ModelMgr::Instance().FindModelByName("Box001");

//          SwitchShader(ShaderHelper::PlaneClip);
//          glFrontFace(GL_CW);
//          glEnable(GL_CLIP_PLANE0);
//          glStencilMask(0xff);
//          glStencilFunc(GL_ALWAYS, 1, 0xff);
//          glColorMask(0, 0, 0, 0);
// 
//          pBox->Draw(matVP, pBox->GetWorldMat(), camPos);
//          glFrontFace(GL_CCW);
//          glDisable(GL_CLIP_PLANE0);
//          glColorMask(1, 1, 1, 1);
// 
//          glStencilMask(0);
//          glStencilFunc(GL_EQUAL, 1, 0xff);
//          SwitchShader(ShaderHelper::PureColor);
//          pBox->Draw(matVP, pBox->GetWorldMat(), camPos);
        }
    }

    //-----------------------------------------------
    // test the frame buffer
    DrawOffScreenTexture();
}
opengl assimp
1个回答
0
投票

最后,我发现问题出在哪里,我暂时放弃了这个问题,但是今天,我的skybox(cubemap)遇到了另一个问题,我只能在绘制队列的最后绘制正确的skybox,否则,多维数据集贴图只能显示一张脸,因此,对我而言不再是捷径了,我决定解决此问题,经过许多小时的调试, >: // set element array(index array) buffer glGenBuffers(1, &m_vaeo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vaeo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndicesMemSize(), vertex_indices, GL_STATIC_DRAW); // set vertex array object glGenVertexArrays(1, &m_vao); glBindVertexArray(m_vao); glVertexArrayElementBuffer(m_vao, m_vaeo);

您应该始终先创建并绑定VAO:

// set vertex array object glGenVertexArrays(1, &m_vao); glBindVertexArray(m_vao); // set element array(index array) buffer glGenBuffers(1, &m_vaeo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vaeo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndicesMemSize(), vertex_indices, GL_STATIC_DRAW); glVertexArrayElementBuffer(m_vao, m_vaeo);
但是,毕竟,我认为它是如此隐式,因为在创建元素缓冲区后,您可以将元素绑定到vao,似乎在生成元素缓冲区时,与vao无关,我可以做什么,请下次再小心。
© www.soinside.com 2019 - 2024. All rights reserved.