-2

I'm trying to load and render a 3D model i exported from blender to 3ds format.

I'm using Assimp to load the model and OpenGL (GLEW) to render it. for some reason some. in some of the models only parts of the model gets rendered. for some this can be fixed by selecting all objects in blender and clicking join. But for others this does not solve the problem.

Here is the code Im using to load the models in: (all of the "Array"s here are std::vector)

void Mesh::recursiveProcess(aiNode* node,const aiScene* scene) {
    for(int i=0;i<node->mNumMeshes;i++) {
        aiMesh* mesh=scene->mMeshes[node->mMeshes[i]];
        processMesh(mesh, scene);
    }

    for(int i=0;i<node->mNumChildren;i++) {
        recursiveProcess(node->mChildren[i], scene);
    }
}

void Mesh::processMesh(aiMesh* m,const aiScene* scene) {
    for(int i=0;i<m->mNumVertices;i++) {

        vertexArray.push_back(m->mVertices[i].x);
        vertexArray.push_back(m->mVertices[i].y);
        vertexArray.push_back(m->mVertices[i].z);

        if(m->mNormals!=NULL) {
            normalArray.push_back(m->mNormals[i].x);
            normalArray.push_back(m->mNormals[i].y);
            normalArray.push_back(m->mNormals[i].z);
        }

        if(m->mTextureCoords[0]!=NULL) {
            uvArray.push_back(m->mTextureCoords[0][i].x);
            uvArray.push_back(m->mTextureCoords[0][i].y);
        }

        if(m->mTangents!=NULL) {
            tangentArray.push_back(m->mTangents[i].x);
            tangentArray.push_back(m->mTangents[i].y);
            tangentArray.push_back(m->mTangents[i].z);
        }
    }

    for(int i=0;i<m->mNumFaces;i++) {
        aiFace face=m->mFaces[i];

        for(int j=0;j<face.mNumIndices;j++) {
            indexArray.push_back(face.mIndices[j]);
        }
    }
}

void Mesh::Load(string path) {
    vertexArray.clear();
    indexArray.clear();
    normalArray.clear();
    uvArray.clear();
    tangentArray.clear();

    const aiScene* scene=aiImportFile(path.c_str(), 
        aiProcess_GenSmoothNormals |
        aiProcess_CalcTangentSpace |
        aiProcess_Triangulate |
        aiProcess_FindInvalidData);

    const char* err = aiGetErrorString();
    if(err!=NULL&&sizeof(err) > 4 && scene==NULL) {
        cout << "The file wasn't successfuly opened " << path << " Because " << err;
        return;
    }

    recursiveProcess(scene->mRootNode,scene);

    if(uvArray.size()==0) uvArray.push_back(0);
    if(normalArray.size()==0) normalArray.push_back(0);
    if(tangentArray.size()==0) tangentArray.push_back(0);
}

and here is how I'm rendering them; first i create the buffers. i do this once

    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, vertexArray.size() * sizeof(float), vertexArray.data(), GL_STATIC_DRAW);

    glGenBuffers(1, &indexbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexArray.size() * sizeof(unsigned int), indexArray.data(), GL_STATIC_DRAW);

    glGenBuffers(1, &uvbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glBufferData(GL_ARRAY_BUFFER, uvArray.size() * sizeof(float), uvArray.data(), GL_STATIC_DRAW);

then I execute this in the main render loop

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_CULL_FACE);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void*)0);

    camera.Update();
    mvp = camera.getProjection() * camera.getView() * Model;
    shader.SetUniformLocationMatrix4fv("MVP", &mvp[0][0]);
    glBindTexture(GL_TEXTURE_2D, akm_tex);
    glUseProgram(shader);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);

    glDrawElements(
            GL_TRIANGLES,      // mode
            indexArray.size(),    // count
            GL_UNSIGNED_INT,   // type
            (void*)0           // element array buffer offset
    );

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);

here is how a model looks like in my program:

enter image description here

and here is how it look in blender enter image description here

Amit Hendin
  • 87
  • 1
  • 8
  • You are missing a VAO. In core profile OpenGL a VAO is mandatory when rendering. – BDL Feb 12 '18 at 22:12
  • @BDL In that case nothing would displayed. A VAO is presumably bound in the code that is not shown. – user253751 Feb 12 '18 at 22:18
  • thanks for your input. From what i understand a vertex buffer object replaces vertex array object but if Im wrong please elaborate more. Also Im quite new to opengl so if you could explain what core profile means that would be helpful. thanks again – Amit Hendin Feb 12 '18 at 22:18

1 Answers1

1

You missed to apply the transformations of the nodes to the vertex buffers you are rendering. Each assimp-node stores a local transformation which need to get applied to all its assigned meshes.

You can introduce in your shader a uniform-variable to represent the global transformation for the vertices. During rendering you need to multiply the local transformation with the global transformation and apply it via this uniform matrix.

Or you can just use glPushMAtrix and glPopMatrix and apply the local transformation of your current node as you can see here (recursive_render)

KimKulling
  • 2,654
  • 1
  • 15
  • 26