Skip to content

Instantly share code, notes, and snippets.

@kusold
Created February 21, 2011 02:15
Show Gist options
  • Select an option

  • Save kusold/836581 to your computer and use it in GitHub Desktop.

Select an option

Save kusold/836581 to your computer and use it in GitHub Desktop.
Requires GLUT
////////////////////////////////////////////////////////
//
// A simple OpenGL program that allows you to place
// line segments, rotate them, and scale them. Some
// other features are changing the color via a right
// click menu, creating a star, creating a polygon,
// and creating a spiral.
//
// When 200 lines are drawn, you need to clear the
// window to draw more.
//
// Author: Mike Kusold
// Date: 1/24/2011
//
////////////////////////////////////////////////////////
#include <GL/glut.h>
#include <GL/gl.h>
#include <math.h>
#include "Lab01.h"
#define MAX_LINES 200 // max number of lines allowed to be displayed.
#define MAX_VERTICES 2 // a line has two vertices.
#define TRUE 1
#define FALSE 0
#define PI (atan((float) 1) * 4) // PI
/**
* Globals
*/
int windowWidth = 500, // display window width
windowHeight = 500; // display window height
float u = 1; // x-axis positioner
float v = 0; // y-axis positioner
int D = 10; // scale
float rotate = PI/6;
int nop = 0; // number of primitives NEED TO CHECK AGAINST MAX_LINES!
float colors[3]; // current color in RGB
int number_of_sides = 5;
float angle = PI/6;
int scale = 2;
int mode = GLUT_RGB|GLUT_SINGLE;
/* Structure for a line */
typedef struct line {
bool clicked; // set to true if the point was selected via mouse.
float lcolor[3]; // color of the line in RGB
int x[MAX_VERTICES]; // x0 and x1 coordinates
int y[MAX_VERTICES]; // y0 and y1 coordinates
} line;
line lines[MAX_LINES]; // used to store the lines
void colormenu(int selected) {
switch (selected) {
case 0:
// white
colors[0] = 1.0;
colors[1] = 1.0;
colors[2] = 1.0;
break;
case 1:
// red
colors[0] = 1.0;
colors[1] = 0.0;
colors[2] = 0.0;
break;
case 2:
// green
colors[0] = 0.0;
colors[1] = 1.0;
colors[2] = 0.0;
break;
case 3:
// blue
colors[0] = 0.0;
colors[1] = 0.0;
colors[2] = 1.0;
break;
}
}
/**
* This only executes when the left mouse button is pushed down.
*/
void getMousePosition(int button, int state, int x, int y) {
if( (button == GLUT_LEFT_BUTTON) && (state == GLUT_UP) ) {
/* Insert to vertex buffers */
lines[nop].x[0] = x;
lines[nop].y[0] = windowHeight - y; /* GLUT and GL define the origin at different positions */
lines[nop].clicked = TRUE;
lines[nop].lcolor[0] = colors[0];
lines[nop].lcolor[1] = colors[1];
lines[nop].lcolor[2] = colors[2];
}
}
void polygon(int sides) {
int i;
unsigned char command;
for(i=0; i<sides; i++) {
command = 'f';
key(command, 0, 0);
rotate = (2*PI)/sides;
command = 't';
key(command, 0, 0);
}
rotate = PI/6;
}
void star(int sides) {
int i;
unsigned char command;
for(i=0; i<sides; i++) {
command = 'f';
key(command, 0, 0);
rotate = (4*PI)/sides;
command = 't';
key(command, 0, 0);
}
rotate = PI/6;
}
void spiral(int sides, float angle, float scale) {
int i;
unsigned char command;
for(i=0; i<sides; i++) {
command = 'f';
key(command, 0, 0);
rotate = angle;
command = 't';
u = u * (scale/1.50);
v = v* (scale/1.50);
key(command, 0, 0);
command = 'S';
key(command, 0, 0);
}
rotate = PI/6;
}
void clear() {
int i,j;
for(i = 0; i < nop; i++) {
for(j=0; j < MAX_VERTICES; j++) {
lines[nop].x[j] = 0;
lines[nop].y[j] = 0;
}
lines[nop].clicked = FALSE;
lines[nop].lcolor[0] = 1.0;
lines[nop].lcolor[1] = 1.0;
lines[nop].lcolor[2] = 1.0;
}
nop = 0;
glClear(GL_COLOR_BUFFER_BIT);
}
void key(unsigned char key, int x, int y) {
float u2, v2;
/* When ‘f’ is pressed, connect the current point (x,y) and the next point (x’,y’) with a line segment.
The next point is calculated as:
x’ = x + D * u
y’ = y + D * v
where (u,v) is the direction that the line is heading to.
*/
if(key == 'f') {
// create a new independant line
if(lines[nop].clicked == TRUE && (nop < MAX_LINES)) {
lines[nop].x[1] = lines[nop].x[0] + D*u;
lines[nop].y[1] = lines[nop].y[0] + D*v;
glBegin(GL_LINES);
glColor3f(lines[nop].lcolor[0],lines[nop].lcolor[1],lines[nop].lcolor[2]);
glVertex2i(lines[nop].x[0], lines[nop].y[0]);
glVertex2i(lines[nop].x[1], lines[nop].y[1]);
glEnd();nop++;
}
// create a line based up the (x1,y1) coordinates of the previous line.
else if (nop!=0 && (nop < MAX_LINES)) {
lines[nop].x[0] = lines[nop-1].x[1];
lines[nop].y[0] = lines[nop-1].y[1];
lines[nop].x[1] = lines[nop].x[0] + D*u+u;
lines[nop].y[1] = lines[nop].y[0] + D*v+v;
lines[nop].lcolor[0] = colors[0];
lines[nop].lcolor[1] = colors[1];
lines[nop].lcolor[2] = colors[2];
glBegin(GL_LINES);
glColor3f(lines[nop].lcolor[0],lines[nop].lcolor[1],lines[nop].lcolor[2]);
glVertex2i(lines[nop].x[0], lines[nop].y[0]);
glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]);
glEnd();
nop++;
}
}
if(key == 't') {
/* When ‘t’ is pressed, you will turn the direction of the line by an angle of A. In other words, you
will rotate (u,v) in the following way:
u’ = u cos(A) – v sin(A)
v’ = u sin(A) + v cos(A).
A = 30 degrees
*/
u2 = u*cos(rotate) - v*sin(rotate);
v2 = u*sin(rotate) + v*cos(rotate);
u=u2;
v=v2;
lines[nop-1].x[1] = lines[nop-1].x[0] + D*u;
lines[nop-1].y[1] = lines[nop-1].y[0] + D*v;
glBegin(GL_LINES);
glVertex2i(lines[nop-1].x[0], lines[nop-1].y[0]);
glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]);
glEnd();
}
if(key == 'S') {
/* When ‘S’ is pressed, you scale up the (u,v) vector by 50%, that is:
u’ = 1.5 * u
v’ = 1.5 * v
*/
u = u*1.5;
v = v*1.5;
lines[nop-1].x[1] = lines[nop-1].x[0] + D*u;
lines[nop-1].y[1] = lines[nop-1].y[0] + D*v;
glBegin(GL_LINES);
glVertex2i(lines[nop-1].x[0], lines[nop-1].y[0]);
glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]);
glEnd();
}
if(key == 's') {
/* When ‘s’ is pressed, you scale down the (u,v) vector by 50%, that is:
u’ = 0.5 * u
v’ = 0.5 * v
*/
u = u*0.5;
v = v*0.5;
lines[nop-1].x[1] = lines[nop-1].x[0] + D*u;
lines[nop-1].y[1] = lines[nop-1].y[0] + D*v;
glBegin(GL_LINES);
glVertex2i(lines[nop-1].x[0], lines[nop-1].y[0]);
glVertex2i(lines[nop-1].x[1], lines[nop-1].y[1]);
glEnd();
}
if(key == 'q') {
/* Exit program */
exit(0);
}
if(key == 'p') {
polygon(6);
}
if( key == 'a') {
star(5);
}
if( key == 'r') {
spiral(20,(PI/4),1.05f);
}
if( key == 'c') {
clear();
}
glFlush();
glutPostRedisplay(); /* Now display everything in the buffers */
}
/**
* Needed for when the user resizes the window.
* Plea to users: Please don't!
*/
void reshape(GLsizei w, GLsizei h) {
/* Adjust clipping box */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* Adjust viewport and clear */
glViewport(0,0,w,h);
glutPostRedisplay(); /* Now display everything in the buffers */
/* Save new window size in global variables */
windowWidth = w;
windowHeight = h;
}
void display_all()
{
int p_idx, //Primative Index
v_idx = 0; // Vertex Index
if ( nop!=0) {
glClear(GL_COLOR_BUFFER_BIT);
for(p_idx=0; (p_idx < nop); p_idx++) { //Cycle through until all primatives are drawn.
glColor3f(lines[p_idx].lcolor[0], lines[p_idx].lcolor[1], lines[p_idx].lcolor[2]);
glBegin(GL_LINES);
for(v_idx = 0; v_idx < MAX_VERTICES; v_idx++) { //Cycle through max vertices
glVertex2i(lines[p_idx].x[v_idx], lines[p_idx].y[v_idx]);
}
glEnd();
}
}
glFlush(); // force OpenGL to draw all the objects
}
void display()
{
glClearColor(0,0,0,1); /* Black Background */
glClear(GL_COLOR_BUFFER_BIT);
/*Set World view */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, windowHeight, 0, windowWidth);
display_all();
}
void init() {
colors[0] = 1.0;
colors[1] = 0.0;
colors[2] = 0.0;
glColor3f(colors[0],colors[1],colors[2]); /* Draw in Red */
glViewport(0,0, windowWidth, windowHeight); /* Set viewport */
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(windowWidth, windowHeight);
glutInitDisplayMode(mode);
glutCreateWindow("Mike Kusold's Lab 01");
init();
/* Register Callbacks */
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(key); /* register the callback that will be called when a key is pressed */
glutMouseFunc(getMousePosition); /* register the callback that will be called when a key is pressed */
// glutMotionFunc(); /*register the callback that will be called when the mouse is in motion while a buton is pressed */
// create menu
glutCreateMenu(colormenu);
glutAddMenuEntry("White", 0);
glutAddMenuEntry("Red", 1);
glutAddMenuEntry("Green", 2);
glutAddMenuEntry("Blue", 3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
}
void getMousePosition(int button, int state, int x, int y);
void colormenu(int selected);
void key(unsigned char key, int x, int y);
void polygon(int sides);
void star(int sides);
void spiral(int sides, int angle, int scale);
void clear();
void reshape(GLsizei w, GLsizei h);
void display_all();
void display();
void init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment