Opengl obj对象加载器与纹理

时间:2013-05-12 22:18:46

标签: c++ opengl glut blender texture-mapping

我正在使用对象加载器来加载我从blender导出的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);    
}

来自blender的示例obj,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

1 个答案:

答案 0 :(得分:3)

您的OBJ加载程序甚至尝试解析MTL文件。

您必须自己添加MTL处理。

您可能只想支持map_Kd

Good luck