2
/* projtex.c - by David Yu and David Blythe, SGI */
5
** Demonstrates simple projective texture mapping.
7
** Button1 changes view, Button2 moves texture.
9
** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli
10
** "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92)
12
** 1994,1995 -- David G Yu
14
** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm
26
/* Some <math.h> files do not define M_PI... */
28
#define M_PI 3.14159265358979323846
34
int winWidth, winHeight;
36
GLboolean redrawContinuously = GL_FALSE;
40
MoveNone, MoveView, MoveObject, MoveTexture
42
enum MoveModes mode = MoveNone;
44
GLfloat objectXform[4][4];
45
GLfloat textureXform[MAX_TEX][4][4];
47
void (*drawObject) (void);
48
void (*loadTexture) (void);
49
GLboolean textureEnabled = GL_TRUE;
50
GLboolean showProjection = GL_TRUE;
51
GLboolean linearFilter = GL_TRUE;
53
char *texFilename[MAX_TEX] = {
57
"../images/reflect.rgb"
61
GLfloat zoomFactor = 1.0;
63
/*****************************************************************/
69
glActiveTextureARB(i);
73
/* matrix = identity */
75
matrixIdentity(GLfloat matrix[16])
95
/* matrix2 = transpose(matrix1) */
97
matrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16])
99
matrix2[0] = matrix1[0];
100
matrix2[1] = matrix1[4];
101
matrix2[2] = matrix1[8];
102
matrix2[3] = matrix1[12];
104
matrix2[4] = matrix1[1];
105
matrix2[5] = matrix1[5];
106
matrix2[6] = matrix1[9];
107
matrix2[7] = matrix1[13];
109
matrix2[8] = matrix1[2];
110
matrix2[9] = matrix1[6];
111
matrix2[10] = matrix1[10];
112
matrix2[11] = matrix1[14];
114
matrix2[12] = matrix1[3];
115
matrix2[13] = matrix1[7];
116
matrix2[14] = matrix1[14];
117
matrix2[15] = matrix1[15];
120
/*****************************************************************/
122
/* load SGI .rgb image (pad with a border of the specified width and color) */
125
imgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4],
126
int *wOut, int *hOut, GLubyte ** imgOut)
128
int border = borderIn;
131
GLubyte *image, *img, *p;
132
int i, j, components;
134
image = (GLubyte *) read_texture(filenameIn, &width, &height, &components);
135
w = width + 2 * border;
136
h = height + 2 * border;
137
img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char));
140
for (j = -border; j < height + border; ++j) {
141
for (i = -border; i < width + border; ++i) {
142
if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) {
143
p[0] = image[4 * (j * width + i) + 0];
144
p[1] = image[4 * (j * width + i) + 1];
145
p[2] = image[4 * (j * width + i) + 2];
148
p[0] = borderColorIn[0] * 0xff;
149
p[1] = borderColorIn[1] * 0xff;
150
p[2] = borderColorIn[2] * 0xff;
151
p[3] = borderColorIn[3] * 0xff;
164
/*****************************************************************/
166
/* Load the image file specified on the command line as the current texture */
168
loadImageTextures(void)
170
GLfloat borderColor[4] =
171
{1.0, 1.0, 1.0, 1.0};
174
for (tex = 0; tex < NumTextures; tex++) {
175
GLubyte *image, *texData3, *texData4;
176
GLint imgWidth, imgHeight;
180
printf("loading %s\n", texFilename[tex]);
181
image = LoadRGBImage(texFilename[tex], &imgWidth, &imgHeight, &imgFormat);
183
printf("can't find %s\n", texFilename[tex]);
186
assert(imgFormat == GL_RGB);
188
/* scale to 256x256 */
189
texData3 = malloc(256 * 256 * 4);
190
texData4 = malloc(256 * 256 * 4);
193
gluScaleImage(imgFormat, imgWidth, imgHeight, GL_UNSIGNED_BYTE, image,
194
256, 256, GL_UNSIGNED_BYTE, texData3);
196
/* convert to rgba */
197
for (i = 0; i < 256 * 256; i++) {
198
texData4[i*4+0] = texData3[i*3+0];
199
texData4[i*4+1] = texData3[i*3+1];
200
texData4[i*4+2] = texData3[i*3+2];
201
texData4[i*4+3] = 128;
204
/* put transparent border around image */
205
for (i = 0; i < 256; i++) {
206
texData4[i*4+0] = 255;
207
texData4[i*4+1] = 255;
208
texData4[i*4+2] = 255;
212
for (i = 0; i < 256; i++) {
213
texData4[j + i*4+0] = 255;
214
texData4[j + i*4+1] = 255;
215
texData4[j + i*4+2] = 255;
216
texData4[j + i*4+3] = 0;
218
for (i = 0; i < 256; i++) {
225
for (i = 0; i < 256; i++) {
226
j = i * 256 * 4 + 255 * 4;
233
ActiveTexture(GL_TEXTURE0_ARB + tex);
234
glBindTexture(GL_TEXTURE_2D, tex + 1);
236
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
237
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
238
GL_RGBA, GL_UNSIGNED_BYTE, texData4);
241
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
242
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
244
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
245
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
247
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
255
/* Create a simple spotlight pattern and make it the current texture */
257
loadSpotlightTexture(void)
259
static int texWidth = 64, texHeight = 64;
260
static GLubyte *texData;
261
GLfloat borderColor[4] =
262
{0.1, 0.1, 0.1, 1.0};
268
texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
271
for (j = 0; j < texHeight; ++j) {
272
float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5);
274
for (i = 0; i < texWidth; ++i) {
275
float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5);
276
float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy));
279
r = (r < 0) ? 0 : r * r;
280
c = 0xff * (r + borderColor[0]);
281
p[0] = (c <= 0xff) ? c : 0xff;
282
c = 0xff * (r + borderColor[1]);
283
p[1] = (c <= 0xff) ? c : 0xff;
284
c = 0xff * (r + borderColor[2]);
285
p[2] = (c <= 0xff) ? c : 0xff;
286
c = 0xff * (r + borderColor[3]);
287
p[3] = (c <= 0xff) ? c : 0xff;
293
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
294
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
296
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
297
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
299
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
300
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
301
GL_RGBA, GL_UNSIGNED_BYTE, texData);
304
/*****************************************************************/
310
while ((error = glGetError()) != GL_NO_ERROR) {
311
fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
320
glNormal3f(-1.0, 0.0, 0.0);
321
glColor3f(0.80, 0.50, 0.50);
322
glVertex3f(-0.5, -0.5, -0.5);
323
glVertex3f(-0.5, -0.5, 0.5);
324
glVertex3f(-0.5, 0.5, 0.5);
325
glVertex3f(-0.5, 0.5, -0.5);
327
glNormal3f(1.0, 0.0, 0.0);
328
glColor3f(0.50, 0.80, 0.50);
329
glVertex3f(0.5, 0.5, 0.5);
330
glVertex3f(0.5, -0.5, 0.5);
331
glVertex3f(0.5, -0.5, -0.5);
332
glVertex3f(0.5, 0.5, -0.5);
334
glNormal3f(0.0, -1.0, 0.0);
335
glColor3f(0.50, 0.50, 0.80);
336
glVertex3f(-0.5, -0.5, -0.5);
337
glVertex3f(0.5, -0.5, -0.5);
338
glVertex3f(0.5, -0.5, 0.5);
339
glVertex3f(-0.5, -0.5, 0.5);
341
glNormal3f(0.0, 1.0, 0.0);
342
glColor3f(0.50, 0.80, 0.80);
343
glVertex3f(0.5, 0.5, 0.5);
344
glVertex3f(0.5, 0.5, -0.5);
345
glVertex3f(-0.5, 0.5, -0.5);
346
glVertex3f(-0.5, 0.5, 0.5);
348
glNormal3f(0.0, 0.0, -1.0);
349
glColor3f(0.80, 0.50, 0.80);
350
glVertex3f(-0.5, -0.5, -0.5);
351
glVertex3f(-0.5, 0.5, -0.5);
352
glVertex3f(0.5, 0.5, -0.5);
353
glVertex3f(0.5, -0.5, -0.5);
355
glNormal3f(0.0, 0.0, 1.0);
356
glColor3f(1.00, 0.80, 0.50);
357
glVertex3f(0.5, 0.5, 0.5);
358
glVertex3f(-0.5, 0.5, 0.5);
359
glVertex3f(-0.5, -0.5, 0.5);
360
glVertex3f(0.5, -0.5, 0.5);
365
drawDodecahedron(void)
367
#define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
368
#define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
369
#define C (0.5 * 1.0)
370
GLfloat vertexes[20][3] =
396
GLint polygons[12][5] =
413
glColor3f(0.75, 0.75, 0.75);
414
for (i = 0; i < 12; ++i) {
415
GLfloat *p0, *p1, *p2, d;
416
GLfloat u[3], v[3], n[3];
418
p0 = &vertexes[polygons[i][0]][0];
419
p1 = &vertexes[polygons[i][1]][0];
420
p2 = &vertexes[polygons[i][2]][0];
422
u[0] = p2[0] - p1[0];
423
u[1] = p2[1] - p1[1];
424
u[2] = p2[2] - p1[2];
426
v[0] = p0[0] - p1[0];
427
v[1] = p0[1] - p1[1];
428
v[2] = p0[2] - p1[2];
430
n[0] = u[1] * v[2] - u[2] * v[1];
431
n[1] = u[2] * v[0] - u[0] * v[2];
432
n[2] = u[0] * v[1] - u[1] * v[0];
434
d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
444
glVertex3fv(vertexes[polygons[i][3]]);
445
glVertex3fv(vertexes[polygons[i][4]]);
456
double majorStep = (M_PI / numMajor);
457
double minorStep = (2.0 * M_PI / numMinor);
460
glColor3f(0.50, 0.50, 0.50);
461
for (i = 0; i < numMajor; ++i) {
462
double a = i * majorStep;
463
double b = a + majorStep;
464
double r0 = radius * sin(a);
465
double r1 = radius * sin(b);
466
GLfloat z0 = radius * cos(a);
467
GLfloat z1 = radius * cos(b);
469
glBegin(GL_TRIANGLE_STRIP);
470
for (j = 0; j <= numMinor; ++j) {
471
double c = j * minorStep;
475
glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
476
glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
477
glVertex3f(x * r0, y * r0, z0);
479
glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
480
glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
481
glVertex3f(x * r1, y * r1, z1);
487
/*****************************************************************/
489
float xmin = -0.035, xmax = 0.035;
490
float ymin = -0.035, ymax = 0.035;
493
float distance = -1.0;
496
loadTextureProjection(int texUnit, GLfloat m[16])
498
GLfloat mInverse[4][4];
500
/* Should use true inverse, but since m consists only of rotations, we can
501
just use the transpose. */
502
matrixTranspose((GLfloat *) mInverse, m);
504
ActiveTexture(GL_TEXTURE0_ARB + texUnit);
505
glMatrixMode(GL_TEXTURE);
507
glTranslatef(0.5, 0.5, 0.0);
508
glScalef(0.5, 0.5, 1.0);
509
glFrustum(xmin, xmax, ymin, ymax, nnear, ffar);
510
glTranslatef(0.0, 0.0, distance);
511
glMultMatrixf((GLfloat *) mInverse);
512
glMatrixMode(GL_MODELVIEW);
516
drawTextureProjection(void)
518
float t = ffar / nnear;
524
n[0][2] = -(nnear + distance);
528
n[1][2] = -(nnear + distance);
532
n[2][2] = -(nnear + distance);
536
n[3][2] = -(nnear + distance);
540
f[0][2] = -(ffar + distance);
544
f[1][2] = -(ffar + distance);
548
f[2][2] = -(ffar + distance);
552
f[3][2] = -(ffar + distance);
554
glColor3f(1.0, 1.0, 0.0);
555
glBegin(GL_LINE_LOOP);
575
/*****************************************************************/
580
GLfloat light0Pos[4] =
581
{0.3, 0.3, 0.0, 1.0};
583
{0.01, 0.01, 0.01, 1.00};
585
{0.65, 0.65, 0.65, 1.00};
587
{0.30, 0.30, 0.30, 1.00};
588
GLfloat matShine = 10.0;
589
GLfloat eyePlaneS[] =
590
{1.0, 0.0, 0.0, 0.0};
591
GLfloat eyePlaneT[] =
592
{0.0, 1.0, 0.0, 0.0};
593
GLfloat eyePlaneR[] =
594
{0.0, 0.0, 1.0, 0.0};
595
GLfloat eyePlaneQ[] =
596
{0.0, 0.0, 0.0, 1.0};
600
glClearColor(0.41, 0.41, 0.31, 0.0);
602
glEnable(GL_DEPTH_TEST);
604
/* glLineWidth(2.0);*/
606
glCullFace(GL_FRONT);
607
glEnable(GL_CULL_FACE);
609
glMatrixMode(GL_PROJECTION);
610
glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
611
glMatrixMode(GL_MODELVIEW);
612
glTranslatef(0, 0, -2);
614
matrixIdentity((GLfloat *) objectXform);
615
for (i = 0; i < NumTextures; i++) {
616
matrixIdentity((GLfloat *) textureXform[i]);
619
glMatrixMode(GL_PROJECTION);
622
glOrtho(0, 1, 0, 1, -1, 1);
623
glMatrixMode(GL_MODELVIEW);
630
glMatrixMode(GL_PROJECTION);
632
glMatrixMode(GL_MODELVIEW);
635
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
636
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
637
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
638
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
640
glEnable(GL_COLOR_MATERIAL);
642
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
645
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
646
glEnable(GL_LIGHTING);
653
for (i = 0; i < NumTextures; i++) {
654
ActiveTexture(GL_TEXTURE0_ARB + i);
656
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
657
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
658
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
660
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
661
glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
663
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
664
glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
666
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
667
glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
669
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
670
glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
679
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
681
if (textureEnabled) {
682
if (mode == MoveTexture || mode == MoveView) {
683
/* Have OpenGL compute the new transformation (simple but slow). */
684
for (i = 0; i < NumTextures; i++) {
689
glRotatef(angle, axis[0], axis[1], axis[2]);
692
glRotatef(angle*(i+1), axis[0], axis[1], axis[2]);
694
glMultMatrixf((GLfloat *) textureXform[i]);
695
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform[i]);
699
for (i = 0; i < NumTextures; i++) {
700
loadTextureProjection(i, (GLfloat *) textureXform[i]);
703
if (showProjection) {
704
for (i = 0; i < NumTextures; i++) {
705
ActiveTexture(GL_TEXTURE0_ARB + i);
707
glMultMatrixf((GLfloat *) textureXform[i]);
708
glDisable(GL_LIGHTING);
709
drawTextureProjection();
710
glEnable(GL_LIGHTING);
714
for (i = 0; i < NumTextures; i++) {
715
ActiveTexture(GL_TEXTURE0_ARB + i);
716
glEnable(GL_TEXTURE_2D);
717
glEnable(GL_TEXTURE_GEN_S);
718
glEnable(GL_TEXTURE_GEN_T);
719
glEnable(GL_TEXTURE_GEN_R);
720
glEnable(GL_TEXTURE_GEN_Q);
723
if (mode == MoveObject || mode == MoveView) {
724
/* Have OpenGL compute the new transformation (simple but slow). */
727
glRotatef(angle, axis[0], axis[1], axis[2]);
728
glMultMatrixf((GLfloat *) objectXform);
729
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
733
glMultMatrixf((GLfloat *) objectXform);
737
for (i = 0; i < NumTextures; i++) {
738
ActiveTexture(GL_TEXTURE0_ARB + i);
739
glDisable(GL_TEXTURE_2D);
740
glDisable(GL_TEXTURE_GEN_S);
741
glDisable(GL_TEXTURE_GEN_T);
742
glDisable(GL_TEXTURE_GEN_R);
743
glDisable(GL_TEXTURE_GEN_Q);
746
if (zoomFactor > 1.0) {
747
glDisable(GL_DEPTH_TEST);
748
glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR);
749
glEnable(GL_DEPTH_TEST);
756
/*****************************************************************/
758
/* simple trackball-like motion control */
759
static float lastPos[3];
763
ptov(int x, int y, int width, int height, float v[3])
767
/* project x,y onto a hemi-sphere centered within width, height */
768
v[0] = (2.0 * x - width) / width;
769
v[1] = (height - 2.0 * y) / height;
770
d = sqrt(v[0] * v[0] + v[1] * v[1]);
771
v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0));
772
a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
779
startMotion(int x, int y, int but, int time)
781
if (but == GLUT_LEFT_BUTTON) {
783
} else if (but == GLUT_MIDDLE_BUTTON) {
790
ptov(x, y, winWidth, winHeight, lastPos);
802
if (visible == GLUT_VISIBLE) {
803
if (redrawContinuously)
804
glutIdleFunc(animate);
806
if (redrawContinuously)
812
stopMotion(int but, int time)
814
if ((but == GLUT_LEFT_BUTTON && mode == MoveView) ||
815
(but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) {
820
if (time == lastTime) {
821
/* redrawContinuously = GL_TRUE;*/
822
glutIdleFunc(animate);
825
redrawContinuously = GL_FALSE;
828
if (!redrawContinuously) {
834
trackMotion(int x, int y)
836
float curPos[3], dx, dy, dz;
838
ptov(x, y, winWidth, winHeight, curPos);
840
dx = curPos[0] - lastPos[0];
841
dy = curPos[1] - lastPos[1];
842
dz = curPos[2] - lastPos[2];
843
angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
845
axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1];
846
axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2];
847
axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0];
849
lastTime = glutGet(GLUT_ELAPSED_TIME);
850
lastPos[0] = curPos[0];
851
lastPos[1] = curPos[1];
852
lastPos[2] = curPos[2];
856
/*****************************************************************/
867
drawObject = drawCube;
870
drawObject = drawDodecahedron;
873
drawObject = drawSphere;
888
static int texture = 0;
892
if (texture == 1 && texFilename == NULL) {
893
/* Skip file texture if not loaded. */
899
textureEnabled = GL_FALSE;
902
loadTexture = loadImageTextures;
904
textureEnabled = GL_TRUE;
907
loadTexture = loadSpotlightTexture;
909
textureEnabled = GL_TRUE;
919
printf("'h' - help\n");
920
printf("'l' - toggle linear/nearest filter\n");
921
printf("'s' - toggle projection frustum\n");
922
printf("'t' - toggle projected texture\n");
923
printf("'o' - toggle object\n");
924
printf("'z' - increase zoom factor\n");
925
printf("'Z' - decrease zoom factor\n");
926
printf("left mouse - move view\n");
927
printf("middle mouse - move projection\n");
932
key(unsigned char key, int x, int y)
939
linearFilter = !linearFilter;
943
showProjection = !showProjection;
953
glPixelZoom(zoomFactor, zoomFactor);
954
glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
958
if (zoomFactor < 1.0)
960
glPixelZoom(zoomFactor, zoomFactor);
961
glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
971
mouse(int button, int state, int x, int y)
973
if (state == GLUT_DOWN)
974
startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
975
else if (state == GLUT_UP)
976
stopMotion(button, glutGet(GLUT_ELAPSED_TIME));
981
reshape(int w, int h)
985
glViewport(0, 0, w / zoomFactor, h / zoomFactor);
992
if (selection == 666) {
995
key((unsigned char) selection, 0, 0);
999
main(int argc, char **argv)
1001
glutInitWindowSize(500,500);
1002
glutInit(&argc, argv);
1003
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
1004
(void) glutCreateWindow("projtex");
1008
NumTextures = atoi(argv[1]);
1010
assert(NumTextures <= MAX_TEX);
1012
loadTexture = loadImageTextures;
1013
drawObject = drawCube;
1015
glutDisplayFunc(display);
1016
glutKeyboardFunc(key);
1017
glutReshapeFunc(reshape);
1018
glutMouseFunc(mouse);
1019
glutMotionFunc(trackMotion);
1020
glutVisibilityFunc(vis);
1021
glutCreateMenu(menu);
1022
glutAddMenuEntry("Toggle showing projection", 's');
1023
glutAddMenuEntry("Switch texture", 't');
1024
glutAddMenuEntry("Switch object", 'o');
1025
glutAddMenuEntry("Toggle filtering", 'l');
1026
glutAddMenuEntry("Quit", 666);
1027
glutAttachMenu(GLUT_RIGHT_BUTTON);
1030
return 0; /* ANSI C requires main to return int. */