1/*
2 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that (i) the above copyright notices and this permission notice appear in
7 * all copies of the software and related documentation, and (ii) the name of
8 * Silicon Graphics may not be used in any advertising or
9 * publicity relating to the software without the specific, prior written
10 * permission of Silicon Graphics.
11 *
12 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
13 * ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25/* BEP: renamed "nearest" as "nnearest" to avoid math.h collision on AIX */
26
27#include <stdio.h>
28#include <string.h>
29#include <math.h>
30#include <stdlib.h>
31#include "glut_wrap.h"
32#include "readtex.h"
33
34
35#ifndef PI
36#define PI    3.14159265358979323846
37#endif
38
39
40GLenum doubleBuffer;
41int W = 400, H = 400;
42
43char *imageFileName = DEMOS_DATA_DIR "reflect.rgb";
44
45float *minFilter, *magFilter, *sWrapMode, *tWrapMode;
46float decal[] = {GL_DECAL};
47float modulate[] = {GL_MODULATE};
48float repeat[] = {GL_REPEAT};
49float clamp[] = {GL_CLAMP};
50float nnearest[] = {GL_NEAREST};
51float linear[] = {GL_LINEAR};
52float nearest_mipmap_nearest[] = {GL_NEAREST_MIPMAP_NEAREST};
53float nearest_mipmap_linear[] = {GL_NEAREST_MIPMAP_LINEAR};
54float linear_mipmap_nearest[] = {GL_LINEAR_MIPMAP_NEAREST};
55float linear_mipmap_linear[] = {GL_LINEAR_MIPMAP_LINEAR};
56GLint sphereMap[] = {GL_SPHERE_MAP};
57
58float xRotation = 0.0, yRotation = 0.0;
59float zTranslate = -3.0;
60GLenum autoRotate = GL_TRUE;
61GLboolean isLit = GL_TRUE;
62GLboolean isFogged = GL_FALSE;
63GLboolean doTexture = GL_TRUE;
64float *textureEnvironment = modulate;
65
66int cube, cage, cylinder, torus, genericObject;
67
68float c[6][4][4][3] = {
69    {
70	{
71	    {
72		1.0, 1.0, -1.0
73	    },
74	    {
75		0.0, 1.0, -1.0
76	    },
77	    {
78		0.0, 0.0, -1.0
79	    },
80	    {
81		1.0, 0.0, -1.0
82	    },
83	},
84	{
85	    {
86		0.0, 1.0, -1.0
87	    },
88	    {
89		-1.0, 1.0, -1.0
90	    },
91	    {
92		-1.0, 0.0, -1.0
93	    },
94	    {
95		0.0, 0.0, -1.0
96	    },
97	},
98	{
99	    {
100		0.0,  0.0, -1.0
101	    },
102	    {
103		-1.0, 0.0, -1.0
104	    },
105	    {
106		-1.0, -1.0, -1.0
107	    },
108	    {
109		0.0, -1.0, -1.0
110	    },
111	},
112	{
113	    {
114		1.0, 0.0, -1.0
115	    },
116	    {
117		0.0, 0.0, -1.0
118	    },
119	    {
120		0.0, -1.0, -1.0
121	    },
122	    {
123		1.0, -1.0, -1.0
124	    },
125	},
126    },
127    {
128	{
129	    {
130		1.0, 1.0, 1.0
131	    },
132	    {
133		1.0, 1.0, 0.0
134	    },
135	    {
136		1.0, 0.0, 0.0
137	    },
138	    {
139		1.0, 0.0, 1.0
140	    },
141	},
142	{
143	    {
144		1.0, 1.0, 0.0
145	    },
146	    {
147		1.0, 1.0, -1.0
148	    },
149	    {
150		1.0, 0.0, -1.0
151	    },
152	    {
153		1.0, 0.0, 0.0
154	    },
155	},
156	{
157	    {
158		1.0, 0.0, -1.0
159	    },
160	    {
161		1.0, -1.0, -1.0
162	    },
163	    {
164		1.0, -1.0, 0.0
165	    },
166	    {
167		1.0, 0.0, 0.0
168	    },
169	},
170	{
171	    {
172		1.0, 0.0, 0.0
173	    },
174	    {
175		1.0, -1.0, 0.0
176	    },
177	    {
178		1.0, -1.0, 1.0
179	    },
180	    {
181		1.0, 0.0, 1.0
182	    },
183	},
184    },
185    {
186	{
187	    {
188		-1.0, 1.0, 1.0
189	    },
190	    {
191		0.0, 1.0, 1.0
192	    },
193	    {
194		0.0, 0.0, 1.0
195	    },
196	    {
197		-1.0, 0.0, 1.0
198	    },
199	},
200	{
201	    {
202		0.0, 1.0, 1.0
203	    },
204	    {
205		1.0, 1.0, 1.0
206	    },
207	    {
208		1.0, 0.0, 1.0
209	    },
210	    {
211		0.0, 0.0, 1.0
212	    },
213	},
214	{
215	    {
216		1.0, 0.0, 1.0
217	    },
218	    {
219		1.0, -1.0, 1.0
220	    },
221	    {
222		0.0, -1.0, 1.0
223	    },
224	    {
225		0.0, 0.0, 1.0
226	    },
227	},
228	{
229	    {
230		0.0, -1.0, 1.0
231	    },
232	    {
233		-1.0, -1.0, 1.0
234	    },
235	    {
236		-1.0, 0.0, 1.0
237	    },
238	    {
239		0.0, 0.0, 1.0
240	    },
241	},
242    },
243    {
244	{
245	    {
246		-1.0, 1.0, -1.0
247	    },
248	    {
249		-1.0, 1.0, 0.0
250	    },
251	    {
252		-1.0, 0.0, 0.0
253	    },
254	    {
255		-1.0, 0.0, -1.0
256	    },
257	},
258	{
259	    {
260		-1.0, 1.0, 0.0
261	    },
262	    {
263		-1.0, 1.0, 1.0
264	    },
265	    {
266		-1.0, 0.0, 1.0
267	    },
268	    {
269		-1.0, 0.0, 0.0
270	    },
271	},
272	{
273	    {
274		-1.0, 0.0, 1.0
275	    },
276	    {
277		-1.0, -1.0, 1.0
278	    },
279	    {
280		-1.0, -1.0, 0.0
281	    },
282	    {
283		-1.0, 0.0, 0.0
284	    },
285	},
286	{
287	    {
288		-1.0, -1.0, 0.0
289	    },
290	    {
291		-1.0, -1.0, -1.0
292	    },
293	    {
294		-1.0, 0.0, -1.0
295	    },
296	    {
297		-1.0, 0.0, 0.0
298	    },
299	},
300    },
301    {
302	{
303	    {
304		-1.0, 1.0, 1.0
305	    },
306	    {
307		-1.0, 1.0, 0.0
308	    },
309	    {
310		0.0, 1.0, 0.0
311	    },
312	    {
313		0.0, 1.0, 1.0
314	    },
315	},
316	{
317	    {
318		-1.0, 1.0, 0.0
319	    },
320	    {
321		-1.0, 1.0, -1.0
322	    },
323	    {
324		0.0, 1.0, -1.0
325	    },
326	    {
327		0.0, 1.0, 0.0
328	    },
329	},
330	{
331	    {
332		0.0, 1.0, -1.0
333	    },
334	    {
335		1.0, 1.0, -1.0
336	    },
337	    {
338		1.0, 1.0, 0.0
339	    },
340	    {
341		0.0, 1.0, 0.0
342	    },
343	},
344	{
345	    {
346		1.0, 1.0, 0.0
347	    },
348	    {
349		1.0, 1.0, 1.0
350	    },
351	    {
352		0.0, 1.0, 1.0
353	    },
354	    {
355		0.0, 1.0, 0.0
356	    },
357	},
358    },
359    {
360	{
361	    {
362		-1.0, -1.0, -1.0
363	    },
364	    {
365		-1.0, -1.0, 0.0
366	    },
367	    {
368		0.0, -1.0, 0.0
369	    },
370	    {
371		0.0, -1.0, -1.0
372	    },
373	},
374	{
375	    {
376		-1.0, -1.0, 0.0
377	    },
378	    {
379		-1.0, -1.0, 1.0
380	    },
381	    {
382		0.0, -1.0, 1.0
383	    },
384	    {
385		0.0, -1.0, 0.0
386	    },
387	},
388	{
389	    {
390		0.0, -1.0, 1.0
391	    },
392	    {
393		1.0, -1.0, 1.0
394	    },
395	    {
396		1.0, -1.0, 0.0
397	    },
398	    {
399		0.0, -1.0, 0.0
400	    },
401	},
402	{
403	    {
404		1.0, -1.0, 0.0
405	    },
406	    {
407		1.0, -1.0, -1.0
408	    },
409	    {
410		0.0, -1.0, -1.0
411	    },
412	    {
413		0.0, -1.0, 0.0
414	    },
415	},
416    }
417};
418
419float n[6][3] = {
420    {
421	0.0, 0.0, -1.0
422    },
423    {
424	1.0, 0.0, 0.0
425    },
426    {
427	0.0, 0.0, 1.0
428    },
429    {
430	-1.0, 0.0, 0.0
431    },
432    {
433	0.0, 1.0, 0.0
434    },
435    {
436	0.0, -1.0, 0.0
437    }
438};
439
440GLfloat identity[16] = {
441    1, 0, 0, 0,
442    0, 1, 0, 0,
443    0, 0, 1, 0,
444    0, 0, 0, 1,
445};
446
447
448static void BuildCylinder(int numEdges)
449{
450    int i, top = 1.0, bottom = -1.0;
451    float x[100], y[100], angle;
452
453    for (i = 0; i <= numEdges; i++) {
454	angle = i * 2.0 * PI / numEdges;
455	x[i] = cos(angle);   /* was cosf() */
456	y[i] = sin(angle);   /* was sinf() */
457    }
458
459    glNewList(cylinder, GL_COMPILE);
460    glBegin(GL_TRIANGLE_STRIP);
461	for (i = 0; i <= numEdges; i++) {
462	    glNormal3f(x[i], y[i], 0.0);
463	    glVertex3f(x[i], y[i], bottom);
464	    glVertex3f(x[i], y[i], top);
465	}
466    glEnd();
467    glBegin(GL_TRIANGLE_FAN);
468	glNormal3f(0.0, 0.0, 1.0);
469	glVertex3f(0.0, 0.0, top);
470	for (i = 0; i <= numEdges; i++) {
471	    glVertex3f(x[i], -y[i], top);
472	}
473    glEnd();
474    glBegin(GL_TRIANGLE_FAN);
475	glNormal3f(0.0, 0.0, -1.0);
476	glVertex3f(0.0, 0.0, bottom);
477	for (i = 0; i <= numEdges; i++) {
478	    glVertex3f(x[i], y[i], bottom);
479	}
480    glEnd();
481    glEndList();
482}
483
484static void BuildTorus(float rc, int numc, float rt, int numt)
485{
486    int i, j, k;
487    double s, t;
488    double x, y, z;
489    double pi, twopi;
490
491    pi = 3.14159265358979323846;
492    twopi = 2.0 * pi;
493
494    glNewList(torus, GL_COMPILE);
495    for (i = 0; i < numc; i++) {
496	glBegin(GL_QUAD_STRIP);
497        for (j = 0; j <= numt; j++) {
498	    for (k = 0; k <= 1; k++) {
499		s = (i + k) % numc + 0.5;
500		t = j % numt;
501
502		x = cos(t*twopi/numt) * cos(s*twopi/numc);
503		y = sin(t*twopi/numt) * cos(s*twopi/numc);
504		z = sin(s*twopi/numc);
505		glNormal3f(x, y, z);
506
507		x = (rt + rc * cos(s*twopi/numc)) * cos(t*twopi/numt);
508		y = (rt + rc * cos(s*twopi/numc)) * sin(t*twopi/numt);
509		z = rc * sin(s*twopi/numc);
510		glVertex3f(x, y, z);
511	    }
512        }
513	glEnd();
514    }
515    glEndList();
516}
517
518static void BuildCage(void)
519{
520    int i;
521    float inc;
522    float right, left, top, bottom, front, back;
523
524    front  = 0.0;
525    back   = -8.0;
526
527    left   = -4.0;
528    bottom = -4.0;
529    right  = 4.0;
530    top    = 4.0;
531
532    inc = 2.0 * 4.0 * 0.1;
533
534    glNewList(cage, GL_COMPILE);
535    for (i = 0; i < 10; i++) {
536
537	/*
538	** Back
539	*/
540	glBegin(GL_LINES);
541	    glVertex3f(left+i*inc, top,    back);
542	    glVertex3f(left+i*inc, bottom, back);
543	glEnd();
544	glBegin(GL_LINES);
545	    glVertex3f(right, bottom+i*inc, back);
546	    glVertex3f(left,  bottom+i*inc, back);
547	glEnd();
548
549	/*
550	** Front
551	*/
552	glBegin(GL_LINES);
553	    glVertex3f(left+i*inc, top,    front);
554	    glVertex3f(left+i*inc, bottom, front);
555	glEnd();
556	glBegin(GL_LINES);
557	    glVertex3f(right, bottom+i*inc, front);
558	    glVertex3f(left,  bottom+i*inc, front);
559	glEnd();
560
561	/*
562	** Left
563	*/
564	glBegin(GL_LINES);
565	    glVertex3f(left, bottom+i*inc, front);
566	    glVertex3f(left, bottom+i*inc, back);
567	glEnd();
568	glBegin(GL_LINES);
569	    glVertex3f(left, top,    back+i*inc);
570	    glVertex3f(left, bottom, back+i*inc);
571	glEnd();
572
573	/*
574	** Right
575	*/
576	glBegin(GL_LINES);
577	    glVertex3f(right, top-i*inc, front);
578	    glVertex3f(right, top-i*inc, back);
579	glEnd();
580	glBegin(GL_LINES);
581	    glVertex3f(right, top,    back+i*inc);
582	    glVertex3f(right, bottom, back+i*inc);
583	glEnd();
584
585	/*
586	** Top
587	*/
588	glBegin(GL_LINES);
589	    glVertex3f(left+i*inc, top, front);
590	    glVertex3f(left+i*inc, top, back);
591	glEnd();
592	glBegin(GL_LINES);
593	    glVertex3f(right, top, back+i*inc);
594	    glVertex3f(left,  top, back+i*inc);
595	glEnd();
596
597	/*
598	** Bottom
599	*/
600	glBegin(GL_LINES);
601	    glVertex3f(right-i*inc, bottom, front);
602	    glVertex3f(right-i*inc, bottom, back);
603	glEnd();
604	glBegin(GL_LINES);
605	    glVertex3f(right, bottom, back+i*inc);
606	    glVertex3f(left,  bottom, back+i*inc);
607	glEnd();
608    }
609    glEndList();
610}
611
612static void BuildCube(void)
613{
614    int i, j;
615
616    glNewList(cube, GL_COMPILE);
617    for (i = 0; i < 6; i++) {
618	for (j = 0; j < 4; j++) {
619	    glNormal3fv(n[i]);
620	    glBegin(GL_POLYGON);
621		glVertex3fv(c[i][j][0]);
622		glVertex3fv(c[i][j][1]);
623		glVertex3fv(c[i][j][2]);
624		glVertex3fv(c[i][j][3]);
625	    glEnd();
626	}
627    }
628    glEndList();
629}
630
631static void BuildLists(void)
632{
633
634    cube = glGenLists(1);
635    BuildCube();
636
637    cage = glGenLists(2);
638    BuildCage();
639
640    cylinder = glGenLists(3);
641    BuildCylinder(60);
642
643    torus = glGenLists(4);
644    BuildTorus(0.65, 20, .85, 65);
645
646    genericObject = torus;
647}
648
649static void SetDefaultSettings(void)
650{
651
652    magFilter = nnearest;
653    minFilter = nnearest;
654    sWrapMode = repeat;
655    tWrapMode = repeat;
656    textureEnvironment = modulate;
657    autoRotate = GL_TRUE;
658}
659
660static unsigned char *AlphaPadImage(int bufSize, unsigned char *inData, int alpha)
661{
662    unsigned char *outData, *out_ptr, *in_ptr;
663    int i;
664
665    outData = (unsigned char *) malloc(bufSize * 4);
666    out_ptr = outData;
667    in_ptr = inData;
668
669    for (i = 0; i < bufSize; i++) {
670	*out_ptr++ = *in_ptr++;
671	*out_ptr++ = *in_ptr++;
672	*out_ptr++ = *in_ptr++;
673	*out_ptr++ = alpha;
674    }
675
676    free (inData);
677    return outData;
678}
679
680static void Init(void)
681{
682    float ambient[] = {0.0, 0.0, 0.0, 1.0};
683    float diffuse[] = {1.0, 1.0, 1.0, 1.0};
684    float specular[] = {1.0, 1.0, 1.0, 1.0};
685    float position[] = {0.0, 0.0,  4.0, 0.0};
686    float fog_color[] = {0.0, 0.0, 0.0, 1.0};
687    float mat_ambient[] = {0.0, 0.0, 0.0, 1.0};
688    float mat_shininess[] = {90.0};
689    float mat_specular[] = {1.0, 1.0, 1.0, 1.0};
690    float mat_diffuse[] = {0.8, 0.8, 0.8, 1.0};
691    float lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0};
692    float lmodel_twoside[] = {GL_TRUE};
693    int w, h;
694    GLenum format;
695    GLubyte *image;
696
697    printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
698
699    SetDefaultSettings();
700
701    image = LoadRGBImage(imageFileName, &w, &h, &format);
702    if (!image) {
703       printf("Error: couldn't load %s\n", imageFileName);
704       exit(1);
705    }
706    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
707    gluBuild2DMipmaps(GL_TEXTURE_2D, format, w, h,
708                      GL_RGB, GL_UNSIGNED_BYTE, image);
709
710    free(image);
711
712    glFogf(GL_FOG_DENSITY, 0.125);
713    glFogi(GL_FOG_MODE, GL_LINEAR);
714    glFogf(GL_FOG_START, 4.0);
715    glFogf(GL_FOG_END, 8.5);
716    glFogfv(GL_FOG_COLOR, fog_color);
717
718    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
719    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
720    glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
721    glLightfv(GL_LIGHT0, GL_POSITION, position);
722    glEnable(GL_LIGHT0);
723
724    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
725    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
726    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
727    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
728
729    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
730    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
731    glShadeModel(GL_SMOOTH);
732
733
734    glClearColor(0.0, 0.0, 0.0, 0.0);
735    glEnable(GL_DEPTH_TEST);
736
737    glFrontFace(GL_CW);
738    glEnable(GL_CULL_FACE);
739    glCullFace(GL_BACK);
740
741    glTexGeniv(GL_S, GL_TEXTURE_GEN_MODE, sphereMap);
742    glTexGeniv(GL_T, GL_TEXTURE_GEN_MODE, sphereMap);
743    glEnable(GL_TEXTURE_GEN_S);
744    glEnable(GL_TEXTURE_GEN_T);
745
746    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
747    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
748    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sWrapMode);
749    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tWrapMode);
750
751    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureEnvironment);
752
753    BuildLists();
754}
755
756static void ReInit(void)
757{
758    if (genericObject == torus) {
759	glEnable(GL_DEPTH_TEST);
760    } else  {
761	glDisable(GL_DEPTH_TEST);
762    }
763	glEnable(GL_DEPTH_TEST);
764
765#if 0
766    if (isFogged) {
767	textureEnvironment = modulate;
768    }
769#endif
770
771    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
772    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
773    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureEnvironment);
774}
775
776static void Draw(void)
777{
778    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
779
780    /* draw cage */
781    if (isFogged)
782	glEnable(GL_FOG);
783    else
784	glDisable(GL_FOG);
785    glColor3f(1, 1, 1);
786    glDisable(GL_LIGHTING);
787    glDisable(GL_TEXTURE_2D);
788    glCallList(cage);
789
790    /* draw object */
791    if (isLit)
792	glEnable(GL_LIGHTING);
793    else
794       glColor3f(1.0, 0.5, 0.2);
795    if (doTexture)
796       glEnable(GL_TEXTURE_2D);
797
798    glPushMatrix();
799        glTranslatef(0.0, 0.0, zTranslate);
800        glRotatef(xRotation, 1, 0, 0);
801        glRotatef(yRotation, 0, 1, 0);
802        glCallList(genericObject);
803    glPopMatrix();
804
805    glFlush();
806    glutSwapBuffers();
807}
808
809static void Reshape(int width, int height)
810{
811    W = width;
812    H = height;
813    ReInit();
814    glViewport( 0, 0, width, height );  /*new*/
815    glMatrixMode(GL_PROJECTION);
816    glLoadIdentity();
817    glFrustum(-0.2, 0.2, -0.2, 0.2, 0.15, 9.0);
818    glMatrixMode(GL_MODELVIEW);
819}
820
821static void Idle(void)
822{
823   static double t0 = -1.;
824   double t, dt;
825   t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
826   if (t0 < 0.)
827      t0 = t;
828   dt = t - t0;
829   t0 = t;
830
831   xRotation += .75*60.*dt;
832   yRotation += .375*60.*dt;
833   glutPostRedisplay();
834}
835
836static void Key2(int key, int x, int y)
837{
838
839    switch (key) {
840      case GLUT_KEY_LEFT:
841	yRotation -= 0.5;
842	autoRotate = GL_FALSE;
843	ReInit();
844	break;
845      case GLUT_KEY_RIGHT:
846	yRotation += 0.5;
847	autoRotate = GL_FALSE;
848	ReInit();
849	break;
850      case GLUT_KEY_UP:
851	xRotation -= 0.5;
852	autoRotate = GL_FALSE;
853	ReInit();
854	break;
855      case GLUT_KEY_DOWN:
856	xRotation += 0.5;
857	autoRotate = GL_FALSE;
858	ReInit();
859	break;
860      default:
861	return;
862    }
863    glutPostRedisplay();
864}
865
866static void Key(unsigned char key, int x, int y)
867{
868
869    switch (key) {
870      case 27:
871         /*	free(image->data);*/
872	exit(1);
873
874      case 'a':
875	autoRotate = !autoRotate;
876        if (autoRotate)
877           glutIdleFunc(Idle);
878        else
879           glutIdleFunc(NULL);
880
881	ReInit();
882	break;
883      case 'o':
884        if (genericObject == cube) {
885          genericObject = cylinder;
886        }
887        else if (genericObject == cylinder) {
888          genericObject = torus;
889        }
890        else {
891          genericObject = cube;
892        }
893	ReInit();
894	break;
895      case 'd':
896	textureEnvironment = decal;
897	ReInit();
898	break;
899      case 'm':
900	textureEnvironment = modulate;
901	ReInit();
902	break;
903      case 'l':
904	isLit = !isLit;
905	ReInit();
906	break;
907      case 'f':
908	isFogged = !isFogged;
909	ReInit();
910	break;
911      case 't':
912        doTexture = !doTexture;
913	ReInit();
914	break;
915      case '0':
916	magFilter = nnearest;
917	ReInit();
918	break;
919      case '1':
920	magFilter = linear;
921	ReInit();
922	break;
923      case '2':
924	minFilter = nnearest;
925	ReInit();
926	break;
927      case '3':
928	minFilter = linear;
929	ReInit();
930	break;
931      case '4':
932	minFilter = nearest_mipmap_nearest;
933	ReInit();
934	break;
935      case '5':
936	minFilter = nearest_mipmap_linear;
937	ReInit();
938	break;
939      case '6':
940	minFilter = linear_mipmap_nearest;
941	ReInit();
942	break;
943      case '7':
944	minFilter = linear_mipmap_linear;
945	ReInit();
946	break;
947      default:
948	return;
949    }
950    glutPostRedisplay();
951}
952
953static GLenum Args(int argc, char **argv)
954{
955    GLint i;
956
957    doubleBuffer = GL_TRUE;
958
959    for (i = 1; i < argc; i++) {
960	if (strcmp(argv[i], "-sb") == 0) {
961	    doubleBuffer = GL_FALSE;
962	} else if (strcmp(argv[i], "-db") == 0) {
963	    doubleBuffer = GL_TRUE;
964	} else if (strcmp(argv[i], "-f") == 0) {
965	    if (i+1 >= argc || argv[i+1][0] == '-') {
966		printf("-f (No file name).\n");
967		return GL_FALSE;
968	    } else {
969		imageFileName = argv[++i];
970	    }
971	} else {
972	    printf("%s (Bad option).\n", argv[i]);
973	    return GL_FALSE;
974	}
975    }
976    return GL_TRUE;
977}
978
979int main(int argc, char **argv)
980{
981    GLenum type;
982
983    glutInit(&argc, argv);
984
985    if (Args(argc, argv) == GL_FALSE) {
986	exit(1);
987    }
988
989    if (imageFileName == 0) {
990	printf("No image file.\n");
991	exit(1);
992    }
993
994    glutInitWindowPosition(0, 0); glutInitWindowSize( W, H);
995
996    type = GLUT_RGB | GLUT_DEPTH;
997    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
998    glutInitDisplayMode(type);
999
1000    if (glutCreateWindow("Texture Test") == GL_FALSE) {
1001        exit(1);
1002    }
1003
1004    Init();
1005
1006    glutReshapeFunc(Reshape);
1007    glutKeyboardFunc(Key);
1008    glutSpecialFunc(Key2);
1009    glutDisplayFunc(Draw);
1010    glutIdleFunc(Idle);
1011
1012    glutMainLoop();
1013	return 0;
1014}
1015