diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index 26ac625ed..9bce7dc89 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -1,6 +1,5 @@ - // ---------------------------------------------------------------------------- -// Simple sample to prove that Assimp is absolutely easy to use with OpenGL. +// Simple sample to prove that Assimp is easy to use with OpenGL. // It takes a file name as command line parameter, loads it using standard // settings and displays it. // @@ -20,7 +19,8 @@ // the global Assimp scene object const struct aiScene* scene = NULL; -struct aiVector3D scene_min,scene_max; +GLuint scene_list = 0; +struct aiVector3D scene_min, scene_max, scene_center; // current rotation angle static float angle = 0.f; @@ -49,6 +49,7 @@ void get_bounding_box_for_node (const struct aiNode* nd, struct aiMatrix4x4 prev; unsigned int n = 0, t; + prev = *trafo; aiMultiplyMatrix4(trafo,&nd->mTransformation); for (; n < nd->mNumMeshes; ++n) { @@ -68,7 +69,6 @@ void get_bounding_box_for_node (const struct aiNode* nd, } } - prev = nd->mTransformation; for (n = 0; n < nd->mNumChildren; ++n) { get_bounding_box_for_node(nd->mChildren[n],min,max,trafo); } @@ -87,37 +87,156 @@ void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max) } // ---------------------------------------------------------------------------- -void recursive_render (const struct aiNode* nd) + +void color4_to_float4(const struct aiColor4D *c, float f[4]) { + f[0] = c->r; + f[1] = c->g; + f[2] = c->b; + f[3] = c->a; +} + +void set_float4(float f[4], float a, float b, float c, float d) +{ + f[0] = a; + f[1] = b; + f[2] = c; + f[3] = d; +} + +// ---------------------------------------------------------------------------- +void apply_material(const struct aiMaterial *mtl) +{ + float c[4]; + + GLenum fill_mode; + int ret1, ret2; + struct aiColor4D diffuse; + struct aiColor4D specular; + struct aiColor4D ambient; + struct aiColor4D emission; + float shininess, strength; + int two_sided; + int wireframe; + int max; + + set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) + color4_to_float4(&diffuse, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) + color4_to_float4(&specular, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + + set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) + color4_to_float4(&ambient, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) + color4_to_float4(&emission, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); + + max = 1; + ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); + max = 1; + ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); + if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS)) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); + else { + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); + set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + } + + max = 1; + if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) + fill_mode = wireframe ? GL_LINE : GL_FILL; + else + fill_mode = GL_FILL; + glPolygonMode(GL_FRONT_AND_BACK, fill_mode); + + max = 1; + if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); +} + +// ---------------------------------------------------------------------------- + +// Can't send color down as a pointer to aiColor4D because AI colors are ABGR. +void Color4f(const struct aiColor4D *color) +{ + glColor4f(color->r, color->g, color->b, color->a); +} + +// ---------------------------------------------------------------------------- +void recursive_render (const struct aiScene *sc, const struct aiNode* nd) +{ + int i; unsigned int n = 0, t; struct aiMatrix4x4 m = nd->mTransformation; // update transform aiTransposeMatrix4(&m); + glPushMatrix(); glMultMatrixf((float*)&m); // draw all meshes assigned to this node for (; n < nd->mNumMeshes; ++n) { const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; - glBegin(GL_TRIANGLES); + apply_material(sc->mMaterials[mesh->mMaterialIndex]); + + if(mesh->mNormals == NULL) { + glDisable(GL_LIGHTING); + } else { + glEnable(GL_LIGHTING); + } + + if(mesh->mColors[0] != NULL) { + glEnable(GL_COLOR_MATERIAL); + } else { + glDisable(GL_COLOR_MATERIAL); + } for (t = 0; t < mesh->mNumFaces; ++t) { const struct aiFace* face = &mesh->mFaces[t]; + GLenum face_mode; - glColor3f(1.f,0.f,0.f); - glVertex3fv(&mesh->mVertices[face->mIndices[0]].x); - glVertex3fv(&mesh->mVertices[face->mIndices[1]].x); - glVertex3fv(&mesh->mVertices[face->mIndices[2]].x); + switch(face->mNumIndices) { + case 1: face_mode = GL_POINTS; break; + case 2: face_mode = GL_LINES; break; + case 3: face_mode = GL_TRIANGLES; break; + default: face_mode = GL_POLYGON; break; + } + + glBegin(face_mode); + + for(i = 0; i < face->mNumIndices; i++) { + int index = face->mIndices[i]; + if(mesh->mColors[0] != NULL) + Color4f(&mesh->mColors[0][index]); + if(mesh->mNormals != NULL) + glNormal3fv(&mesh->mNormals[index].x); + glVertex3fv(&mesh->mVertices[index].x); + } + + glEnd(); } - glEnd(); } // draw all children for (n = 0; n < nd->mNumChildren; ++n) { - recursive_render(nd->mChildren[n]); + recursive_render(sc, nd->mChildren[n]); } + + glPopMatrix(); } // ---------------------------------------------------------------------------- @@ -136,29 +255,40 @@ void do_motion (void) void display(void) { float tmp; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f); - // scale the whole asset to fit into our view frustum - tmp = scene_max.x-scene_min.x; - tmp = aisgl_max(scene_max.y-scene_min.y,tmp); - tmp = aisgl_max(scene_max.z-scene_min.z,tmp); - - tmp = 1.f/(tmp); - glScalef(tmp,tmp,tmp); - - // fixme: center around origin - // rotate it around the y axis glRotatef(angle,0.f,1.f,0.f); - // now begin at the root node of the imported data and traverse - // the scenegraph by multipliying subsequent local transforms - // together on GL's matrix stack. - recursive_render(scene->mRootNode); + // scale the whole asset to fit into our view frustum + tmp = scene_max.x-scene_min.x; + tmp = aisgl_max(scene_max.y - scene_min.y,tmp); + tmp = aisgl_max(scene_max.z - scene_min.z,tmp); + tmp = 1.f / tmp; + glScalef(tmp, tmp, tmp); + + // center the model + glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z ); + + // if the display list has not been made yet, create a new one and + // fill it with scene contents + if(scene_list == 0) { + scene_list = glGenLists(1); + glNewList(scene_list, GL_COMPILE); + // now begin at the root node of the imported data and traverse + // the scenegraph by multiplying subsequent local transforms + // together on GL's matrix stack. + recursive_render(scene, scene->mRootNode); + glEndList(); + } + + glCallList(scene_list); + glutSwapBuffers(); do_motion(); @@ -172,8 +302,10 @@ int loadasset (const char* path) scene = aiImportFile(path,aiProcessPreset_TargetRealtime_Quality); if (scene) { - get_bounding_box(&scene_min,&scene_max); + scene_center.x = (scene_min.x + scene_max.x) / 2.0f; + scene_center.y = (scene_min.y + scene_max.y) / 2.0f; + scene_center.z = (scene_min.z + scene_max.z) / 2.0f; return 0; } return 1; @@ -183,6 +315,7 @@ int loadasset (const char* path) int main(int argc, char **argv) { struct aiLogStream stream; + glutInitWindowSize(900,600); glutInitWindowPosition(100,100); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); @@ -209,10 +342,22 @@ int main(int argc, char **argv) } } - glPolygonMode(GL_FRONT,GL_LINE); - glPolygonMode(GL_BACK,GL_LINE); glClearColor(0.1f,0.1f,0.1f,1.f); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); // Uses default lighting parameters + + glEnable(GL_DEPTH_TEST); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glEnable(GL_NORMALIZE); + + // XXX docs say all polygons are emitted CCW, but tests show that some aren't. + if(getenv("MODEL_IS_BROKEN")) + glFrontFace(GL_CW); + + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glutGet(GLUT_ELAPSED_TIME); glutMainLoop(); diff --git a/samples/workspaces/vc8/SimpleOpenGL/SimpleOpenGL.vcproj b/samples/workspaces/vc8/SimpleOpenGL/SimpleOpenGL.vcproj index a3939fe87..80f7f02ce 100644 --- a/samples/workspaces/vc8/SimpleOpenGL/SimpleOpenGL.vcproj +++ b/samples/workspaces/vc8/SimpleOpenGL/SimpleOpenGL.vcproj @@ -63,7 +63,7 @@ Name="VCLinkerTool" AdditionalDependencies="glut32.lib assimp.lib" LinkIncremental="2" - AdditionalLibraryDirectories="..\..\..\glut;"..\..\..\..\lib\assimp_release-dll_win32"" + AdditionalLibraryDirectories="..\..\..\glut;"..\..\..\..\lib\assimp_debug_win32"" GenerateDebugInformation="true" SubSystem="1" TargetMachine="1"