2013-05-12 213 views
1

我正在使用對象加載器來加載我從攪拌器中導出的obj模型。我可以加載模型,但沒有紋理加載,我不知道爲什麼。當我在主類中渲染模型時應該加載它們還是需要加載紋理以及渲染模型?Opengl obj物體加載器與紋理

objloader.cpp

/************************************************************ 
*Loads obj file - limited to vertices, faces, normals, texture maps 
*loads to object structure as defined in .h file 
************************************************************/ 

#include <stdio.h> 
#include <iostream> 
#include <io.h> 
#include <stdlib.h> 
#include "glut.h" 

#include "objloader.h" 

using namespace std; 

void object_type::render() 
{ 
    glBegin(GL_TRIANGLES); // glBegin and glEnd delimit the vertices that define a primitive (in our case triangles) 

    for (int j=0;j<polygons_qty;j++) 
    { 
     //----------------- FIRST VERTEX ----------------- 
     //Normal coordinates of the first vertex 
     glNormal3f(normcoord[ polygon[j].n[0] - 1 ].i, 
       normcoord[ polygon[j].n[0] - 1 ].j, 
       normcoord[ polygon[j].n[0] - 1 ].k); 
     // Texture coordinates of the first vertex 
      glTexCoord2f(mapcoord[ polygon[j].t[0] - 1 ].u, 
        mapcoord[ polygon[j].t[0] - 1 ].v); 
     // Coordinates of the first vertex 
     glVertex3f(vertex[ polygon[j].v[0] - 1].x, 
       vertex[ polygon[j].v[0] - 1].y, 
       vertex[ polygon[j].v[0] - 1].z); 

     //----------------- SECOND VERTEX ----------------- 
     //Normal coordinates of the first vertex 
     glNormal3f(normcoord[ polygon[j].n[1] - 1 ].i, 
       normcoord[ polygon[j].n[1] - 1 ].j, 
       normcoord[ polygon[j].n[1] - 1 ].k); 
     // Texture coordinates of the first vertex 
     glTexCoord2f(mapcoord[ polygon[j].t[1] - 1 ].u, 
        mapcoord[ polygon[j].t[1] - 1 ].v); 
     // Coordinates of the first vertex 
     glVertex3f(vertex[ polygon[j].v[1] - 1].x, 
       vertex[ polygon[j].v[1] - 1].y, 
       vertex[ polygon[j].v[1] - 1].z); 

     //----------------- THIRD VERTEX ----------------- 
     //Normal coordinates of the first vertex 
     glNormal3f(normcoord[ polygon[j].n[2] - 1 ].i, 
       normcoord[ polygon[j].n[2] - 1 ].j, 
       normcoord[ polygon[j].n[2] - 1 ].k); 
     // Texture coordinates of the first vertex 
     glTexCoord2f(mapcoord[ polygon[j].t[2] - 1 ].u, 
        mapcoord[ polygon[j].t[2] - 1 ].v); 
     // Coordinates of the first vertex 
     glVertex3f(vertex[ polygon[j].v[2] - 1].x, 
       vertex[ polygon[j].v[2] - 1].y, 
       vertex[ polygon[j].v[2] - 1].z); 
    } 
    glEnd(); 
} 


/* 
vertex_type vertex[MAX_VERTICES]; 
mapcoord_type mapcoord[MAX_VERTICES]; 
normcoord_type normcoord[MAX_NORMALS]; 
polygon_type polygon[MAX_POLYGONS]; 
int id_texture 
*/ 


int object_type::objdatadisplay() 
{ 
    int i; 
    printf("VERTICES: %d\n",vertices_qty); 
for (i =0;i<vertices_qty;i++) 
{ 
    printf("%f %f %f\n",vertex[i].x,vertex[i].y,vertex[i].z); 
} 

    printf("NORMALS: %d\n",normcoord_qty); 
for (i =0;i<normcoord_qty;i++) 
{ 
    printf("%f %f %f\n",normcoord[i].i,normcoord[i].j,normcoord[i].k); 
} 
    printf("MAP COORDS: %d\n",mapcoord_qty); 
for (i =0;i<mapcoord_qty;i++) 
{ 
    printf("%f %f\n",mapcoord[i].u,mapcoord[i].v); 
} 
    printf("POLYGONS: %d\n",polygons_qty); 
for (i=0;i<polygons_qty;i++) //for each vertex of polygon (triangle) 
{ 
    for (int j = 0;j<3;j++) 
    { 
      printf("%d::%d/%d/%d\n",i,polygon[i].v[j],polygon[i].t[j],polygon[i].n[j]); 
    } 
} 
return 1; 
} 


int object_type::objloader(char *p_filename) 
{ 
    int ivertex=0; //Index variable 
    int inormal =0; 
    int ipolygon=0; 
    int imap=0; 
    char string[256]; 
FILE *l_file; //File pointer 

char l_char; //Char variable 

unsigned short l_face_flags; //Flag that stores some face information 

if ((l_file=fopen (p_filename, "rt"))== NULL) return 0; //Open the file 


while (!feof(l_file)) //Loop to scan the whole file 
{ 
    fscanf(l_file,"%c",&l_char); 
    if(l_char=='\n')//read char if'/n' -skip to next and read 
     fscanf(l_file,"%c",&l_char); 
    switch (l_char) //parse 
    { 
    default: fgets(string,256,l_file); 
     break; 
    case 'v': //a vertex or a normal or a text co-ord 
     fscanf(l_file,"%c",&l_char); 
     switch (l_char) 
     { 
     case ' ': //a vertex -expect and so read 3 floats next 
       fscanf(l_file,"%f %f %f",&vertex[ivertex].x, &vertex[ivertex].y,&vertex[ivertex].z); 


       ivertex++; 
       break; 
     case 'n': //a normal -expect and so read 3 floats next 
       fscanf(l_file,"%f %f %f",&normcoord[inormal].i, &normcoord[inormal].j,&normcoord[inormal].k); 
       inormal++; 
       break; 
     case 't': //a texture map coord-expect and so read 2 floats next 
       fscanf(l_file,"%f %f",&mapcoord[imap].u, &mapcoord[imap].v); 
       imap++; 
       break; 
     } //end switch 
     break; 
    case 'f': //a face read next assume format is -> f 1/1/1 2/2/2 3/3/3 
     for (int i=0;i<3;i++) //for each vertex of polygon (triangle) 
     { 
      fscanf(l_file,"%c",&l_char); //read space char - ignore this 
      fscanf(l_file,"%d",&polygon[ipolygon].v[i]); //read vertex. 
      fscanf(l_file,"%c",&l_char); //read space char - ignore this 
      fscanf(l_file,"%d",&polygon[ipolygon].t[i]); //read text coord. 
      fscanf(l_file,"%c",&l_char); //read space char - ignore this 
      fscanf(l_file,"%d",&polygon[ipolygon].n[i]); //read normal. 
     } 
     ipolygon++; 
     break; 

    } //end switch 
} 

fclose (l_file); // Closes the file stream 
vertices_qty = ivertex; 
polygons_qty = ipolygon; 
mapcoord_qty = imap; 
normcoord_qty = inormal; 

return 1; //if successful  
} 

objloader.h

#ifndef OBJLOAD 
#define OBJLOAD 

/************************************************ 
*Loads obj file - limited to vertices, faces, normals, texture maps 
*loads to object structure as defined in .h file 
****************************************************/ 


#define MAX_VERTICES 8000 // Max number of vertices (for each object) 
#define MAX_POLYGONS 8000 // Max number of polygons (for each object) 
#define MAX_NORMALS 8000 // Max number of polygons (for each object) 

// Our vertex type 
typedef struct{ 
float x,y,z; 
}vertex_type; 

// Our normal type 
typedef struct{ 
float i,j,k; 
}normcoord_type; 

// The polygon (triangle), 3 numbers that aim 3 vertices 
typedef struct{ 
int v[3],t[3],n[3]; 
}polygon_type; 

// The mapcoord type, 2 texture coordinates for each vertex 
typedef struct{ 
float u,v; 
}mapcoord_type; 

// The object type 
class object_type{ 
public: 
int id_texture; 
object_type(){} 
~object_type(){} 
int objloader(char *p_filename); 
int objdatadisplay(); 
void render(); 

private: 
char name[20]; 
int vertices_qty; 
int polygons_qty; 
int mapcoord_qty; 
int normcoord_qty; 

vertex_type vertex[MAX_VERTICES]; 
mapcoord_type mapcoord[MAX_VERTICES]; 
normcoord_type normcoord[MAX_NORMALS]; 
polygon_type polygon[MAX_POLYGONS]; 

}; 
#endif 

的main.cpp

#include "objloader.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <GL/glew.h> 

#ifdef __WIN32__ 
#include <windows.h> 
#endif 

#include "glut.h" //glut has all ogl relevant .h files included 

int screen_width=800; 
int screen_height=600; 

//angle of rotation 
float xpos = 0, ypos = 0, zpos = 0, xrot = 0, yrot = 0, angle=0.0; 

float cRadius = 10.0f; // our radius distance from our character 

float lastx, lasty; 

object_type *objarray[2]; //objects container for our world. Used throughout so global 

//Lights settings 
GLfloat light_ambient[]= { 0.1f, 0.1f, 0.1f, 0.1f }; 
GLfloat light_diffuse[]= { 1.0f, 1.0f, 1.0f, 0.0f }; 
GLfloat light_specular[]= { 1.0f, 1.0f, 1.0f, 0.0f }; 
GLfloat light_position[]= { 100.0f, 0.0f, -10.0f, 1.0f }; 

//Materials settings 
GLfloat mat_ambient[]= { 0.5f, 0.5f, 0.0f, 0.0f }; 
GLfloat mat_diffuse[]= { 0.5f, 0.5f, 0.0f, 0.0f }; 
GLfloat mat_specular[]= { 1.0f, 1.0f, 1.0f, 0.0f }; 
GLfloat mat_shininess[]= { 1.0f }; 


/************************************ 
* 
* SUBROUTINE init(void) 
* 
* Used to initialize OpenGL and to setup our world 
* 
************************************/ 

void init(void) 
{ 
    glClearColor(0.0, 0.0, 0.0, 0.0); // Clear background color to black 

    // Viewport transformation 
    glViewport(0,0,screen_width,screen_height); 

    // Projection transformation 
    glMatrixMode(GL_PROJECTION); // Specifies which matrix stack is the target for matrix operations 
    glLoadIdentity(); // We initialize the projection matrix as identity 
    gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,5.0f,10000.0f);  


//Lights initialization and activation 
    glLightfv (GL_LIGHT1, GL_AMBIENT, light_ambient); 
    glLightfv (GL_LIGHT1, GL_DIFFUSE, light_diffuse); 
    glLightfv (GL_LIGHT1, GL_DIFFUSE, light_specular); 
    glLightfv (GL_LIGHT1, GL_POSITION, light_position);  
    glEnable (GL_LIGHT1); 
    glEnable (GL_LIGHTING); 

    //Materials initialization and activation 
glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient); 
    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse); 
    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_specular); 
    glMaterialfv (GL_FRONT, GL_POSITION, mat_shininess);  

//Other initializations 
    glShadeModel(GL_SMOOTH); // Type of shading for the polygons 
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Texture mapping perspective correction 
    glEnable(GL_TEXTURE_2D); // Texture mapping ON 
    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Polygon rasterization mode (polygon filled) 
glEnable(GL_CULL_FACE); // Enable the back face culling 
    glEnable(GL_DEPTH_TEST); // Enable the depth test 

glTranslatef(0.0f, 0.0f, -cRadius); 
    glRotatef(xrot,1.0,0.0,0.0); 

angle++; //increase the angle 

for (int i=0;i<2;i++) 
{ 
printf("*************\n"); 
    objarray[i] = new (object_type); 
    objarray[i]->objloader("C:/3dModels/Museum.obj"); 
    objarray[i]->objdatadisplay();  
} 

} 


/********************************************************** 
* 
* SUBROUTINE resize(int p_width, int p_height) 
* 
* This routine must be called everytime we resize our window. 
* 
* Input parameters: p_width = width in pixels of our viewport 
*     p_height = height in pixels of our viewport 
* 
*********************************************************/ 

void resize (int p_width, int p_height) 
{ 
if (screen_width==0 && screen_height==0) exit(0); 
    screen_width=p_width; // We obtain the new screen width values and store it 
    screen_height=p_height; // Height value 

    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We clear both the color and the depth buffer so to draw the next frame 
    glViewport(0,0,screen_width,screen_height); // Viewport transformation 

    glMatrixMode(GL_PROJECTION); // Projection transformation 
    glLoadIdentity(); // We initialize the projection matrix as identity 
    gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,5.0f,10000.0f); 

    glutPostRedisplay(); // This command redraw the scene (it calls the same routine of glutDisplayFunc) 
} 

/********************************************************** 
* 
* SUBROUTINE keyboard(void) 
* 
* Subroutine to handle keyboard input 
* 
*********************************************************/ 


void keyboard (unsigned char key, int x, int y) { 
    if (key=='q') 
    { 
    xrot += 1; 
    if (xrot >360) xrot -= 360; 
    } 

    if (key=='z') 
    { 
    xrot -= 1; 

if (xrot < -360) xrot += 360; 
    } 

    if (key=='w') 
    { 
    float xrotrad, yrotrad; 
    yrotrad = (yrot/180 * 3.141592654f); 
    xrotrad = (xrot/180 * 3.141592654f); 
    xpos += float(sin(yrotrad)); 
    zpos -= float(cos(yrotrad)); 
    ypos -= float(sin(xrotrad)); 
    } 

    if (key=='s') 
    { 
    float xrotrad, yrotrad; 
    yrotrad = (yrot/180 * 3.141592654f); 
    xrotrad = (xrot/180 * 3.141592654f); 
    xpos -= float(sin(yrotrad)); 
    zpos += float(cos(yrotrad)); 
    ypos += float(sin(xrotrad)); 
    } 

    if (key=='d') 
    { 
    float yrotrad; 
    yrotrad = (yrot/180 * 3.141592654f); 
    xpos += float(cos(yrotrad)) * 0.2; 
    zpos += float(sin(yrotrad)) * 0.2; 
    } 

    if (key=='a') 
    { 
    float yrotrad; 
    yrotrad = (yrot/180 * 3.141592654f); 
    xpos -= float(cos(yrotrad)) * 0.2; 
    zpos -= float(sin(yrotrad)) * 0.2; 
    } 

    if (key==27) 
    { 
    exit(0); 
    } 
} 

/********************************************************** 
* 
* SUBROUTINE mouseMovement(void) 
* 
* Subroutine to handle mouse input 
* 
*********************************************************/ 

void mouseMovement(int x, int y) { 
int diffx=x-lastx; //check the difference between the current x and the last x position 
int diffy=y-lasty; //check the difference between the current y and the last y position 
lastx=x; //set lastx to the current x position 
lasty=y; //set lasty to the current y position 
xrot += (float) diffy; //set the xrot to xrot with the addition of the difference in the y position 
yrot += (float) diffx; //set the xrot to yrot with the addition of the difference in the x position 
} 


/********************************************************** 
* 
* SUBROUTINE display(void) 
* 
* This is our main rendering subroutine, called each frame 
* 
*********************************************************/ 

void display(void) 
{ 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // This clear the background color to dark blue 
    glMatrixMode(GL_MODELVIEW); // Modeling transformation 
    glPushMatrix(); 
glLoadIdentity(); // Initialize the model matrix as identity 

    glTranslatef(0.0f, 0.0f, -cRadius); // We move the object forward (the model matrix is multiplied by the translation matrix) 
    glRotatef(xrot,1.0,0.0,0.0); // Rotations of the object (the model matrix is multiplied by the rotation matrices) 

    glRotatef(yrot,0.0,1.0,0.0); 

glTranslated(-xpos,0.0f,-zpos); //translate the screen to the position of our camera 


if (objarray[0]->id_texture!=-1) 
{ 
    glBindTexture(GL_TEXTURE_2D, objarray[0]->id_texture); // We set the active texture 
    glEnable(GL_TEXTURE_2D); // Texture mapping ON 
    printf("Txt map ON"); 
} 
else 
    glDisable(GL_TEXTURE_2D); // Texture mapping OFF 


objarray[0]->render(); 
glPopMatrix(); 
glPushMatrix(); 
glTranslatef(5.0,0.0,-20.0); 
glFlush(); // This force the execution of OpenGL commands 
glutSwapBuffers(); // In double buffered mode we invert the positions of the visible buffer and the writing buffer 
} 



/********************************************************** 
* 
* The main routine 
* 
*********************************************************/ 


int main(int argc, char **argv) 
{ 
    // We use the GLUT utility to initialize the window, to handle the input and to interact with the windows system 
    glutInit(&argc, argv);  
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowSize(screen_width,screen_height); 
    glutInitWindowPosition(0,0); 
    glutCreateWindow("Demo 1: To exit press ESC");  
    glutDisplayFunc(display); 
    glutIdleFunc(display); 
    glutReshapeFunc (resize); 

glutPassiveMotionFunc(mouseMovement); //check for mouse movement 
glutKeyboardFunc (keyboard); 

init(); 
    glutMainLoop(); 

    return(0);  
} 

實施例物鏡從攪拌器,cube.obj:

# Blender v2.66 (sub 1) OBJ File: 'cube.blend' 
# www.blender.org 
mtllib cube.mtl 
g Cube 
v 1.000000 0.665869 -1.000000 
v 1.000000 0.665869 1.000000 
v -1.000000 0.665869 1.000000 
v -1.000000 0.665869 -1.000000 
v 1.000000 2.665869 -0.999999 
v 0.999999 2.665869 1.000001 
v -1.000000 2.665869 1.000000 
v -1.000000 2.665869 -1.000000 
vt 0.000000 0.334353 
vt 0.332314 0.333333 
vt 0.333333 0.665647 
vt 1.000000 0.001019 
vt 0.998981 0.333333 
vt 0.666667 0.332314 
vt 1.000000 0.665647 
vt 0.667686 0.666667 
vt 0.334353 0.666667 
vt 0.333333 0.334353 
vt 0.666667 0.665647 
vt 0.333333 0.332314 
vt 0.001020 0.333333 
vt 0.332314 0.000000 
vt 0.333333 0.001019 
vt 0.665647 0.000000 
vt 0.001019 0.666667 
vt 0.667686 0.000000 
vt 0.666667 0.334353 
vt 0.665647 0.333333 
vt 0.000000 0.001020 
vt 0.334353 0.333333 
vn 0.000000 -1.000000 0.000000 
vn -0.000000 1.000000 0.000000 
vn 1.000000 -0.000000 0.000001 
vn -0.000000 -0.000000 1.000000 
vn -1.000000 -0.000000 -0.000000 
vn 0.000000 0.000000 -1.000000 
vn 1.000000 0.000000 -0.000000 
usemtl Material 
s off 
f 1/1/1 2/2/1 3/3/1 
f 5/4/2 8/5/2 7/6/2 
f 1/5/3 5/7/3 6/8/3 
f 2/9/4 6/10/4 3/11/4 
f 3/12/5 7/13/5 4/14/5 
f 5/15/6 1/16/6 4/6/6 
f 4/17/1 1/1/1 3/3/1 
f 6/18/2 5/4/2 7/6/2 
f 2/19/7 1/5/7 6/8/7 
f 6/10/4 7/20/4 3/11/4 
f 7/13/5 8/21/5 4/14/5 
f 8/22/6 5/15/6 4/6/6 
+0

你的MTL解析器在哪裏?爲什麼你沒有任何'glTexImage2D()'調用? – genpfault 2013-05-13 13:51:38

+0

嗨,感謝您的回覆。我從來沒有使用過一個對象解析器,所以這對我來說都是新的。我只在一個星期內做了一點OpenGL編程。我以爲對象加載器也處理了mtl文件。 – 2013-05-13 20:36:02

回答

3

您的OBJ加載程序甚至沒有嘗試來解析MTL文件。

您必須自己添加MTL處理。您可能只想支持map_Kd

Good luck

+1

噢,我明白了。謝謝你的建議。我似乎在嘗試跑步,然後才能走到這裏。 – 2013-05-13 21:09:17