Importing 3D Models with Assimp
Prev: Loading an Image File and Creating a Texture | Next: OpenGL 3.3 + GLSL 1.5 Sample |
Importing 3D models is easy with Assimp. This sample works with Assimp 3.0 and was based on the Assimp’s demo extending it to use core OpenGL 3.3 together with GLSL 3.3.
The sample also uses DevIL, an image loading library to provide the sample the ability to display textured models.
Freeglut is the window toolkit used in this sample. A 3.3 OpenGL context is used, together with multisampling and wheel mouse for zooming on the model.
GLEW is also being used to provide access to the new OpenGL functions.
A simple untextured model in OBJ format is provided to try this code. To test it with other models just replace the name of the model in the source code below.
A VS2010 project with the full source code and OBJ model are available in L3DAssimpModelImport Demo.
Some parts of the code:
Vertex Shader
#version 330 layout (std140) uniform Matrices { mat4 projMatrix; mat4 viewMatrix; mat4 modelMatrix; }; in vec3 position; in vec3 normal; in vec2 texCoord; out vec4 vertexPos; out vec2 TexCoord; out vec3 Normal; void main() { Normal = normalize(vec3(viewMatrix * modelMatrix * vec4(normal,0.0))); TexCoord = vec2(texCoord); gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(position,1.0); }
Fragment Shader
#version 330 layout (std140) uniform Material { vec4 diffuse; vec4 ambient; vec4 specular; vec4 emissive; float shininess; int texCount; }; uniform sampler2D texUnit; in vec3 Normal; in vec2 TexCoord; out vec4 output; void main() { vec4 color; vec4 amb; float intensity; vec3 lightDir; vec3 n; lightDir = normalize(vec3(1.0,1.0,1.0)); n = normalize(Normal); intensity = max(dot(lightDir,n),0.0); if (texCount == 0) { color = diffuse; amb = ambient; } else { color = texture2D(texUnit, TexCoord); amb = color * 0.33; } output = (color * intensity) + amb; }
Importing the model with Assimp
bool Import3DFromFile( const std::string& pFile) { //check if file exists std::ifstream fin(pFile.c_str()); if(!fin.fail()) { fin.close(); } else{ printf("Couldn't open file: %s\n", pFile.c_str()); printf("%s\n", importer.GetErrorString()); return false; } scene = importer.ReadFile( pFile, aiProcessPreset_TargetRealtime_Quality); // If the import failed, report it if( !scene) { printf("%s\n", importer.GetErrorString()); return false; } // Now we can access the file's contents. printf("Import of scene %s succeeded.",pFile.c_str()); aiVector3D scene_min, scene_max, scene_center; get_bounding_box(&scene_min, &scene_max); float tmp; tmp = scene_max.x-scene_min.x; tmp = scene_max.y - scene_min.y > tmp?scene_max.y - scene_min.y:tmp; tmp = scene_max.z - scene_min.z > tmp?scene_max.z - scene_min.z:tmp; scaleFactor = 1.f / tmp; // We're done. Everything will be cleaned up by the importer destructor return true; }
Loading images with DevIL and creating textures
int LoadGLTextures(const aiScene* scene) { ILboolean success; /* initialization of DevIL */ ilInit(); /* scan scene's materials for textures */ for (unsigned int m=0; m<scene->mNumMaterials; ++m) { int texIndex = 0; aiString path; // filename aiReturn texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); while (texFound == AI_SUCCESS) { //fill map with textures, OpenGL image ids set to 0 textureIdMap[path.data] = 0; // more textures? texIndex++; texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); } } int numTextures = textureIdMap.size(); /* create and fill array with DevIL texture ids */ ILuint* imageIds = new ILuint[numTextures]; ilGenImages(numTextures, imageIds); /* create and fill array with GL texture ids */ GLuint* textureIds = new GLuint[numTextures]; glGenTextures(numTextures, textureIds); /* Texture name generation */ /* get iterator */ std::map<std::string, GLuint>::iterator itr = textureIdMap.begin(); int i=0; for (; itr != textureIdMap.end(); ++i, ++itr) { //save IL image ID std::string filename = (*itr).first; // get filename (*itr).second = textureIds[i]; // save texture id for filename in map ilBindImage(imageIds[i]); /* Binding of DevIL image name */ ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT); success = ilLoadImage((ILstring)filename.c_str()); if (success) { /* Convert image to RGBA */ ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE); /* Create and load textures to OpenGL */ glBindTexture(GL_TEXTURE_2D, textureIds[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGBA, GL_UNSIGNED_BYTE, ilGetData()); } else printf("Couldn't load Image: %s\n", filename.c_str()); } /* Because we have already copied image data into texture data we can release memory used by image. */ ilDeleteImages(numTextures, imageIds); //Cleanup delete [] imageIds; delete [] textureIds; //return success; return true; }
Vertex Array Objects
void genVAOsAndUniformBuffer(const aiScene *sc) { struct MyMesh aMesh; struct MyMaterial aMat; GLuint buffer; // For each mesh for (unsigned int n = 0; n < sc->mNumMeshes; ++n) { const aiMesh* mesh = sc->mMeshes[n]; // create array with faces // have to convert from Assimp format to array unsigned int *faceArray; faceArray = (unsigned int *)malloc(sizeof(unsigned int) * mesh->mNumFaces * 3); unsigned int faceIndex = 0; for (unsigned int t = 0; t < mesh->mNumFaces; ++t) { const aiFace* face = &mesh->mFaces[t]; memcpy(&faceArray[faceIndex], face->mIndices,3 * sizeof(unsigned int)); faceIndex += 3; } aMesh.numFaces = sc->mMeshes[n]->mNumFaces; // generate Vertex Array for mesh glGenVertexArrays(1,&(aMesh.vao)); glBindVertexArray(aMesh.vao); // buffer for faces glGenBuffers(1, &buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * mesh->mNumFaces * 3, faceArray, GL_STATIC_DRAW); // buffer for vertex positions if (mesh->HasPositions()) { glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->mNumVertices, mesh->mVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(vertexLoc); glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); } // buffer for vertex normals if (mesh->HasNormals()) { glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->mNumVertices, mesh->mNormals, GL_STATIC_DRAW); glEnableVertexAttribArray(normalLoc); glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0); } // buffer for vertex texture coordinates if (mesh->HasTextureCoords(0)) { float *texCoords = (float *)malloc(sizeof(float)*2*mesh->mNumVertices); for (unsigned int k = 0; k < mesh->mNumVertices; ++k) { texCoords[k*2] = mesh->mTextureCoords[0][k].x; texCoords[k*2+1] = mesh->mTextureCoords[0][k].y; } glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->mNumVertices, texCoords, GL_STATIC_DRAW); glEnableVertexAttribArray(texCoordLoc); glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, 0, 0, 0); } // unbind buffers glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); // create material uniform buffer aiMaterial *mtl = sc->mMaterials[mesh->mMaterialIndex]; aiString texPath; //contains filename of texture if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, 0, &texPath)){ //bind texture unsigned int texId = textureIdMap[texPath.data]; aMesh.texIndex = texId; aMat.texCount = 1; } else aMat.texCount = 0; float c[4]; set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); aiColor4D diffuse; if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) color4_to_float4(&diffuse, c); memcpy(aMat.diffuse, c, sizeof(c)); set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); aiColor4D ambient; if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) color4_to_float4(&ambient, c); memcpy(aMat.ambient, c, sizeof(c)); set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); aiColor4D specular; if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) color4_to_float4(&specular, c); memcpy(aMat.specular, c, sizeof(c)); set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); aiColor4D emission; if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) color4_to_float4(&emission, c); memcpy(aMat.emissive, c, sizeof(c)); float shininess = 0.0; unsigned int max; aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); aMat.shininess = shininess; glGenBuffers(1,&(aMesh.uniformBlockIndex)); glBindBuffer(GL_UNIFORM_BUFFER,aMesh.uniformBlockIndex); glBufferData(GL_UNIFORM_BUFFER, sizeof(aMat), (void *)(&aMat), GL_STATIC_DRAW); myMeshes.push_back(aMesh); } }
Model Render
void recursive_render (const aiScene *sc, const aiNode* nd) { // Get node transformation matrix aiMatrix4x4 m = nd->mTransformation; // OpenGL matrices are column major m.Transpose(); // save model matrix and apply node transformation pushMatrix(); float aux[16]; memcpy(aux,&m,sizeof(float) * 16); multMatrix(modelMatrix, aux); setModelMatrix(); // draw all meshes assigned to this node for (unsigned int n=0; n < nd->mNumMeshes; ++n){ // bind material uniform glBindBufferRange(GL_UNIFORM_BUFFER, materialUniLoc, myMeshes[nd->mMeshes[n]].uniformBlockIndex, 0, sizeof(struct MyMaterial)); // bind texture glBindTexture(GL_TEXTURE_2D, myMeshes[nd->mMeshes[n]].texIndex); // bind VAO glBindVertexArray(myMeshes[nd->mMeshes[n]].vao); // draw glDrawElements(GL_TRIANGLES,myMeshes[nd->mMeshes[n]].numFaces*3,GL_UNSIGNED_INT,0); } // draw all children for (unsigned int n=0; n < nd->mNumChildren; ++n){ recursive_render(sc, nd->mChildren[n]); } popMatrix(); }
Prev: Loading an Image File and Creating a Texture | Next: OpenGL 3.3 + GLSL 1.5 Sample |
60 Responses to “Importing 3D Models with Assimp”
Leave a Reply to ARF Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
AssimpModelImport Demo.exe’ (Win32): Loaded ‘C:\Windows\SysWOW64\ntdll.dll’. Symbols loaded.
‘AssimpModelImport Demo.exe’ (Win32): Loaded ‘C:\Windows\SysWOW64\kernel32.dll’. Symbols loaded.
‘AssimpModelImport Demo.exe’ (Win32): Loaded ‘C:\Windows\SysWOW64\KernelBase.dll’. Symbols loaded.
The program ‘[20724] AssimpModelImport Demo.exe’ has exited with code -1073741701 (0xc000007b).
It doesn’t seam to load the devil and assimp dll even though I have them in the sysWOW64 floader
Can you pinpoint the line where the program crashes?
I think I don’t think I have the entire code something went wrong.
Hello,
Happy New Year. Sorry for replying late.
I tried again and I get the following.
'AssimpModelImport Demo.exe': Loaded 'C:\Users\Nandita_D\Desktop\exntutorials\L3DAssimpModelImport Demo\Debug\AssimpModelImport Demo.exe', Symbols loaded.
'AssimpModelImport Demo.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Exports loaded.
'AssimpModelImport Demo.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Exports loaded.
'AssimpModelImport Demo.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Exports loaded.
Debugger:: An unhandled non-continuable STATUS_DLL_NOT_FOUND exception was thrown during process load
The program '[8604] AssimpModelImport Demo.exe: Native' has exited with code -1073741515 (0xc0000135).
Thanks
Hi, have you checked the version at git hub?
https://github.com/lighthouse3d/VSL
Nope I haven’t tried the new version. Will try and let you know .
Thanks
And I can’t find the line where it breaks. since its braking before the main function.
Hello,
I have tried the new code on Visual studio 2013. It give following link errors.
Error 3 error LNK2019: unresolved external symbol "public: __thiscall Assimp::Importer::Importer(void)" (??0Importer@Assimp@@QAE@XZ) referenced in function "public: virtual bool __thiscall VSResModelLib::load(class std::basic_string<char,struct std::char_traits,class std::allocator >)" (?load@VSResModelLib@@UAE_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) C:\Users\username\Desktop\VSL-master\Models\l3dvsld.lib(vsResModelLib.obj) Models
Error 4 error LNK2019: unresolved external symbol "public: __thiscall Assimp::Importer::~Importer(void)" (??1Importer@Assimp@@QAE@XZ) referenced in function "public: virtual bool __thiscall VSResModelLib::load(class std::basic_string<char,struct std::char_traits,class std::allocator >)" (?load@VSResModelLib@@UAE_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) C:\Users\username\Desktop\VSL-master\Models\l3dvsld.lib(vsResModelLib.obj) Models
Error 5 error LNK2019: unresolved external symbol "public: struct aiScene const * __thiscall Assimp::Importer::ReadFile(char const *,unsigned int)" (?ReadFile@Importer@Assimp@@QAEPBUaiScene@@PBDI@Z) referenced in function "public: struct aiScene const * __thiscall Assimp::Importer::ReadFile(class std::basic_string<char,struct std::char_traits,class std::allocator > const &,unsigned int)" (?ReadFile@Importer@Assimp@@QAEPBUaiScene@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@I@Z) C:\Users\username\Desktop\VSL-master\Models\l3dvsld.lib(vsResModelLib.obj) Models
Error 6 error LNK2019: unresolved external symbol _aiGetMaterialFloatArray referenced in function "private: void __thiscall VSResModelLib::genVAOsAndUniformBuffer(struct aiScene const *)" (?genVAOsAndUniformBuffer@VSResModelLib@@AAEXPBUaiScene@@@Z) C:\Users\username\Desktop\VSL-master\Models\l3dvsld.lib(vsResModelLib.obj) Models
Error 7 error LNK2019: unresolved external symbol _aiGetMaterialColor referenced in function "private: void __thiscall VSResModelLib::genVAOsAndUniformBuffer(struct aiScene const *)" (?genVAOsAndUniformBuffer@VSResModelLib@@AAEXPBUaiScene@@@Z) C:\Users\username\Desktop\VSL-master\Models\l3dvsld.lib(vsResModelLib.obj) Models
Error 8 error LNK2019: unresolved external symbol _aiGetMaterialTexture referenced in function "public: enum aiReturn __thiscall aiMaterial::GetTexture(enum aiTextureType,unsigned int,struct aiString *,enum aiTextureMapping *,unsigned int *,float *,enum aiTextureOp *,enum aiTextureMapMode *)const " (?GetTexture@aiMaterial@@QBE?AW4aiReturn@@W4aiTextureType@@IPAUaiString@@PAW4aiTextureMapping@@PAIPAMPAW4aiTextureOp@@PAW4aiTextureMapMode@@@Z) C:\Users\username\Desktop\VSL-master\Models\l3dvsld.lib(vsResModelLib.obj) Models
Hi,
It looks as If you are not linking with Assimp. I’m using Assimp 3.0.
Hello,
Good Day!
I have connected the Assimp libs to the solution. Still it gives link errors.
Thanks
Nandita
Hi !
In your Import3DFromFile function, you have a magic function called get_bounding_box(&scene_min, &scene_max) which interests me.
Is it a function you developped on your own ? I don’t see this function in the Assimp documentation =/
Hi,
Yes, I did implement it. You can get the code in the ZIP provided in the page, or at github (search for VSL)
How would the procedure change if the input file is type .step (popular in PCB 3d modeling)?
Also any thoughts on using assimp with pyqt-opengl? I understand its a good platform to do quick GUI applications.
Thanks!
Hi Ben,
As far as I know Assimp does not support the step format. The only short term solution, until Assimp adds STEP as an aceepted format, would be to convert the model to an accepted format by Assimp.
Regarding pyqt-opengl I’m afraid I can be of much assistance.
Best Regards,
Antonio
If it isn’t too much trouble, could you explain a little about how the texturing process works? My model shows up untextured. It’s an exported .obj from Blender, the texture was usually loaded from an associated png.
Hi,
In the mtl file there should be a path to the texture file. Is the texture placed in the right folder? PNGs are OK for DevIL.
Hope this helps
From the bottom of my heart, thank you. I’ve spent over a week looking for a single working example for assimp, and yours is the only one I’ve found.
You should update the tutorial package with the change from “output” in the fragment shader so that it works out of the box.
Thanks you. I’ll do that.
You’re right, must change the “output”. I’m slowly moving the source code to github to make it easier to mantain.
Thanks
This is the best written and most effective assimp to opengl loader out there.
Thank you so much for this. May the beautiful girls bless you.
I have a similar error to Jeffrey but not with texture2D, it’s something indicated as ‘output’ although I’ve searched the whole solution and barely see where it is defined
Ready for OpenGL 3.3
Import of scene bench.obj succeeded. WARNING: 0:? : ” : Version number deprecated in OGL 3.0 forward compatible context driver
No errors.
WARNING: 0:? : ” : Version number deprecated in OGL 3.0 forward compatible context driver
ERROR: 0:16: ‘output’ : Reserved word.
ERROR: 0:16: ‘output’ : syntax error syntax error
Vendor: Intel
Renderer: Intel HD Graphics 4000
Version: 3.3.0 – Build 9.17.10.2843
GLSL: 3.30 – Build 9.17.10.2843
How should I fix it?
Hi,
Thansk for the bug report. To fix it, go to the fragment shader and replace the out vec4 named output with outputColor (for example). It happens that, although not used, “output” is a reserved keyword in GLSL.
hi guys! Anybody know to convert to opengl view matrix from dx view matrix?
I run the demo and got the following output:
Ready for OpenGL 3.3
Import of scene bench.obj succeeded.WARNING: 0:? : ” : Version number deprecate
d in OGL 3.0 forward compatible context driver
No errors.
WARNING: 0:? : ” : Version number deprecated in OGL 3.0 forward compatible cont
ext driver
ERROR: 0:35: ‘texture2D’ : function is removed in Forward Compatibile context
ERROR: 0:35: ‘texture2D’ : no matching overloaded function found (using implicit
conversion)
ERROR: 0:35: ‘assign’ : cannot convert from ‘const float’ to ‘4-component vecto
r of float’
Vendor: Intel
Renderer: Intel(R) HD Graphics 2500
Version: 3.3.0 – Build 9.17.10.2875
GLSL: 3.30 – Build 9.17.10.2875
It seens that the code color = texture2D(texUnit, TexCoord); in shader dirlightdiffambpix.frag not working.
Hi,
“texture2D” is in fact deprecated, although NVIDIA drivers don’t complain. You could replace it with “texture”. That should remove the problems in the shader.
P.S: The demo has been updated
Is it possible to share a full source file. Because I can’t use it without errors.
Will this code work with Assimp 3.0.1270?
With other words. This tutorial is useless for new Assimp users.
Yes, I know 🙁 I’ll update the tutorial soon.
Thanks.
I realize this is a little old now, so it doesn’t compile straight out of the box. Assimp headers need to change for the latest version (below) and most of the “struct” keywords needs to be removed (at least VS2012 doesn’t like them). Also, all the libraries need to be compiled and attached. Other than that it works.
#include
#include
#include
Assimp/Importer.hpp
Assimp/postprocess.h
Assimp/scene.h
Apparently comments can’t include angle brackets.
This tutorial has too many missing parts to it
> void main()
– I’d seen enough.
And all the ‘struct aiXXXX’ instances. The includes relying on case-insensitivity. All the manual memory management. And then passing a std::string as a format parameter to printf. Unused variables. Mutable `char*` for literals…
Based on the sheer amount of trouble I wouldn’t exactly recommend this code to people learning assimp/devil.
Agree !! put in the bask the lack of use of Glm (thats because the aiXXXX) , const char * is a requeriment nowdaws !!! and the absence of smart pointers make me believe that People will never really learn c11 with others teaching ansi c.
I had come up with a fixed version here https://gist.github.com/sehe/0f8f711f44d48b9ecbbf (at least, fixed enough to make it work with cc on linux). Includes a makefile and sample inputs.
Cheers,
Seth
Line 21 under Vertex Array Objects has sizeof(float) but the indices are unsigned ints; is that intentional?
Fixed. Thanks
I am having problems with struct aiVector3D scene_min… I am using C++, and the problem is “incomplete type”, if I change to aiVector3D* scene_min, the problem is when I try to use scene_min-> (then, it says pointer to incomplete class type)…
What can I do?
Why there are recusive render but not use for(int i=0; imNumMesh; ++i) {render scene->mMeshes[i]; }??
I think it’s because of how assimp “scene graph” is made. Each object may have subobjects and they might have their own subobjects and … 🙂
Which is why it kind of “requires” recursive rendering.
You also say that you’re creating a material uniform buffer but that doesn’t seem to be the case:
// create material uniform buffer
struct aiMaterial *mtl = sc->mMaterials[mesh->mMaterialIndex];
Why aren’t you creating the material uniform buffer like the matrices ubo?
In this tutorial, the recursive render function tries to access the root Node but when I implemented this, by the time the program had reached the render function, the importer had gone out of scope and as a result the data in the scene object had been destroyed and so the data being pointed to was invalid. Didn’t anyone else run into this problem?
I got this code working perfect with the model that comes with it (bench.obj and bench.mtl).
However, any other models that either created by myself using 3dsMax or downloaded from Internet doesn’t work as expected. They are either loaded without texture or are not loaded at all. When not loaded, I usually get error: vector::_M_range_check.
Is there anything special with the way you export bench.obj and bench.mtl?
Anyway, thanks a lot for the code.
Hi Mike,
No, the bench model has nothing special. Can you send me one of the models that cause an error? What file types are you trying to load?
Sir
I am starting the whole project from scratch
Some how i am not able to create shader
if you see the snippet it never pass the after the variable declared check point
Some how it is not able to execute these command v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER);
On debugging
Unhandled exception at 0x773a15de in SimpleOpenGL_Debug.exe: 0xC0000005: Access violation reading location 0x00000000.
Any sight will be appreciated
Aditya
——————————————————————————–Snipper for setupShader————————————————
GLuint setupShaders() {
const char * vertexShaderSource = {
“#version 130\n”
“in vec3 position;”
“void main () {”
” gl_Position = position;”
“}”
};
const char * fragmentShaderSource = {
“#version 130\n”
“out vec4 fragColor;”
“void main() {”
” fragColor = vec4(0.5, 0.5, 1.0, 1.0);”
“}”
};
GLuint p,v,f;
cout<< "variables declared check point";
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
cout<< "create shader";
printf("\n");
glShaderSource(v, 1, &vertexShaderSource, NULL);
printf("\n");
glShaderSource(f, 1, &fragmentShaderSource, NULL);
cout<< "compile shader";
printf("\n");
glCompileShader(v);
glCompileShader(f);
cout<< "finish compiling shader";
printf("\n");
program = glCreateProgram();
glAttachShader(p, v);
glAttachShader(p, f);
glBindFragDataLocation(program, 0, "output");
glBindAttribLocation(program,vertexLoc,"position");
glBindAttribLocation(program,normalLoc,"normal");
glBindAttribLocation(program,texCoordLoc,"texCoord");
glLinkProgram(p);
glValidateProgram(p);
return(p);
}
i am getting an unhandled exception
Unhandled exception at 0x01e6e620 in Adv_Graphics.exe: 0xC0000005: Access violation reading location 0x00000000.
its in the line 26 of the Model Render code
// draw
glDrawElements(GL_TRIANGLES,myMeshes[nd->mMeshes[n]].numFaces*3,GL_UNSIGNED_INT,0);
pls help
The assimp importer is probably going out of scope before that call. The importer object keeps ownership of the data and will destroy it upon destruction.
Check the api docs:
http://assimp.sourceforge.net/lib_html/class_assimp_1_1_importer.html#339882c7acb47d5b5110bbd078d870a9
I was trying to run the program. but i got a breakpoint
#undef _CrtDbgBreak
/* These methods don’t need a separate
wchar version. Hence they need to be compiled only once from
the original file */
_CRTIMP void _cdecl _CrtDbgBreak(
void
)
{
__debugbreak();
}
can u please help
Hi Jose,
The function pushMatrix is part of the source code. Perhaps you’re confusing it with glPushMatrix?
Oh! I was confusing it yes. Thanks for a great tutorial anyway. Keep it up!
Thanks! Just what I was looking for after I went down several false paths.
I did run into an issue loading dae (Collada) files exported from Sketchup, because it drops the textures in a directory below the model file. I got around this by passing the path to the model file to LoadGLTextures and trying to load relative to that path if the first load failed (too lazy to test the paths first – not for production code). Relevant hacks:
in init:
LoadGLTextures(scene, dirname(strdup(modelname.c_str())));
in LoadGLTextures:
success = ilLoadImage((ILstring)filename.c_str());
// if it doesn't load to start with, look for it relative to the
// source file
if (!success) {
fs::path temp_basepath (basepath);
fs::path temp_filename (filename.c_str());
fs::path full_path = temp_basepath / temp_filename;
success = ilLoadImage((ILstring)full_path.string().c_str());
}
if (success) {
in header:
#include
#include
namespace fs = boost::filesystem;
The munged includes should be libgen.h and boost/filesystem.hpp
I tried to port the code provided in ASSIMP’s sample code to glut & OpenGL. For some reasons, I avoid using GLSL & OpenGL 3.x context. I found some models loaded incorrectly, and I think there is something wrong with how the code access the normal and vertex positions from the mesh.
glBegin(face_mode);
for(i = 0; i mNumIndices; i++){
int vertexIndex = face->mIndices[i]; // get group index for current index
if(mesh->mColors[0] != NULL)
Color4f(&mesh->mColors[0][vertexIndex]);
if(mesh->mNormals != NULL)
if(mesh->HasTextureCoords(0)){
glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, mesh->mTextureCoords[0][vertexIndex].y);
}
glNormal3fv(&mesh->mNormals[vertexIndex].x);
glVertex3fv(&mesh->mVertices[vertexIndex].x);
}
glEnd();
Do you have any suggestion on how to fix this problem?
Hello!
I’m trying to get this example to work but I can’t seem to get all the linkings properly, I’m using CodeBlocks, can you tell me exactly what files do I need to link?
Thanks in advance.
The code has been compiled successfully. However, VS place the executable file inside ‘Debug’ or ‘Release’ folder. Therefore, the executable can not recognize the shaders and obj file. This is resulting Access Violation error. When we run the executable manually with shaders and obj file placed at the same directory, the executable runs smoothly.
Please ignore my not-yet-moderated comment. 🙂 . Indeed, i think it is important to include the cmakelists.txt file.
Thank you. Your site is amazing!
I tried to compile the source using VS2008, unfortunately, I got access violation error: Unhandled exception at 0x69a59436 in modelimport.exe: 0xC0000005: Access violation reading location 0x00000000.
I believe ASSIMP and DevIL has been installed correctly.
Would you mind to provide the project file or instruction to compile this? Thanks! 🙂
Do you have any zipped archive of your sample? one containing .cpp and .vcproj? Please insert it if you have! we are kind of new to ASSIMP and not so familiar with loading meshes.
I’ll add a Cmake file as soon as I have some time. Thanks for the suggestion.
what’s with the redefinition of some GL functions in the source code, aren’t these already defined in GLEW?
glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) glutGetProcAddress("glGetUniformBlockIndex");
glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) glutGetProcAddress("glUniformBlockBinding");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) glutGetProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)glutGetProcAddress("glBindVertexArray");
glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) glutGetProcAddress("glBindBufferRange");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) glutGetProcAddress("glDeleteVertexArrays");
Well, yes and no. They become accessible if you use glewExperimental = true, but by default they are not accessible.
See this previous post.