Code:
The program loads a number of shapes from a file.
It then reads characters indicating what to draw of the given size.
'c' = circle, 's' = square, 't' = triangle.
The shapes are drawn across the screen in a row.
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#ifdef __APPLE__
/* this preprocessor statement avoids warnings about using OpenGL 2.0 standard */
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
#define DEG2RAD (3.1415926536 / 180)
#define WINWIDTH 800 /* window width */
#define WINHEIGHT 400 /* window height */
int nshapes; /* the number of shapes to draw */
char *Shapes; /* 1D array of shapes */
float shapewidth; /* width of one shape */
/*
Load the shapes from the disk file. Allocate memory for the shape array
and establish the initial window width and height.
Returns 0 if maze read successfully, returns non-zero error code if not
*/
int loadShapes(char filename[]) {
FILE *shapefile;
int nok;
int col;
char ch;
shapefile = fopen(filename, "r");
if (shapefile == NULL)
return 1;
nok = fscanf(shapefile, "%d\n", &nshapes);
if (nok != 1)
return 2;
Shapes = (char *)malloc(nshapes * sizeof(char));
for (col = 0; col < nshapes; col++) {
ch = getc(shapefile);
while (isspace(ch))
ch = getc(shapefile);
if (ch == EOF)
return 3;
Shapes[col] = ch;
}
shapewidth = (float)WINWIDTH / (float)nshapes;
return 0;
}
/*
Reshape Routine: update the screen viewport to keep the maze
in correct proportions
*/
void reshapeWindow(int width, int height) {
glViewport(0, 0, width, height);
/* lower left of window is (0, 0), upper right is (W, H) */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, WINWIDTH, 0, WINHEIGHT);
}
void drawCircle(float cx, float cy) {
float x, y;
int theta;
float r = shapewidth / 2;
glBegin(GL_POLYGON);
for (theta = 0; theta < 360; theta += 5) {
x = cx + r * cos(theta * DEG2RAD);
y = cy + r * sin(theta * DEG2RAD);
glVertex2f(x, y);
}
glEnd();
}
void drawSquare(float cx, float cy) {
float delta = shapewidth / 2;
glBegin(GL_POLYGON);
glVertex2f(cx - delta, cy - delta);
glVertex2f(cx + delta, cy - delta);
glVertex2f(cx + delta, cy + delta);
glVertex2f(cx - delta, cy + delta);
glEnd();
}
void drawTriangle(float cx, float cy) {
float delta = shapewidth / 2;
glBegin(GL_POLYGON);
glVertex2f(cx - delta, cy - delta);
glVertex2f(cx + delta, cy - delta);
glVertex2f(cx, cy + delta);
glEnd();
}
/*
Display Routine: clear the screen and draw the shapes
*/
void drawShapes() {
int col;
float x, y;
/* clear the window to the background color */
glClear(GL_COLOR_BUFFER_BIT);
/* draw the circles in red, squares in green, triangles in blue */
y = WINHEIGHT / 2.0;
for (col = 0; col < nshapes; col++) {
x = (col + 0.5) * shapewidth;
switch (Shapes[col]) {
case 'c':
glColor3f(1.00, 0.0, 0.0);
drawCircle(x, y);
break;
case 's':
glColor3f(0.0, 1.0, 0.0);
drawSquare(x, y);
break;
case 't':
glColor3f(0.0, 0.0, 1.0);
drawTriangle(x, y);
break;
}
}
glutSwapBuffers();
}
/*
This routine is called every time a key is pressed on the keyboard
It causes the program to quit if the q or ESC key is pressed
*/
void handleKey(unsigned char key, int x, int y) {
switch (key) {
case 'q': /* q - quit */
case 'Q':
case 27: /* esc - quit */
exit(0);
default: /* not a valid key -- just ignore it */
return;
}
}
/*
Initialize the maze, and the graphics interface.
Entering the main loop initiates display
*/
int main(int argc, char *argv[]) {
int errorcode;
/* shape file name is the only argument */
if (argc != 2) {
printf("usage: shapes <name>.txt\n");
exit(1);
}
/* load the shapes from the disk file and initialize */
/* exit with an error flag if shapes not loaded correctly */
errorcode = loadShapes(argv[1]);
if (errorcode != 0) {
fprintf(stderr, "load error %d\n", errorcode);
return 1;
}
/* start up the glut utilities */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
/* create the graphics window, giving width, height, and title text */
glutInitWindowSize(WINWIDTH, WINHEIGHT);
glutCreateWindow("Load Some Shapes");
/* post routine called to handle keyboard key presses */
glutKeyboardFunc(handleKey);
/* post routine called to draw graphics when window exposed */
glutDisplayFunc(drawShapes);
/* post routine called to update board size when window reshaped */
glutReshapeFunc(reshapeWindow);
/* specify window clear (background) color to be black */
glClearColor(0, 0, 0, 0);
glutMainLoop();
return 0;
}