Sample programs [cross-platform source, PC binaries]
Following are sources for several programs (plus PC executables).
Hierarchical modeling
robot.c - robot arm
robot.exe
view code
/*
* Copyright (c) 1993-1997, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
*/
/*
* robot.c
* This program shows how to composite modeling transformations
* to draw translated and rotated hierarchical models.
* Interaction: pressing the s and e keys (shoulder and elbow)
* alters the rotation of the robot arm.
*/
#include "glut.h"
#include
static int shoulder = 0, elbow = 0;
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef (-1.0, 0.0, 0.0);
glRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0);
glTranslatef (1.0, 0.0, 0.0);
glPushMatrix();
glScalef (2.0, 0.4, 1.0);
glutWireCube (1.0);
glPopMatrix();
glTranslatef (1.0, 0.0, 0.0);
glRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0);
glTranslatef (1.0, 0.0, 0.0);
glPushMatrix();
glScalef (2.0, 0.4, 1.0);
glutWireCube (1.0);
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef (0.0, 0.0, -5.0);
}
/* ARGSUSED1 */
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case 's':
shoulder = (shoulder + 5) % 360;
glutPostRedisplay();
break;
case 'S':
shoulder = (shoulder - 5) % 360;
glutPostRedisplay();
break;
case 'e':
elbow = (elbow + 5) % 360;
glutPostRedisplay();
break;
case 'E':
elbow = (elbow - 5) % 360;
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Interaction
picksquare.c - 'picking' squares
picksquare.exe
view code
/*
* Copyright (c) 1993-1997, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
*/
/*
* picksquare.c
* Use of multiple names and picking are demonstrated.
* A 3x3 grid of squares is drawn. When the left mouse
* button is pressed, all squares under the cursor position
* have their color changed.
*/
#include
#include
#include "glut.h"
int board[3][3]; /* amount of color for each square */
/* Clear color value for every square on the board */
void init(void)
{
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j ++)
board[i][j] = 0;
glClearColor (0.0, 0.0, 0.0, 0.0);
}
/* The nine squares are drawn. In selection mode, each
* square is given two names: one for the row and the
* other for the column on the grid. The color of each
* square is determined by its position on the grid, and
* the value in the board[][] array.
*/
void drawSquares(GLenum mode)
{
GLuint i, j;
for (i = 0; i < 3; i++) {
if (mode == GL_SELECT)
glLoadName (i);
for (j = 0; j < 3; j ++) {
if (mode == GL_SELECT)
glPushName (j);
glColor3f ((GLfloat) i/3.0, (GLfloat) j/3.0,
(GLfloat) board[i][j]/3.0);
glRecti (i, j, i+1, j+1);
if (mode == GL_SELECT)
glPopName ();
}
}
}
/* processHits prints out the contents of the
* selection array.
*/
void processHits (GLint hits, GLuint buffer[])
{
unsigned int i, j;
GLuint ii, jj, names, *ptr;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
for (i = 0; i < hits; i++) { /* for each hit */
names = *ptr;
printf (" number of names for this hit = %d\n", names); ptr++;
printf(" z1 is %g;", (float) *ptr/0x7fffffff); ptr++;
printf(" z2 is %g\n", (float) *ptr/0x7fffffff); ptr++;
printf (" names are ");
for (j = 0; j < names; j++) { /* for each name */
printf ("%d ", *ptr);
if (j == 0) /* set row and column */
ii = *ptr;
else if (j == 1)
jj = *ptr;
ptr++;
}
printf ("\n");
board[ii][jj] = (board[ii][jj] + 1) % 3;
}
}
/* pickSquares() sets up selection mode, name stack,
* and projection matrix for picking. Then the
* objects are drawn.
*/
#define BUFSIZE 512
void pickSquares(int button, int state, int x, int y)
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)
return;
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (BUFSIZE, selectBuf);
(void) glRenderMode (GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
/* create 5x5 pixel picking region near cursor location */
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),
5.0, 5.0, viewport);
gluOrtho2D (0.0, 3.0, 0.0, 3.0);
drawSquares (GL_SELECT);
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush ();
hits = glRenderMode (GL_RENDER);
processHits (hits, selectBuf);
glutPostRedisplay();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
drawSquares (GL_RENDER);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (0.0, 3.0, 0.0, 3.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/* ARGSUSED1 */
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}
/* Main Loop */
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (100, 100);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutReshapeFunc (reshape);
glutDisplayFunc(display);
glutMouseFunc (pickSquares);
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}
glpuzzle.c - 'sliding' puzzle blocks
trackball.h - 'trackball' header
trackball.c - 'trackball' source
glpuzzle.exe
view code
/* glpuzzle - written by Kevin Smith (kpsmith@engr.sgi.com) */
#include
#include
#include
#include
#include
#include
#include "glut.h"
#include "trackball.h"
#define WIDTH 4
#define HEIGHT 5
#define PIECES 10
#define OFFSETX -2
#define OFFSETY -2.5
#define OFFSETZ -0.5
typedef unsigned char Config[HEIGHT][WIDTH];
struct puzzle {
struct puzzle *backptr;
struct puzzle *solnptr;
Config pieces;
struct puzzle *next;
unsigned hashvalue;
};
#define HASHSIZE 10691
struct puzzlelist {
struct puzzle *puzzle;
struct puzzlelist *next;
};
static char convert[PIECES + 1] =
{0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4};
static unsigned char colors[PIECES + 1][3] =
{
{0, 0, 0},
{255, 255, 127},
{255, 255, 127},
{255, 255, 127},
{255, 255, 127},
{255, 127, 255},
{255, 127, 255},
{255, 127, 255},
{255, 127, 255},
{255, 127, 127},
{255, 255, 255},
};
void changeState(void);
static struct puzzle *hashtable[HASHSIZE];
static struct puzzle *startPuzzle;
static struct puzzlelist *puzzles;
static struct puzzlelist *lastentry;
int curX, curY, visible;
#define MOVE_SPEED 0.2
static unsigned char movingPiece;
static float move_x, move_y;
static float curquat[4];
static int doubleBuffer = 1;
static int depth = 1;
static char xsize[PIECES + 1] =
{0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
static char ysize[PIECES + 1] =
{0, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2};
static float zsize[PIECES + 1] =
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.6};
static Config startConfig =
{
{8, 10, 10, 7},
{8, 10, 10, 7},
{6, 9, 9, 5},
{6, 4, 3, 5},
{2, 0, 0, 1}
};
static Config thePuzzle =
{
{8, 10, 10, 7},
{8, 10, 10, 7},
{6, 9, 9, 5},
{6, 4, 3, 5},
{2, 0, 0, 1}
};
static int xadds[4] =
{-1, 0, 1, 0};
static int yadds[4] =
{0, -1, 0, 1};
static int W = 400, H = 300;
static GLint viewport[4];
#define srandom srand
#define random() (rand() >> 2)
unsigned
hash(Config config)
{
int i, j, value;
value = 0;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
value = value + convert[config[i][j]];
value *= 6;
}
}
return (value);
}
int
solution(Config config)
{
if (config[4][1] == 10 && config[4][2] == 10)
return (1);
return (0);
}
float boxcoords[][3] =
{
{0.2, 0.2, 0.9},
{0.8, 0.2, 0.9},
{0.8, 0.8, 0.9},
{0.2, 0.8, 0.9},
{0.2, 0.1, 0.8},
{0.8, 0.1, 0.8},
{0.9, 0.2, 0.8},
{0.9, 0.8, 0.8},
{0.8, 0.9, 0.8},
{0.2, 0.9, 0.8},
{0.1, 0.8, 0.8},
{0.1, 0.2, 0.8},
{0.2, 0.1, 0.2},
{0.8, 0.1, 0.2},
{0.9, 0.2, 0.2},
{0.9, 0.8, 0.2},
{0.8, 0.9, 0.2},
{0.2, 0.9, 0.2},
{0.1, 0.8, 0.2},
{0.1, 0.2, 0.2},
{0.2, 0.2, 0.1},
{0.8, 0.2, 0.1},
{0.8, 0.8, 0.1},
{0.2, 0.8, 0.1},
};
float boxnormals[][3] =
{
{0, 0, 1}, /* 0 */
{0, 1, 0},
{1, 0, 0},
{0, 0, -1},
{0, -1, 0},
{-1, 0, 0},
{0.7071, 0.7071, 0.0000}, /* 6 */
{0.7071, -0.7071, 0.0000},
{-0.7071, 0.7071, 0.0000},
{-0.7071, -0.7071, 0.0000},
{0.7071, 0.0000, 0.7071}, /* 10 */
{0.7071, 0.0000, -0.7071},
{-0.7071, 0.0000, 0.7071},
{-0.7071, 0.0000, -0.7071},
{0.0000, 0.7071, 0.7071}, /* 14 */
{0.0000, 0.7071, -0.7071},
{0.0000, -0.7071, 0.7071},
{0.0000, -0.7071, -0.7071},
{0.5774, 0.5774, 0.5774}, /* 18 */
{0.5774, 0.5774, -0.5774},
{0.5774, -0.5774, 0.5774},
{0.5774, -0.5774, -0.5774},
{-0.5774, 0.5774, 0.5774},
{-0.5774, 0.5774, -0.5774},
{-0.5774, -0.5774, 0.5774},
{-0.5774, -0.5774, -0.5774},
};
int boxfaces[][4] =
{
{0, 1, 2, 3}, /* 0 */
{9, 8, 16, 17},
{6, 14, 15, 7},
{20, 23, 22, 21},
{12, 13, 5, 4},
{19, 11, 10, 18},
{7, 15, 16, 8}, /* 6 */
{13, 14, 6, 5},
{18, 10, 9, 17},
{19, 12, 4, 11},
{1, 6, 7, 2}, /* 10 */
{14, 21, 22, 15},
{11, 0, 3, 10},
{20, 19, 18, 23},
{3, 2, 8, 9}, /* 14 */
{17, 16, 22, 23},
{4, 5, 1, 0},
{20, 21, 13, 12},
{2, 7, 8, -1}, /* 18 */
{16, 15, 22, -1},
{5, 6, 1, -1},
{13, 21, 14, -1},
{10, 3, 9, -1},
{18, 17, 23, -1},
{11, 4, 0, -1},
{20, 12, 19, -1},
};
#define NBOXFACES (sizeof(boxfaces)/sizeof(boxfaces[0]))
/* Draw a box. Bevel as desired. */
void
drawBox(int piece, float xoff, float yoff)
{
int xlen, ylen;
int i, k;
float x, y, z;
float zlen;
float *v;
xlen = xsize[piece];
ylen = ysize[piece];
zlen = zsize[piece];
glColor3ubv(colors[piece]);
glBegin(GL_QUADS);
for (i = 0; i < 18; i++) {
glNormal3fv(boxnormals[i]);
for (k = 0; k < 4; k++) {
if (boxfaces[i][k] == -1)
continue;
v = boxcoords[boxfaces[i][k]];
x = v[0] + OFFSETX;
if (v[0] > 0.5)
x += xlen - 1;
y = v[1] + OFFSETY;
if (v[1] > 0.5)
y += ylen - 1;
z = v[2] + OFFSETZ;
if (v[2] > 0.5)
z += zlen - 1;
glVertex3f(xoff + x, yoff + y, z);
}
}
glEnd();
glBegin(GL_TRIANGLES);
for (i = 18; i < NBOXFACES; i++) {
glNormal3fv(boxnormals[i]);
for (k = 0; k < 3; k++) {
if (boxfaces[i][k] == -1)
continue;
v = boxcoords[boxfaces[i][k]];
x = v[0] + OFFSETX;
if (v[0] > 0.5)
x += xlen - 1;
y = v[1] + OFFSETY;
if (v[1] > 0.5)
y += ylen - 1;
z = v[2] + OFFSETZ;
if (v[2] > 0.5)
z += zlen - 1;
glVertex3f(xoff + x, yoff + y, z);
}
}
glEnd();
}
float containercoords[][3] =
{
{-0.1, -0.1, 1.0},
{-0.1, -0.1, -0.1},
{4.1, -0.1, -0.1},
{4.1, -0.1, 1.0},
{1.0, -0.1, 0.6}, /* 4 */
{3.0, -0.1, 0.6},
{1.0, -0.1, 0.0},
{3.0, -0.1, 0.0},
{1.0, 0.0, 0.0}, /* 8 */
{3.0, 0.0, 0.0},
{3.0, 0.0, 0.6},
{1.0, 0.0, 0.6},
{0.0, 0.0, 1.0}, /* 12 */
{4.0, 0.0, 1.0},
{4.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 5.0, 0.0}, /* 16 */
{0.0, 5.0, 1.0},
{4.0, 5.0, 1.0},
{4.0, 5.0, 0.0},
{-0.1, 5.1, -0.1}, /* 20 */
{4.1, 5.1, -0.1},
{4.1, 5.1, 1.0},
{-0.1, 5.1, 1.0},
};
float containernormals[][3] =
{
{0, -1, 0},
{0, -1, 0},
{0, -1, 0},
{0, -1, 0},
{0, -1, 0},
{0, 1, 0},
{0, 1, 0},
{0, 1, 0},
{1, 0, 0},
{1, 0, 0},
{1, 0, 0},
{-1, 0, 0},
{-1, 0, 0},
{-1, 0, 0},
{0, 1, 0},
{0, 0, -1},
{0, 0, -1},
{0, 0, 1},
{0, 0, 1},
{0, 0, 1},
{0, 0, 1},
{0, 0, 1},
{0, 0, 1},
{0, 0, 1},
};
int containerfaces[][4] =
{
{1, 6, 4, 0},
{0, 4, 5, 3},
{1, 2, 7, 6},
{7, 2, 3, 5},
{16, 19, 18, 17},
{23, 22, 21, 20},
{12, 11, 8, 15},
{10, 13, 14, 9},
{15, 16, 17, 12},
{2, 21, 22, 3},
{6, 8, 11, 4},
{1, 0, 23, 20},
{14, 13, 18, 19},
{9, 7, 5, 10},
{12, 13, 10, 11},
{1, 20, 21, 2},
{4, 11, 10, 5},
{15, 8, 19, 16},
{19, 8, 9, 14},
{8, 6, 7, 9},
{0, 3, 13, 12},
{13, 3, 22, 18},
{18, 22, 23, 17},
{17, 23, 0, 12},
};
#define NCONTFACES (sizeof(containerfaces)/sizeof(containerfaces[0]))
/* Draw the container */
void
drawContainer(void)
{
int i, k;
float *v;
/* Y is reversed here because the model has it reversed */
/* Arbitrary bright wood-like color */
glColor3ub(209, 103, 23);
glBegin(GL_QUADS);
for (i = 0; i < NCONTFACES; i++) {
v = containernormals[i];
glNormal3f(v[0], -v[1], v[2]);
for (k = 3; k >= 0; k--) {
v = containercoords[containerfaces[i][k]];
glVertex3f(v[0] + OFFSETX, -(v[1] + OFFSETY), v[2] + OFFSETZ);
}
}
glEnd();
}
void
drawAll(void)
{
int i, j;
int piece;
char done[PIECES + 1];
float m[4][4];
build_rotmatrix(m, curquat);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -10);
glMultMatrixf(&(m[0][0]));
glRotatef(180, 0, 0, 1);
if (depth) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} else {
glClear(GL_COLOR_BUFFER_BIT);
}
for (i = 1; i <= PIECES; i++) {
done[i] = 0;
}
glLoadName(0);
drawContainer();
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
piece = thePuzzle[i][j];
if (piece == 0)
continue;
if (done[piece])
continue;
done[piece] = 1;
glLoadName(piece);
if (piece == movingPiece) {
drawBox(piece, move_x, move_y);
} else {
drawBox(piece, j, i);
}
}
}
}
void
redraw(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1.0, 0.1, 100.0);
drawAll();
if (doubleBuffer)
glutSwapBuffers();
else
glFinish();
}
void
solidifyChain(struct puzzle *puzzle)
{
int i;
char buf[256];
i = 0;
while (puzzle->backptr) {
i++;
puzzle->backptr->solnptr = puzzle;
puzzle = puzzle->backptr;
}
sprintf(buf, "%d moves to complete!", i);
glutSetWindowTitle(buf);
}
int
addConfig(Config config, struct puzzle *back)
{
unsigned hashvalue;
struct puzzle *newpiece;
struct puzzlelist *newlistentry;
hashvalue = hash(config);
newpiece = hashtable[hashvalue % HASHSIZE];
while (newpiece != NULL) {
if (newpiece->hashvalue == hashvalue) {
int i, j;
for (i = 0; i < WIDTH; i++) {
for (j = 0; j < HEIGHT; j++) {
if (convert[config[j][i]] !=
convert[newpiece->pieces[j][i]])
goto nomatch;
}
}
return 0;
}
nomatch:
newpiece = newpiece->next;
}
newpiece = (struct puzzle *) malloc(sizeof(struct puzzle));
newpiece->next = hashtable[hashvalue % HASHSIZE];
newpiece->hashvalue = hashvalue;
memcpy(newpiece->pieces, config, HEIGHT * WIDTH);
newpiece->backptr = back;
newpiece->solnptr = NULL;
hashtable[hashvalue % HASHSIZE] = newpiece;
newlistentry = (struct puzzlelist *) malloc(sizeof(struct puzzlelist));
newlistentry->puzzle = newpiece;
newlistentry->next = NULL;
if (lastentry) {
lastentry->next = newlistentry;
} else {
puzzles = newlistentry;
}
lastentry = newlistentry;
if (back == NULL) {
startPuzzle = newpiece;
}
if (solution(config)) {
solidifyChain(newpiece);
return 1;
}
return 0;
}
/* Checks if a space can move */
int
canmove0(Config pieces, int x, int y, int dir, Config newpieces)
{
char piece;
int xadd, yadd;
int l, m;
xadd = xadds[dir];
yadd = yadds[dir];
if (x + xadd < 0 || x + xadd >= WIDTH ||
y + yadd < 0 || y + yadd >= HEIGHT)
return 0;
piece = pieces[y + yadd][x + xadd];
if (piece == 0)
return 0;
memcpy(newpieces, pieces, HEIGHT * WIDTH);
for (l = 0; l < WIDTH; l++) {
for (m = 0; m < HEIGHT; m++) {
if (newpieces[m][l] == piece)
newpieces[m][l] = 0;
}
}
xadd = -xadd;
yadd = -yadd;
for (l = 0; l < WIDTH; l++) {
for (m = 0; m < HEIGHT; m++) {
if (pieces[m][l] == piece) {
int newx, newy;
newx = l + xadd;
newy = m + yadd;
if (newx < 0 || newx >= WIDTH ||
newy < 0 || newy >= HEIGHT)
return 0;
if (newpieces[newy][newx] != 0)
return 0;
newpieces[newy][newx] = piece;
}
}
}
return 1;
}
/* Checks if a piece can move */
int
canmove(Config pieces, int x, int y, int dir, Config newpieces)
{
int xadd, yadd;
xadd = xadds[dir];
yadd = yadds[dir];
if (x + xadd < 0 || x + xadd >= WIDTH ||
y + yadd < 0 || y + yadd >= HEIGHT)
return 0;
if (pieces[y + yadd][x + xadd] == pieces[y][x]) {
return canmove(pieces, x + xadd, y + yadd, dir, newpieces);
}
if (pieces[y + yadd][x + xadd] != 0)
return 0;
return canmove0(pieces, x + xadd, y + yadd, (dir + 2) % 4, newpieces);
}
int
generateNewConfigs(struct puzzle *puzzle)
{
int i, j, k;
Config pieces;
Config newpieces;
memcpy(pieces, puzzle->pieces, HEIGHT * WIDTH);
for (i = 0; i < WIDTH; i++) {
for (j = 0; j < HEIGHT; j++) {
if (pieces[j][i] == 0) {
for (k = 0; k < 4; k++) {
if (canmove0(pieces, i, j, k, newpieces)) {
if (addConfig(newpieces, puzzle))
return 1;
}
}
}
}
}
return 0;
}
void
freeSolutions(void)
{
struct puzzlelist *nextpuz;
struct puzzle *puzzle, *next;
int i;
while (puzzles) {
nextpuz = puzzles->next;
free((char *) puzzles);
puzzles = nextpuz;
}
lastentry = NULL;
for (i = 0; i < HASHSIZE; i++) {
puzzle = hashtable[i];
hashtable[i] = NULL;
while (puzzle) {
next = puzzle->next;
free((char *) puzzle);
puzzle = next;
}
}
startPuzzle = NULL;
}
int
continueSolving(void)
{
struct puzzle *nextpuz;
int i, j;
int movedPiece;
int movedir;
int fromx, fromy;
int tox, toy;
if (startPuzzle == NULL)
return 0;
if (startPuzzle->solnptr == NULL) {
freeSolutions();
return 0;
}
nextpuz = startPuzzle->solnptr;
movedPiece = 0;
movedir = 0;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
if (startPuzzle->pieces[i][j] != nextpuz->pieces[i][j]) {
if (startPuzzle->pieces[i][j]) {
movedPiece = startPuzzle->pieces[i][j];
fromx = j;
fromy = i;
if (i < HEIGHT - 1 && nextpuz->pieces[i + 1][j] == movedPiece) {
movedir = 3;
} else {
movedir = 2;
}
goto found_piece;
} else {
movedPiece = nextpuz->pieces[i][j];
if (i < HEIGHT - 1 &&
startPuzzle->pieces[i + 1][j] == movedPiece) {
fromx = j;
fromy = i + 1;
movedir = 1;
} else {
fromx = j + 1;
fromy = i;
movedir = 0;
}
goto found_piece;
}
}
}
}
glutSetWindowTitle("What! No change?");
freeSolutions();
return 0;
found_piece:
if (!movingPiece) {
movingPiece = movedPiece;
move_x = fromx;
move_y = fromy;
}
move_x += xadds[movedir] * MOVE_SPEED;
move_y += yadds[movedir] * MOVE_SPEED;
tox = fromx + xadds[movedir];
toy = fromy + yadds[movedir];
if (move_x > tox - MOVE_SPEED / 2 && move_x < tox + MOVE_SPEED / 2 &&
move_y > toy - MOVE_SPEED / 2 && move_y < toy + MOVE_SPEED / 2) {
startPuzzle = nextpuz;
movingPiece = 0;
}
memcpy(thePuzzle, startPuzzle->pieces, HEIGHT * WIDTH);
changeState();
return 1;
}
int
solvePuzzle(void)
{
struct puzzlelist *nextpuz;
char buf[256];
int i;
if (solution(thePuzzle)) {
glutSetWindowTitle("Puzzle already solved!");
return 0;
}
addConfig(thePuzzle, NULL);
i = 0;
while (puzzles) {
i++;
if (generateNewConfigs(puzzles->puzzle))
break;
nextpuz = puzzles->next;
free((char *) puzzles);
puzzles = nextpuz;
}
if (puzzles == NULL) {
freeSolutions();
sprintf(buf, "I can't solve it! (%d positions examined)", i);
glutSetWindowTitle(buf);
return 1;
}
return 1;
}
int
selectPiece(int mousex, int mousey)
{
long hits;
GLuint selectBuf[1024];
GLuint closest;
GLuint dist;
glSelectBuffer(1024, selectBuf);
(void) glRenderMode(GL_SELECT);
glInitNames();
/* Because LoadName() won't work with no names on the stack */
glPushName(-1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(mousex, H - mousey, 4, 4, viewport);
gluPerspective(45, 1.0, 0.1, 100.0);
drawAll();
hits = glRenderMode(GL_RENDER);
if (hits <= 0) {
return 0;
}
closest = 0;
dist = 4294967295U;
while (hits) {
if (selectBuf[(hits - 1) * 4 + 1] < dist) {
dist = selectBuf[(hits - 1) * 4 + 1];
closest = selectBuf[(hits - 1) * 4 + 3];
}
hits--;
}
return closest;
}
void
nukePiece(int piece)
{
int i, j;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
if (thePuzzle[i][j] == piece) {
thePuzzle[i][j] = 0;
}
}
}
}
void
multMatrices(const GLfloat a[16], const GLfloat b[16], GLfloat r[16])
{
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
r[i * 4 + j] =
a[i * 4 + 0] * b[0 * 4 + j] +
a[i * 4 + 1] * b[1 * 4 + j] +
a[i * 4 + 2] * b[2 * 4 + j] +
a[i * 4 + 3] * b[3 * 4 + j];
}
}
}
void
makeIdentity(GLfloat m[16])
{
m[0 + 4 * 0] = 1;
m[0 + 4 * 1] = 0;
m[0 + 4 * 2] = 0;
m[0 + 4 * 3] = 0;
m[1 + 4 * 0] = 0;
m[1 + 4 * 1] = 1;
m[1 + 4 * 2] = 0;
m[1 + 4 * 3] = 0;
m[2 + 4 * 0] = 0;
m[2 + 4 * 1] = 0;
m[2 + 4 * 2] = 1;
m[2 + 4 * 3] = 0;
m[3 + 4 * 0] = 0;
m[3 + 4 * 1] = 0;
m[3 + 4 * 2] = 0;
m[3 + 4 * 3] = 1;
}
/*
** inverse = invert(src)
*/
int
invertMatrix(const GLfloat src[16], GLfloat inverse[16])
{
int i, j, k, swap;
double t;
GLfloat temp[4][4];
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
temp[i][j] = src[i * 4 + j];
}
}
makeIdentity(inverse);
for (i = 0; i < 4; i++) {
/*
** Look for largest element in column */
swap = i;
for (j = i + 1; j < 4; j++) {
if (fabs(temp[j][i]) > fabs(temp[i][i])) {
swap = j;
}
}
if (swap != i) {
/*
** Swap rows. */
for (k = 0; k < 4; k++) {
t = temp[i][k];
temp[i][k] = temp[swap][k];
temp[swap][k] = t;
t = inverse[i * 4 + k];
inverse[i * 4 + k] = inverse[swap * 4 + k];
inverse[swap * 4 + k] = t;
}
}
if (temp[i][i] == 0) {
/*
** No non-zero pivot. The matrix is singular, which
shouldn't ** happen. This means the user gave us a
bad matrix. */
return 0;
}
t = temp[i][i];
for (k = 0; k < 4; k++) {
temp[i][k] /= t;
inverse[i * 4 + k] /= t;
}
for (j = 0; j < 4; j++) {
if (j != i) {
t = temp[j][i];
for (k = 0; k < 4; k++) {
temp[j][k] -= temp[i][k] * t;
inverse[j * 4 + k] -= inverse[i * 4 + k] * t;
}
}
}
}
return 1;
}
/*
** This is a screwball function. What it does is the following:
** Given screen x and y coordinates, compute the corresponding object space
** x and y coordinates given that the object space z is 0.9 + OFFSETZ.
** Since the tops of (most) pieces are at z = 0.9 + OFFSETZ, we use that
** number.
*/
int
computeCoords(int piece, int mousex, int mousey,
GLfloat * selx, GLfloat * sely)
{
GLfloat modelMatrix[16];
GLfloat projMatrix[16];
GLfloat finalMatrix[16];
GLfloat in[4];
GLfloat a, b, c, d;
GLfloat top, bot;
GLfloat z;
GLfloat w;
GLfloat height;
if (piece == 0)
return 0;
height = zsize[piece] - 0.1 + OFFSETZ;
glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
multMatrices(modelMatrix, projMatrix, finalMatrix);
if (!invertMatrix(finalMatrix, finalMatrix))
return 0;
in[0] = (2.0 * (mousex - viewport[0]) / viewport[2]) - 1;
in[1] = (2.0 * ((H - mousey) - viewport[1]) / viewport[3]) - 1;
a = in[0] * finalMatrix[0 * 4 + 2] +
in[1] * finalMatrix[1 * 4 + 2] +
finalMatrix[3 * 4 + 2];
b = finalMatrix[2 * 4 + 2];
c = in[0] * finalMatrix[0 * 4 + 3] +
in[1] * finalMatrix[1 * 4 + 3] +
finalMatrix[3 * 4 + 3];
d = finalMatrix[2 * 4 + 3];
/*
** Ok, now we need to solve for z: ** (a + b z) / (c + d
z) = height. ** ("height" is the height in object space we
want to solve z for) ** ** ==> a + b z = height c +
height d z ** bz - height d z = height c - a ** z =
(height c - a) / (b - height d) */
top = height * c - a;
bot = b - height * d;
if (bot == 0.0)
return 0;
z = top / bot;
/*
** Ok, no problem. ** Now we solve for x and y. We know
that w = c + d z, so we compute it. */
w = c + d * z;
/*
** Now for x and y: */
*selx = (in[0] * finalMatrix[0 * 4 + 0] +
in[1] * finalMatrix[1 * 4 + 0] +
z * finalMatrix[2 * 4 + 0] +
finalMatrix[3 * 4 + 0]) / w - OFFSETX;
*sely = (in[0] * finalMatrix[0 * 4 + 1] +
in[1] * finalMatrix[1 * 4 + 1] +
z * finalMatrix[2 * 4 + 1] +
finalMatrix[3 * 4 + 1]) / w - OFFSETY;
return 1;
}
static int selected;
static int selectx, selecty;
static float selstartx, selstarty;
void
grabPiece(int piece, float selx, float sely)
{
int hit;
selectx = selx;
selecty = sely;
if (selectx < 0 || selecty < 0 || selectx >= WIDTH || selecty >= HEIGHT) {
return;
}
hit = thePuzzle[selecty][selectx];
if (hit != piece)
return;
if (hit) {
movingPiece = hit;
while (selectx > 0 && thePuzzle[selecty][selectx - 1] == movingPiece) {
selectx--;
}
while (selecty > 0 && thePuzzle[selecty - 1][selectx] == movingPiece) {
selecty--;
}
move_x = selectx;
move_y = selecty;
selected = 1;
selstartx = selx;
selstarty = sely;
} else {
selected = 0;
}
changeState();
}
void
moveSelection(float selx, float sely)
{
float deltax, deltay;
int dir;
Config newpieces;
if (!selected)
return;
deltax = selx - selstartx;
deltay = sely - selstarty;
if (fabs(deltax) > fabs(deltay)) {
deltay = 0;
if (deltax > 0) {
if (deltax > 1)
deltax = 1;
dir = 2;
} else {
if (deltax < -1)
deltax = -1;
dir = 0;
}
} else {
deltax = 0;
if (deltay > 0) {
if (deltay > 1)
deltay = 1;
dir = 3;
} else {
if (deltay < -1)
deltay = -1;
dir = 1;
}
}
if (canmove(thePuzzle, selectx, selecty, dir, newpieces)) {
move_x = deltax + selectx;
move_y = deltay + selecty;
if (deltax > 0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selectx++;
selstartx++;
} else if (deltax < -0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selectx--;
selstartx--;
} else if (deltay > 0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selecty++;
selstarty++;
} else if (deltay < -0.5) {
memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
selecty--;
selstarty--;
}
} else {
if (deltay > 0 && thePuzzle[selecty][selectx] == 10 &&
selectx == 1 && selecty == 3) {
/* Allow visual movement of solution piece outside of the
box */
move_x = selectx;
move_y = sely - selstarty + selecty;
} else {
move_x = selectx;
move_y = selecty;
}
}
}
void
dropSelection(void)
{
if (!selected)
return;
movingPiece = 0;
selected = 0;
changeState();
}
static int left_mouse, middle_mouse;
static int mousex, mousey;
static int solving;
static int spinning;
static float lastquat[4];
static int sel_piece;
static void
Reshape(int width, int height)
{
W = width;
H = height;
glViewport(0, 0, W, H);
glGetIntegerv(GL_VIEWPORT, viewport);
}
void
toggleSolve(void)
{
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
} else {
glutChangeToMenuEntry(1, "Stop solving", 1);
glutSetWindowTitle("Solving...");
if (solvePuzzle()) {
solving = 1;
}
}
changeState();
glutPostRedisplay();
}
void reset(void)
{
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
movingPiece = 0;
changeState();
}
glutSetWindowTitle("glpuzzle");
memcpy(thePuzzle, startConfig, HEIGHT * WIDTH);
glutPostRedisplay();
}
void
keyboard(unsigned char c, int x, int y)
{
int piece;
switch (c) {
case 27:
exit(0);
break;
case 'D':
case 'd':
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
changeState();
}
piece = selectPiece(x, y);
if (piece) {
nukePiece(piece);
}
glutPostRedisplay();
break;
case 'R':
case 'r':
reset();
break;
case 'S':
case 's':
toggleSolve();
break;
case 'b':
case 'B':
depth = 1 - depth;
if (depth) {
glEnable(GL_DEPTH_TEST);
} else {
glDisable(GL_DEPTH_TEST);
}
glutPostRedisplay();
break;
default:
break;
}
}
void
motion(int x, int y)
{
float selx, sely;
if (middle_mouse && !left_mouse) {
if (mousex != x || mousey != y) {
trackball(lastquat,
(2.0*mousex - W) / W,
(H - 2.0*mousey) / H,
(2.0*x - W) / W,
(H - 2.0*y) / H);
spinning = 1;
} else {
spinning = 0;
}
changeState();
} else {
computeCoords(sel_piece, x, y, &selx, &sely);
moveSelection(selx, sely);
}
mousex = x;
mousey = y;
glutPostRedisplay();
}
void
mouse(int b, int s, int x, int y)
{
float selx, sely;
mousex = x;
mousey = y;
curX = x;
curY = y;
if (s == GLUT_DOWN) {
switch (b) {
case GLUT_LEFT_BUTTON:
if (solving) {
freeSolutions();
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
movingPiece = 0;
}
left_mouse = GL_TRUE;
sel_piece = selectPiece(mousex, mousey);
if (computeCoords(sel_piece, mousex, mousey, &selx, &sely)) {
grabPiece(sel_piece, selx, sely);
}
glutPostRedisplay();
break;
case GLUT_MIDDLE_BUTTON:
middle_mouse = GL_TRUE;
glutPostRedisplay();
break;
}
} else {
switch (b) {
case GLUT_LEFT_BUTTON:
left_mouse = GL_FALSE;
dropSelection();
glutPostRedisplay();
break;
case GLUT_MIDDLE_BUTTON:
middle_mouse = GL_FALSE;
glutPostRedisplay();
break;
}
}
motion(x, y);
}
void
animate(void)
{
if (spinning) {
add_quats(lastquat, curquat, curquat);
}
glutPostRedisplay();
if (solving) {
if (!continueSolving()) {
solving = 0;
glutChangeToMenuEntry(1, "Solving", 1);
glutSetWindowTitle("glpuzzle");
}
}
if (!solving && !spinning && !visible) {
glutIdleFunc(NULL);
}
}
void
changeState(void)
{
if (visible) {
if (!solving && !spinning) {
glutIdleFunc(NULL);
} else {
glutIdleFunc(animate);
}
} else {
glutIdleFunc(NULL);
}
}
void
init(void)
{
static float lmodel_ambient[] =
{0.0, 0.0, 0.0, 0.0};
static float lmodel_twoside[] =
{GL_FALSE};
static float lmodel_local[] =
{GL_FALSE};
static float light0_ambient[] =
{0.1, 0.1, 0.1, 1.0};
static float light0_diffuse[] =
{1.0, 1.0, 1.0, 0.0};
static float light0_position[] =
{0.8660254, 0.5, 1, 0};
static float light0_specular[] =
{0.0, 0.0, 0.0, 0.0};
static float bevel_mat_ambient[] =
{0.0, 0.0, 0.0, 1.0};
static float bevel_mat_shininess[] =
{40.0};
static float bevel_mat_specular[] =
{0.0, 0.0, 0.0, 0.0};
static float bevel_mat_diffuse[] =
{1.0, 0.0, 0.0, 0.0};
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
glClearColor(0.5, 0.5, 0.5, 0.0);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glEnable(GL_LIGHT0);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient);
glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess);
glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular);
glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_FLAT);
trackball(curquat, 0.0, 0.0, 0.0, 0.0);
srandom(time(NULL));
}
static void
Usage(void)
{
printf("Usage: puzzle [-s]\n");
printf(" -s: Run in single buffered mode\n");
exit(-1);
}
void
visibility(int v)
{
if (v == GLUT_VISIBLE) {
visible = 1;
} else {
visible = 0;
}
changeState();
}
void
menu(int choice)
{
switch(choice) {
case 1:
toggleSolve();
break;
case 2:
reset();
break;
case 3:
exit(0);
break;
}
}
int
main(int argc, char **argv)
{
long i;
glutInit(&argc, argv);
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 's':
doubleBuffer = 0;
break;
default:
Usage();
}
} else {
Usage();
}
}
glutInitWindowSize(W, H);
if (doubleBuffer) {
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
} else {
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_SINGLE | GLUT_MULTISAMPLE);
}
glutCreateWindow("glpuzzle");
init();
glGetIntegerv(GL_VIEWPORT, viewport);
printf("\n");
printf("r Reset puzzle\n");
printf("s Solve puzzle (may take a few seconds to compute)\n");
printf("d Destroy a piece - makes the puzzle easier\n");
printf("b Toggles the depth buffer on and off\n");
printf("\n");
printf("Left mouse moves pieces\n");
printf("Middle mouse spins the puzzle\n");
printf("Right mouse has menu\n");
glutReshapeFunc(Reshape);
glutDisplayFunc(redraw);
glutKeyboardFunc(keyboard);
glutMotionFunc(motion);
glutMouseFunc(mouse);
glutVisibilityFunc(visibility);
glutCreateMenu(menu);
glutAddMenuEntry("Solve", 1);
glutAddMenuEntry("Reset", 2);
glutAddMenuEntry("Quit", 3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
More info. on selection/picking is here.
Animation
simpleanim.c - simple animation
simpleanim_doublebuffer.exe
simpleanim_singlebuffer.exe
view code
// code based on example from
// http://www.site.uottawa.ca/~nbobic/csi4130/Animation.htm
/** This program demonstrates the use of GLUT to create a window
* in which we will use OpenGL drawing commands and to add a
* display callback function to this window. We will also show
* the use of the idle callback function for animation
*/
/*@{*/
#include
#include
#include "glut.h"
/** the angle of rotation of our object.
*/
int angle = 0;
/** display callback function.
* This function is called everytime a display event is generated.
* It clears the screen and redraws the cube rotated by "angle" about
* the y axis.
*/
void display (void)
{
glClear (GL_COLOR_BUFFER_BIT); /* clear the opengl area */
glPushMatrix();
glRotatef(-20,1,0,0);
glRotatef(angle,0,1,0); /* Do the rotation */
glutWireCube(0.9); /* Draw the cube */
glutSwapBuffers();
glPopMatrix();
}
/** Animation function used as the idle callback function.
* This function Increases the rotation angle and then calls for
* another display event to be signalled.
*/
void animate (void)
{
angle += 2;
glutPostRedisplay(); /* Signal for display event */
}
/** main function.
* This function initialises the GLUT graphics library, and creates a
* window. It then enters the event loop waiting for display events.
*/
int main (int argc, char **argv)
{
glutInit (&argc, argv); /* Initialise glut */
glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE); /* Initialise the display mode */
glutCreateWindow ("simple animation demo"); /* create your window */
glutDisplayFunc(display); /* Set up the display callback */
/**********************/
glutIdleFunc(animate); /* Set up the animation function */
/**********************/
glutMainLoop (); /* Enter the event processing loop */
}
/*@}*/
animate.c - another simple animation
animate.exe
view code
/************************************************************
Add Opengl32.lib glu32.lib glut32.lib to
Project->Setting->Link->General->Object/Library Modules.
*************************************************************/
// Source: http://www.site.uottawa.ca/~nbobic/csi4130
#include "glut.h"
#include
#define M_PI (4*atan(1))
/* animation step */
int step;
void circle( GLint res, GLfloat radius ){
int i;
glBegin(GL_POLYGON);
for (i=0;i 1.0)
glOrtho(0.0,100.0*ar,0.0,100.0,10.0,-10.0);
else
glOrtho(0.0,100.0,0.0,100.0/ar,10.0,-10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void animate(int value){
/* stop after 30 steps */
if(value == 30)
{
// return;
value=0;
step=0;
}
glutPostRedisplay();
step++;
/* call animate again in 200 mili-Secs */
glutTimerFunc(200,animate,step);
}
void menuControl(int value){
switch (value){
case 1:
/* call animate in 200 mili-Secs */
glutTimerFunc(200,animate,step);
break;
case 2:
step = 0;
/* call animate in 200 mili-Secs */
glutTimerFunc(200,animate,step);
break;
case 101:
exit(1);
break;
}
}
int main(int argc,char **argv){
glutInit(&argc,argv);
/* window definition and creation */
/* the viewport is the same as window coords */
glutInitWindowSize(800,800);
glutInitWindowPosition(50,50);
glutCreateWindow("Animation: Flickering");
/* the reshape function */
glutReshapeFunc(reshapeWin);
/* the display function */
glutDisplayFunc(displayWin);
glutCreateMenu(menuControl);
glutAddMenuEntry("Start",1);
glutAddMenuEntry("Restart",2);
glutAddMenuEntry("Exit",101);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
return 0;
}
gears.c - gears
gears.exe
view code
pendulum.c - pendulum
pendulum.exe
view code
origami.c - origami
origami.exe
view code
/* Copyright (c) Mark J. Kilgard, 1994. */
/* This program is freely distributable without licensing fees
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
#include
#include
#include
#define GL_EXT_polygon_offset 0 /* be safe */
/* Uses EXT_polygon_offset extension if available to better
render the fold outlines. */
#if GL_EXT_polygon_offset
int polygon_offset;
#endif
enum {
FLAT, /* completely flat sheet of paper */
FLAP1, /* left flap being folded in */
FLAP2, /* right flap being folded int */
CENTER2, /* right side folded up at center */
WING2, /* right wing folded down */
CENTER1, /* left side folded up at center */
WING1, /* left wing folded down */
FOLDED /* fully folded paper airplane */
} States;
int motion = 1;
int spinning = 1;
int state = FLAT;
int click = 0;
int delay = 0;
int direction;
float flap1_angle = 0;
float flap2_angle = 0;
float center1_angle = 0;
float center2_angle = 0;
float wing1_angle = 0;
float wing2_angle = 0;
/**
These correspond to the polygons for the paper sections:
+----------+----------+
| /|\ |
| 2 / | \ 3 |
| / | \ |
+------/ | \------+
| /| | |\ |
| 1 / | | | \ 4 |
| / | | | \ |
| / | | | \ |
| / | 5 | 6 | \ |
|/ | | | \|
+ | | | +
| 7 | | | 8 |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
+------+---+---+------+
*/
typedef GLfloat Point[2];
Point poly1[] =
{
{-1, 0},
{-1 / 3.0, 2 / 3.0},
{-1, 2 / 3.0}
};
Point poly2[] =
{
{-1, 1},
{-1, 2 / 3.0},
{-1 / 3.0, 2 / 3.0},
{0, 1}
};
Point poly3[] =
{
{0, 1},
{1, 1},
{1, 2 / 3.0},
{1 / 3.0, 2 / 3.0}
};
Point poly4[] =
{
{1 / 3.0, 2 / 3.0},
{1, 2 / 3.0},
{1, 0}
};
Point poly5[] =
{
{-1 / 3.0, 2 / 3.0},
{0, 1},
{0, -1.5},
{-1 / 3.0, -1.5}
};
Point poly6[] =
{
{0, 1},
{1 / 3.0, 2 / 3.0},
{1 / 3.0, -1.5},
{0, -1.5}
};
Point poly7[] =
{
{-1, 0},
{-1 / 3.0, 2 / 3.0},
{-1 / 3.0, -1.5},
{-1, -1.5}
};
Point poly8[] =
{
{1, 0},
{1 / 3.0, 2 / 3.0},
{1 / 3.0, -1.5},
{1, -1.5}
};
void
polydlist(int dlist, int num, Point points[])
{
int i;
glNewList(dlist, GL_COMPILE);
glBegin(GL_POLYGON);
for (i = 0; i < num; i++) {
glVertex2fv(&points[i][0]);
}
glEnd();
glEndList();
}
void
idle(void)
{
if (spinning)
click++;
switch (state) {
case FLAT:
delay++;
if (delay >= 80) {
delay = 0;
state = FLAP1;
glutSetWindowTitle("origami (folding)");
direction = 1;
}
break;
case FLAP1:
flap1_angle += 2 * direction;
if (flap1_angle >= 180) {
state = FLAP2;
} else if (flap1_angle <= 0) {
state = FLAT;
}
break;
case FLAP2:
flap2_angle += 2 * direction;
if (flap2_angle >= 180) {
state = CENTER2;
} else if (flap2_angle <= 0) {
state = FLAP1;
}
break;
case CENTER2:
center2_angle += 2 * direction;
if (center2_angle >= 84) {
state = WING2;
} else if (center2_angle <= 0) {
state = FLAP2;
}
break;
case WING2:
wing2_angle += 2 * direction;
if (wing2_angle >= 84) {
state = CENTER1;
} else if (wing2_angle <= 0) {
state = CENTER2;
}
break;
case CENTER1:
center1_angle += 2 * direction;
if (center1_angle >= 84) {
state = WING1;
} else if (center1_angle <= 0) {
state = WING2;
}
break;
case WING1:
wing1_angle += 2 * direction;
if (wing1_angle >= 84) {
state = FOLDED;
} else if (wing1_angle <= 0) {
state = CENTER1;
}
break;
case FOLDED:
delay++;
if (delay >= 80) {
delay = 0;
glutSetWindowTitle("origami (unfolding)");
direction = -1;
state = WING1;
}
break;
}
glutPostRedisplay();
}
void
draw_folded_plane(void)
{
/* *INDENT-OFF* */
glPushMatrix();
glRotatef(click, 0, 0, 1);
glRotatef(click / 5.0, 0, 1, 0);
glTranslatef(0, .25, 0);
glPushMatrix();
glRotatef(center1_angle, 0, 1, 0);
glPushMatrix();
glTranslatef(-.5, .5, 0);
glRotatef(flap1_angle, 1, 1, 0);
glTranslatef(.5, -.5, 0);
glCallList(2);
glPopMatrix();
glCallList(5);
glPushMatrix();
glTranslatef(-1 / 3.0, 0, 0);
glRotatef(-wing1_angle, 0, 1, 0);
glTranslatef(1 / 3.0, 0, 0);
glCallList(7);
glPushMatrix();
glTranslatef(-.5, .5, 0);
glRotatef(flap1_angle, 1, 1, 0);
glTranslatef(.5, -.5, 0);
glCallList(1);
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPushMatrix();
glRotatef(-center2_angle, 0, 1, 0);
glPushMatrix();
glTranslatef(.5, .5, 0);
glRotatef(-flap2_angle, -1, 1, 0);
glTranslatef(-.5, -.5, 0);
glCallList(3);
glPopMatrix();
glCallList(6);
glPushMatrix();
glTranslatef(1 / 3.0, 0, 0);
glRotatef(wing2_angle, 0, 1, 0);
glTranslatef(-1 / 3.0, 0, 0);
glCallList(8);
glPushMatrix();
glTranslatef(.5, .5, 0);
glRotatef(-flap2_angle, -1, 1, 0);
glTranslatef(-.5, -.5, 0);
glCallList(4);
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
/* *INDENT-ON* */
}
void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glColor3ub(67, 205, 128);
#if GL_EXT_polygon_offset
if (polygon_offset) {
glPolygonOffsetEXT(0.5, 0.0);
glEnable(GL_POLYGON_OFFSET_EXT);
}
#endif
draw_folded_plane();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3ub(255, 255, 255);
#if GL_EXT_polygon_offset
if (polygon_offset) {
glPolygonOffsetEXT(0.0, 0.0);
/* XXX a bug in the unpatched IRIX 5.3 OpenGL posts
GL_INVALID_ENUM when GL_POLYGON_OFFSET_EXT is disabled;
please ignore it. */
glDisable(GL_POLYGON_OFFSET_EXT);
} else {
glPushMatrix();
glTranslatef(0, 0, .05);
}
#else
glPushMatrix();
glTranslatef(0, 0, .05);
#endif
draw_folded_plane();
#if GL_EXT_polygon_offset
if (!polygon_offset) {
glPopMatrix();
}
#else
glPopMatrix();
#endif
glutSwapBuffers();
}
void
visible(int state)
{
if (state == GLUT_VISIBLE) {
if (motion)
glutIdleFunc(idle);
} else {
glutIdleFunc(NULL);
}
}
void
menu(int value)
{
switch (value) {
case 1:
direction = -direction;
if (direction > 0) {
glutSetWindowTitle("origami (folding)");
} else {
glutSetWindowTitle("origami (unfolding)");
}
break;
case 2:
motion = 1 - motion;
if (motion) {
glutIdleFunc(idle);
} else {
glutIdleFunc(NULL);
}
break;
case 3:
spinning = 1 - spinning;
break;
case 666:
exit(0);
}
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("origami");
glutDisplayFunc(display);
glutVisibilityFunc(visible);
glClearColor(.488, .617, .75, 1.0);
glMatrixMode(GL_PROJECTION);
gluPerspective(40.0, 1.0, 0.1, 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, 0, 5.5,
0, 0, 0,
0, 1, 0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glLineWidth(2.0);
polydlist(1, sizeof(poly1) / sizeof(Point), poly1);
polydlist(2, sizeof(poly2) / sizeof(Point), poly2);
polydlist(3, sizeof(poly3) / sizeof(Point), poly3);
polydlist(4, sizeof(poly4) / sizeof(Point), poly4);
polydlist(5, sizeof(poly5) / sizeof(Point), poly5);
polydlist(6, sizeof(poly6) / sizeof(Point), poly6);
polydlist(7, sizeof(poly7) / sizeof(Point), poly7);
polydlist(8, sizeof(poly8) / sizeof(Point), poly8);
glutCreateMenu(menu);
glutAddMenuEntry("Reverse direction", 1);
glutAddMenuEntry("Toggle motion", 2);
glutAddMenuEntry("Toggle spinning", 3);
glutAddMenuEntry("Quit", 666);
glutAttachMenu(GLUT_RIGHT_BUTTON);
#if GL_EXT_polygon_offset
polygon_offset = glutExtensionSupported("GL_EXT_polygon_offset");
#endif
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
noof.c - 'noof'!
noof.exe
view code
/* XXX Very crufty code follows. */
#include
#include "glut.h"
#include
#ifndef _WIN32
#include
#else
#define random rand
#define srandom srand
#endif
/* Some files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#include
#include
/* For portability... */
#undef fcos
#undef fsin
#define fcos cos
#define fsin sin
/* --- shape parameters def'n --- */
#define N_SHAPES 7
float pos[N_SHAPES * 3];
float dir[N_SHAPES * 3];
float acc[N_SHAPES * 3];
float col[N_SHAPES * 3];
float hsv[N_SHAPES * 3];
float hpr[N_SHAPES * 3];
float ang[N_SHAPES];
float spn[N_SHAPES];
float sca[N_SHAPES];
float geep[N_SHAPES];
float peep[N_SHAPES];
float speedsq[N_SHAPES];
int blad[N_SHAPES];
float ht, wd;
void
initshapes(int i)
{
int k;
float f;
/* random init of pos, dir, color */
for (k = i * 3; k <= i * 3 + 2; k++) {
f = random() / 2147483647.0;
pos[k] = f;
f = random() / 2147483647.0;
f = (f - 0.5) * 0.05;
dir[k] = f;
f = random() / 2147483647.0;
f = (f - 0.5) * 0.0002;
acc[k] = f;
f = random() / 2147483647.0;
col[k] = f;
}
speedsq[i] = dir[i * 3] * dir[i * 3] + dir[i * 3 + 1] * dir[i * 3 + 1];
f = random() / 2147483647.0;
blad[i] = 2 + (int) (f * 17.0);
f = random() / 2147483647.0;
ang[i] = f;
f = random() / 2147483647.0;
spn[i] = (f - 0.5) * 40.0 / (10 + blad[i]);
f = random() / 2147483647.0;
sca[i] = (f * 0.1 + 0.08);
dir[i * 3] *= sca[i];
dir[i * 3 + 1] *= sca[i];
f = random() / 2147483647.0;
hsv[i * 3] = f * 360.0;
f = random() / 2147483647.0;
hsv[i * 3 + 1] = f * 0.6 + 0.4;
f = random() / 2147483647.0;
hsv[i * 3 + 2] = f * 0.7 + 0.3;
f = random() / 2147483647.0;
hpr[i * 3] = f * 0.005 * 360.0;
f = random() / 2147483647.0;
hpr[i * 3 + 1] = f * 0.03;
f = random() / 2147483647.0;
hpr[i * 3 + 2] = f * 0.02;
geep[i] = 0;
f = random() / 2147483647.0;
peep[i] = 0.01 + f * 0.2;
}
int tko = 0;
float bladeratio[] =
{
/* nblades = 2..7 */
0.0, 0.0, 3.00000, 1.73205, 1.00000, 0.72654, 0.57735, 0.48157,
/* 8..13 */
0.41421, 0.36397, 0.19076, 0.29363, 0.26795, 0.24648,
/* 14..19 */
0.22824, 0.21256, 0.19891, 0.18693, 0.17633, 0.16687,
};
void
drawleaf(int l)
{
int b, blades;
float x, y;
float wobble;
blades = blad[l];
y = 0.10 * fsin(geep[l] * M_PI / 180.0) + 0.099 * fsin(geep[l] * 5.12 * M_PI / 180.0);
if (y < 0)
y = -y;
x = 0.15 * fcos(geep[l] * M_PI / 180.0) + 0.149 * fcos(geep[l] * 5.12 * M_PI / 180.0);
if (x < 0.0)
x = 0.0 - x;
if (y < 0.001 && x > 0.000002 && ((tko & 0x1) == 0)) {
initshapes(l); /* let it become reborn as something
else */
tko++;
return;
} {
float w1 = fsin(geep[l] * 15.3 * M_PI / 180.0);
wobble = 3.0 + 2.00 * fsin(geep[l] * 0.4 * M_PI / 180.0) + 3.94261 * w1;
}
/**
if(blades == 2) if (y > 3.000*x) y = x*3.000;
if(blades == 3) if (y > 1.732*x) y = x*1.732;
if(blades == 4) if (y > x) y = x;
if(blades == 5) if (y > 0.726*x) y = x*0.726;
if(blades == 6) if (y > 0.577*x) y = x*0.577;
if(blades == 7) if (y > 0.481*x) y = x*0.481;
if(blades == 8) if (y > 0.414*x) y = x*0.414;
*/
if (y > x * bladeratio[blades])
y = x * bladeratio[blades];
for (b = 0; b < blades; b++) {
glPushMatrix();
glTranslatef(pos[l * 3], pos[l * 3 + 1], pos[l * 3 + 2]);
glRotatef(ang[l] + b * (360.0 / blades), 0.0, 0.0, 1.0);
glScalef(wobble * sca[l], wobble * sca[l], wobble * sca[l]);
/**
if(tko & 0x40000) glColor3f(col[l*3], col[l*3+1], col[l*3+2]);
else
*/
glColor4ub(0, 0, 0, 0x60);
/* constrain geep cooridinates here XXX */
glEnable(GL_BLEND);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(x * sca[l], 0.0);
glVertex2f(x, y);
glVertex2f(x, -y); /* C */
glVertex2f(0.3, 0.0); /* D */
glEnd();
/**
if(tko++ & 0x40000) glColor3f(0,0,0);
else
*/
glColor3f(col[l * 3], col[l * 3 + 1], col[l * 3 + 2]);
glBegin(GL_LINE_LOOP);
glVertex2f(x * sca[l], 0.0);
glVertex2f(x, y);
glVertex2f(0.3, 0.0); /* D */
glVertex2f(x, -y); /* C */
glEnd();
glDisable(GL_BLEND);
glPopMatrix();
}
}
void
motionUpdate(int t)
{
if (pos[t * 3] < -sca[t] * wd && dir[t * 3] < 0.0) {
dir[t * 3] = -dir[t * 3];
/**
acc[t*3+1] += 0.8*acc[t*3];
acc[t*3] = -0.8*acc[t*3];
*/
} else if (pos[t * 3] > (1 + sca[t]) * wd && dir[t * 3] > 0.0) {
dir[t * 3] = -dir[t * 3];
/**
acc[t*3+1] += 0.8*acc[t*3];
acc[t*3] = -0.8*acc[t*3];
*/
} else if (pos[t * 3 + 1] < -sca[t] * ht && dir[t * 3 + 1] < 0.0) {
dir[t * 3 + 1] = -dir[t * 3 + 1];
/**
acc[t*3] += 0.8*acc[t*3+1];
acc[t*3+1] = -0.8*acc[t*3+1];
*/
} else if (pos[t * 3 + 1] > (1 + sca[t]) * ht && dir[t * 3 + 1] > 0.0) {
dir[t * 3 + 1] = -dir[t * 3 + 1];
/**
acc[t*3] += 0.8*acc[t*3+1];
acc[t*3+1] = -0.8*acc[t*3+1];
*/
}
pos[t * 3] += dir[t * 3];
pos[t * 3 + 1] += dir[t * 3 + 1];
/**
dir[t*3] += acc[t*3];
dir[t*3+1] += acc[t*3+1];
*/
ang[t] += spn[t];
geep[t] += peep[t];
if (geep[t] > 360 * 5.0)
geep[t] -= 360 * 5.0;
if (ang[t] < 0.0) {
ang[t] += 360.0;
}
if (ang[t] > 360.0) {
ang[t] -= 360.0;
}
}
void
colorUpdate(int i)
{
if (hsv[i * 3 + 1] <= 0.5 && hpr[i * 3 + 1] < 0.0)
hpr[i * 3 + 1] = -hpr[i * 3 + 1]; /* adjust s */
if (hsv[i * 3 + 1] >= 1.0 && hpr[i * 3 + 1] > 0.0)
hpr[i * 3 + 1] = -hpr[i * 3 + 1]; /* adjust s */
if (hsv[i * 3 + 2] <= 0.4 && hpr[i * 3 + 2] < 0.0)
hpr[i * 3 + 2] = -hpr[i * 3 + 2]; /* adjust s */
if (hsv[i * 3 + 2] >= 1.0 && hpr[i * 3 + 2] > 0.0)
hpr[i * 3 + 2] = -hpr[i * 3 + 2]; /* adjust s */
hsv[i * 3] += hpr[i * 3];
hsv[i * 3 + 1] += hpr[i * 3 + 1];
hsv[i * 3 + 2] += hpr[i * 3 + 2];
/* --- hsv -> rgb --- */
#define H(hhh) hhh[i*3 ]
#define S(hhh) hhh[i*3+1]
#define V(hhh) hhh[i*3+2]
#define R(hhh) hhh[i*3 ]
#define G(hhh) hhh[i*3+1]
#define B(hhh) hhh[i*3+2]
if (V(hsv) < 0.0)
V(hsv) = 0.0;
if (V(hsv) > 1.0)
V(hsv) = 1.0;
if (S(hsv) <= 0.0) {
R(col) = V(hsv);
G(col) = V(hsv);
B(col) = V(hsv);
} else {
float f, h, p, q, t, v;
int hi;
while (H(hsv) < 0.0)
H(hsv) += 360.0;
while (H(hsv) >= 360.0)
H(hsv) -= 360.0;
if (S(hsv) < 0.0)
S(hsv) = 0.0;
if (S(hsv) > 1.0)
S(hsv) = 1.0;
h = H(hsv) / 60.0;
hi = (int) (h);
f = h - hi;
v = V(hsv);
p = V(hsv) * (1 - S(hsv));
q = V(hsv) * (1 - S(hsv) * f);
t = V(hsv) * (1 - S(hsv) * (1 - f));
if (hi <= 0) {
R(col) = v;
G(col) = t;
B(col) = p;
} else if (hi == 1) {
R(col) = q;
G(col) = v;
B(col) = p;
} else if (hi == 2) {
R(col) = p;
G(col) = v;
B(col) = t;
} else if (hi == 3) {
R(col) = p;
G(col) = q;
B(col) = v;
} else if (hi == 4) {
R(col) = t;
G(col) = p;
B(col) = v;
} else {
R(col) = v;
G(col) = p;
B(col) = q;
}
}
}
void
gravity(float fx)
{
int a, b;
for (a = 0; a < N_SHAPES; a++) {
for (b = 0; b < a; b++) {
float t, d2;
t = pos[b * 3] - pos[a * 3];
d2 = t * t;
t = pos[b * 3 + 1] - pos[a * 3 + 1];
d2 += t * t;
if (d2 < 0.000001)
d2 = 0.00001;
if (d2 < 0.1) {
float v0, v1, z;
v0 = pos[b * 3] - pos[a * 3];
v1 = pos[b * 3 + 1] - pos[a * 3 + 1];
z = 0.00000001 * fx / (d2);
dir[a * 3] += v0 * z * sca[b];
dir[b * 3] += -v0 * z * sca[a];
dir[a * 3 + 1] += v1 * z * sca[b];
dir[b * 3 + 1] += -v1 * z * sca[a];
}
}
/** apply brakes
if(dir[a*3]*dir[a*3] + dir[a*3+1]*dir[a*3+1]
> 0.0001) {
dir[a*3] *= 0.9;
dir[a*3+1] *= 0.9;
}
*/
}
}
void
oneFrame(void)
{
int i;
/**
if((random() & 0xff) == 0x34){
glClear(GL_COLOR_BUFFER_BIT);
}
if((tko & 0x1f) == 0x1f){
glEnable(GL_BLEND);
glColor4f(0.0, 0.0, 0.0, 0.09);
glRectf(0.0, 0.0, wd, ht);
glDisable(GL_BLEND);
#ifdef __sgi
sginap(0);
#endif
}
*/
gravity(-2.0);
for (i = 0; i < N_SHAPES; i++) {
motionUpdate(i);
#ifdef __sgi
sginap(0);
#endif
colorUpdate(i);
#ifdef __sgi
sginap(0);
#endif
drawleaf(i);
#ifdef __sgi
sginap(0);
#endif
}
glFlush();
}
void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
}
void
myReshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
wd = 1.0;
ht = (GLfloat) h / (GLfloat) w;
glOrtho(0.0, 1.0,
0.0, 1.0 * (GLfloat) h / (GLfloat) w,
-16.0, 4.0);
} else {
wd = (GLfloat) w / (GLfloat) h;
ht = 1.0;
glOrtho(0.0, 1.0 * (GLfloat) w / (GLfloat) h,
0.0, 1.0,
-16.0, 4.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void
visibility(int status)
{
if (status == GLUT_VISIBLE) {
glutIdleFunc(oneFrame);
} else {
glutIdleFunc(NULL);
}
}
void
myinit(void)
{
int i;
srandom(getpid());
glClearColor(0.0, 0.0, 0.0, 1.0);
glEnable(GL_LINE_SMOOTH);
glShadeModel(GL_FLAT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (i = 0; i < N_SHAPES; i++)
initshapes(i);
myReshape(200, 200);
}
/* ARGSUSED1 */
void
keys(unsigned char c, int x, int y)
{
if (c == 0x1b)
exit(0); /* escape */
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(300, 300);
glutCreateWindow(argv[0]);
myinit();
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutKeyboardFunc(keys);
glutVisibilityFunc(visibility);
glutIdleFunc(oneFrame);
glutPostRedisplay();
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
text3d.c - 3D text
text3d.exe
view code
/* Text3d by Robert J. Doyle, Jr., Naval Research Laboratory, Washington, DC. */
#include
#include
#include
#include
#ifndef _WIN32
#include
#endif
#include "glut.h"
typedef enum {RESERVED, M_SIDE, M_EDGE, M_WHOLE, O_SIDE, O_EDGE, O_WHOLE,
T_SIDE, T_EDGE, T_WHOLE, H_SIDE, H_EDGE, H_WHOLE,REPEAT_SIDE, REPEAT_EDGE, REPEAT1,
REPEAT2_SIDE, REPEAT2_EDGE,REPEAT2, REPEAT3_SIDE, REPEAT3_EDGE,REPEAT3,
REPEAT4_SIDE, REPEAT4_EDGE,REPEAT4} displayLists;
GLfloat sideColor[] = {0.0, 0.0, 0.5, 1.0};
GLfloat edgeColor[] = {0.7, 0.7, 0.0, 1.0};
GLfloat shininess[] = {128.0};
GLfloat mat_specular[] = {0.7, 0.7, 0.7, 1.0};
GLfloat width = 0.0;
GLfloat width2 = 2.0;
GLfloat letterM[][3] =
{
{-3.125000, 0.000000, 0.000000},
{-3.125000, 6.208000, 0.000000},
{-1.233000, 6.208000, 0.000000},
{0.003000, 1.484000, 0.000000},
{1.223000, 6.208000, 0.000000},
{3.123000, 6.208000, 0.000000},
{3.123000, 0.000000, 0.000000},
{1.923000, 0.000000, 0.000000},
{1.923000, 5.010000, 0.000000},
{0.659000, 0.000000, 0.000000},
{-0.649000, 0.000000, 0.000000},
{-1.925000, 5.010000, 0.000000},
{-1.925000, 0.000000, 0.000000}
};
GLfloat letterO[][3] =
{
{-3.038000, 3.102000, 0.000000},
{-2.974000, 3.874000, 0.000000},
{-2.827000, 4.440000, 0.000000},
{-2.802000, 4.508000, 0.000000},
{-2.544000, 5.042000, 0.000000},
{-2.502000, 5.110000, 0.000000},
{-2.223000, 5.479000, 0.000000},
{-2.132000, 5.576000, 0.000000},
{-1.784000, 5.869000, 0.000000},
{-1.678000, 5.940000, 0.000000},
{-1.260000, 6.155000, 0.000000},
{-1.148000, 6.198000, 0.000000},
{-0.677000, 6.321000, 0.000000},
{-0.638000, 6.328000, 0.000000},
{-0.002000, 6.378000, 0.000000},
{0.634000, 6.328000, 0.000000},
{1.107000, 6.210000, 0.000000},
{1.144000, 6.198000, 0.000000},
{1.570000, 6.002000, 0.000000},
{1.674000, 5.940000, 0.000000},
{2.038000, 5.661000, 0.000000},
{2.128000, 5.576000, 0.000000},
{2.428000, 5.217000, 0.000000},
{2.504000, 5.104000, 0.000000},
{2.762000, 4.598000, 0.000000},
{2.798000, 4.508000, 0.000000},
{2.960000, 3.913000, 0.000000},
{2.970000, 3.862000, 0.000000},
{3.034000, 3.102000, 0.000000},
{2.970000, 2.342000, 0.000000},
{2.815000, 1.745000, 0.000000},
{2.798000, 1.696000, 0.000000},
{2.554000, 1.182000, 0.000000},
{2.504000, 1.100000, 0.000000},
{2.221000, 0.726000, 0.000000},
{2.128000, 0.628000, 0.000000},
{1.776000, 0.332000, 0.000000},
{1.674000, 0.264000, 0.000000},
{1.256000, 0.049000, 0.000000},
{1.144000, 0.006000, 0.000000},
{0.672000, -0.117000, 0.000000},
{0.634000, -0.124000, 0.000000},
{-0.002000, -0.174000, 0.000000},
{-0.638000, -0.124000, 0.000000},
{-1.112000, -0.006000, 0.000000},
{-1.148000, 0.006000, 0.000000},
{-1.576000, 0.202000, 0.000000},
{-1.678000, 0.264000, 0.000000},
{-2.041000, 0.540000, 0.000000},
{-2.132000, 0.628000, 0.000000},
{-2.430000, 0.983000, 0.000000},
{-2.502000, 1.094000, 0.000000},
{-2.773000, 1.622000, 0.000000},
{-2.802000, 1.696000, 0.000000},
{-2.962000, 2.258000, 0.000000},
{-2.974000, 2.330000, 0.000000},
{-1.736000, 3.102000, 10000.0},
{-1.710000, 3.578000, 0.000000},
{-1.644000, 3.934000, 0.000000},
{-1.503000, 4.328000, 0.000000},
{-1.494000, 4.346000, 0.000000},
{-1.352000, 4.593000, 0.000000},
{-1.306000, 4.656000, 0.000000},
{-1.120000, 4.857000, 0.000000},
{-1.040000, 4.926000, 0.000000},
{-0.825000, 5.067000, 0.000000},
{-0.726000, 5.116000, 0.000000},
{-0.480000, 5.200000, 0.000000},
{-0.402000, 5.218000, 0.000000},
{-0.041000, 5.257000, 0.000000},
{-0.002000, 5.258000, 0.000000},
{0.361000, 5.227000, 0.000000},
{0.400000, 5.220000, 0.000000},
{0.650000, 5.147000, 0.000000},
{0.726000, 5.116000, 0.000000},
{0.950000, 4.990000, 0.000000},
{1.038000, 4.926000, 0.000000},
{1.239000, 4.736000, 0.000000},
{1.306000, 4.656000, 0.000000},
{1.462000, 4.413000, 0.000000},
{1.498000, 4.342000, 0.000000},
{1.635000, 3.964000, 0.000000},
{1.644000, 3.934000, 0.000000},
{1.710000, 3.568000, 0.000000},
{1.736000, 3.102000, 0.000000},
{1.710000, 2.636000, 0.000000},
{1.642000, 2.268000, 0.000000},
{1.508000, 1.886000, 0.000000},
{1.496000, 1.860000, 0.000000},
{1.351000, 1.610000, 0.000000},
{1.304000, 1.546000, 0.000000},
{1.115000, 1.343000, 0.000000},
{1.036000, 1.276000, 0.000000},
{0.823000, 1.135000, 0.000000},
{0.724000, 1.086000, 0.000000},
{0.480000, 1.001000, 0.000000},
{0.400000, 0.984000, 0.000000},
{0.035000, 0.946000, 0.000000},
{-0.002000, 0.946000, 0.000000},
{-0.368000, 0.979000, 0.000000},
{-0.402000, 0.986000, 0.000000},
{-0.653000, 1.057000, 0.000000},
{-0.726000, 1.088000, 0.000000},
{-0.952000, 1.213000, 0.000000},
{-1.040000, 1.278000, 0.000000},
{-1.240000, 1.467000, 0.000000},
{-1.306000, 1.548000, 0.000000},
{-1.460000, 1.788000, 0.000000},
{-1.494000, 1.858000, 0.000000},
{-1.639000, 2.251000, 0.000000},
{-1.644000, 2.270000, 0.000000},
{-1.710000, 2.626000, 0.000000}
};
GLfloat letterT[][3] =
{
{-0.640000, 0.000000, 0.000000},
{-0.640000, 5.104000, 0.000000},
{-2.476000, 5.104000, 0.000000},
{-2.476000, 6.208000, 0.000000},
{2.476000, 6.208000, 0.000000},
{2.476000, 5.104000, 0.000000},
{0.640000, 5.104000, 0.000000},
{0.640000, 0.000000, 0.000000}
};
GLfloat letterH[][3] =
{
{-2.570000, 0.000000, 0.000000},
{-2.570000, 6.208000, 0.000000},
{-1.282000, 6.208000, 0.000000},
{-1.282000, 3.900000, 0.000000},
{1.280000, 3.900000, 0.000000},
{1.280000, 6.208000, 0.000000},
{2.568000, 6.208000, 0.000000},
{2.568000, 0.000000, 0.000000},
{1.280000, 0.000000, 0.000000},
{1.280000, 2.760000, 0.000000},
{-1.282000, 2.760000, 0.000000},
{-1.282000, 0.000000, 0.000000}
};
/* Initialize light source and lighting.
*/
static void checkErrors(void)
{
GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
}
}
void myinit(void)
{
int count1 = sizeof(letterM) / (3 * sizeof(GLfloat));
int count2 = sizeof(letterO) / (3 * sizeof(GLfloat));
int count3 = sizeof(letterT) / (3 * sizeof(GLfloat));
int count4 = sizeof(letterH) / (3 * sizeof(GLfloat));
int i;
GLfloat light_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
/* light_position is NOT default value */
GLfloat light_position[] = { -1.0, -1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glDrawBuffer(GL_FRONT_AND_BACK);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_ACCUM_BUFFER_BIT);
glDrawBuffer(GL_BACK);
/* Zero position of text */
for(i = 0; i < count1; i++) {
letterM[i][1] = letterM[i][1] - 3.175;
}
for(i = 0; i < count2; i++) {
letterO[i][1] = letterO[i][1] - 3.175;
}
for(i = 0; i < count3; i++) {
letterT[i][1] = letterT[i][1] - 3.175;
}
for(i = 0; i < count4; i++) {
letterH[i][1] = letterH[i][1] - 3.175;
}
}
/* Mark Kilgard's tessellation code from the "dino" demos. */
void extrudeSolidFromPolygon(GLfloat data[][3], unsigned int dataSize,
GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
{
GLdouble vertex[3], dx, dy, len;
int i, k;
int flag = 0;
int count = dataSize / (3 * sizeof(GLfloat));
static GLUtriangulatorObj *tobj = NULL;
if (tobj == NULL) {
tobj = gluNewTess();
gluTessCallback(tobj, GLU_BEGIN, glBegin);
gluTessCallback(tobj, GLU_VERTEX, glVertex3fv);
gluTessCallback(tobj, GLU_END, glEnd);
}
glNewList(side, GL_COMPILE);
glShadeModel(GL_SMOOTH);
gluBeginPolygon(tobj);
for(i = 0; i < count; i++) {
/* This detects a new contour from a large number placed in
the unused z coordinate of the vertex where the new contour
starts. See the coordinates for letterO, above. The coordinate
must be reset below for additional calls. */
if (data[i][2] > 1000.0) {
data[i][2] = 0.0;
flag = 1; k = i;
gluNextContour(tobj, GLU_INTERIOR);
}
vertex[0] = data[i][0];
vertex[1] = data[i][1];
vertex[2] = 0.0;
gluTessVertex(tobj, vertex, data[i]);
}
gluEndPolygon(tobj);
glEndList();
/* Reset coordinate for new calls. */
if (flag == 1) {
data[k][2] = 10000.0;
flag = 0;
}
glNewList(edge, GL_COMPILE);
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= count; i++) {
glVertex3f(data[i % count][0], data[i % count][1], 0.0);
glVertex3f(data[i % count][0], data[i % count][1], thickness);
/* Normals */
dx = data[(i+ 1) % count][1] - data[i % count][1];
dy = data[i % count][0] - data[(i + 1) % count][0];
len = sqrt(dx * dx + dy * dy);
glNormal3f(dx / len, dy / len, 0.0);
}
glEnd();
glEndList();
glNewList(whole, GL_COMPILE);
glFrontFace(GL_CW);
glMaterialfv(GL_FRONT, GL_DIFFUSE, edgeColor);
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glCallList(edge);
glNormal3f(0.0, 0.0, -1.0);
glCallList(side);
glPushMatrix();
glTranslatef(0.0, 0.0, thickness);
glFrontFace(GL_CCW);
glNormal3f(0.0, 0.0, 1.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, sideColor);
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glCallList(side);
glPopMatrix();
glEndList();
}
void repeat(int j)
{
if(j == 2){
glPushMatrix();
glTranslatef((31 * -0.34) , 9.3, -9.6);
glCallList(REPEAT1);
glPopMatrix();
}
if(j == 3){
glPushMatrix();
glTranslatef(31 * -0.34, 9.3, -9.6);
glCallList(REPEAT1);
glPopMatrix();
glPushMatrix();
glTranslatef(31 * -.09, 9.3, -9.6);
glCallList(REPEAT2);
glPopMatrix();
}
if(j == 4){
glPushMatrix();
glTranslatef(31 * -0.34, 9.3, -9.6);
glCallList(REPEAT1);
glPopMatrix();
glPushMatrix();
glTranslatef(31 * -.09, 9.3, -9.6);
glCallList(REPEAT2);
glPopMatrix();
glPushMatrix();
glTranslatef(31 * 0.12, 9.3, -9.6);
glCallList(REPEAT3);
glPopMatrix();
}
}
void display(void)
{
int i, j;
GLfloat xPos = -0.34;
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.0, 0.0, -10.0);
extrudeSolidFromPolygon(letterM, sizeof(letterM), width2, REPEAT_SIDE,
REPEAT_EDGE, REPEAT1);
extrudeSolidFromPolygon(letterO, sizeof(letterO), width2, REPEAT2_SIDE,
REPEAT2_EDGE, REPEAT2);
extrudeSolidFromPolygon(letterT, sizeof(letterT), width2, REPEAT3_SIDE,
REPEAT3_EDGE, REPEAT3);
extrudeSolidFromPolygon(letterH, sizeof(letterH), width2, REPEAT4_SIDE,
REPEAT4_EDGE, REPEAT4);
for(j = 1; j < 5; j++){
width = 0.0;
checkErrors();
for(i = 0; i < 10; i++){
glPushMatrix();
repeat(j);
glPopMatrix();
glPushMatrix();
glRotatef(90.0, 0.0, 1.0, 0.0);
if(j == 1){
extrudeSolidFromPolygon(letterM, sizeof(letterM), width, M_SIDE,
M_EDGE, M_WHOLE);
glCallList(M_WHOLE);
}
if(j == 2){
extrudeSolidFromPolygon(letterO, sizeof(letterO), width, O_SIDE,
O_EDGE, O_WHOLE);
glCallList(O_WHOLE);
}
if(j == 3){
extrudeSolidFromPolygon(letterT, sizeof(letterT), width, T_SIDE,
T_EDGE, T_WHOLE);
glCallList(T_WHOLE);
}
if(j == 4){
extrudeSolidFromPolygon(letterH, sizeof(letterH), width, H_SIDE,
H_EDGE, H_WHOLE);
glCallList(H_WHOLE);
}
glutSwapBuffers();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
width = width + 0.2;
glPopMatrix();
}
for(i = 0; i < 45 ; i++){
glPushMatrix();
repeat(j);
glPopMatrix();
glPushMatrix();
glRotatef(90.0 - (2.0 * i), 0.0, 1.0, 0.0);
if(j == 1){
glCallList(M_WHOLE);
}
if(j == 2){
glCallList(O_WHOLE);
}
if(j == 3){
glCallList(T_WHOLE);
}
if(j == 4){
glCallList(H_WHOLE);
}
glutSwapBuffers();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPopMatrix();
}
for(i = 1; i < 32 ; i++){
glPushMatrix();
repeat(j);
glPopMatrix();
glPushMatrix();
glTranslatef(i * xPos, i * 0.3, i * -0.3);
if(j == 1){
glCallList(M_WHOLE);
}
if(j == 2){
glCallList(O_WHOLE);
}
if(j == 3){
glCallList(T_WHOLE);
}
if(j == 4){
glCallList(H_WHOLE);
}
glutSwapBuffers();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPopMatrix();
}
if(j == 1){
xPos = xPos + 0.25;
}
else{
xPos = xPos + 0.21;
}
}
glFlush();
}
void myReshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-7.0, 7.0, -7.0, 7.0, 6.0, 20.0);
/* if (w <= h)
glOrtho (-7.0, 7.0, -7.0*(GLfloat)h/(GLfloat)w,
7.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-7.0*(GLfloat)w/(GLfloat)h,
7.0*(GLfloat)w/(GLfloat)h, -7.0, 7.0, -10.0, 10.0); */
glMatrixMode(GL_MODELVIEW);
}
/* Main Loop
* Open window with initial window size, title bar,
* RGBA display mode, and handle input events.
*/
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow ("text3d");
/*glCullFace(GL_FRONT);*/
/*glEnable(GL_CULL_FACE);*/
myinit();
glutReshapeFunc (myReshape);
glutDisplayFunc (display);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
camzoom.c - camera zooming
camzoom.exe