Go Back

#include <GL/glut.h>
#include "ppmimage.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#define PI 3.14159265358979
#define TOL 1E-5

// Window and Light Variables
int window;
float light_diffuse[] = {.05, .05, .10, 1.0};
float light_position[] = {100.0, 100.0, -5.0, 0.0};
float mat_specular[] = {1.0, 1.0, 1.0, 1.0};
float mat_shininess[] = {010};
float mat_emission[] = {0.375, 0.3, 0.25};

// Rotation of the entire system (around both axes)
int doxrot=0, doyrot=0;

// Zooming amount
float zoom = 1.0;

// Image to draw
image pic;

// Window control functions
void init();
void display();
void mouse(int button, int state, int x, int y);
void keypress(unsigned char key, int x, int y);

int main(int argc, char **argv)
{
  // Load the image;
  pic.load("/home/atlas1/gsivek/supercomp/cowoutln.ppm");

  // Initialize OpenGL Stuff
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(400,400);

  // Create window and set window functions
  window = glutCreateWindow("Bovine Mountain");
  init();
  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keypress);

  // Do the OpenGL loop until the program is exited.
  glutMainLoop();
  return 0;
}

void init()
{
  // Initialize view settings
  glLoadIdentity();
  gluPerspective(31.0, 1.0, -5.0, 5.0);
  glMatrixMode(GL_MODELVIEW);

  // Enable lights and light settings
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);
  glColorMaterial(GL_FRONT, GL_DIFFUSE);

  // Look from (0,0,5) to (0,0,0) with the y-axis being up
  gluLookAt(0.0,0.0,5.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
}

void setNorm(double ax, double ay, double az,
	     double bx, double by, double bz,
	     double cx, double cy, double cz)
{
  // Given three points (ax,ay,az),(bx,by,bz),(cx,cy,cz), calculate
  // the appropiate normal vector for lighting effects. This uses
  // the cross-product to do so.

  float norm[3];
  double d, d1[3], d2[3];

  // Define vectors as differences of points...
  d1[0]=bx-ax;
  d1[1]=by-ay;
  d1[2]=bz-az;
  d2[0]=cx-bx;
  d2[1]=cy-by;
  d2[2]=cz-bz;

  // ... and take their cross product.
  norm[0] = d1[1]*d2[2] - d1[2]*d2[1];
  norm[1] = d1[2]*d2[0] - d1[0]*d2[2];
  norm[2] = d1[0]*d2[1] - d1[1]*d2[0];

  d=sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
  if (d < TOL) return;
  norm[0] /= d;
  norm[1] /= d;
  norm[2] /= d;

  // Assign the normal vector to the triangle!
  glNormal3fv(norm);
}

void drawImage(image myImage)
{
  int i, j;
  double col1, col2, col3, col4;

  // Change in position between pixels on the image.
  double dwidth = 1/double(myImage.width);
  double dheight = 1/double(myImage.height);

  for (i = 0; i < myImage.width-1; i++)
  {
    glBegin(GL_TRIANGLE_STRIP);

    // Get the first two points in a triangle strip...
    col1 = myImage.getColor(i,0,RED);
    col2 = myImage.getColor(i+1,0,RED);
    glColor3f(0.75*col1, 0.6*col1, 0.5*col1);
    glVertex3f((double(i)*dwidth)-0.5,
	       0.5,
	       -6.0*(1.0-col1)+3.0);
    glColor3f(0.5*col2, 0.5*col2, 0.75*col2);
    glVertex3f((double(i+1)*dwidth)-0.5,
	       0.5,
	       -6.0*(1.0-col2)+3.0);
    for (j = 1; j < myImage.height; j++)
    {
        // ...and then proceed down the strip.
        col3 = myImage.getColor(i,j,RED);
        col4 = myImage.getColor(i+1,j,RED);

        glColor3f(col3/10, col3/10, col3/10);
        glVertex3f((double(i)*dwidth)-0.5,
      	           (0.5-double(j)*dheight),
      	           -6.0*(1.0-col3)+3.0);
        // This makes a new triangle, so set the normal vector
        setNorm(0,dheight,3-6*(1.0-col1),
		dwidth,dheight,3-6*(1.0-col2),
	        0,0,5-10*(1.0-col3));

        glColor3f(col4/10, col4/10, col4/10);
	glVertex3f((double(i+1)*dwidth)-0.5,
	           (0.5-double(j)*dheight),
		   -6.0*(1.0-col4)+3.0);
        // This makes a new triangle, so set the normal vector
        setNorm(0,dheight,3-6*(1.0-col1),
		dwidth,dheight,3-6*(1.0-col2),
	        0,0,5-10*(1.0-col3));

      // Rotate the values; the two points calculated in this
      // iteration become the old ones for the next iteration.
      col1 = col3;
      col2 = col4;
    }
  }
  glEnd();
}

void display()
{
  glClearColor(0.0, 0.0, 0.4, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  glPushMatrix();
  // Set user-specified zooming and rotation
  glScalef(zoom, zoom, zoom);
  glRotatef(doxrot, 1.0, 0.0, 0.0);
  glRotatef(doyrot, 0.0, 1.0, 0.0);

  // Rotate the screen some more anyway
  glRotatef(70, 1, 0, 0);

    glPushMatrix();
      // This stuff draws the platform and outline.
      glScalef(0.9, 0.9, 0.1);
      glColor3f(0.5, 0.5, 0.75);

      glPushMatrix();
        glTranslatef(0.0, 0.0, 3.0);
        glutSolidCube(1.0);
	glLineWidth(2);
	glColor3f(0.0, 0.0, 0.0);
	glutWireCube(1.0);
	glLineWidth(1);
      glPopMatrix();

      // Using the same translation (so we don't draw outside
      // the cube), draw the image right above the platform.
      drawImage(pic);
    glPopMatrix();

  glPopMatrix();

  // Force drawing with double buffering.
  glFlush();
  glutSwapBuffers();
  glutPostRedisplay();
}

void mouse(int button, int state, int x, int y)
{
  // If left-click, rotate one way.
  // If right-click, rotate the other way.

  if (state==GLUT_DOWN)
  {
    if (button==0)
      doxrot += 5;
    else if (button==2)
      doxrot -= 5;
  }
}

void keypress(unsigned char key, int x, int y)
{
  // If "z" then zoom out. If "Z" then zoom in.
  // If "r" then rotate the camera. If "R" then rotate it the other way.

  if (key == 'z')
  {
    zoom *= 1.2;
    if (zoom > 2.0) zoom = 2.0;
  }
  else if (key == 'Z')
  {
    zoom /= 1.2;
    if (zoom < 0.25) zoom = 0.25;
  }
  else if (key == 'r')
  {
    doyrot += 5;
  }
  else if (key == 'R')
  {
    doyrot -= 5;
  }
}

My Supercomp front page.
This page was created by Gary Sivek for 7th Period Supercomp.