glDrawElements()绘制我的.obj模型错误

时间:2013-05-04 08:18:12

标签: c++ opengl glut

我在OpenGL中遇到“glDrawElements”函数问题。使用函数绘制模型时,我看到了工件:

postimg.org/image/wcbjnp93r/  (the image.)

我没有添加任何光线或纹理。

我用C ++编写了一个类:

//The obj-catcher.h
//Just ignore the Chinese in the code....
#include <gl\glut.h>
#include <gl\glaux.h>
#include"stdlib.h"
#include"string.h"
#include"cstdio"
#include"math.h"
#include"time.h"
#define MAX_LINE_LENGTH 1024 //å­ç¬¦ä¸²å¤å¶æ大é¿åº¦

AUX_RGBImageRec *LoadBMP(char *Filename)                // Loads A Bitmap Image
{
    FILE *File=NULL;                                    // File Handle

    if (!Filename)                                      // Make Sure A Filename Was Given
    {
        return NULL;                                    // If Not Return NULL
    }
    File=fopen(Filename,"r");                           // Check To See If The File Exists
    if (File)                                           // Does The File Exist?
    {
        fclose(File);                                   // Close The Handle
        return auxDIBImageLoad(Filename);               // Load The Bitmap And Return A Pointer
    }

    return NULL;                                        // If Load Failed Return NULL
}
int LoadGLTextures(int num,char *dir,unsigned int * texture)                    // Load Bitmaps And Convert To Textures å è½½çå¾ååªè½æ¯2çå¹
{
    int Status=FALSE;                                   // Status Indicator
    AUX_RGBImageRec *TextureImage[1];                   // Create Storage Space For The Texture
    memset(TextureImage,0,sizeof(TextureImage));        // Set The Pointer To NULL
    // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
    if (TextureImage[0]=LoadBMP(dir))
    {
        Status=TRUE;                                    // Set The Status To TRUE
        glGenTextures(1, &texture[num]);                // Create The Texture
        // Typical Texture Generation Using Data From The Bitmap
        glBindTexture(GL_TEXTURE_2D, texture[num]);
        glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    }
    if (TextureImage[0])                                    // If Texture Exists
    {
        if (TextureImage[0]->data)                          // If Texture Image Exists
            free(TextureImage[0]->data);                    // Free The Texture Image Memory
        free(TextureImage[0]);                              // Free The Image Structure
    }
    return Status;                                      // Return The Status
}
typedef struct vertex
{
    GLfloat pos[3];//ä¾æ¬¡æ¯x,y,z
}vertex;
typedef struct vertexnormals
{
    GLfloat io[3];
}vertexnormals;
typedef struct texturecoords
{
    GLfloat io[3];
}texturecoords;
typedef struct vertexindex
{
    unsigned int Vertex[3];
}vertexindex;
bool fco(FILE *file)
{
    if(fclose(file)!=0)
    {
        perror("fclose");
        exit(EXIT_FAILURE);
    }
    return true;
}
bool getSurface(char *src,vertexindex &vindex)//get surface
{
    if(src[0]!='f'||src[1]!=' ') return false;
    int i;
    int result=0;
    for(i=1;i==' ';i++);i++;
    for(;;i++)
    {
        if(src[i]==' ') break;
        if(src[i]=='/')
            break;
        else
        {
            result*=10;
            result+=src[i]-48;
        }
    }
    vindex.Vertex[0]=result-1;
    for(;;i++) if(src[i]==' ') break;
    for(;i==' ';i++);i++;
    result=0;
    for(;;i++)
    {
        if(src[i]==' ') break;
        if(src[i]=='/') break;
        else
        {
            result*=10;
            result+=src[i]-48;
        }
    }
    vindex.Vertex[1]=result-1;
    for(;;i++) if(src[i]==' ') break;
    for(;i==' ';i++);i++;
    result=0;
    for(;;i++)
    {
        if(src[i]==' '||src[i]=='\0'||src[i]=='\n') break;
        if(src[i]=='/')
            break;
        else
        {
            result*=10;
            result+=src[i]-48;
        }
    }
    vindex.Vertex[2]=result-1;
    return true;
}
bool getVertex(char *src,vertex &dir)//some shit in here|add:->the shit is done
{

    int i;
    bool flag[3];
    bool pc[3];
    double result=0;
    int db=0;
    bool floa;
    memset(flag,0,sizeof(flag));//æ¥åç¹åæ å®æ度å¤æ­
    memset(pc,0,sizeof(pc));//æ­£è´å¤æ­
    if(src[0]!='v'||src[1]!=' ')
        return false;
    else
    {
        floa=false;
        for(i=1;src[i+1]==' ';i++);i++;//æ¾å°vä¹å第ä¸ä¸ªæ°æ®ä½ç½®
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') return false;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[0]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[0]) result=-result; 
        dir.pos[0]=result; 
        for(;src[i+1]==' ';i++);i++;//æ¾å°ç¬¬ä¸ä¸ªæ°æ®ä¹å第äºä¸ªæ°æ®ä½ç½®
        floa=false;
        db=0;
        result=0;
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') return false;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[1]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[1]) result=-result; 
        dir.pos[1]=result; 
        for(;src[i+1]==' ';i++);i++;//æ¾å°ç¬¬ä¸ä¸ªæ°æ®ä¹å第äºä¸ªæ°æ®ä½ç½®
        floa=false;
        db=0;
        result=0;
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') break;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[2]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[2]) result=-result; 
        dir.pos[2]=result; 
        return true;
    }
}
bool getVertexNormals(char *src,vertexnormals &dir)
{
    int i;
    bool flag[2];
    bool pc[3];
    double result=0;
    int db=0;
    bool floa;
    memset(flag,0,sizeof(flag));
    memset(pc,0,sizeof(pc));
    if(!(src[0]=='v'&&src[1]=='n'&&src[2]==' '))
    {
        return false;
    }
    else
    {
        floa=false;
        for(i=1;src[i+1]==' ';i++);i++;//æ¾å°vä¹å第ä¸ä¸ªæ°æ®ä½ç½®
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') return false;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[0]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[0]) result=-result; 
        dir.io[0]=result; 
        for(;src[i+1]==' ';i++);i++;//æ¾å°ç¬¬ä¸ä¸ªæ°æ®ä¹å第äºä¸ªæ°æ®ä½ç½®
        floa=false;
        db=0;
        result=0;
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') return false;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[1]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[1]) result=-result; 
        dir.io[1]=result; 
        for(;src[i+1]==' ';i++);i++;//æ¾å°ç¬¬ä¸ä¸ªæ°æ®ä¹å第äºä¸ªæ°æ®ä½ç½®
        floa=false;
        db=0;
        result=0;
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') break;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[2]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[2]) result=-result; 
        dir.io[2]=result; 
        return true;
    }
}
bool getTextureCoords(char *src,texturecoords &dir)
{
    int i;
    bool flag[2];
    bool pc[3];
    double result=0;
    int db=0;
    bool floa;
    memset(flag,0,sizeof(flag));
    memset(pc,0,sizeof(pc));
    if(!(src[0]=='v'&&src[1]=='t'&&src[2]==' '))
    {
        return false;
    }
    else
    {
        floa=false;
        for(i=1;src[i+1]==' ';i++);i++;//æ¾å°vä¹å第ä¸ä¸ªæ°æ®ä½ç½®
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') return false;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[0]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[0]) result=-result; 
        dir.io[0]=result; 
        for(;src[i+1]==' ';i++);i++;//æ¾å°ç¬¬ä¸ä¸ªæ°æ®ä¹å第äºä¸ªæ°æ®ä½ç½®
        floa=false;
        db=0;
        result=0;
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') return false;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[1]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[1]) result=-result; 
        dir.io[1]=result; 
        for(;src[i+1]==' ';i++);i++;//æ¾å°ç¬¬ä¸ä¸ªæ°æ®ä¹å第äºä¸ªæ°æ®ä½ç½®
        floa=false;
        db=0;
        result=0;
        for(;;i++)
        {
            if(src[i]=='\n'||src[i]=='\0') break;
            if(src[i]==' ')
                break;
            if(src[i]=='-')
                pc[2]=true;
            if(src[i]<=57&&src[i]>=48)
            {
                if(!floa)
                {
                    result*=10;
                    result+=src[i]-48;
                }
                else
                {
                    result+=(src[i]-48)*pow(10.0,--db);
                }
            }
            else
            {
                if(src[i]=='.') floa=true;
            }
        }
        if(pc[2]) result=-result; 
        dir.io[2]=result; 
        return true;
    }
}
bool getdir(char * dir,char * tem)
{
    int i,m=strlen(tem),num=0,j;
    for(i=0;i<m;i++)
    {
        if(dir[i]=='\\')
            num++;
    }
    for(i=0,j=0;i<m;i++)
    {
        tem[i]=dir[i];
        if(dir[i]=='\\')
            j++;
        if(j==num)
            break;
    }
    tem[i+1]='\0';
    return true;
}
bool getmtl(char *src,FILE *fp,char * dir)
{
    int i,m=strlen(src),n;
    char  temp[100];
    if(m<6) return false;
    if(!(src[0]=='m'&&src[1]=='t'&&src[2]=='l'&&src[3]=='l'&&src[4]=='i'&&src[5]=='b'&&src[6]==' ')) return false;
    src[m-1]='\0';
    getdir(dir,temp);
    n=strlen(temp);
    for(i=n;i<m;i++)
        temp[i]=src[i-n+7];
    fp=fopen(temp,"r");
    if(fp==NULL)
    {
        perror(temp);
        return false;
    }
    else
        printf("导å¥æè´¨åºæå :%s\n",temp);
    return true;
}
class Container
{
public:
    Container(char *fp)//使ç¨æ¶å¿é¡»ä¿è¯obj中æ¯è¡åªæä¸æ¡æ令
    {
        int t1,t2;
        t1=clock();
        int cur=0;
        int i[8]={0,0,0,0,0,0,0,0};
        int vcur=0;
        int tcur=0;
        mtlfnum=0;
        VertexNumber=0;
        TriangleNumber=0;
        VertexNormals=0;
        TextureCoords=0;
        if((file=fopen(fp,"r"))==NULL)
        {
            perror(fp);
            exit(1);
        }
        printf("第ä¸æ¬¡éåæ件é¢å¤ç中...\n");
        while(fgets(buffer,MAX_LINE_LENGTH,file)!=NULL)
        {
            cur++;
            if(buffer[0]=='#')
                continue;
            if(buffer[0]=='m'&&buffer[1]=='t'&&buffer[2]=='l'&&buffer[3]=='l'&&buffer[4]=='i'&&buffer[5]=='b'&&buffer[6]==' ')//ç±äº&&符å·çç­è·¯æåºæ以ä¸ä¼éæ³è®¿é®åå­
                mtlfnum++;
            if(buffer[0]=='v'&&buffer[1]==' ')
                VertexNumber++;
            if(buffer[0]=='f')
                TriangleNumber++;
            if(buffer[0]=='v'&&buffer[1]=='n')
                VertexNormals++;
            if(buffer[0]=='v'&&buffer[1]=='t')
                TextureCoords++;
        }
        printf("第ä¸æ¬¡é¢å¤çå·²ç»æ\nåå¾ä¿¡æ¯:æè´¨åºæ°:%d 顶ç¹æ°ï¼%d é¢æ°:%d æ³çº¿æ°ï¼%d 纹çåæ æ°:%d\n",mtlfnum,VertexNumber,TriangleNumber,VertexNormals,TextureCoords);
        v=new vertex [VertexNumber];
        vn=new vertexnormals[VertexNormals];
        vt=new texturecoords[TextureCoords];
        vindex=new vertexindex[TriangleNumber];
        mtl=new FILE * [mtlfnum];
        fco(file);
        if((file=fopen(fp,"r"))==NULL)
        {
            perror(fp);
            exit(1);
        }
        cur=0;
        printf("æ­£å¨è¯»å¥æ¨¡åæ°æ®...\n");
        while(fgets(buffer,MAX_LINE_LENGTH,file)!=NULL)
        {
            cur++;
            if(i[0]<=VertexNumber)
                if(getVertex(buffer,v[i[0]]))
                    i[0]++;
            if(i[1]<=TriangleNumber)
                if(getSurface(buffer,vindex[i[1]]))
                    i[1]++;
            if(i[2]<=VertexNormals)
                if(getVertexNormals(buffer,vn[i[2]]))
                    i[2]++;
            if(i[3]<=TextureCoords)
                if(getTextureCoords(buffer,vt[i[3]]))
                    i[3]++;
            if(i[4]<=mtlfnum)
                if(getmtl(buffer,mtl[i[4]],fp))
                    i[4]++;
        }
        t2=clock();
        printf("读å¥æ¨¡åæåï¼\nç¨æ¶%5d(ms)\n",t2-t1);
    }
    ~Container()
    {
        fco(file);
        if(v)
        {
            delete(v);
            v=NULL;
        }
        if(vt)
        {
            delete(vt);
            vt=NULL;
        }
        if(vn)
        {
            delete(vn);
            vn=NULL;
        }
        if(mtl)
        {
            for(int i=0;i<mtlfnum;i++)
                fco(mtl[i]);
            delete mtl;
            mtl=NULL;
        }
    }
    inline int get_tnum(){return TriangleNumber;}
    inline int get_vnum(){return VertexNumber;}
    inline int get_vnnum(){return VertexNormals;}
    inline int get_vtnum(){return TextureCoords;}
    inline vertex *             get_v() {return v;      }
    inline vertexnormals*       get_vn(){return vn;     }
    inline texturecoords*       get_vt(){return vt;     }
    inline vertexindex*         get_vi(){return vindex; }
private:
    FILE *file;
    int VertexNumber;
    int TriangleNumber;
    int VertexNormals;
    int mtlfnum;
    int TextureCoords;
    char buffer[MAX_LINE_LENGTH];
    FILE **mtl;
    vertexindex *vindex;
    vertex *v;
    texturecoords *vt;
    vertexnormals *vn;
};

#include <Gl\glut.h>
#include <math.h>
#include"obj-catcher.h"
#include"stdlib.h"
Container A("models\\SCAR.obj");
#define GL_PI 3.1415926f
#define bCull 1
#define bDepth 1
#define bOutline 1
double xRot=0.0f,yRot=0.0f,x=0.0f,y=0.0f,dx=0.8f,dy=1.0f;
GLfloat nRange=50.0f;
static GLfloat aspe;
unsigned int te[37];
GLuint sample=1;
void SetupRC()
{
    glClearColor(0.0f,0.0f,0.0f,1.0f);
    glColor3f(0.0f,1.0f,0.0f);
    glShadeModel(GL_FLAT);//单调着色
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3,GL_FLOAT,0,(float *)A.get_v());
    glNewList(sample,GL_COMPILE);
        glDrawElements(GL_TRIANGLES,A.get_tnum()*3,GL_UNSIGNED_INT,A.get_vi());
    glEndList();
}
void ChangeSize(GLsizei w,GLsizei h)
{
    if(h==0)
        h=1;
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if(w<=h)
    {
        aspe=h/w;
        glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,-nRange,nRange);
    }
    else
    {
        aspe=w/h;
        glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,-nRange,nRange);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glutSwapBuffers();
}
void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0,1.0,1.0);
    glPushMatrix();
//  yRot++;
    if(yRot>360) yRot=0;
    glRotatef(xRot,1.0f,0.0f,0.0f);
    glRotatef(yRot,0.0f,1.0f,0.0f);
    glCallList(sample);
    glPopMatrix();
    glutSwapBuffers();  
}
void processSpecialKeys(int key,int x,int y)//键位控制
{
    if(key==GLUT_KEY_UP)
        xRot--;
    if(key==GLUT_KEY_DOWN)
        xRot++;
    if(key==GLUT_KEY_RIGHT)
        yRot++;
    if(key==GLUT_KEY_LEFT)
        yRot--;
    if(key==27)
        exit(1);
}
void TimerFunction(int value)
{
    glutPostRedisplay();
    glutTimerFunc(1,TimerFunction,1);
}
int main(int argc,char*argv[])
{
    glutInit( &argc , argv );
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
    glutInitWindowSize(400,400);
    glutCreateWindow("caption");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutSpecialFunc(processSpecialKeys);
    glutTimerFunc(1,TimerFunction,1);
    SetupRC();
    glutMainLoop();
    return 0;
}

你能给我一些解决问题的建议吗?

3 个答案:

答案 0 :(得分:1)

您是否在不使用显示列表的情况下尝试过它?

来自Microsoft的文档:

  

您可以在显示列表中包含glDrawElements函数。当glDrawElements包含在显示列表中时,必要的数组数据(由数组指针和启用确定)也会输入到显示列表中。因为数组指针和启用是客户端状态变量,所以它们的值会在创建列表时影响显示列表,而不是在执行列表时。

答案 1 :(得分:1)

看起来您的元素数据或顶点数据不正确或它们之间未对齐。如果没有正确指定顶点数据的步幅或偏移量,我会看到类似的问题。在这里发布一些关于如何在调用glDrawElements之前设置元素和顶点数组的代码。

提示:从小处开始,例如使用Quad或Cube,然后移动到复杂网格,然后添加纹理和光照。

答案 2 :(得分:0)

您的问题可能是索引顺序。当您从obj读取面部时,只需从每个索引中减去1,因为索引从1开始而不是从0开始。