void C3D_MODEL_VIEWER::ogl_set_arrow_material() { glEnable( GL_COLOR_MATERIAL ); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f ); glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r ); glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f ); }
C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode ) { m_ogl_idx_list_meshes = 0; m_ogl_idx_list_opaque = 0; m_ogl_idx_list_transparent = 0; m_nr_meshes = 0; m_meshs_bbox = NULL; // Validate a3DModel pointers wxASSERT( a3DModel.m_Materials != NULL ); wxASSERT( a3DModel.m_Meshes != NULL ); wxASSERT( a3DModel.m_MaterialsSize > 0 ); wxASSERT( a3DModel.m_MeshesSize > 0 ); if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) && (a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) ) { m_nr_meshes = a3DModel.m_MeshesSize; m_meshs_bbox = new CBBOX[a3DModel.m_MeshesSize]; // Generate m_MeshesSize auxiliar lists to render the meshes m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize ); // Render each mesh of the model // ///////////////////////////////////////////////////////////////////// for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i ) { if( glIsList( m_ogl_idx_list_meshes + mesh_i ) ) { const SMESH &mesh = a3DModel.m_Meshes[mesh_i]; // Validate the mesh pointers wxASSERT( mesh.m_Positions != NULL ); wxASSERT( mesh.m_FaceIdx != NULL ); wxASSERT( mesh.m_Normals != NULL ); if( (mesh.m_Positions != NULL) && (mesh.m_Normals != NULL) && (mesh.m_FaceIdx != NULL) && (mesh.m_FaceIdxSize > 0) && (mesh.m_VertexSize > 0) ) { SFVEC4F *pColorRGBA = NULL; // Create the bbox for this mesh // ///////////////////////////////////////////////////////// m_meshs_bbox[mesh_i].Reset(); for( unsigned int vertex_i = 0; vertex_i < mesh.m_VertexSize; ++vertex_i ) { m_meshs_bbox[mesh_i].Union( mesh.m_Positions[vertex_i] ); } // Make sure we start with client state disabled // ///////////////////////////////////////////////////////// glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); // Enable arrays client states // ///////////////////////////////////////////////////////// glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, mesh.m_Positions ); glNormalPointer( GL_FLOAT, 0, mesh.m_Normals ); if( mesh.m_Color != NULL ) { glEnableClientState( GL_COLOR_ARRAY ); float transparency = 0.0f; if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize ) transparency = a3DModel.m_Materials[mesh.m_MaterialIdx].m_Transparency; if( (transparency > FLT_EPSILON) && (aMaterialMode == MATERIAL_MODE_NORMAL) ) { // Create a new array of RGBA colors pColorRGBA = new SFVEC4F[mesh.m_VertexSize]; // Copy RGB array and add the Alpha value for( unsigned int i = 0; i < mesh.m_VertexSize; ++i ) pColorRGBA[i] = SFVEC4F( mesh.m_Color[i], 1.0f - transparency ); // Load an RGBA array glColorPointer( 4, GL_FLOAT, 0, pColorRGBA ); } else { switch( aMaterialMode ) { case MATERIAL_MODE_NORMAL: case MATERIAL_MODE_DIFFUSE_ONLY: // load the original RGB color array glColorPointer( 3, GL_FLOAT, 0, mesh.m_Color ); break; case MATERIAL_MODE_CAD_MODE: // Create a new array of RGBA colors pColorRGBA = new SFVEC4F[mesh.m_VertexSize]; // Copy RGB array and add the Alpha value for( unsigned int i = 0; i < mesh.m_VertexSize; ++i ) { pColorRGBA[i] = SFVEC4F( MaterialDiffuseToColorCAD( mesh.m_Color[i] ), 1.0f ); } // Load an RGBA array glColorPointer( 4, GL_FLOAT, 0, pColorRGBA ); break; default: break; } } } if( mesh.m_Texcoords != NULL ) { glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glTexCoordPointer( 2, GL_FLOAT, 0, mesh.m_Texcoords ); } // Compile the display list to store triangles // ///////////////////////////////////////////////////////// glNewList( m_ogl_idx_list_meshes + mesh_i, GL_COMPILE ); // Set material properties // ///////////////////////////////////////////////////////// if( mesh.m_Color != NULL ) { // This enables the use of the Color Pointer information glEnable( GL_COLOR_MATERIAL ); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); } else { glDisable( GL_COLOR_MATERIAL ); } if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize ) { switch( aMaterialMode ) { case MATERIAL_MODE_NORMAL: OGL_SetMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx] ); break; case MATERIAL_MODE_DIFFUSE_ONLY: OGL_SetDiffuseOnlyMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse ); break; case MATERIAL_MODE_CAD_MODE: OGL_SetDiffuseOnlyMaterial( MaterialDiffuseToColorCAD( a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse ) ); break; default: break; } } // Draw mesh // ///////////////////////////////////////////////////////// glDrawElements( GL_TRIANGLES, mesh.m_FaceIdxSize, GL_UNSIGNED_INT, mesh.m_FaceIdx ); glDisable( GL_COLOR_MATERIAL ); glEndList(); // Disable arrays client states // ///////////////////////////////////////////////////////// glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); glDisableClientState( GL_VERTEX_ARRAY ); glFinish(); delete [] pColorRGBA; } } }// for each mesh m_ogl_idx_list_opaque = glGenLists( 1 ); // Check if the generated list is valid if( glIsList( m_ogl_idx_list_opaque ) ) { bool have_opaque_meshes = false; bool have_transparent_meshes = false; // Compile the model display list glNewList( m_ogl_idx_list_opaque, GL_COMPILE ); // Render each mesh display list (opaque first) // ///////////////////////////////////////////////////////////////// for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i ) { const SMESH &mesh = a3DModel.m_Meshes[mesh_i]; if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize ) { const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx]; if( material.m_Transparency == 0.0f ) { have_opaque_meshes = true; // Flag that we have at least one opaque mesh glCallList( m_ogl_idx_list_meshes + mesh_i ); } else { have_transparent_meshes = true; // Flag that we found a transparent mesh } } } glEndList(); if( !have_opaque_meshes ) { // If we dont have opaque meshes, we can free the list glDeleteLists( m_ogl_idx_list_opaque, 1 ); m_ogl_idx_list_opaque = 0; } if( have_transparent_meshes ) { m_ogl_idx_list_transparent = glGenLists( 1 ); // Check if the generated list is valid if( glIsList( m_ogl_idx_list_transparent ) ) { // Compile the model display list glNewList( m_ogl_idx_list_transparent, GL_COMPILE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // Render each mesh display list // ///////////////////////////////////////////////////////// for( unsigned mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i ) { const SMESH &mesh = a3DModel.m_Meshes[mesh_i]; if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize ) { const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx]; // Render the transparent mesh if it have a transparency value if( material.m_Transparency != 0.0f ) glCallList( m_ogl_idx_list_meshes + mesh_i ); } } glDisable( GL_BLEND ); glEndList(); } else { m_ogl_idx_list_transparent = 0; } } } else { m_ogl_idx_list_opaque = 0; } // Create the main bbox // ///////////////////////////////////////////////////////////////////// m_model_bbox.Reset(); for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i ) m_model_bbox.Union( m_meshs_bbox[mesh_i] ); glFinish(); } }