diff options
Diffstat (limited to 'pyramid.cpp')
-rw-r--r-- | pyramid.cpp | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/pyramid.cpp b/pyramid.cpp new file mode 100644 index 0000000..76bf89e --- /dev/null +++ b/pyramid.cpp @@ -0,0 +1,372 @@ +/* pyramid.cpp + * + */ + +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +/* for some reason order of the headers matters */ +#include "lib/gltools.h" +#include "lib/math3d.h" +#include "lib/glframe.h" +#include <sys/time.h> +#define FRAMES_PER_SECOND 300 + +static GLfloat xRot = 0.0f; +static GLfloat yRot = 0.0f; + +/* global camera used to walk in the scene */ +GLFrame frameCamera; + +static void resize(int w, int h) +{ + printf("window: resizing to %dx%d\n", w, h); + GLfloat fAspect = (GLfloat) w / (GLfloat) h; + if (h == 0) + h = 1; + glViewport(0, 0, w, h); + + /* reset coordinate system */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + /* produce the perspective projection */ + gluPerspective(40.0f, fAspect, 1.0, 40.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + /* this needs to be ran again, glut does it for you I suppose */ + SDL_SetVideoMode(w, h, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_RESIZABLE); +} + +static void SetupRC() +{ + GLbyte *pBytes; + GLint iWidth, iHeight, iComponents; + GLenum eFormat; + + /* light values and coordinates */ + GLfloat whiteLight[] = { 0.05f, 0.05f, 0.05f, 1.0f }; + GLfloat sourceLight[] = { 0.75f, 0.75f, 0.75f, 1.0f }; + GLfloat lightPos[] = { -10.f, 5.0f, 5.0f, 1.0f }; + + glEnable(GL_DEPTH_TEST); /* hidden surface removal */ + glFrontFace(GL_CCW); /* counter clock-wise polygons face out */ + glEnable(GL_CULL_FACE); /* do not calculate inside of a pyramid */ + + /* enable lighting */ + glEnable(GL_LIGHTING); + + /* setup and enable light 0 */ + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, whiteLight); + glLightfv(GL_LIGHT0, GL_AMBIENT, sourceLight); + glLightfv(GL_LIGHT0, GL_DIFFUSE, sourceLight); + glLightfv(GL_LIGHT0, GL_POSITION, lightPos); + glEnable(GL_LIGHT0); + + /* enable color tracking */ + glEnable(GL_COLOR_MATERIAL); + + /* set Material properties to follow glColor values */ + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + + /* gray background */ + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + + /* load texture */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + pBytes = gltLoadTGA("stone.tga", &iWidth, &iHeight, &iComponents, &eFormat); + if (!pBytes) + fprintf(stderr, "gltLoadTGA: failed to load texture!\n"); + + /* load texture image */ + glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, + GL_UNSIGNED_BYTE, pBytes); + free(pBytes); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glEnable(GL_TEXTURE_2D); +} + +static void keys(SDL_keysym *keysym, unsigned int *keys_held, int flag) +{ + if (!flag) + { + switch (keysym->sym) + { + case SDLK_ESCAPE: exit(0); break; + case SDLK_w: xRot -= 1.0f; break; + case SDLK_s: xRot += 1.0f; break; + case SDLK_a: yRot -= 1.0f; break; + case SDLK_d: yRot += 1.0f; break; + case SDLK_UP: frameCamera.MoveForward(0.1f); break; + case SDLK_DOWN: frameCamera.MoveForward(-0.1f); break; + case SDLK_LEFT: frameCamera.RotateLocalY(0.1f); break; + case SDLK_RIGHT: frameCamera.RotateLocalY(-0.1f); break; + default: break; + } + } + else + { + if (keys_held[SDLK_w]) + xRot -= 1.0f; + if (keys_held[SDLK_s]) + xRot += 1.0f; + if (keys_held[SDLK_a]) + yRot -= 1.0f; + if (keys_held[SDLK_d]) + yRot += 1.0f; + + if (keys_held[SDLK_UP]) + frameCamera.MoveForward(0.01f); + if (keys_held[SDLK_DOWN]) + frameCamera.MoveForward(-0.01f); + if (keys_held[SDLK_LEFT]) + frameCamera.RotateLocalY(0.01f); + if (keys_held[SDLK_RIGHT]) + frameCamera.RotateLocalY(-0.01f); + } + + xRot = (GLfloat) ((const int) xRot % 360); + yRot = (GLfloat) ((const int) yRot % 360); +} + +/* process SDL events */ +void processEvents() +{ + SDL_Event event; + unsigned static int keys_held[323]; + SDLKey sym; + /* helper flag for keys() */ + int flag = 0; + + while (SDL_PollEvent(&event)) + { + sym = event.key.keysym.sym; + + switch (event.type) + { + case SDL_KEYUP: + { + /* reset the key to 0 */ + keys_held[sym] = 0; + break; + } + case SDL_KEYDOWN: + { + keys_held[sym] = 1; + keys(&event.key.keysym, keys_held, flag); + break; + } + case SDL_VIDEORESIZE: { resize(event.resize.w, event.resize.h); break; } + case SDL_QUIT: { printf("status: exiting...\n"); exit(0); break; } + default: break; + } + } + + /* XXX below code has the be below of the above */ + /* check for keys that are being constantly pressed */ + if (keys_held[SDLK_w] || keys_held[SDLK_s] || keys_held[SDLK_a] || keys_held[SDLK_d] || + keys_held[SDLK_UP] || keys_held[SDLK_DOWN] || keys_held[SDLK_LEFT] || keys_held[SDLK_RIGHT]) + { + flag = !flag; + keys(NULL, keys_held, flag); + } + else + flag = !flag; +} + +static void draw_ground(void) +{ + GLfloat fExtent = 20.0f; + GLfloat fStep = 0.5f; + GLfloat y = -0.4f; + GLfloat iLine; + + glBegin(GL_LINES); + for (iLine = -fExtent; iLine <= fExtent; iLine += fStep) + { + glVertex3f(iLine, y, fExtent); + glVertex3f(iLine, y, -fExtent); + glVertex3f(fExtent, y, iLine); + glVertex3f(-fExtent, y, iLine); + } + glEnd(); +} + +static void render(void) +{ + M3DVector3f vNormal; + M3DVector3f vCorners[5] = { + { 0.0f, 0.6f, 0.0f }, /* top 0 */ + { -0.5f, -0.2f, -.50f }, /* back left 1 */ + { 0.5f, -0.2f, -0.50f }, /* back right 2 */ + { 0.5f, -0.2f, 0.5f }, /* front right 3 */ + { -0.5f, -0.2f, 0.5f } /* front left 4 */ + }; + + /* clear the window with current clearing color */ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* save the matrix state and do the rotations */ + glPushMatrix(); + frameCamera.ApplyCameraTransform(); + draw_ground(); + /* move object back and do in place rotation */ + glTranslatef(0.0f, 0.2f, -3.5f); + glRotatef(xRot, 1.0f, 0.0f, 0.0f); + glRotatef(yRot, 0.0f, 1.0f, 0.0f); + + /* draw the pyramid */ + glColor3f(1.0f, 1.0f, 1.0f); + glBegin(GL_TRIANGLES); + + /* bottom section - two triangles */ + glNormal3f(0.0f, -1.0f, 0.0f); + + /* map texture to geometry */ + glTexCoord2f(1.0f, 1.0f); + glVertex3fv(vCorners[2]); + glTexCoord2f(0.0f, 1.0f); + glVertex3fv(vCorners[4]); + glTexCoord2f(0.0f, 0.0f); + glVertex3fv(vCorners[1]); + glTexCoord2f(1.0f, 1.0f); + glVertex3fv(vCorners[2]); + glTexCoord2f(1.0f, 0.0f); + glVertex3fv(vCorners[3]); + glTexCoord2f(0.0f, 0.0f); + glVertex3fv(vCorners[4]); + + /* front face */ + m3dFindNormal(vNormal, vCorners[0], vCorners[4], vCorners[3]); + glNormal3fv(vNormal); + glTexCoord2f(0.5f, 1.0f); + glVertex3fv(vCorners[0]); + glTexCoord2f(0.0f, 0.0f); + glVertex3fv(vCorners[4]); + glTexCoord2f(1.0f, 0.0f); + glVertex3fv(vCorners[3]); + + /* left face */ + m3dFindNormal(vNormal, vCorners[0], vCorners[1], vCorners[4]); + glNormal3fv(vNormal); + glTexCoord2f(0.5f, 1.0f); + glVertex3fv(vCorners[0]); + glTexCoord2f(0.0f, 0.0f); + glVertex3fv(vCorners[1]); + glTexCoord2f(1.0f, 0.0f); + glVertex3fv(vCorners[4]); + + /* back face */ + m3dFindNormal(vNormal, vCorners[0], vCorners[2], vCorners[1]); + glNormal3fv(vNormal); + glTexCoord2f(0.5f, 1.0f); + glVertex3fv(vCorners[0]); + glTexCoord2f(0.0f, 0.0f); + glVertex3fv(vCorners[2]); + glTexCoord2f(1.0f, 0.0f); + glVertex3fv(vCorners[1]); + + /* right face */ + m3dFindNormal(vNormal, vCorners[0], vCorners[3], vCorners[2]); + glNormal3fv(vNormal); + glTexCoord2f(0.5f, 1.0f); + glVertex3fv(vCorners[0]); + glTexCoord2f(0.0f, 0.0f); + glVertex3fv(vCorners[3]); + glTexCoord2f(1.0f, 0.0f); + glVertex3fv(vCorners[2]); + glEnd(); + + /* restore the matrix state */ + glPopMatrix(); + + /* buffer swap */ + SDL_GL_SwapBuffers(); +} + +int main(int argc, char **argv) +{ + SDL_Surface *screen; + + if (SDL_Init(SDL_INIT_VIDEO) < 0 ) + { + fprintf(stderr, "unable to init SDL: %s\n", SDL_GetError()); + exit(-1); + } + atexit(SDL_Quit); + SDL_WM_SetCaption("Textured Pyramid", NULL); + + if ((screen = SDL_SetVideoMode(640, 480, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER + | SDL_RESIZABLE)) == NULL) + { + fprintf(stderr, "unable to set video mode: %s\n", SDL_GetError()); + exit(-1); + } + + SDL_EnableUNICODE(1); + /* SDL doesn't trigger off a ResizeEvent at startup, but as we need this + * for OpenGL, we do this ourselves */ + SDL_Event resizeEvent; + resizeEvent.type = SDL_VIDEORESIZE; + resizeEvent.resize.w = 640; + resizeEvent.resize.h = 480; + SDL_PushEvent(&resizeEvent); + + /* initalize glew */ + GLenum glewerr = glewInit(); + if (GLEW_OK != glewerr) + { + fprintf(stderr, "error: %s\n", glewGetErrorString(glewerr)); + return -1; + } + else + fprintf(stdout, "status: using GLEW %s\n", glewGetString(GLEW_VERSION)); + + SetupRC(); + +#ifdef STAT_FPS + /* fps counter */ + Uint32 startclock = 0; + Uint32 deltaclock = 0; + Uint32 current_fps = 0; +#endif + struct timeval m_LastCount; + struct timeval lcurrent; + for (;;) + { + gettimeofday(&m_LastCount, 0); +#ifdef STAT_FPS + startclock = SDL_GetTicks(); +#endif + processEvents(); + render(); + + gettimeofday(&lcurrent, 0); + float fSeconds = (float) (lcurrent.tv_sec - m_LastCount.tv_sec); + float fFraction = (float) (lcurrent.tv_usec - m_LastCount.tv_usec) * 0.000001f; + float delta = fSeconds + fFraction; + + if (delta < 1000 / FRAMES_PER_SECOND) + SDL_Delay((1000 / FRAMES_PER_SECOND) - delta); + +#ifdef STAT_FPS + deltaclock = SDL_GetTicks() - startclock; + if (deltaclock != 0 ) + current_fps = 1000 / deltaclock; + + static char buffer[30] = { 0 }; + sprintf(buffer, "Textured Pyramid: %04d fps", current_fps); + SDL_WM_SetCaption(buffer, NULL); +#endif + } + + return 0; +} + |