summaryrefslogtreecommitdiffstats
path: root/pyramid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pyramid.cpp')
-rw-r--r--pyramid.cpp372
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;
+}
+