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;
}
}