Go Back

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

#define PI 3.14159265358979

// Window and Light Variables
int window;
float light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
float light_position[] = {10.0, 10.0, -10.0, 0.0};
float light2_diffuse[] = {0.5, 0.5, 0.5, 1.0};
float light2_position[] = {0.0, 0.0, 10.0, 0.0};
float light3_diffuse[] = {0.5, 0.5, 0.5, 1.0};
float light3_position[] = {-10.0, 0.0, 0.0, 0.0};
float light4_diffuse[] = {0.5, 0.375, 0.25, 1.0};
float light4_position[] = {0.0, 1.0, 0.0, 0.0};
float light5_diffuse[] = {0.5, 0.375, 0.25, 1.0};
float light5_position[] = {0.0, -1.0, 0.0, 0.0};
float mat_specular[] = {0.5, 0.5, 0.5, 1.0};     
float mat_shininess[]= {10.0};

// Gravity and Elasticity of the Ball
float gravity = 10.0;
float elast = 0.9;

// Position and Velocity of the Ball
float xpos=0, ypos=0, zpos=0;
float xvel=1.0, yvel=0.0, zvel=1.0;

// Total Rotation and Rotation Speed of the entire system
int yrot=0, doyrot=0;

// Rotation of the camera
int cam_rot = 0;

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)
{
  // Initialize OpenGL Stuff
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(400,400);

  // Create window and set window functions
  window = glutCreateWindow("Sivek 3D: R/r=Rotate, L/l=Lights");
  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);

  // Initialize all 5 lights and enable the first 3
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  glLightfv(GL_LIGHT1, GL_DIFFUSE, light2_diffuse);
  glLightfv(GL_LIGHT1, GL_POSITION, light2_position);
  glLightfv(GL_LIGHT2, GL_DIFFUSE, light3_diffuse);
  glLightfv(GL_LIGHT2, GL_POSITION, light3_position);
  glLightfv(GL_LIGHT3, GL_DIFFUSE, light4_diffuse);
  glLightfv(GL_LIGHT3, GL_POSITION, light4_position);
  glLightfv(GL_LIGHT4, GL_DIFFUSE, light5_diffuse);
  glLightfv(GL_LIGHT4, GL_POSITION, light5_position);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);
  glEnable(GL_LIGHT2);
  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);
}

double abs(double n)
{  return ((n >= 0) ? n : -1*n);  }

void updatepos()
{
  float delta = 50;

  // Update ball's x-position. If it hits the wall, reverse direction.
  xpos += xvel / delta;
  if (abs(xpos) >= 0.7) xvel *= -1;

  // Update ball's y-position.
  ypos += yvel / delta;
  if (ypos <= -1.3 || ypos >= 0.3)
  {
    // If the ball hits the ground, reverse its direction
    // and take off some velocity (elasticity).
    if (ypos <= -1.3)
    {
      ypos = -1.3;
      yvel *= elast;
    }
    // If the ball hits the ceiling, bounce it back.
    else ypos = 0.3;
    yvel *= -1;
  }
  // Account for acceleration of the ball.
  yvel += -1*gravity/delta;

  // Update screen rotation as appropriate.
  yrot = (yrot + doyrot) % 360;
}

// This is the stolen function to do stroke characters. Don't ask me.
void stroke_output(GLfloat x, GLfloat y, char *format,...)
{
  va_list args;
  char buffer[200], *p;

  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);
  glPushMatrix();
  glTranslatef(x, y, 0);
  glScalef(0.00045, 0.001, 0.0007);
  for (p = buffer; *p; p++)
    glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
  glPopMatrix();
}

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

  // glPushMatrix so the camera seems to rotate around everything
  glPushMatrix();
  glRotatef(cam_rot, 0.0, 1.0, 0.0);

  // Welcome sign:
  glPushMatrix();
    glTranslatef(0.0, 0.4, 0.0);
    glScalef(0.7,0.7, 0.7);
    glPushMatrix();
      // Turn off main lights, turn on sign lights
      glDisable(GL_LIGHT0);
      glDisable(GL_LIGHT1);
      glDisable(GL_LIGHT2);
      glEnable(GL_LIGHT3);
      glEnable(GL_LIGHT4);
      glTranslatef(0.0,0.1,0.0);

      glScalef(1.294, 0.8, 0.01);
      glRotatef(5, -1.0, -1.0, -1.0);
      glPushMatrix();
        // Draw the sign with a slight outline
        glTranslatef(0.0, 0.25, 0.0);
        glColor3f(0.05, 0.0375, 0.025);
        glutSolidCube(0.5);
        glColor3f(0.0, 0.0, 0.0);
        glutWireCube(0.5);

        // Print the sign text
        glTranslate(0.0, 0.0, -1.0);
	glLineWidth(3);
        stroke_output(-0.20,0.08,"Welcome to");
        stroke_output(-0.25,-0.08,"my 3D world!");
        glLineWidth(1.0);
      glPopMatrix();

      // The sign post
      glPushMatrix();
        glScalef(0.05, 2.5, 0.9);
        glColor3f(0.05, 0.0375, 0.025);
        glutSolidCube(0.5);
        glColor3f(0.0, 0.0, 0.0);
        glutWireCube(0.5);
      glPopMatrix();

      // Put lights back to normal for the rest of the scene.
      glDisable(GL_LIGHT3);
      glDisable(GL_LIGHT4);
      glEnable(GL_LIGHT0);
      glEnable(GL_LIGHT1);
      glEnable(GL_LIGHT2);
    glPopMatrix();
  glPopMatrix();

  // The crazy blue bouncing ball
  glPushMatrix();
    glTranslatef(xpos,ypos+0.7,0);
    glColor3f(0.0,0.0,1.0);
    glutSolidSphere(0.15, 50, 50);
  glPopMatrix();

  // A small "pole" (actually a deformed cube) to which a leash is attached.
  glPushMatrix();
    glTranslatef(0.0,-0.6,0.0);
    glScalef(0.25, 1.0, 0.25);
    glColor3f(0.0,1.0,0.0);
    glutSolidCube(0.1);
  glPopMatrix();

  glRotatef(yrot, 0.0, 1.0, 0.0);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  glLightfv(GL_LIGHT1, GL_DIFFUSE, light2_diffuse);
  glLightfv(GL_LIGHT1, GL_POSITION, light2_position);
  glLightfv(GL_LIGHT2, GL_DIFFUSE, light3_diffuse);
  glLightfv(GL_LIGHT2, GL_POSITION, light3_position);

  // A small cube that goes on a leash and rotates around.
  glColor3f(0.0, 1.0, 0.0);
  glPushMatrix();
    glTranslatef(-0.7, -0.7, 0.0);
    glRotatef(20, 0.0, 1.0, 0.0);
    glRotatef(-20, 1.0, 0.0, 0.0);
    glutSolidCube(0.1);
  glPopMatrix();

  // The leash. It's a very scaled cube.
  glColor3f(1.0, 1.0, 0.0);
  glPushMatrix();
    glTranslatef(-0.35, -0.65, 0.0);
    glRotatef(10, 0.0, 0.0, 1.0);
    glScalef(7.0, 0.1, 0.1);
    glutSolidCube(0.1);
  glPopMatrix();

  // The randomish teapot and plain donut (a brown torus, in fact).
  glPushMatrix();
    glRotatef(-1*yrot, 0.0, 1.0, 0.0);
    glTranslatef(0.0, -0.2, 0.45);
    glRotatef(-yrot, 0.0, 1.0, 0.0);

    glColor3f(1.0, 0.0, 0.0);
    glPushMatrix();
      glutSolidTeapot(0.3);
    glPopMatrix();

    // Not only is this a donut, but it stays on the handle of the teapot!
    glColor3f(0.667, 0.5, 0.333);
    glPushMatrix();
      glTranslatef(-0.42, -0.0, 0.0);
      glRotatef(80, 1.0, 0.0, 0.0);
      glutSolidTorus(0.03, 0.1, 10, 50);
    glPopMatrix();
  glPopMatrix();

  glPopMatrix();

  // Get new ball and rotation settings.
  updatepos();

  // Draw, swap buffers for double buffering, etc.
  glFlush();
  glutSwapBuffers();
  glutPostRedisplay();
}

void mouse(int button, int state, int x, int y)
{
  double dtheta = PI/36;
  double xnew, znew;

  // If left-click, speed rotation one way.
  // If right-click, speed rotation the other way.
  // If middle-click, give the ball an extra boost.

  if (state==GLUT_DOWN)
  {
    if (button==0)
      doyrot += 1;
    else if (button==1)
      yvel *= 3;
    else if (button==2)
      doyrot -= 1;
  }
}

void keypress(unsigned char key, int x, int y)
{
  int i;
  float dtheta = PI/12;

  // If "l" then dim the lights. If "L" then brighten them.
  // If "r" then rotate the camera. If "R" then rotate it the other way.

  if (key == 'l')
  {
    for (i = 0; i < 3; i++)
    {
      light_diffuse[i] *= 0.9;
      light2_diffuse[i] *= 0.9;
      light3_diffuse[i] *= 0.9;
    }
  }
  else if (key == 'L')
  {
    for (i = 0; i < 3; i++)
    {
      light_diffuse[i] /= 0.9;
      light2_diffuse[i] /= 0.9;
      light3_diffuse[i] /= 0.9;
    }
  }
  else if (key == 'r')
  {
    cam_rot = (cam_rot+5) % 360;
  }
  else if (key == 'R')
  {
    cam_rot = (cam_rot+355)%360;
  }
}

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