I am still having major trouble with my openGL model program. The big issue is that I cannot figure out how to debug it since I am saving the important data to the graphics chip using vertex buffer objects (VBOs) so at least as far as I can tell, I cant read it. Also I am no computer so I cant interpolate the data. Anyways here is my code:
#ifdef LAB3DGLGUI_H
#ifndef GLMODELS_H
#define GLMODELS_H
#ifndef GOODGL
typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);
PFNGLGENBUFFERSARBPROC glGenBuffersD=(PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
PFNGLBINDBUFFERARBPROC glBindBufferD=(PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
PFNGLBUFFERDATAARBPROC glBufferDataD=(PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersD=(PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB");
#else
#include <gl/glext.h>
#endif
#include <stdio.h>
struct glVertexStructure
{
float vert[3];
float text[2];
float norm[3];
}NULLV;
/* Model File Format (.mdl)
4 bytes (int) -> numv
32*numv bytes (glVertexStructure)-> vars
-> 12 bytes (float[3]) -> vert
-> 8 bytes (float[2]) -> text
-> 12 bytes (float[3]) -> norm
*/
int HIGH_ID=0;
int COMPILED_ID=0;
class glModel
{
private:
int id;
unsigned int numv;
unsigned int model;
glVertexStructure *vars;
glModel &Compile();
public:
glModel():numv(0),model(0),vars(0),id(++HIGH_ID){}
glModel(const glModel&);
glModel(const char*);//Load from .mdl
~glModel()
{
if (numv>1)
delete[]vars;
else if (numv>0)
delete vars;
//Clean up VBOs??? Research needed!
}
glModel &operator=(const glModel&);
glModel &operator=(const char*);//Load from .mdl
glModel operator+(const glVertexStructure&)const;//Add Vertices
glModel operator+(const glModel&)const;
glModel &operator+=(const glVertexStructure&);//Append Vertices
glModel &operator+=(const glModel&);
glModel &Load(const char*);//Load from .mdl
glModel &Save(const char*);//Save to .mdl
glModel &Vertex(float tx, float ty, float x, float y, float z);
glModel &Draw();
glModel &Move(float x, float y, float z){glTranslatef(x,y,z);return *this;}
int len()const{return numv;}
glVertexStructure &operator[](int x)const{if (x<numv){return vars[x];}else{return NULLV;}}
};
glModel::glModel(const glModel &source)
{
numv=source.len();
vars=new glVertexStructure[numv];
for (int i=0; i<numv; i++)
{
vars[i]=source[i];
}
model=0;
id=++HIGH_ID;
}
glModel::glModel(const char *filename)
{
FILE *file=fopen(filename,"rb");
if (file)
{
fread(&numv, sizeof(numv), 1, file);
vars=new glVertexStructure[numv];
for (unsigned int i=0; i<numv; i++)
fread(&(vars[i].vert[0]), sizeof(float), 8, file);//I hope this works :P
}
fclose(file);
id=++HIGH_ID;
}
glModel &glModel::operator=(const glModel &source)
{
if (COMPILED_ID==id)
COMPILED_ID=0;
if (numv>0)
delete[]vars;
numv=source.len();
vars=new glVertexStructure[numv];
for (int i=0; i<numv; i++)
{
vars[i]=source[i];
}
model=0;//Must I clean up the old model?
return *this;
}
glModel &glModel::operator=(const char *filename)
{
if (COMPILED_ID==id)
COMPILED_ID=0;
if (numv>0)
delete[]vars;
FILE *file=fopen(filename,"rb");
if (file)
{
fread(&numv, sizeof(numv), 1, file);
vars=new glVertexStructure[numv];
for (unsigned int i=0; i<numv; i++)
fread(&(vars[i].vert[0]), sizeof(float), 8, file);//again I hope this works ><
}
fclose(file);
return *this;
}
glModel glModel::operator+(const glVertexStructure& add)const
{
if (COMPILED_ID==id)
COMPILED_ID=0;
glModel ret=*this;
ret+=add;
return ret;
}
glModel glModel::operator+(const glModel&add)const
{
if (COMPILED_ID==id)
COMPILED_ID=0;
glModel ret=*this;
ret+=add;
return ret;
}
glModel &glModel::operator+=(const glVertexStructure& add)
{
if (COMPILED_ID==id)
COMPILED_ID=0;
glVertexStructure *temp=new glVertexStructure[numv];
for (int i=0; i<numv; i++)
temp[i]=vars[i];
vars[numv]=add;
delete[]vars;
vars=temp;
numv++;
return *this;
}
glModel &glModel::operator+=(const glModel& add)
{
if (COMPILED_ID==id)
COMPILED_ID=0;
for (int i=0; i<add.len(); i++)
(*this)+=add[i];
return *this;
}
glModel &glModel::Load(const char *fname)
{
if (COMPILED_ID==id)
COMPILED_ID=0;
if (numv>1)
delete[]vars;
else if (numv>0)
delete vars;
FILE *file=fopen(fname,"rb");
if (file)
{
fread(&numv,sizeof(numv), 1, file);
vars=new glVertexStructure[numv];
for (unsigned int i=0; i<numv; i++)
fread(&(vars[i].vert[0]),sizeof(float), 8, file);
}
fclose(file);
return *this;
}
glModel &glModel::Save(const char *fname)
{
FILE *file=fopen(fname,"wb");
fwrite(&numv, sizeof(unsigned int), 1, file);
fwrite(vars, sizeof(float), numv, file);//Again.... I hope this works!!!
fclose(file);
return *this;
}
glModel &glModel::Vertex(float tx, float ty, float x, float y, float z)
{
if (COMPILED_ID==id)
COMPILED_ID=0;
glVertexStructure *temp=new glVertexStructure[numv+1];
for (int i=0; i<numv; i++)
temp[i]=vars[i];
delete[]vars;
vars=temp;
temp=NULL;
vars[numv].vert[0]=x;
vars[numv].vert[1]=y;
vars[numv].vert[2]=z;
vars[numv].text[0]=tx;
vars[numv].text[1]=ty;
vars[numv].norm[0]=0.0;
vars[numv].norm[1]=0.0;
vars[numv].norm[2]=0.0;
numv++;
if (numv%3==0)
{
float &zz0=vars[numv-3].vert[2];
float &zz1=vars[numv-2].vert[2];
float &zz2=vars[numv-1].vert[2];
float &yy0=vars[numv-3].vert[1];
float &yy1=vars[numv-2].vert[1];
float &yy2=vars[numv-1].vert[1];
float &xx0=vars[numv-3].vert[0];
float &xx1=vars[numv-2].vert[0];
float &xx2=vars[numv-1].vert[0];
float ox=(yy1-yy0)*(zz2-zz0)-(zz1-zz0)*(yy2-yy0);
float oy=(zz1-zz0)*(xx2-xx0)-(xx1-xx0)*(zz2-zz0);
float oz=(xx1-xx0)*(yy2-yy0)-(yy1-yy0)*(xx2-xx0);
float mag=sqrt(ox*ox+oy*oy+oz*oz);
ox/=mag;
oy/=mag;
oz/=mag;
vars[numv-1].norm[0]=vars[numv-2].norm[0]=vars[numv-3].norm[0]=ox;
vars[numv-1].norm[1]=vars[numv-2].norm[1]=vars[numv-3].norm[1]=oy;
vars[numv-1].norm[2]=vars[numv-2].norm[2]=vars[numv-3].norm[2]=oz;
}
return *this;
}
glModel &glModel::Compile()
{
#ifndef GOODGL
glGenBuffersD(1,&model);//1st sigseg here
glBindBufferD(GL_ARRAY_BUFFER, model);
glBufferDataD(GL_ARRAY_BUFFER, numv*sizeof(glVertexStructure), vars, GL_STATIC_DRAW);
#else
glGenBuffers(1,&model);
glBindBuffer(GL_ARRAY_BUFFER,model);
glBufferData(GL_ARRAY_BUFFER, numv*sizeof(glVertexStructure), vars, GL_STATIC_DRAW);
#endif
COMPILED_ID=id;
return *this;
}
glModel &glModel::Draw()
{
if (COMPILED_ID!=id){Compile();}//1st sigseg comes from here
int numt=numv-numv%3;
if (numt==0)
return *this;
#ifndef GOODGL
glBindBufferD(GL_ARRAY_BUFFER,model);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(glVertexStructure),0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,sizeof(glVertexStructure),(void*)((char*)(NULL)+sizeof(float)*(&(vars[0].text[0])-&(vars[0].vert[0]))));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT,sizeof(glVertexStructure),(void*)((char*)(NULL)+sizeof(float)*(&(vars[0].norm[0])-&(vars[0].vert[0]))));
glDrawArrays(GL_TRIANGLES, 0, numt);
#else
glBindBuffer(GL_ARRAY_BUFFER,model);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(glVertexStructure),0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,sizeof(glVertexStructure),(void*)((char*)(NULL)+sizeof(float)*(&(vars[0].text[0])-&(vars[0].vert[0]))));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT,sizeof(glVertexStructure),(void*)((char*)(NULL)+sizeof(float)*(&(vars[0].norm[0])-&(vars[0].vert[0]))));
glDrawArrays(GL_TRIANGLES, 0, numt);
#endif
return *this;
}
#endif
#endif
This works in tandem with a header that sets up OpenGL. My test case that sigsegs is here:
#include "3dglgui.h"
int main()
{
GL.Init("TEST",500,500,24,false,0,0);
glModel model;
model.Vertex(0,0,0,0,0);
model.Vertex(1,1,1,1,1);
model.Vertex(1,0,1,1,0);
model.Draw();
do{
GL.Update();
}while(!GL.window.key[VK_ESCAPE]);
return 0;
}
GL.Init refers to this function in my OpenGL set up header:
OpenGLInstance &OpenGLInstance::Init(const char *title, int width, int height, int bpp, bool fullscreen, int posx, int posy)
{
DEVMODE tmp;
EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&tmp);
window.fps=tmp.dmDisplayFrequency;
unsigned int PixelFormat;
DWORD dwExStyle,dwStyle;
RECT WindowRect={(long)0,(long)0,(long)width,(long)height};
window.fullscreen=fullscreen;
hInstance=GetModuleHandle(NULL);
WNDCLASS wc={CS_HREDRAW|CS_VREDRAW|CS_OWNDC,(WNDPROC)WndProc,0,0,hInstance,LoadIcon(NULL,IDI_WINLOGO),LoadCursor(NULL,IDC_ARROW),NULL,NULL,CLASS_NAME};
(!RegisterClass(&wc))?ERRORCODE|=ERR_CLASS_REGISTRY_FAILED:ERRORCODE=ERRORCODE;
if (fullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth=width;
dmScreenSettings.dmPelsHeight=height;
dmScreenSettings.dmBitsPerPel=bpp;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSHEIGHT|DM_PELSWIDTH;
(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)?ERRORCODE|=ERR_FULLSCREEN_FAILED:ERRORCODE=ERRORCODE;
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP;
ShowCursor(false);
}
else
{
dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&WindowRect,dwStyle,false,dwExStyle);
if (!(hWnd=CreateWindowEx(dwExStyle,CLASS_NAME,title,WS_CLIPSIBLINGS|WS_CLIPCHILDREN|dwStyle,posx,posy,WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top,NULL,NULL,hInstance,NULL)))
{
Kill();
ERRORCODE|=ERR_WINDOW_CREATION_FAILED;
}
static PIXELFORMATDESCRIPTOR pfd={sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,PFD_TYPE_RGBA,bpp,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,PFD_MAIN_PLANE,0,0,0,0};
if (!(hDC=GetDC(hWnd)))
{
Kill();
ERRORCODE|=ERR_GET_DC_FAILED;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
{
Kill();
ERRORCODE|=ERR_PIXEL_FORMAT_CHOICE_FAILED;
}
if (!SetPixelFormat(hDC,PixelFormat,&pfd))
{
Kill();
ERRORCODE|=ERR_NO_VALID_PIXEL_FORMAT;
}
if (!wglMakeCurrent(hDC,hRC))
{
Kill();
ERRORCODE|=ERR_MAKE_CURRENT_FAILED;
}
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
Resize(width,height);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_COLOR_MATERIAL);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
quadricobject=gluNewQuadric();
gluQuadricNormals(quadricobject,GLU_SMOOTH);
gluQuadricTexture(quadricobject,GL_TRUE);
return *this;
}