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#include <stdio.h>
26#include <string.h>
27#include <math.h>
28#include <stdlib.h>
29#include "glut_wrap.h"
30
31
32#include "loadppm.c"
33
34GLenum doubleBuffer;
35
36char *texFileName = 0;
37PPMImage *image;
38
39float *minFilter, *magFilter, *sWrapMode, *tWrapMode;
40float decal[] = {GL_DECAL};
41float modulate[] = {GL_MODULATE};
42float repeat[] = {GL_REPEAT};
43float clamp[] = {GL_CLAMP};
44float nr[] = {GL_NEAREST};
45float ln[] = {GL_LINEAR};
46float nr_mipmap_nr[] = {GL_NEAREST_MIPMAP_NEAREST};
47float nr_mipmap_ln[] = {GL_NEAREST_MIPMAP_LINEAR};
48float ln_mipmap_nr[] = {GL_LINEAR_MIPMAP_NEAREST};
49float ln_mipmap_ln[] = {GL_LINEAR_MIPMAP_LINEAR};
50GLint sphereMap[] = {GL_SPHERE_MAP};
51
52GLenum doSphere = GL_FALSE;
53float xRotation = 0.0, yRotation = 0.0, zTranslate = -3.125;
54
55GLint cube;
56float c[6][4][3] = {
57    {
58	{
59	    1.0, 1.0, -1.0
60	},
61	{
62	    -1.0, 1.0, -1.0
63	},
64	{
65	    -1.0, -1.0, -1.0
66	},
67	{
68	    1.0, -1.0, -1.0
69	}
70    },
71    {
72	{
73	    1.0, 1.0, 1.0
74	},
75	{
76	    1.0, 1.0, -1.0
77	},
78	{
79	    1.0, -1.0, -1.0
80	},
81	{
82	    1.0, -1.0, 1.0
83	}
84    },
85    {
86	{
87	    -1.0, 1.0, 1.0
88	},
89	{
90	    1.0, 1.0, 1.0
91	},
92	{
93	    1.0, -1.0, 1.0
94	},
95	{
96	    -1.0, -1.0, 1.0
97	}
98    },
99    {
100	{
101	    -1.0, 1.0, -1.0
102	},
103	{
104	    -1.0, 1.0, 1.0
105	},
106	{
107	    -1.0, -1.0, 1.0
108	},
109	{
110	    -1.0, -1.0, -1.0
111	}
112    },
113    {
114	{
115	    -1.0, 1.0, 1.0
116	},
117	{
118	    -1.0, 1.0, -1.0
119	},
120	{
121	    1.0, 1.0, -1.0
122	},
123	{
124	    1.0, 1.0, 1.0
125	}
126    },
127    {
128	{
129	    -1.0, -1.0, -1.0
130	},
131	{
132	    -1.0, -1.0, 1.0
133	},
134	{
135	    1.0, -1.0, 1.0
136	},
137	{
138	    1.0, -1.0, -1.0
139	}
140    }
141};
142static float n[6][3] = {
143    {
144	0.0, 0.0, -1.0
145    },
146    {
147	1.0, 0.0, 0.0
148    },
149    {
150	0.0, 0.0, 1.0
151    },
152    {
153	-1.0, 0.0, 0.0
154    },
155    {
156	0.0, 1.0, 0.0
157    },
158    {
159	0.0, -1.0, 0.0
160    }
161};
162static float t[6][4][2] = {
163    {
164	{
165	    1.1,  1.1
166	},
167	{
168	    -0.1, 1.1
169	},
170	{
171	    -0.1, -0.1
172	},
173	{
174	    1.1,  -0.1
175	}
176    },
177    {
178	{
179	    1.1,  1.1
180	},
181	{
182	    -0.1, 1.1
183	},
184	{
185	    -0.1, -0.1
186	},
187	{
188	    1.1,  -0.1
189	}
190    },
191    {
192	{
193	    -0.1,  1.1
194	},
195	{
196	    1.1, 1.1
197	},
198	{
199	    1.1, -0.1
200	},
201	{
202	    -0.1,  -0.1
203	}
204    },
205    {
206	{
207	    1.1,  1.1
208	},
209	{
210	    -0.1, 1.1
211	},
212	{
213	    -0.1, -0.1
214	},
215	{
216	    1.1,  -0.1
217	}
218    },
219    {
220	{
221	    1.1,  1.1
222	},
223	{
224	    -0.1, 1.1
225	},
226	{
227	    -0.1, -0.1
228	},
229	{
230	    1.1,  -0.1
231	}
232    },
233    {
234	{
235	    1.1,  1.1
236	},
237	{
238	    -0.1, 1.1
239	},
240	{
241	    -0.1, -0.1
242	},
243	{
244	    1.1,  -0.1
245	}
246    },
247};
248
249static void BuildCube(void)
250{
251    GLint i;
252
253    glNewList(cube, GL_COMPILE);
254    for (i = 0; i < 6; i++) {
255	glBegin(GL_POLYGON);
256	    glNormal3fv(n[i]); glTexCoord2fv(t[i][0]); glVertex3fv(c[i][0]);
257	    glNormal3fv(n[i]); glTexCoord2fv(t[i][1]); glVertex3fv(c[i][1]);
258	    glNormal3fv(n[i]); glTexCoord2fv(t[i][2]); glVertex3fv(c[i][2]);
259	    glNormal3fv(n[i]); glTexCoord2fv(t[i][3]); glVertex3fv(c[i][3]);
260	glEnd();
261    }
262    glEndList();
263}
264
265static void BuildLists(void)
266{
267
268    cube = glGenLists(1);
269    BuildCube();
270}
271
272static void Init(void)
273{
274
275    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
276    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->sizeX, image->sizeY,
277		      GL_RGB, GL_UNSIGNED_BYTE, image->data);
278    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, decal);
279    glEnable(GL_TEXTURE_2D);
280
281    glFrontFace(GL_CCW);
282    glCullFace(GL_FRONT);
283    glEnable(GL_CULL_FACE);
284
285    BuildLists();
286
287    glClearColor(0.0, 0.0, 0.0, 0.0);
288
289    magFilter = nr;
290    minFilter = nr;
291    sWrapMode = repeat;
292    tWrapMode = repeat;
293}
294
295static void Reshape(int width, int height)
296{
297
298    glViewport(0, 0, (GLint)width, (GLint)height);
299
300    glMatrixMode(GL_PROJECTION);
301    glLoadIdentity();
302    gluPerspective(145.0, 1.0, 0.01, 1000);
303    glMatrixMode(GL_MODELVIEW);
304}
305
306static void Key2(int key, int x, int y)
307{
308
309    switch (key) {
310      case GLUT_KEY_LEFT:
311	yRotation -= 0.5;
312	break;
313      case GLUT_KEY_RIGHT:
314	yRotation += 0.5;
315	break;
316      case GLUT_KEY_UP:
317	xRotation -= 0.5;
318	break;
319      case GLUT_KEY_DOWN:
320	xRotation += 0.5;
321	break;
322      default:
323	return;
324    }
325
326    glutPostRedisplay();
327}
328
329static void Key(unsigned char key, int x, int y)
330{
331
332    switch (key) {
333      case 27:
334	exit(1);
335
336      case 'T':
337	zTranslate += 0.25;
338	break;
339      case 't':
340	zTranslate -= 0.25;
341	break;
342
343      case 's':
344	doSphere = !doSphere;
345	if (doSphere) {
346	    glTexGeniv(GL_S, GL_TEXTURE_GEN_MODE, sphereMap);
347	    glTexGeniv(GL_T, GL_TEXTURE_GEN_MODE, sphereMap);
348	    glEnable(GL_TEXTURE_GEN_S);
349	    glEnable(GL_TEXTURE_GEN_T);
350	} else {
351	    glDisable(GL_TEXTURE_GEN_S);
352	    glDisable(GL_TEXTURE_GEN_T);
353	}
354	break;
355
356      case '0':
357	magFilter = nr;
358	break;
359      case '1':
360	magFilter = ln;
361	break;
362      case '2':
363	minFilter = nr;
364	break;
365      case '3':
366	minFilter = ln;
367	break;
368      case '4':
369	minFilter = nr_mipmap_nr;
370	break;
371      case '5':
372	minFilter = nr_mipmap_ln;
373	break;
374      case '6':
375	minFilter = ln_mipmap_nr;
376	break;
377      case '7':
378	minFilter = ln_mipmap_ln;
379	break;
380      default:
381	return;
382    }
383
384    glutPostRedisplay();
385}
386
387static void Draw(void)
388{
389
390    glClear(GL_COLOR_BUFFER_BIT);
391
392    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sWrapMode);
393    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tWrapMode);
394    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
395    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
396
397    glPushMatrix();
398
399    glTranslatef(0.0, 0.0, zTranslate);
400    glRotatef(xRotation, 1, 0, 0);
401    glRotatef(yRotation, 0, 1, 0);
402    glCallList(cube);
403
404    glPopMatrix();
405
406    glFlush();
407
408    if (doubleBuffer) {
409	glutSwapBuffers();
410    }
411}
412
413static GLenum Args(int argc, char **argv)
414{
415    GLint i;
416
417    doubleBuffer = GL_FALSE;
418
419    for (i = 1; i < argc; i++) {
420	if (strcmp(argv[i], "-sb") == 0) {
421	    doubleBuffer = GL_FALSE;
422	} else if (strcmp(argv[i], "-db") == 0) {
423	    doubleBuffer = GL_TRUE;
424	} else if (strcmp(argv[i], "-f") == 0) {
425	    if (i+1 >= argc || argv[i+1][0] == '-') {
426		printf("-f (No file name).\n");
427		return GL_FALSE;
428	    } else {
429		texFileName = argv[++i];
430	    }
431	} else {
432	    printf("%s (Bad option).\n", argv[i]);
433	    return GL_FALSE;
434	}
435    }
436    return GL_TRUE;
437}
438
439int main(int argc, char **argv)
440{
441    GLenum type;
442
443    glutInit(&argc, argv);
444
445    if (Args(argc, argv) == GL_FALSE) {
446	exit(1);
447    }
448
449    if (texFileName == 0) {
450	printf("No image file.\n");
451	exit(1);
452    }
453
454    image = LoadPPM(texFileName);
455
456    glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
457
458    type = GLUT_RGB;
459    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
460    glutInitDisplayMode(type);
461
462    if (glutCreateWindow("Texture Test") == GL_FALSE) {
463	exit(1);
464    }
465
466    Init();
467
468    glutReshapeFunc(Reshape);
469    glutKeyboardFunc(Key);
470    glutSpecialFunc(Key2);
471    glutDisplayFunc(Draw);
472    glutMainLoop();
473	return 0;
474}
475