Mesh loading with Assimp

I know there are many out  there who have problems starting game dev in c++ (or other languages) because of the amount of work it takes.  One monster of a problem is loading models. It was one thing that deterred me for a while from writing a game engine before i finally mustered up the courage to write a mesh exporter for blender and an importer in c++ (for the said game engine). It was a lot of work, but the experience it worth it. I now have my own mesh format  can easily get models in my android and webgl apps.

Not many people have the time and patience to write their own importer/exporter. A tool to take away all the pain of doing that is Assimp. It is model importer written in c++. It loads a variety of formats, even .blend files. This is a short tutorial of how to use it.

First download the libraries and link them to your project and add the include files in your include directory. I’m using assimp 3.0

Next create the importer and load your model

Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(filename,aiProcessPreset_TargetRealtime_Fast);//aiProcessPreset_TargetRealtime_Fast has the configs you'll need

aiMesh *mesh = scene->mMeshes[0]; //assuming you only want the first mesh

Here are the variables needed:

float *vertexArray;
float *normalArray;
float *uvArray;

int numVerts;

next extract the data

numVerts = mesh->mNumFaces*3;

vertexArray = new float[mesh->mNumFaces*3*3];
normalArray = new float[mesh->mNumFaces*3*3];
uvArray = new float[mesh->mNumFaces*3*2];

for(unsigned int i=0;i<mesh->mNumFaces;i++)
{
const aiFace& face = mesh->mFaces[i];

for(int j=0;j<3;j++)
{
aiVector3D uv = mesh->mTextureCoords[0][face.mIndices[j]];
memcpy(uvArray,&uv,sizeof(float)*2);
uvArray+=2;

aiVector3D normal = mesh->mNormals[face.mIndices[j]];
memcpy(normalArray,&normal,sizeof(float)*3);
normalArray+=3;

aiVector3D pos = mesh->mVertices[face.mIndices[j]];
memcpy(vertexArray,&pos,sizeof(float)*3);
vertexArray+=3;
}
}

uvArray-=mesh->mNumFaces*3*2;
normalArray-=mesh->mNumFaces*3*3;
vertexArray-=mesh->mNumFaces*3*3;

and that’s it. The rest is just rendering.

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(3,GL_FLOAT,0,vertexArray);
glNormalPointer(GL_FLOAT,0,normalArray);

glClientActiveTexture(GL_TEXTURE0_ARB);
glTexCoordPointer(2,GL_FLOAT,0,uvArray);

glDrawArrays(GL_TRIANGLES,0,numVerts);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

look at my demo:

sdl app

In another tutorial, i’ll show you how to load entire scenes with each model having its own transformation and material.

Assimp may be a bit heavy for some (you have to ship it with 6.9mb dll, not good for making demos >.< ), so you may want a smaller library that only loads the model format you want to use.
Here are other libraries to explore:
http://code.google.com/p/slimmesh/
http://code.google.com/p/obj-mesh-libs/
http://code.google.com/p/lib3ds/

The best thing to do it to have your own format that has exactly what you want in it. Most of these other formats are filled with ‘garbage’ that will  make the size of your meshes, and ultimately your  game, bigger and make loading times longer.

Hope this was helpful

Advertisements

18 responses to “Mesh loading with Assimp

  1. How did you load assets with assimp on Android?

    Assets included with the apk are not accessible with standard I/O methods. I know assimp allows to implement your own IOSystem and IOStream but I’m not sure I can adhere the interface with Android’s AAssetManager.

    Do you have some example code on github or alike? Thank you!

    The code above will be helpful once I can load some assets. 😀

      • I was using java code to load and display the assets. I created a c++ program (using assimp) to load models (like obj and fbx) and write them in my own binary format. Then i’d load them in java with a custom loader. This strips away unnecessary data from the standard model formats and saves it in a binary form (eg. fbx is pure xml and contains things i dont need). This makes 3d models a lot smaller, faster to load and eliminates the use of 3rd party libraries to load models. Assimp is huge and i wouldnt want to package it in any of my android applications. I’m going to write a tutorial on how to do this in the near future.

        From the sound of things you’re using the NDK. My approach was to load the asset’s bytes from java then pass them to the native code. I just found this tutorial on how to use the AAssetManager to load contents from files inside the apk: http://vkswtips.blogspot.com/2012/02/android-ndk-how-to-load-resource-files.html
        I’ve never use the AAssetManager before, so tell me if it works for you.

  2. This is an old post, but it comes up in Google so why not:
    I noticed something weird with your variables.

    numTriangles = mesh->mNumFaces*3;
    int index=0;
    numUvCoords = mesh->GetNumUVChannels();

    -That first one is storing the number of vertices, not the number of triangles (a triangle is a face).
    -You never use the second one
    -You never use the third one either. You go through the trouble of querying the number of uv channels, and then just assume for the rest of the code that it’s 2.

    Also, your “//assume all faces are triangulated” comment is out of place, since you’re already making the triangulated assumption on line 1 at “numTriangles = mesh->mNumFaces*3;”

    • Thanks for pointing out those errors. I admit this tutorial was rushed. I mindlessly copied the code i mindlessly wrote in this post. Also, using an index buffer would have saved me the trouble of creating the vertexArray,normalArray and uvArray arrays.

      • You could also save yourself a lot of multiplication and make the code more readable by replacing every instance of “mNumFaces*3” with “numVerts”.
        Right now you’re only using that variable once, in the command to draw arrays.

  3. Pingback: Pem's Code Blog » Adding some 3D models with Open Asset Import Library (assimp)·

  4. Hi! first of all, sorry for replying to an old post, bit this is the first assimp, or should I say the model loading tutorial that makes at list a bit of sense to me. But I still have a lot of problems… The biggest one of them is a tight deadline in school for a project that includes loading a 3d model… I should also state that I know that 3d modelling and programming is not for novice programers (which I am 😦 ), but needs must… So I am a bit desperate for help :/ btw I use Windows and Visual Studio.
    What I did:
    I downloaded, installed and linked assimp (and freeglut), so I think there are no problems there.
    I made a simple 3d model and a .obj file, placed in Debug dir (project .exe file is also there).
    I tried to load the object with your code. It compiled, but then it crashes with this error: ” Access violation reading location 0x0000000C”
    The problem seems to be in this line: “aiMesh *mesh = scene->mMeshes[0];”
    Any ideas why?
    I would be forever grateful if you could explain a few more basics, what else do I need to add to actually display the model…
    And, to clarify, this is a school project, if I end up using any of your code it will be quoted, and the final product will never ever be distributed in any way, shape or form 🙂

    • If you’re getting an error on that line it means that the file isn’t being loaded because the importer.ReadFile function call is returning NULL rather than an aiScene* instance. If you are running the application from inside Visual Studio, place the obj file in the project’s directory rather than the inside the Debug folder.

      • That worked. Thanks 🙂 Now it runs with no errors, all i have to do now is to get it to display on my gl window… any advice?

      • That would depend on the OpenGL version you are using. If you have any more issues, you can always send me an email and i’ll help however i can.

  5. Hi,
    I’m trying to get this to work on android and get

    error: ‘GL_TEXTURE0_ARB’ was not declared in this scope

    what to I need to import to get ‘GL_TEXTURE0_ARB’ ?

    Cheers
    S

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s