在opengl中的对象加载器
我已经在C ++中创build了一个包含opengl的程序,我也想创build一个obj加载器来加载一个obj文件。 我已经创build了两个function:
void ReadFile(model *md) { // Open the file for reading OBJINFO.TXT ifstream obj_file("tree.obj"); if (obj_file.fail()) exit(1); // Get the number of vertices obj_file >> md->vertices; // Get the number of faces obj_file >> md->faces; // Get the vertex coordinates for (int i = 0; i < md->vertices; i++) { obj_file >> md->obj_points[i].x; obj_file >> md->obj_points[i].y; obj_file >> md->obj_points[i].z; } // Get the face structure for (int i = 0; i < md->faces; i++) { obj_file >> md->obj_faces[i].vn[0]; obj_file >> md->obj_faces[i].vn[1]; obj_file >> md->obj_faces[i].vn[2]; obj_file >> md->obj_faces[i].vn[3]; } obj_file.close(); } void DisplayModel(model md) { glPushMatrix(); glBegin(GL_TRIANGLES); for (int i = 0; i < md.faces; i++) { glVertex3f(md.obj_points[md.obj_faces[i].vn[0]-1].x, md.obj_points[md.obj_faces[i].vn[0]-1].y, md.obj_points[md.obj_faces[i].vn[0]-1].z); glVertex3f(md.obj_points[md.obj_faces[i].vn[1]-1].x, md.obj_points[md.obj_faces[i].vn[1]-1].y, md.obj_points[md.obj_faces[i].vn[1]-1].z); glVertex3f(md.obj_points[md.obj_faces[i].vn[2]-1].x, md.obj_points[md.obj_faces[i].vn[2]-1].y, md.obj_points[md.obj_faces[i].vn[2]-1].z); glVertex3f(md.obj_points[md.obj_faces[i].vn[2]-1].x, md.obj_points[md.obj_faces[i].vn[2]-1].y, md.obj_points[md.obj_faces[i].vn[3]-1].z); } glEnd(); glPopMatrix(); }
主要的问题是,当我编译项目并运行它,没有什么会出现在视口中。 为了出现物体,我也增加了视口的尺寸,但情况依然如此! 所以我达到了这些function做错了的结果! 任何人都可以帮助我吗?!
另外我给我的obj文件的一些值:
v 0.158000 0.975000 0.151491 1.000000 v 0.188743 0.025000 0.173826 1.000000 v 0.196000 0.025000 0.151491 1.000000 v 0.158000 0.025000 0.151491 1.000000 v 0.169743 0.025000 0.187631 1.000000 v 0.146257 0.025000 0.187631 1.000000 v 0.127257 0.025000 0.173826 1.000000 vn 0.950370 0.038015 0.308791 vn 0.950370 0.038015 0.308791 vn 0.950370 0.038015 0.308791 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 -0.000000 vn 0.587380 0.038015 0.808418 f 1//1 2//2 3//3 f 4//4 3//5 2//6 f 1//7 5//8 2//9 f 4//10 2//11 5//12 f 1//13 6//14 5//15 f 4//16 5//17 6//18 f 1//19 7//20 6//21
// Get the number of vertices obj_file >> md->vertices; // Get the number of faces obj_file >> md->faces;
再次阅读规范 。 这不是OBJ的工作方式。 你一直在parsing出顶点/纹理坐标/法线/面。
尝试这样的事情:
// g++ main.cpp -o main -lglut -lGL -lGLU && ./main #include <GL/glut.h> #include <glm/glm.hpp> #include <glm/gtx/component_wise.hpp> #include <vector> #include <fstream> #include <sstream> using namespace std; using namespace glm; struct Vertex { vec3 position; vec2 texcoord; vec3 normal; }; struct VertRef { VertRef( int v, int vt, int vn ) : v(v), vt(vt), vn(vn) { } int v, vt, vn; }; vector< Vertex > LoadOBJ( istream& in ) { vector< Vertex > verts; vector< vec4 > positions( 1, vec4( 0, 0, 0, 0 ) ); vector< vec3 > texcoords( 1, vec3( 0, 0, 0 ) ); vector< vec3 > normals( 1, vec3( 0, 0, 0 ) ); string lineStr; while( getline( in, lineStr ) ) { istringstream lineSS( lineStr ); string lineType; lineSS >> lineType; // vertex if( lineType == "v" ) { float x = 0, y = 0, z = 0, w = 1; lineSS >> x >> y >> z >> w; positions.push_back( vec4( x, y, z, w ) ); } // texture if( lineType == "vt" ) { float u = 0, v = 0, w = 0; lineSS >> u >> v >> w; texcoords.push_back( vec3( u, v, w ) ); } // normal if( lineType == "vn" ) { float i = 0, j = 0, k = 0; lineSS >> i >> j >> k; normals.push_back( normalize( vec3( i, j, k ) ) ); } // polygon if( lineType == "f" ) { vector< VertRef > refs; string refStr; while( lineSS >> refStr ) { istringstream ref( refStr ); string vStr, vtStr, vnStr; getline( ref, vStr, '/' ); getline( ref, vtStr, '/' ); getline( ref, vnStr, '/' ); int v = atoi( vStr.c_str() ); int vt = atoi( vtStr.c_str() ); int vn = atoi( vnStr.c_str() ); v = ( v >= 0 ? v : positions.size() + v ); vt = ( vt >= 0 ? vt : texcoords.size() + vt ); vn = ( vn >= 0 ? vn : normals.size() + vn ); refs.push_back( VertRef( v, vt, vn ) ); } if( refs.size() < 3 ) { // error, skip continue; } // triangulate, assuming n>3-gons are convex and coplanar VertRef* p[3] = { &refs[0], NULL, NULL }; for( size_t i = 1; i+1 < refs.size(); ++i ) { p[1] = &refs[i+0]; p[2] = &refs[i+1]; // http://www.opengl.org/wiki/Calculating_a_Surface_Normal vec3 U( positions[ p[1]->v ] - positions[ p[0]->v ] ); vec3 V( positions[ p[2]->v ] - positions[ p[0]->v ] ); vec3 faceNormal = normalize( cross( U, V ) ); for( size_t j = 0; j < 3; ++j ) { Vertex vert; vert.position = vec3( positions[ p[j]->v ] ); vert.texcoord = vec2( texcoords[ p[j]->vt ] ); vert.normal = ( p[j]->vn != 0 ? normals[ p[j]->vn ] : faceNormal ); verts.push_back( vert ); } } } } return verts; } int btn; ivec2 startMouse; ivec2 startRot, curRot; ivec2 startTrans, curTrans; void mouse(int button, int state, int x, int y ) { if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) { btn = button; startMouse = ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y ); startRot = curRot; } if( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN ) { btn = button; startMouse = ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y ); startTrans = curTrans; } } void motion( int x, int y ) { ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y ); if( btn == GLUT_LEFT_BUTTON ) { curRot = startRot + ( curMouse - startMouse ); } else if( btn == GLUT_RIGHT_BUTTON ) { curTrans = startTrans + ( curMouse - startMouse ); } glutPostRedisplay(); } vector< Vertex > model; void display() { glClearColor( 0.2f, 0.2f, 0.2f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); double w = glutGet( GLUT_WINDOW_WIDTH ); double h = glutGet( GLUT_WINDOW_HEIGHT ); double ar = w / h; glTranslatef( curTrans.x / w * 2, curTrans.y / h * 2, 0 ); gluPerspective( 60, ar, 0.1, 100 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0, 0, -10 ); glPushMatrix(); { glRotatef( curRot.x % 360, 0, 1, 0 ); glRotatef( -curRot.y % 360, 1, 0, 0 ); // object glColor3ub( 255, 0, 0 ); glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position ); glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), &model[0].texcoord ); glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal ); glDrawArrays( GL_TRIANGLES, 0, model.size() ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); // bounding cube glDisable( GL_LIGHTING ); glColor3ub( 255, 255, 255 ); glutWireCube( 7 ); glEnable( GL_LIGHTING ); } glPopMatrix(); glutSwapBuffers(); } // return the min/max points of pts template< typename Vec > pair< Vec, Vec > GetExtents( const Vec* pts, size_t stride, size_t count ) { unsigned char* base = (unsigned char*)pts; Vec pmin( *(Vec*)base ); Vec pmax( *(Vec*)base ); for( size_t i = 0; i < count; ++i, base += stride ) { const Vec& pt = *(Vec*)base; pmin = glm::min( pmin, pt ); pmax = glm::max( pmax, pt ); } return make_pair( pmin, pmax ); } // centers geometry around the origin // and scales it to fit in a size^3 box template< typename Vec > void CenterAndScale( Vec* pts, size_t stride, size_t count, const typename Vec::value_type& size ) { typedef typename Vec::value_type Scalar; // get min/max extents pair< Vec, Vec > exts = GetExtents( pts, stride, count ); // center and scale const Vec center = ( exts.first * Scalar( 0.5 ) ) + ( exts.second * Scalar( 0.5f ) ); const Scalar factor = size / glm::compMax( exts.second - exts.first ); unsigned char* base = (unsigned char*)pts; for( size_t i = 0; i < count; ++i, base += stride ) { Vec& pt = *(Vec*)base; pt = ( ( pt - center ) * factor ); } } int main( int argc, char **argv ) { ifstream ifile( "test.obj" ); model = LoadOBJ( ifile ); CenterAndScale( &model[0].position, sizeof( Vertex ), model.size(), 7 ); glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE ); glutInitWindowSize( 640, 480 ); glutCreateWindow( "OBJ" ); glutDisplayFunc( display ); glutMouseFunc( mouse ); glutMotionFunc( motion ); glEnable( GL_DEPTH_TEST ); // set up "headlamp"-like light glShadeModel( GL_SMOOTH ); glEnable( GL_COLOR_MATERIAL ); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ; glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); GLfloat position[] = { 0, 0, 1, 0 }; glLightfv( GL_LIGHT0, GL_POSITION, position ); glPolygonMode( GL_FRONT, GL_FILL ); glPolygonMode( GL_BACK, GL_LINE ); glutMainLoop(); return 0; }
LMB拖动旋转,RMB拖动“平底锅”。
并使用这个:
v 0.000000 2.000000 2.000000 v 0.000000 0.000000 2.000000 v 2.000000 0.000000 2.000000 v 2.000000 2.000000 2.000000 f -4 -3 -2 -1 v 2.000000 2.000000 0.000000 v 2.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000 v 0.000000 2.000000 0.000000 f -4 -3 -2 -1 v 2.000000 2.000000 2.000000 v 2.000000 0.000000 2.000000 v 2.000000 0.000000 0.000000 v 2.000000 2.000000 0.000000 f -4 -3 -2 -1 v 0.000000 2.000000 0.000000 v 0.000000 2.000000 2.000000 v 2.000000 2.000000 2.000000 v 2.000000 2.000000 0.000000 f -4 -3 -2 -1 v 0.000000 2.000000 0.000000 v 0.000000 0.000000 0.000000 v 0.000000 0.000000 2.000000 v 0.000000 2.000000 2.000000 f -4 -3 -2 -1 v 0.000000 0.000000 2.000000 v 0.000000 0.000000 0.000000 v 2.000000 0.000000 0.000000 v 2.000000 0.000000 2.000000 f -4 -3 -2 -1
或这个:
v 0.000000 2.000000 0.000000 v 0.000000 0.000000 0.000000 v 2.000000 0.000000 0.000000 v 2.000000 2.000000 0.000000 v 4.000000 0.000000 -1.255298 v 4.000000 2.000000 -1.255298 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.276597 0.000000 0.960986 vn 0.276597 0.000000 0.960986 vn 0.531611 0.000000 0.846988 vn 0.531611 0.000000 0.846988 # 6 vertices # 6 normals g all s 1 f 1//1 2//2 3//3 4//4 f 4//4 3//3 5//5 6//6 # 2 elements
为test.obj
。
glm.hpp
来自GLM库 。