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\$
3
  • \$\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, 2014 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\$ Sep 2, 2014 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, 2014 at 12:38

2 Answers 2

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);
}
\$\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)

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .