我在OpenGL中遇到“glDrawElements”函数问题。使用函数绘制模型时,我看到了工件:
我没有添加任何光线或纹理。
我用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;
}
你能给我一些解决问题的建议吗?
答案 0 :(得分:1)
您是否在不使用显示列表的情况下尝试过它?
来自Microsoft的文档:
您可以在显示列表中包含glDrawElements函数。当glDrawElements包含在显示列表中时,必要的数组数据(由数组指针和启用确定)也会输入到显示列表中。因为数组指针和启用是客户端状态变量,所以它们的值会在创建列表时影响显示列表,而不是在执行列表时。
答案 1 :(得分:1)
看起来您的元素数据或顶点数据不正确或它们之间未对齐。如果没有正确指定顶点数据的步幅或偏移量,我会看到类似的问题。在这里发布一些关于如何在调用glDrawElements之前设置元素和顶点数组的代码。
提示:从小处开始,例如使用Quad或Cube,然后移动到复杂网格,然后添加纹理和光照。
答案 2 :(得分:0)
您的问题可能是索引顺序。当您从obj
读取面部时,只需从每个索引中减去1,因为索引从1开始而不是从0开始。