summaryrefslogtreecommitdiffstats
path: root/sdl/pyramid.c
diff options
context:
space:
mode:
Diffstat (limited to 'sdl/pyramid.c')
-rw-r--r--sdl/pyramid.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/sdl/pyramid.c b/sdl/pyramid.c
new file mode 100644
index 0000000..c31531c
--- /dev/null
+++ b/sdl/pyramid.c
@@ -0,0 +1,277 @@
+/* pyramid.c
+ *
+ * TODO: use native tga loader, fix window resize, multiple keys
+ */
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+/* for some reason order of the headers matters */
+#include "math3d.h"
+
+static GLfloat xRot = 0.0f;
+static GLfloat yRot = 0.0f;
+
+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(35.0f, fAspect, 1.0, 40.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+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);
+
+ /* 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)
+{
+ switch (keysym->sym)
+ {
+ case SDLK_ESCAPE: exit(0); break;
+ case SDLK_w: xRot -= 5.0f; break;
+ case SDLK_s: xRot += 5.0f; break;
+ case SDLK_a: yRot -= 5.0f; break;
+ case SDLK_d: yRot += 5.0f; break;
+ default: break;
+ }
+
+ xRot = (GLfloat) ((const int) xRot % 360);
+ yRot = (GLfloat) ((const int) yRot % 360);
+}
+
+/* process SDL events */
+void processEvents()
+{
+ SDL_Event event;
+ unsigned static int m_Keys[SDLK_LAST];
+ SDLKey sym = event.key.keysym.sym;
+
+ while (SDL_PollEvent(&event))
+ {
+ switch (event.type)
+ {
+ case SDL_KEYUP:
+ {
+ m_Keys[sym] = 0;
+ keys(&event.key.keysym);
+ break;
+ }
+ case SDL_KEYDOWN:
+ {
+ m_Keys[sym] = 1;
+ keys(&event.key.keysym);
+ break;
+ }
+ case SDL_VIDEORESIZE: { resize(event.resize.w, event.resize.h); break; }
+ case SDL_QUIT: { printf("status: exiting...\n"); exit(0); break; }
+ default:
+ }
+ }
+}
+
+static void render(void)
+{
+ M3DVector3f vNormal;
+ M3DVector3f vCorners[5] = {
+ { 0.0f, .80f, 0.0f }, /* top 0 */
+ { -0.5f, 0.0f, -.50f }, /* back left 1 */
+ { 0.5f, 0.0f, -0.50f }, /* back right 2 */
+ { 0.5f, 0.0f, 0.5f }, /* front right 3 */
+ { -0.5f, 0.0f, 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();
+ /* move object back and do in place rotation */
+ glTranslatef(0.0f, -0.25f, -4.0f);
+ 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", "Textured Pyramid");
+
+ 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();
+
+ for (;;)
+ {
+ processEvents();
+ render();
+ }
+
+ return 0;
+}
+