4
\$\begingroup\$

I am loading a model in my OpenGL application using Assimp library like this :

bool CGameObject::LoadModelFromFile(char* sZFilePath)
{
std::string fn = sZFilePath;
std::string td = "\\";
std::string mfn = _getcwd(NULL, 0) + td + fn;
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(mfn,
    aiProcess_CalcTangentSpace      |
    aiProcess_Triangulate           |
    aiProcess_JoinIdenticalVertices |
    aiProcess_SortByPType);

if (!scene) {
    return false;
}

const int iVertexTotalSize = sizeof(aiVector3D) * 2 + sizeof(aiVector2D);
int iTotalVertices = 0;

for(UINT i = 0; i < scene->mNumMeshes; i++) {
    aiMesh* mesh = scene->mMeshes[i];
    int iMeshFaces = mesh->mNumFaces;
    for (UINT f = 0; f <iMeshFaces; f++) {
        const aiFace* face = &mesh->mFaces[f];
        for (UINT k = 0; k < 3; k++) {
            aiVector3D pos = mesh->mVertices[face->mIndices[k]];
            Model.vertices.push_back(pos.x);
            Model.vertices.push_back(pos.y);
            Model.vertices.push_back(pos.z);
        }
    }
}

// VAO
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);

// VBO
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, this->Model.vertices.size() * sizeof(GLfloat), &this->Model.vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

// unbind buffers
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

// return success when everything is loaded
return true;
}

and then render it like this :

for (GameObject::iterator i = GameObjects.begin(); i != GameObjects.end(); ++i)
{
    CGameObject* pObj = *i;
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, GetMVPMatrix(pObj->position));

    glBindVertexArray(pObj->m_vao);
    glVertexAttrib3f((GLuint)1, 1.0, 0.0, 0.0); // set constant color attribute
    glDrawArrays(GL_TRIANGLES, 0, pObj->Model.vertices.size());

}
.
.
.

// function used to set MVP matrix
GLfloat* GetMVPMatrix(glm::vec3 position)
{
glm::mat4 Model = glm::translate(mat4(1.0), position);
glm::mat4 MVP3 = Projection * View * Model;
return &MVP3[0][0];
}

I created and exported my model using Blender. if I use OBJ format then it is rendered correctly : enter image description here

but with DAE format it is like this : enter image description here

My model has 5 meshes and debugging in Visual Studio shows that all 5 meshes are loaded.

Loading the DAE file in assimp_viewer shows the model file has been exported correctly :

enter image description here

Where am i doing it wrong ?

\$\endgroup\$
  • \$\begingroup\$ I think you're only grabbing the first item out of the hierarchy which is why you only get one wheel instead of all 5 parts. I definitely came across a similar issue when I was working with assimp earlier. Maybe check if you're looking at all of the scenes. there might be 5 total scenes. \$\endgroup\$ – Steven Lu Sep 2 '14 at 14:58
  • \$\begingroup\$ @StevenLu there is only one scene in the file. I checked that file by loading in "assimp_viewer"; shown in last image. \$\endgroup\$ – Manmohan Bishnoi Sep 2 '14 at 16:35
  • 2
    \$\begingroup\$ Well, then Scene 0 contains 5 meshes. Looking at it I think I see the outline of the square box around the wheel. Maybe the 4 wheels are overlapping on each other, so you actually are rendering all 5 meshes, but inside the wrong coordinate space. I reckon there's some transforms specified in the COLLADA file that you're not reading and applying. \$\endgroup\$ – Steven Lu Sep 3 '14 at 12:38
1
\$\begingroup\$

As Stephen said in the comments there is transformation data that you are missing. This data is not stored in aiMesh, but in aiNode. Instead of iterating over scene->mMeshes iterate recursively over scene->mRootNode and it's mChildren. Then you iterate over node->mMeshes and use them as the index of scene->mMeshes[index]. Lastly, you need to apply node->mTransformation to each vertex before adding them to the container.

For example (not tested, probably has some minor mistakes.)

Replacing the main for loop:

LoadModelFromNode(scene, scene->mRootNode, aiMatrix4x4());

Where LoadModelFromNode(aiScene* scene, aiNode* node, aiMatrix4x4 transformation) is something like:

// accumulate from parent transformation.
transformation *= node->mTransformation;

for(UINT i = 0; i < node->mNumMeshes; ++i) { 
    aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
    for (UINT f = 0; f < mesh->mNumFaces; ++f) {
        const aiFace* face = &mesh->mFaces[f]; 
        for (UINT k = 0; k < 3; ++k) { 
            aiVector3D pos = mesh->mVertices[face->mIndices[k]] * transformation;
            Model.vertices.push_back(pos.x);
            Model.vertices.push_back(pos.y);
            Model.vertices.push_back(pos.z);
        }
    }
}
for(int i = 0; i < node->mNumChildren; ++i){
    LoadModelFromNode(scene, node->mChildren[i], transformation);
}
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Your problem and a possible solution is supplied by chipgw.

But there is an alternate solution, which is an importer flag, which will pre-transform everything for you.

So you can simply add this flag to your importer: aiProcess_PreTransformVertices.

But note that this has a huge negative: It drops all animations.(Although the node tree is kept)

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.