Monday, May 4, 2009

Final Project

For my final project I made a simple game with OpenGL GLut. My original intention was to make a nice looking environment using my OBJ viewer as a starting point. The original camera movements using gluLookAt() proved adequate, and I attached an .obj shotgun to the camera. Due to technical difficulties getting textures uv mapped onto .obj files, I drew most of the environment manually, drawing several buildings into city blocks, which were then translated and rotated into 9 square blocks. I then added a ufo and a single bullet to make a quick gametype.
Use the W key and the mouse to move.
H toggles the hud
J activates player debug information, giving the player location and rotation
K activates ufo and bullet debug information, giving the ufo location, the bullet location, and the distance between them.
Although it still needs alot of work, it is not bad for only 1400 lines of code (many involved the creation of Open GL primatives.)
CLICK THE PICTURE TO DOWNLOAD AND PLAY.

Credits:
Shotgun .obj file:
http://www.turbosquid.com/FullPreview/Index.cfm/ID/308701

Mouse Movement:
http://www.lighthouse3d.com/opengl/glut/index.php?9

Loading Textures:
http://www.nullterminator.net/gltexture.html

Drawing to Viewscreen, Hud, Text to Screen:
http://www.songho.ca/opengl/gl_vbo.html

Obj file specs:
http://people.sc.fsu.edu/~burkardt/txt/obj_format.txt

Other reference:
Open GL SuperBible

Thursday, April 2, 2009

Project 2 Obj Viewer

Here are some screenshots of my .obj viewer. The first screenshot is of a skyscraper model. I included an algorithm to calculate the face normals. I just set them perpendicular to the face plane. My program only handles models that have been triangulated.

The second screenshot shows the teapot model, which I am sure everyone is tired of seeing. The shot on the left shows the teapot with normals turned on, and the shot on the right shows normals turned off.
The final screenshot shows the F22 model I did for CSC 220. Maya does not seem to "wind" all of the faces counterclockwise when it exports .obj files, so some of the normals are pointing in the wrong direction. The first shot shows the F22 with normals turned off. I also changed the colors using the R G and B keys.


Finally here is a link to my final version of the
OBJViewer. This version only works when you drag and drop a .obj file onto it. Models that are not triangulated will not look good.
The camera does not work perfectly, sometimes it will turn completely around.

Keyboard Instructions:
HOME: Resets camera to origin
Arrow UP/DOWN: moves the camera forwards and backwards in whatever direction you are facing
Arrow LEFT/RIGHT: Rotates left and right
INSERT/END: Pan left and right
R G B: change colors (reduces r g and b values)
M: toggle background black/white
N: toggle faces normals

Thanks to: lighthouse3D for this tutorial on using a vector for camera control with gluLookAt();
Thanks to: Richard Sabbarton for writing this article on Calculating normals

Saturday, March 28, 2009

Web Exercise 2

Here is the sample from the OpenGl redbook running, This screenshot was taken after I messed around with gluPerspective():


Here are some examples of my simple camera movement system. I was able to get the camera to pan left and right, up and down, and also tilt left and right and up and down. I used the home key to reset the camera to the origin. I made a simple model of an airplane to demonstrate my camera. Here are pictures of the plane after various camera movements:



// Camera4.cpp
// Demonstrates Camera Movement
// CSC 370 March 2009
// Michael Haizlip

#include
#include

// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat zRot = 0.0f;
static GLfloat zMove= 0.0f;
static GLfloat yMove= 0.0f;
static GLfloat xMove= 0.0f;


// Change viewing volume and viewport. Called when window is resized
void ChangeSize(int w, int h)
{
GLfloat fAspect;
// Prevent a divide by zero
if(h == 0)
h = 1;

// Set Viewport to window dimensions
glViewport(0, 0, w, h);

fAspect = (GLfloat)w/(GLfloat)h;

// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Produce the perspective projection
gluPerspective(60.0f, fAspect, 1.0, 400.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}


// This function does any needed initialization on the rendering
// context. Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
{
// Light values and coordinates
GLfloat whiteLight[] = { 0.45f, 0.45f, 0.45f, 1.0f };
GLfloat sourceLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
GLfloat lightPos[] = { -50.f, 25.0f, 250.0f, 0.0f };

glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glDisable(GL_CULL_FACE); // Do not calculate inside of jet

// 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);

// Black blue background
glClearColor(0.0f, 1.0f, 1.0f, 1.0f );
}

// Respond to arrow keys
void SpecialKeys(int key, int x, int y)
{
//Move Forwards and Backwards
if(key == GLUT_KEY_UP)
zMove += 5.0f;

if(key == GLUT_KEY_DOWN)
zMove -= 5.0f;

//Pan left and right
if(key == GLUT_KEY_RIGHT)
{
xMove -= 5.0f;
xRot -= 5.0f;
}
if(key == GLUT_KEY_LEFT)
{
xMove += 5.0f;
xRot += 5.0f;
}
//pan straight up and down
if(key == GLUT_KEY_PAGE_UP)
{
yRot += 5.0f;
yMove += 5.0f;
}
if(key == GLUT_KEY_PAGE_DOWN)
{
yRot -= 5.0f;
yMove -= 5.0f;
}
//reset to home
if(key == GLUT_KEY_HOME)
{
xRot = 0.0f;
yRot = 0.0f;
zRot = 0.0f;
zMove= 0.0f;
yMove= 0.0f;
xMove= 0.0f;
}
//rotate right
if(key == GLUT_KEY_INSERT)
xRot += 5.0f;
//rotate left
if(key == GLUT_KEY_END)
xRot -= 5.0f;

// Refresh the Window
glutPostRedisplay();
}


// Called to draw scene
void RenderScene(void)
{
float fZ,bZ;

// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

fZ = 100.0f;
bZ = -100.0f;

glLoadIdentity();

gluLookAt (xMove, yMove, zMove, xRot, yRot, zRot, 0.0, 1.0, 0.0);

glScalef (0.5,0.5,0.5);
// Set material color, Red
glColor3f(1.0f, 1.0f, 1.0f);

glBegin(GL_QUADS);

// Top Panel
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-3.0f, 5.0f, fZ);
glVertex3f(3.0f, 5.0f, fZ);
glVertex3f(3.0f, 5.0f,bZ);
glVertex3f(-3.0f, 5.0f, bZ);

// Bottom Panel
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-3.0f, -5.0f, fZ);
glVertex3f(-3.0f, -5.0f, bZ);
glVertex3f(3.0f, -5.0f,bZ);
glVertex3f(3.0f, -5.0f, fZ);

glNormal3f(1.0f, 1.0f, 0.0f);
glVertex3f(-6.0f, 0.0f, fZ);
glVertex3f(-3.0f, 5.0f, fZ);
glVertex3f(-3.0f, 5.0f, bZ);
glVertex3f(-6.0f, 0.0f,bZ);

glNormal3f(-1.0f, 1.0f, 0.0f);
glVertex3f(-3.0f, -5.0f, fZ);
glVertex3f(-6.0f, 0.0f, fZ);
glVertex3f(-6.0f, 0.0f,bZ);
glVertex3f(-3.0f, -5.0f, bZ);

glNormal3f(1.0f, -1.0f, 0.0f);
glVertex3f(3.0f, 5.0f, fZ);
glVertex3f(6.0f, 0.0f, fZ);
glVertex3f(6.0f, 0.0f,bZ);
glVertex3f(3.0f, 5.0f, bZ);

glNormal3f(-1.0f, -1.0f, 0.0f);
glVertex3f(6.0f, 0.0f, fZ);
glVertex3f(3.0f, -5.0f, fZ);
glVertex3f(3.0f, -5.0f, bZ);
glVertex3f(6.0f, 0.0f,bZ);

glEnd();

glBegin(GL_TRIANGLES);

glNormal3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -120.0f);
glVertex3f(3.0f, 5.0f, bZ);
glVertex3f(6.0f, 0.0f, bZ);

glNormal3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -120.0f);
glVertex3f(-3.0f, 5.0f, bZ);
glVertex3f(3.0f, 5.0f, bZ);

glNormal3f(-1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -120.0f);
glVertex3f(-6.0f, 0.0f, bZ);
glVertex3f(-3.0f, 5.0f, bZ);

glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -120.0f);
glVertex3f(6.0f, 0.0f, bZ);
glVertex3f(3.0f, -5.0f, bZ);

glNormal3f(-1.0f, -1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -120.0f);
glVertex3f(3.0f, -5.0f, bZ);
glVertex3f(-3.0f, -5.0f, bZ);

glNormal3f(1.0f, -1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -120.0f);
glVertex3f(-3.0f, -5.0f, bZ);
glVertex3f(-6.0f, 0.0f, bZ);

glEnd();

glBegin(GL_QUADS);

glColor3f(0.0f, 0.0f, 0.0f);
glVertex3f(6.0f, 0.0f, fZ);
glVertex3f(60.0f, 0.0f, fZ);
glVertex3f(60.0f, 0.0f, 40.0f);
glVertex3f(6.0f, 0.0f,-40.0f);

glVertex3f(-6.0f, 0.0f,-40.0f);
glVertex3f(-60.0f, 0.0f, 40.0f);
glVertex3f(-60.0f, 0.0f, fZ);
glVertex3f(-6.0f, 0.0f, fZ);

glVertex3f(0.0f, 0.0f,fZ);
glVertex3f(0.0f, 50.0f, fZ);
glVertex3f(0.0f, 50.0f, 80.0f);
glVertex3f(0.0f, 0.0f, 50.0f);

glEnd();

// Buffer swap
glutSwapBuffers();
}

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("Perspective Projection");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();

return 0;
}

Friday, March 27, 2009

Web Excersise

The most interesting thing I learned was in the PyOpenGL article. It was the breakdown of the hierarchy for drawing geometry. I think for my project I will try to use the Vertex Buffer Objects. It seems better to me to keep the objects in video card memory, then call them when you need them. The Unreal Engine uses this technique for rendering static meshes. If you store a model in video card memory, you can then draw it onscreen in many different places with a lot less overhead.
That OpenGL is available for Processing is also very interesting. I wish I had known this when I started working on my SuperShape Project.

Here is a screenshot of my Bezier curve program implemented in OpenGL:


For the perspective example, I first "cut" all of the 4 inside faces, and duplicated them, then added faces in the middle, creating a kind of wall in the center of the "hallway." Then I moved the 4 outside faces to make a diamond shape, and I added triangles to fill out the front and back faces. I also played with the colors. Here is a shot of the front, with red white and blue colors, and the back, with all 4 primary and secondary colors:



Finally here is a picture where I put in ridiculous values for the normals, just trying to figure out how they worked. I included this picture also because it shows how I added triangles to fill out those front and back faces:

Tuesday, March 3, 2009

Project 1: Supershape Monsters

Here are my processing monsters:

First I started off generating shape with the superformula:
Next I started generating many shapes and having them move around the screen, detect collision etc:
Then I added some color variation by varying the saturation from the center of each creature towards its outside radius:

Finally I added various random eyeball characteristics to give them personality:

Friday, February 27, 2009

How to get glut working in Dev C++

If you are having trouble getting this program working in Dev C++ in Windows

Step 1: Follow these instructions:
http://www.astahost.com/info.php/installing-glut-dev-c_t14192.html

Step2:
Click File>New>Project
In the tabs across the top click "Multimedia" then click on the icon with the words glut under it.
Save the project file.
This creates a new project called "main.cpp"
You can run it and check it out if you want but then:
Click "Save As" and save the file but rename it simple. cpp
Then copy all of the code from the original simple.cpp and paste it over all the code in this file.
Comment out this line:
#include "../../shared/gltools.h"

use these two lines instead (I stole them from that main.cpp it created earlier):

#include <GL/glut.h>
#include <stdlib.h>

Now compile and run it. No really. Do it.

Saturday, February 14, 2009

Transformations: Homework 4

Here is an image from the first part of Homework 4, rotating a triangle:


The Code:
int x1, x2, x3, y1, y2, y3;
Point p1, p2, p3, temp1, temp2, temp3, centroid;
float a,theta;

void setup()
{
size(720, 480);
background(0);
stroke(255);
p1=new Point(0, 0);
p2=new Point(0 ,0);
p3=new Point(0 ,0);
temp1=new Point(0, 0);
temp2=new Point(0 ,0);
temp3=new Point(0 ,0);
centroid=new Point(0 ,0);
a=90;
mousePressed();
}

void mousePressed()
{
background(0);
x1=int(random(720));
x2=int(random(720));
x3=int(random(720));
y1=int(random(480));
y2=int(random(480));
y3=int(random(480));

p1=new Point(x1,y1);
p2=new Point(x2 ,y2);
p3=new Point(x3 ,y3);

centroid = new Point((p1.x+p2.x+p3.x)/3,(p1.y+p2.y+p3.y)/3);

//move all points to the origin TEMPORARLILY
temp1=new Point(p1.x-centroid.x, p1.y-centroid.y);
temp2=new Point(p2.x-centroid.x, p2.y-centroid.y);
temp3=new Point(p3.x-centroid.x, p3.y-centroid.y);

}

void draw()
{
background(0);
frameRate(60);
stroke(255);
a = (mouseX / (float) width) * 360f;
// Convert it to radians
theta = radians(a);

//rotate the temporary points around the origin
p1=rotatePoint(temp1,theta);
p2=rotatePoint(temp2,theta);
p3=rotatePoint(temp3,theta);

//now move them back to OG location
p1=new Point(p1.x+centroid.x, p1.y+centroid.y);
p2=new Point(p2.x+centroid.x, p2.y+centroid.y);
p3=new Point(p3.x+centroid.x, p3.y+centroid.y);

//draw it
point(centroid.x, centroid.y);
myTri(p1,p2,p3);
}


void myTri(Point a, Point b, Point c)
{
line(a.x,a.y,b.x,b.y);
line(b.x,b.y,c.x,c.y);
line(c.x,c.y,a.x,a.y);
}


Point rotatePoint(Point p, float angle)
{
float[] coord = new float[3];
int[] newCoord= new int[3];
float[][] matrix= new float[3][3];
float c=cos(angle);
float s=sin(angle);
Point myPoint=new Point(0,0);

//setup the 3x1 matrix for the point
coord[0]=p.x;
coord[1]=p.y;
coord[2]=1;

//setup the 3x3 matrix for the rotation
matrix[0][0]=c;
matrix[0][1]=s;
matrix[0][2]=0;
matrix[1][0]=-s;
matrix[1][1]=c;
matrix[1][2]=0;
matrix[2][0]=0;
matrix[2][1]=0;
matrix[2][2]=1;

newCoord=matrixMult(matrix, coord);
myPoint.x=newCoord[0];
myPoint.y=newCoord[1];
return myPoint;

}

int[] matrixMult(float matA[][], float matB[])
{
float[] temp= new float[3];
int[] ntemp= new int[3];
temp[0]=0;
temp[1]=0;
temp[2]=0;
for(int i=0; i<3; j="0;" ntemp="int(temp);">

Here are some interesting images I made by rotating several randomly colored triangles, while changing the brightness each time the draw function ran:






The Code:
int x1, x2, x3, y1, y2, y3;
final int num=5;
Point[] p1=new Point[num];
Point[] p2=new Point[num];
Point[] p3=new Point[num];
Point[] temp1=new Point[num];
Point[] temp2=new Point[num];
Point[] temp3=new Point[num];
Point[] centroid=new Point[num];
int h=0;
int s=0;
int v=0;
color c=color(h, s, v);

float a,theta;

void setup()
{
size(720, 480);
background(0);
stroke(255);
colorMode(HSB, 255);
for(int i=0; i255)
v=0;
color c= color(h, s, v);
stroke(c);
point(centroid[i].x, centroid[i].y);
myTri(p1[i],p2[i],p3[i]);
}
}


void myTri(Point a, Point b, Point c)
{
line(a.x,a.y,b.x,b.y);
line(b.x,b.y,c.x,c.y);
line(c.x,c.y,a.x,a.y);
}


Point rotatePoint(Point p, float angle)
{
float[] coord = new float[3];
int[] newCoord= new int[3];
float[][] matrix= new float[3][3];
float c=cos(angle);
float s=sin(angle);
Point myPoint=new Point(0,0);

//setup the 3x1 matrix for the point
coord[0]=p.x;
coord[1]=p.y;
coord[2]=1;

//setup the 3x3 matrix for the rotation
matrix[0][0]=c;
matrix[0][1]=s;
matrix[0][2]=0;
matrix[1][0]=-s;
matrix[1][1]=c;
matrix[1][2]=0;
matrix[2][0]=0;
matrix[2][1]=0;
matrix[2][2]=1;

newCoord=matrixMult(matrix, coord);
myPoint.x=newCoord[0];
myPoint.y=newCoord[1];
return myPoint;

}

int[] matrixMult(float matA[][], float matB[])
{
float[] temp= new float[3];
int[] ntemp= new int[3];
temp[0]=0;
temp[1]=0;
temp[2]=0;
for(int i=0; i<3; j="0;" ntemp="int(temp);">


Finally here is another image I made using pushMatrix() and popMatrix();
They especially made it easy to return to the middle of the screen after each iteration of a loop:




The Code:

int h=0;
int s=0;
int v=0;
color c=color(h, s, v);
int scal=0;
int rot=0;

void setup(){
size(720, 480);
background(0,0,0);
colorMode(HSB, 255);
noLoop();
}

void draw(){
//just draw colored rectangles in each quadrant
randomColor();
rect(0,0,width/2, height/2);
randomColor();
rect(width/2, height/2,width/2, height/2);
randomColor();
rect(0,height/2,width/2, height/2);
randomColor();
rect(width/2,0,width/2, height/2);

//push Matrix, then move to middle of screen
pushMatrix();

translate(width/2, height/2);

for(int j=0; j<4; i="10;" j="0;" i="10;" h="int(random(200));" s="int(random(250));" v="int(random(255));" c="color(h,s,v);">