132001f49Smrg/*
232001f49Smrg * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
332001f49Smrg *
432001f49Smrg * Permission to use, copy, modify, distribute, and sell this software and
532001f49Smrg * its documentation for any purpose is hereby granted without fee, provided
632001f49Smrg * that (i) the above copyright notices and this permission notice appear in
732001f49Smrg * all copies of the software and related documentation, and (ii) the name of
832001f49Smrg * Silicon Graphics may not be used in any advertising or
932001f49Smrg * publicity relating to the software without the specific, prior written
1032001f49Smrg * permission of Silicon Graphics.
1132001f49Smrg *
1232001f49Smrg * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
1332001f49Smrg * ANY KIND,
1432001f49Smrg * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
1532001f49Smrg * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
1632001f49Smrg *
1732001f49Smrg * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
1832001f49Smrg * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
1932001f49Smrg * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2032001f49Smrg * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
2132001f49Smrg * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2232001f49Smrg * OF THIS SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg/* BEP: renamed "nearest" as "nnearest" to avoid math.h collision on AIX */
2632001f49Smrg
2732001f49Smrg#include <stdio.h>
2832001f49Smrg#include <string.h>
2932001f49Smrg#include <math.h>
3032001f49Smrg#include <stdlib.h>
3132001f49Smrg#include "glut_wrap.h"
3232001f49Smrg#include "readtex.h"
3332001f49Smrg
3432001f49Smrg
3532001f49Smrg#ifndef PI
3632001f49Smrg#define PI    3.14159265358979323846
3732001f49Smrg#endif
3832001f49Smrg
3932001f49Smrg
4032001f49SmrgGLenum doubleBuffer;
4132001f49Smrgint W = 400, H = 400;
4232001f49Smrg
4332001f49Smrgchar *imageFileName = DEMOS_DATA_DIR "reflect.rgb";
4432001f49Smrg
4532001f49Smrgfloat *minFilter, *magFilter, *sWrapMode, *tWrapMode;
4632001f49Smrgfloat decal[] = {GL_DECAL};
4732001f49Smrgfloat modulate[] = {GL_MODULATE};
4832001f49Smrgfloat repeat[] = {GL_REPEAT};
4932001f49Smrgfloat clamp[] = {GL_CLAMP};
5032001f49Smrgfloat nnearest[] = {GL_NEAREST};
5132001f49Smrgfloat linear[] = {GL_LINEAR};
5232001f49Smrgfloat nearest_mipmap_nearest[] = {GL_NEAREST_MIPMAP_NEAREST};
5332001f49Smrgfloat nearest_mipmap_linear[] = {GL_NEAREST_MIPMAP_LINEAR};
5432001f49Smrgfloat linear_mipmap_nearest[] = {GL_LINEAR_MIPMAP_NEAREST};
5532001f49Smrgfloat linear_mipmap_linear[] = {GL_LINEAR_MIPMAP_LINEAR};
5632001f49SmrgGLint sphereMap[] = {GL_SPHERE_MAP};
5732001f49Smrg
5832001f49Smrgfloat xRotation = 0.0, yRotation = 0.0;
5932001f49Smrgfloat zTranslate = -3.0;
6032001f49SmrgGLenum autoRotate = GL_TRUE;
6132001f49SmrgGLboolean isLit = GL_TRUE;
6232001f49SmrgGLboolean isFogged = GL_FALSE;
6332001f49SmrgGLboolean doTexture = GL_TRUE;
6432001f49Smrgfloat *textureEnvironment = modulate;
6532001f49Smrg
6632001f49Smrgint cube, cage, cylinder, torus, genericObject;
6732001f49Smrg
6832001f49Smrgfloat c[6][4][4][3] = {
6932001f49Smrg    {
7032001f49Smrg	{
7132001f49Smrg	    {
7232001f49Smrg		1.0, 1.0, -1.0
7332001f49Smrg	    },
7432001f49Smrg	    {
7532001f49Smrg		0.0, 1.0, -1.0
7632001f49Smrg	    },
7732001f49Smrg	    {
7832001f49Smrg		0.0, 0.0, -1.0
7932001f49Smrg	    },
8032001f49Smrg	    {
8132001f49Smrg		1.0, 0.0, -1.0
8232001f49Smrg	    },
8332001f49Smrg	},
8432001f49Smrg	{
8532001f49Smrg	    {
8632001f49Smrg		0.0, 1.0, -1.0
8732001f49Smrg	    },
8832001f49Smrg	    {
8932001f49Smrg		-1.0, 1.0, -1.0
9032001f49Smrg	    },
9132001f49Smrg	    {
9232001f49Smrg		-1.0, 0.0, -1.0
9332001f49Smrg	    },
9432001f49Smrg	    {
9532001f49Smrg		0.0, 0.0, -1.0
9632001f49Smrg	    },
9732001f49Smrg	},
9832001f49Smrg	{
9932001f49Smrg	    {
10032001f49Smrg		0.0,  0.0, -1.0
10132001f49Smrg	    },
10232001f49Smrg	    {
10332001f49Smrg		-1.0, 0.0, -1.0
10432001f49Smrg	    },
10532001f49Smrg	    {
10632001f49Smrg		-1.0, -1.0, -1.0
10732001f49Smrg	    },
10832001f49Smrg	    {
10932001f49Smrg		0.0, -1.0, -1.0
11032001f49Smrg	    },
11132001f49Smrg	},
11232001f49Smrg	{
11332001f49Smrg	    {
11432001f49Smrg		1.0, 0.0, -1.0
11532001f49Smrg	    },
11632001f49Smrg	    {
11732001f49Smrg		0.0, 0.0, -1.0
11832001f49Smrg	    },
11932001f49Smrg	    {
12032001f49Smrg		0.0, -1.0, -1.0
12132001f49Smrg	    },
12232001f49Smrg	    {
12332001f49Smrg		1.0, -1.0, -1.0
12432001f49Smrg	    },
12532001f49Smrg	},
12632001f49Smrg    },
12732001f49Smrg    {
12832001f49Smrg	{
12932001f49Smrg	    {
13032001f49Smrg		1.0, 1.0, 1.0
13132001f49Smrg	    },
13232001f49Smrg	    {
13332001f49Smrg		1.0, 1.0, 0.0
13432001f49Smrg	    },
13532001f49Smrg	    {
13632001f49Smrg		1.0, 0.0, 0.0
13732001f49Smrg	    },
13832001f49Smrg	    {
13932001f49Smrg		1.0, 0.0, 1.0
14032001f49Smrg	    },
14132001f49Smrg	},
14232001f49Smrg	{
14332001f49Smrg	    {
14432001f49Smrg		1.0, 1.0, 0.0
14532001f49Smrg	    },
14632001f49Smrg	    {
14732001f49Smrg		1.0, 1.0, -1.0
14832001f49Smrg	    },
14932001f49Smrg	    {
15032001f49Smrg		1.0, 0.0, -1.0
15132001f49Smrg	    },
15232001f49Smrg	    {
15332001f49Smrg		1.0, 0.0, 0.0
15432001f49Smrg	    },
15532001f49Smrg	},
15632001f49Smrg	{
15732001f49Smrg	    {
15832001f49Smrg		1.0, 0.0, -1.0
15932001f49Smrg	    },
16032001f49Smrg	    {
16132001f49Smrg		1.0, -1.0, -1.0
16232001f49Smrg	    },
16332001f49Smrg	    {
16432001f49Smrg		1.0, -1.0, 0.0
16532001f49Smrg	    },
16632001f49Smrg	    {
16732001f49Smrg		1.0, 0.0, 0.0
16832001f49Smrg	    },
16932001f49Smrg	},
17032001f49Smrg	{
17132001f49Smrg	    {
17232001f49Smrg		1.0, 0.0, 0.0
17332001f49Smrg	    },
17432001f49Smrg	    {
17532001f49Smrg		1.0, -1.0, 0.0
17632001f49Smrg	    },
17732001f49Smrg	    {
17832001f49Smrg		1.0, -1.0, 1.0
17932001f49Smrg	    },
18032001f49Smrg	    {
18132001f49Smrg		1.0, 0.0, 1.0
18232001f49Smrg	    },
18332001f49Smrg	},
18432001f49Smrg    },
18532001f49Smrg    {
18632001f49Smrg	{
18732001f49Smrg	    {
18832001f49Smrg		-1.0, 1.0, 1.0
18932001f49Smrg	    },
19032001f49Smrg	    {
19132001f49Smrg		0.0, 1.0, 1.0
19232001f49Smrg	    },
19332001f49Smrg	    {
19432001f49Smrg		0.0, 0.0, 1.0
19532001f49Smrg	    },
19632001f49Smrg	    {
19732001f49Smrg		-1.0, 0.0, 1.0
19832001f49Smrg	    },
19932001f49Smrg	},
20032001f49Smrg	{
20132001f49Smrg	    {
20232001f49Smrg		0.0, 1.0, 1.0
20332001f49Smrg	    },
20432001f49Smrg	    {
20532001f49Smrg		1.0, 1.0, 1.0
20632001f49Smrg	    },
20732001f49Smrg	    {
20832001f49Smrg		1.0, 0.0, 1.0
20932001f49Smrg	    },
21032001f49Smrg	    {
21132001f49Smrg		0.0, 0.0, 1.0
21232001f49Smrg	    },
21332001f49Smrg	},
21432001f49Smrg	{
21532001f49Smrg	    {
21632001f49Smrg		1.0, 0.0, 1.0
21732001f49Smrg	    },
21832001f49Smrg	    {
21932001f49Smrg		1.0, -1.0, 1.0
22032001f49Smrg	    },
22132001f49Smrg	    {
22232001f49Smrg		0.0, -1.0, 1.0
22332001f49Smrg	    },
22432001f49Smrg	    {
22532001f49Smrg		0.0, 0.0, 1.0
22632001f49Smrg	    },
22732001f49Smrg	},
22832001f49Smrg	{
22932001f49Smrg	    {
23032001f49Smrg		0.0, -1.0, 1.0
23132001f49Smrg	    },
23232001f49Smrg	    {
23332001f49Smrg		-1.0, -1.0, 1.0
23432001f49Smrg	    },
23532001f49Smrg	    {
23632001f49Smrg		-1.0, 0.0, 1.0
23732001f49Smrg	    },
23832001f49Smrg	    {
23932001f49Smrg		0.0, 0.0, 1.0
24032001f49Smrg	    },
24132001f49Smrg	},
24232001f49Smrg    },
24332001f49Smrg    {
24432001f49Smrg	{
24532001f49Smrg	    {
24632001f49Smrg		-1.0, 1.0, -1.0
24732001f49Smrg	    },
24832001f49Smrg	    {
24932001f49Smrg		-1.0, 1.0, 0.0
25032001f49Smrg	    },
25132001f49Smrg	    {
25232001f49Smrg		-1.0, 0.0, 0.0
25332001f49Smrg	    },
25432001f49Smrg	    {
25532001f49Smrg		-1.0, 0.0, -1.0
25632001f49Smrg	    },
25732001f49Smrg	},
25832001f49Smrg	{
25932001f49Smrg	    {
26032001f49Smrg		-1.0, 1.0, 0.0
26132001f49Smrg	    },
26232001f49Smrg	    {
26332001f49Smrg		-1.0, 1.0, 1.0
26432001f49Smrg	    },
26532001f49Smrg	    {
26632001f49Smrg		-1.0, 0.0, 1.0
26732001f49Smrg	    },
26832001f49Smrg	    {
26932001f49Smrg		-1.0, 0.0, 0.0
27032001f49Smrg	    },
27132001f49Smrg	},
27232001f49Smrg	{
27332001f49Smrg	    {
27432001f49Smrg		-1.0, 0.0, 1.0
27532001f49Smrg	    },
27632001f49Smrg	    {
27732001f49Smrg		-1.0, -1.0, 1.0
27832001f49Smrg	    },
27932001f49Smrg	    {
28032001f49Smrg		-1.0, -1.0, 0.0
28132001f49Smrg	    },
28232001f49Smrg	    {
28332001f49Smrg		-1.0, 0.0, 0.0
28432001f49Smrg	    },
28532001f49Smrg	},
28632001f49Smrg	{
28732001f49Smrg	    {
28832001f49Smrg		-1.0, -1.0, 0.0
28932001f49Smrg	    },
29032001f49Smrg	    {
29132001f49Smrg		-1.0, -1.0, -1.0
29232001f49Smrg	    },
29332001f49Smrg	    {
29432001f49Smrg		-1.0, 0.0, -1.0
29532001f49Smrg	    },
29632001f49Smrg	    {
29732001f49Smrg		-1.0, 0.0, 0.0
29832001f49Smrg	    },
29932001f49Smrg	},
30032001f49Smrg    },
30132001f49Smrg    {
30232001f49Smrg	{
30332001f49Smrg	    {
30432001f49Smrg		-1.0, 1.0, 1.0
30532001f49Smrg	    },
30632001f49Smrg	    {
30732001f49Smrg		-1.0, 1.0, 0.0
30832001f49Smrg	    },
30932001f49Smrg	    {
31032001f49Smrg		0.0, 1.0, 0.0
31132001f49Smrg	    },
31232001f49Smrg	    {
31332001f49Smrg		0.0, 1.0, 1.0
31432001f49Smrg	    },
31532001f49Smrg	},
31632001f49Smrg	{
31732001f49Smrg	    {
31832001f49Smrg		-1.0, 1.0, 0.0
31932001f49Smrg	    },
32032001f49Smrg	    {
32132001f49Smrg		-1.0, 1.0, -1.0
32232001f49Smrg	    },
32332001f49Smrg	    {
32432001f49Smrg		0.0, 1.0, -1.0
32532001f49Smrg	    },
32632001f49Smrg	    {
32732001f49Smrg		0.0, 1.0, 0.0
32832001f49Smrg	    },
32932001f49Smrg	},
33032001f49Smrg	{
33132001f49Smrg	    {
33232001f49Smrg		0.0, 1.0, -1.0
33332001f49Smrg	    },
33432001f49Smrg	    {
33532001f49Smrg		1.0, 1.0, -1.0
33632001f49Smrg	    },
33732001f49Smrg	    {
33832001f49Smrg		1.0, 1.0, 0.0
33932001f49Smrg	    },
34032001f49Smrg	    {
34132001f49Smrg		0.0, 1.0, 0.0
34232001f49Smrg	    },
34332001f49Smrg	},
34432001f49Smrg	{
34532001f49Smrg	    {
34632001f49Smrg		1.0, 1.0, 0.0
34732001f49Smrg	    },
34832001f49Smrg	    {
34932001f49Smrg		1.0, 1.0, 1.0
35032001f49Smrg	    },
35132001f49Smrg	    {
35232001f49Smrg		0.0, 1.0, 1.0
35332001f49Smrg	    },
35432001f49Smrg	    {
35532001f49Smrg		0.0, 1.0, 0.0
35632001f49Smrg	    },
35732001f49Smrg	},
35832001f49Smrg    },
35932001f49Smrg    {
36032001f49Smrg	{
36132001f49Smrg	    {
36232001f49Smrg		-1.0, -1.0, -1.0
36332001f49Smrg	    },
36432001f49Smrg	    {
36532001f49Smrg		-1.0, -1.0, 0.0
36632001f49Smrg	    },
36732001f49Smrg	    {
36832001f49Smrg		0.0, -1.0, 0.0
36932001f49Smrg	    },
37032001f49Smrg	    {
37132001f49Smrg		0.0, -1.0, -1.0
37232001f49Smrg	    },
37332001f49Smrg	},
37432001f49Smrg	{
37532001f49Smrg	    {
37632001f49Smrg		-1.0, -1.0, 0.0
37732001f49Smrg	    },
37832001f49Smrg	    {
37932001f49Smrg		-1.0, -1.0, 1.0
38032001f49Smrg	    },
38132001f49Smrg	    {
38232001f49Smrg		0.0, -1.0, 1.0
38332001f49Smrg	    },
38432001f49Smrg	    {
38532001f49Smrg		0.0, -1.0, 0.0
38632001f49Smrg	    },
38732001f49Smrg	},
38832001f49Smrg	{
38932001f49Smrg	    {
39032001f49Smrg		0.0, -1.0, 1.0
39132001f49Smrg	    },
39232001f49Smrg	    {
39332001f49Smrg		1.0, -1.0, 1.0
39432001f49Smrg	    },
39532001f49Smrg	    {
39632001f49Smrg		1.0, -1.0, 0.0
39732001f49Smrg	    },
39832001f49Smrg	    {
39932001f49Smrg		0.0, -1.0, 0.0
40032001f49Smrg	    },
40132001f49Smrg	},
40232001f49Smrg	{
40332001f49Smrg	    {
40432001f49Smrg		1.0, -1.0, 0.0
40532001f49Smrg	    },
40632001f49Smrg	    {
40732001f49Smrg		1.0, -1.0, -1.0
40832001f49Smrg	    },
40932001f49Smrg	    {
41032001f49Smrg		0.0, -1.0, -1.0
41132001f49Smrg	    },
41232001f49Smrg	    {
41332001f49Smrg		0.0, -1.0, 0.0
41432001f49Smrg	    },
41532001f49Smrg	},
41632001f49Smrg    }
41732001f49Smrg};
41832001f49Smrg
41932001f49Smrgfloat n[6][3] = {
42032001f49Smrg    {
42132001f49Smrg	0.0, 0.0, -1.0
42232001f49Smrg    },
42332001f49Smrg    {
42432001f49Smrg	1.0, 0.0, 0.0
42532001f49Smrg    },
42632001f49Smrg    {
42732001f49Smrg	0.0, 0.0, 1.0
42832001f49Smrg    },
42932001f49Smrg    {
43032001f49Smrg	-1.0, 0.0, 0.0
43132001f49Smrg    },
43232001f49Smrg    {
43332001f49Smrg	0.0, 1.0, 0.0
43432001f49Smrg    },
43532001f49Smrg    {
43632001f49Smrg	0.0, -1.0, 0.0
43732001f49Smrg    }
43832001f49Smrg};
43932001f49Smrg
44032001f49SmrgGLfloat identity[16] = {
44132001f49Smrg    1, 0, 0, 0,
44232001f49Smrg    0, 1, 0, 0,
44332001f49Smrg    0, 0, 1, 0,
44432001f49Smrg    0, 0, 0, 1,
44532001f49Smrg};
44632001f49Smrg
44732001f49Smrg
44832001f49Smrgstatic void BuildCylinder(int numEdges)
44932001f49Smrg{
45032001f49Smrg    int i, top = 1.0, bottom = -1.0;
45132001f49Smrg    float x[100], y[100], angle;
45232001f49Smrg
45332001f49Smrg    for (i = 0; i <= numEdges; i++) {
45432001f49Smrg	angle = i * 2.0 * PI / numEdges;
45532001f49Smrg	x[i] = cos(angle);   /* was cosf() */
45632001f49Smrg	y[i] = sin(angle);   /* was sinf() */
45732001f49Smrg    }
45832001f49Smrg
45932001f49Smrg    glNewList(cylinder, GL_COMPILE);
46032001f49Smrg    glBegin(GL_TRIANGLE_STRIP);
46132001f49Smrg	for (i = 0; i <= numEdges; i++) {
46232001f49Smrg	    glNormal3f(x[i], y[i], 0.0);
46332001f49Smrg	    glVertex3f(x[i], y[i], bottom);
46432001f49Smrg	    glVertex3f(x[i], y[i], top);
46532001f49Smrg	}
46632001f49Smrg    glEnd();
46732001f49Smrg    glBegin(GL_TRIANGLE_FAN);
46832001f49Smrg	glNormal3f(0.0, 0.0, 1.0);
46932001f49Smrg	glVertex3f(0.0, 0.0, top);
47032001f49Smrg	for (i = 0; i <= numEdges; i++) {
47132001f49Smrg	    glVertex3f(x[i], -y[i], top);
47232001f49Smrg	}
47332001f49Smrg    glEnd();
47432001f49Smrg    glBegin(GL_TRIANGLE_FAN);
47532001f49Smrg	glNormal3f(0.0, 0.0, -1.0);
47632001f49Smrg	glVertex3f(0.0, 0.0, bottom);
47732001f49Smrg	for (i = 0; i <= numEdges; i++) {
47832001f49Smrg	    glVertex3f(x[i], y[i], bottom);
47932001f49Smrg	}
48032001f49Smrg    glEnd();
48132001f49Smrg    glEndList();
48232001f49Smrg}
48332001f49Smrg
48432001f49Smrgstatic void BuildTorus(float rc, int numc, float rt, int numt)
48532001f49Smrg{
48632001f49Smrg    int i, j, k;
48732001f49Smrg    double s, t;
48832001f49Smrg    double x, y, z;
48932001f49Smrg    double pi, twopi;
49032001f49Smrg
49132001f49Smrg    pi = 3.14159265358979323846;
49232001f49Smrg    twopi = 2.0 * pi;
49332001f49Smrg
49432001f49Smrg    glNewList(torus, GL_COMPILE);
49532001f49Smrg    for (i = 0; i < numc; i++) {
49632001f49Smrg	glBegin(GL_QUAD_STRIP);
49732001f49Smrg        for (j = 0; j <= numt; j++) {
49832001f49Smrg	    for (k = 0; k <= 1; k++) {
49932001f49Smrg		s = (i + k) % numc + 0.5;
50032001f49Smrg		t = j % numt;
50132001f49Smrg
50232001f49Smrg		x = cos(t*twopi/numt) * cos(s*twopi/numc);
50332001f49Smrg		y = sin(t*twopi/numt) * cos(s*twopi/numc);
50432001f49Smrg		z = sin(s*twopi/numc);
50532001f49Smrg		glNormal3f(x, y, z);
50632001f49Smrg
50732001f49Smrg		x = (rt + rc * cos(s*twopi/numc)) * cos(t*twopi/numt);
50832001f49Smrg		y = (rt + rc * cos(s*twopi/numc)) * sin(t*twopi/numt);
50932001f49Smrg		z = rc * sin(s*twopi/numc);
51032001f49Smrg		glVertex3f(x, y, z);
51132001f49Smrg	    }
51232001f49Smrg        }
51332001f49Smrg	glEnd();
51432001f49Smrg    }
51532001f49Smrg    glEndList();
51632001f49Smrg}
51732001f49Smrg
51832001f49Smrgstatic void BuildCage(void)
51932001f49Smrg{
52032001f49Smrg    int i;
52132001f49Smrg    float inc;
52232001f49Smrg    float right, left, top, bottom, front, back;
52332001f49Smrg
52432001f49Smrg    front  = 0.0;
52532001f49Smrg    back   = -8.0;
52632001f49Smrg
52732001f49Smrg    left   = -4.0;
52832001f49Smrg    bottom = -4.0;
52932001f49Smrg    right  = 4.0;
53032001f49Smrg    top    = 4.0;
53132001f49Smrg
53232001f49Smrg    inc = 2.0 * 4.0 * 0.1;
53332001f49Smrg
53432001f49Smrg    glNewList(cage, GL_COMPILE);
53532001f49Smrg    for (i = 0; i < 10; i++) {
53632001f49Smrg
53732001f49Smrg	/*
53832001f49Smrg	** Back
53932001f49Smrg	*/
54032001f49Smrg	glBegin(GL_LINES);
54132001f49Smrg	    glVertex3f(left+i*inc, top,    back);
54232001f49Smrg	    glVertex3f(left+i*inc, bottom, back);
54332001f49Smrg	glEnd();
54432001f49Smrg	glBegin(GL_LINES);
54532001f49Smrg	    glVertex3f(right, bottom+i*inc, back);
54632001f49Smrg	    glVertex3f(left,  bottom+i*inc, back);
54732001f49Smrg	glEnd();
54832001f49Smrg
54932001f49Smrg	/*
55032001f49Smrg	** Front
55132001f49Smrg	*/
55232001f49Smrg	glBegin(GL_LINES);
55332001f49Smrg	    glVertex3f(left+i*inc, top,    front);
55432001f49Smrg	    glVertex3f(left+i*inc, bottom, front);
55532001f49Smrg	glEnd();
55632001f49Smrg	glBegin(GL_LINES);
55732001f49Smrg	    glVertex3f(right, bottom+i*inc, front);
55832001f49Smrg	    glVertex3f(left,  bottom+i*inc, front);
55932001f49Smrg	glEnd();
56032001f49Smrg
56132001f49Smrg	/*
56232001f49Smrg	** Left
56332001f49Smrg	*/
56432001f49Smrg	glBegin(GL_LINES);
56532001f49Smrg	    glVertex3f(left, bottom+i*inc, front);
56632001f49Smrg	    glVertex3f(left, bottom+i*inc, back);
56732001f49Smrg	glEnd();
56832001f49Smrg	glBegin(GL_LINES);
56932001f49Smrg	    glVertex3f(left, top,    back+i*inc);
57032001f49Smrg	    glVertex3f(left, bottom, back+i*inc);
57132001f49Smrg	glEnd();
57232001f49Smrg
57332001f49Smrg	/*
57432001f49Smrg	** Right
57532001f49Smrg	*/
57632001f49Smrg	glBegin(GL_LINES);
57732001f49Smrg	    glVertex3f(right, top-i*inc, front);
57832001f49Smrg	    glVertex3f(right, top-i*inc, back);
57932001f49Smrg	glEnd();
58032001f49Smrg	glBegin(GL_LINES);
58132001f49Smrg	    glVertex3f(right, top,    back+i*inc);
58232001f49Smrg	    glVertex3f(right, bottom, back+i*inc);
58332001f49Smrg	glEnd();
58432001f49Smrg
58532001f49Smrg	/*
58632001f49Smrg	** Top
58732001f49Smrg	*/
58832001f49Smrg	glBegin(GL_LINES);
58932001f49Smrg	    glVertex3f(left+i*inc, top, front);
59032001f49Smrg	    glVertex3f(left+i*inc, top, back);
59132001f49Smrg	glEnd();
59232001f49Smrg	glBegin(GL_LINES);
59332001f49Smrg	    glVertex3f(right, top, back+i*inc);
59432001f49Smrg	    glVertex3f(left,  top, back+i*inc);
59532001f49Smrg	glEnd();
59632001f49Smrg
59732001f49Smrg	/*
59832001f49Smrg	** Bottom
59932001f49Smrg	*/
60032001f49Smrg	glBegin(GL_LINES);
60132001f49Smrg	    glVertex3f(right-i*inc, bottom, front);
60232001f49Smrg	    glVertex3f(right-i*inc, bottom, back);
60332001f49Smrg	glEnd();
60432001f49Smrg	glBegin(GL_LINES);
60532001f49Smrg	    glVertex3f(right, bottom, back+i*inc);
60632001f49Smrg	    glVertex3f(left,  bottom, back+i*inc);
60732001f49Smrg	glEnd();
60832001f49Smrg    }
60932001f49Smrg    glEndList();
61032001f49Smrg}
61132001f49Smrg
61232001f49Smrgstatic void BuildCube(void)
61332001f49Smrg{
61432001f49Smrg    int i, j;
61532001f49Smrg
61632001f49Smrg    glNewList(cube, GL_COMPILE);
61732001f49Smrg    for (i = 0; i < 6; i++) {
61832001f49Smrg	for (j = 0; j < 4; j++) {
61932001f49Smrg	    glNormal3fv(n[i]);
62032001f49Smrg	    glBegin(GL_POLYGON);
62132001f49Smrg		glVertex3fv(c[i][j][0]);
62232001f49Smrg		glVertex3fv(c[i][j][1]);
62332001f49Smrg		glVertex3fv(c[i][j][2]);
62432001f49Smrg		glVertex3fv(c[i][j][3]);
62532001f49Smrg	    glEnd();
62632001f49Smrg	}
62732001f49Smrg    }
62832001f49Smrg    glEndList();
62932001f49Smrg}
63032001f49Smrg
63132001f49Smrgstatic void BuildLists(void)
63232001f49Smrg{
63332001f49Smrg
63432001f49Smrg    cube = glGenLists(1);
63532001f49Smrg    BuildCube();
63632001f49Smrg
63732001f49Smrg    cage = glGenLists(2);
63832001f49Smrg    BuildCage();
63932001f49Smrg
64032001f49Smrg    cylinder = glGenLists(3);
64132001f49Smrg    BuildCylinder(60);
64232001f49Smrg
64332001f49Smrg    torus = glGenLists(4);
64432001f49Smrg    BuildTorus(0.65, 20, .85, 65);
64532001f49Smrg
64632001f49Smrg    genericObject = torus;
64732001f49Smrg}
64832001f49Smrg
64932001f49Smrgstatic void SetDefaultSettings(void)
65032001f49Smrg{
65132001f49Smrg
65232001f49Smrg    magFilter = nnearest;
65332001f49Smrg    minFilter = nnearest;
65432001f49Smrg    sWrapMode = repeat;
65532001f49Smrg    tWrapMode = repeat;
65632001f49Smrg    textureEnvironment = modulate;
65732001f49Smrg    autoRotate = GL_TRUE;
65832001f49Smrg}
65932001f49Smrg
66032001f49Smrgstatic unsigned char *AlphaPadImage(int bufSize, unsigned char *inData, int alpha)
66132001f49Smrg{
66232001f49Smrg    unsigned char *outData, *out_ptr, *in_ptr;
66332001f49Smrg    int i;
66432001f49Smrg
66532001f49Smrg    outData = (unsigned char *) malloc(bufSize * 4);
66632001f49Smrg    out_ptr = outData;
66732001f49Smrg    in_ptr = inData;
66832001f49Smrg
66932001f49Smrg    for (i = 0; i < bufSize; i++) {
67032001f49Smrg	*out_ptr++ = *in_ptr++;
67132001f49Smrg	*out_ptr++ = *in_ptr++;
67232001f49Smrg	*out_ptr++ = *in_ptr++;
67332001f49Smrg	*out_ptr++ = alpha;
67432001f49Smrg    }
67532001f49Smrg
67632001f49Smrg    free (inData);
67732001f49Smrg    return outData;
67832001f49Smrg}
67932001f49Smrg
68032001f49Smrgstatic void Init(void)
68132001f49Smrg{
68232001f49Smrg    float ambient[] = {0.0, 0.0, 0.0, 1.0};
68332001f49Smrg    float diffuse[] = {1.0, 1.0, 1.0, 1.0};
68432001f49Smrg    float specular[] = {1.0, 1.0, 1.0, 1.0};
68532001f49Smrg    float position[] = {0.0, 0.0,  4.0, 0.0};
68632001f49Smrg    float fog_color[] = {0.0, 0.0, 0.0, 1.0};
68732001f49Smrg    float mat_ambient[] = {0.0, 0.0, 0.0, 1.0};
68832001f49Smrg    float mat_shininess[] = {90.0};
68932001f49Smrg    float mat_specular[] = {1.0, 1.0, 1.0, 1.0};
69032001f49Smrg    float mat_diffuse[] = {0.8, 0.8, 0.8, 1.0};
69132001f49Smrg    float lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0};
69232001f49Smrg    float lmodel_twoside[] = {GL_TRUE};
69332001f49Smrg    int w, h;
69432001f49Smrg    GLenum format;
69532001f49Smrg    GLubyte *image;
69632001f49Smrg
69732001f49Smrg    printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
69832001f49Smrg
69932001f49Smrg    SetDefaultSettings();
70032001f49Smrg
70132001f49Smrg    image = LoadRGBImage(imageFileName, &w, &h, &format);
70232001f49Smrg    if (!image) {
70332001f49Smrg       printf("Error: couldn't load %s\n", imageFileName);
70432001f49Smrg       exit(1);
70532001f49Smrg    }
70632001f49Smrg    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
70732001f49Smrg    gluBuild2DMipmaps(GL_TEXTURE_2D, format, w, h,
70832001f49Smrg                      GL_RGB, GL_UNSIGNED_BYTE, image);
70932001f49Smrg
71032001f49Smrg    free(image);
71132001f49Smrg
71232001f49Smrg    glFogf(GL_FOG_DENSITY, 0.125);
71332001f49Smrg    glFogi(GL_FOG_MODE, GL_LINEAR);
71432001f49Smrg    glFogf(GL_FOG_START, 4.0);
71532001f49Smrg    glFogf(GL_FOG_END, 8.5);
71632001f49Smrg    glFogfv(GL_FOG_COLOR, fog_color);
71732001f49Smrg
71832001f49Smrg    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
71932001f49Smrg    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
72032001f49Smrg    glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
72132001f49Smrg    glLightfv(GL_LIGHT0, GL_POSITION, position);
72232001f49Smrg    glEnable(GL_LIGHT0);
72332001f49Smrg
72432001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
72532001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
72632001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
72732001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
72832001f49Smrg
72932001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
73032001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
73132001f49Smrg    glShadeModel(GL_SMOOTH);
73232001f49Smrg
73332001f49Smrg
73432001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
73532001f49Smrg    glEnable(GL_DEPTH_TEST);
73632001f49Smrg
73732001f49Smrg    glFrontFace(GL_CW);
73832001f49Smrg    glEnable(GL_CULL_FACE);
73932001f49Smrg    glCullFace(GL_BACK);
74032001f49Smrg
74132001f49Smrg    glTexGeniv(GL_S, GL_TEXTURE_GEN_MODE, sphereMap);
74232001f49Smrg    glTexGeniv(GL_T, GL_TEXTURE_GEN_MODE, sphereMap);
74332001f49Smrg    glEnable(GL_TEXTURE_GEN_S);
74432001f49Smrg    glEnable(GL_TEXTURE_GEN_T);
74532001f49Smrg
74632001f49Smrg    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
74732001f49Smrg    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
74832001f49Smrg    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sWrapMode);
74932001f49Smrg    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tWrapMode);
75032001f49Smrg
75132001f49Smrg    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureEnvironment);
75232001f49Smrg
75332001f49Smrg    BuildLists();
75432001f49Smrg}
75532001f49Smrg
75632001f49Smrgstatic void ReInit(void)
75732001f49Smrg{
75832001f49Smrg    if (genericObject == torus) {
75932001f49Smrg	glEnable(GL_DEPTH_TEST);
76032001f49Smrg    } else  {
76132001f49Smrg	glDisable(GL_DEPTH_TEST);
76232001f49Smrg    }
76332001f49Smrg	glEnable(GL_DEPTH_TEST);
76432001f49Smrg
76532001f49Smrg#if 0
76632001f49Smrg    if (isFogged) {
76732001f49Smrg	textureEnvironment = modulate;
76832001f49Smrg    }
76932001f49Smrg#endif
77032001f49Smrg
77132001f49Smrg    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
77232001f49Smrg    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
77332001f49Smrg    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureEnvironment);
77432001f49Smrg}
77532001f49Smrg
77632001f49Smrgstatic void Draw(void)
77732001f49Smrg{
77832001f49Smrg    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
77932001f49Smrg
78032001f49Smrg    /* draw cage */
78132001f49Smrg    if (isFogged)
78232001f49Smrg	glEnable(GL_FOG);
78332001f49Smrg    else
78432001f49Smrg	glDisable(GL_FOG);
78532001f49Smrg    glColor3f(1, 1, 1);
78632001f49Smrg    glDisable(GL_LIGHTING);
78732001f49Smrg    glDisable(GL_TEXTURE_2D);
78832001f49Smrg    glCallList(cage);
78932001f49Smrg
79032001f49Smrg    /* draw object */
79132001f49Smrg    if (isLit)
79232001f49Smrg	glEnable(GL_LIGHTING);
79332001f49Smrg    else
79432001f49Smrg       glColor3f(1.0, 0.5, 0.2);
79532001f49Smrg    if (doTexture)
79632001f49Smrg       glEnable(GL_TEXTURE_2D);
79732001f49Smrg
79832001f49Smrg    glPushMatrix();
79932001f49Smrg        glTranslatef(0.0, 0.0, zTranslate);
80032001f49Smrg        glRotatef(xRotation, 1, 0, 0);
80132001f49Smrg        glRotatef(yRotation, 0, 1, 0);
80232001f49Smrg        glCallList(genericObject);
80332001f49Smrg    glPopMatrix();
80432001f49Smrg
80532001f49Smrg    glFlush();
80632001f49Smrg    glutSwapBuffers();
80732001f49Smrg}
80832001f49Smrg
80932001f49Smrgstatic void Reshape(int width, int height)
81032001f49Smrg{
81132001f49Smrg    W = width;
81232001f49Smrg    H = height;
81332001f49Smrg    ReInit();
81432001f49Smrg    glViewport( 0, 0, width, height );  /*new*/
81532001f49Smrg    glMatrixMode(GL_PROJECTION);
81632001f49Smrg    glLoadIdentity();
81732001f49Smrg    glFrustum(-0.2, 0.2, -0.2, 0.2, 0.15, 9.0);
81832001f49Smrg    glMatrixMode(GL_MODELVIEW);
81932001f49Smrg}
82032001f49Smrg
82132001f49Smrgstatic void Idle(void)
82232001f49Smrg{
82332001f49Smrg   static double t0 = -1.;
82432001f49Smrg   double t, dt;
82532001f49Smrg   t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
82632001f49Smrg   if (t0 < 0.)
82732001f49Smrg      t0 = t;
82832001f49Smrg   dt = t - t0;
82932001f49Smrg   t0 = t;
83032001f49Smrg
83132001f49Smrg   xRotation += .75*60.*dt;
83232001f49Smrg   yRotation += .375*60.*dt;
83332001f49Smrg   glutPostRedisplay();
83432001f49Smrg}
83532001f49Smrg
83632001f49Smrgstatic void Key2(int key, int x, int y)
83732001f49Smrg{
83832001f49Smrg
83932001f49Smrg    switch (key) {
84032001f49Smrg      case GLUT_KEY_LEFT:
84132001f49Smrg	yRotation -= 0.5;
84232001f49Smrg	autoRotate = GL_FALSE;
84332001f49Smrg	ReInit();
84432001f49Smrg	break;
84532001f49Smrg      case GLUT_KEY_RIGHT:
84632001f49Smrg	yRotation += 0.5;
84732001f49Smrg	autoRotate = GL_FALSE;
84832001f49Smrg	ReInit();
84932001f49Smrg	break;
85032001f49Smrg      case GLUT_KEY_UP:
85132001f49Smrg	xRotation -= 0.5;
85232001f49Smrg	autoRotate = GL_FALSE;
85332001f49Smrg	ReInit();
85432001f49Smrg	break;
85532001f49Smrg      case GLUT_KEY_DOWN:
85632001f49Smrg	xRotation += 0.5;
85732001f49Smrg	autoRotate = GL_FALSE;
85832001f49Smrg	ReInit();
85932001f49Smrg	break;
86032001f49Smrg      default:
86132001f49Smrg	return;
86232001f49Smrg    }
86332001f49Smrg    glutPostRedisplay();
86432001f49Smrg}
86532001f49Smrg
86632001f49Smrgstatic void Key(unsigned char key, int x, int y)
86732001f49Smrg{
86832001f49Smrg
86932001f49Smrg    switch (key) {
87032001f49Smrg      case 27:
87132001f49Smrg         /*	free(image->data);*/
87232001f49Smrg	exit(1);
87332001f49Smrg
87432001f49Smrg      case 'a':
87532001f49Smrg	autoRotate = !autoRotate;
87632001f49Smrg        if (autoRotate)
87732001f49Smrg           glutIdleFunc(Idle);
87832001f49Smrg        else
87932001f49Smrg           glutIdleFunc(NULL);
88032001f49Smrg
88132001f49Smrg	ReInit();
88232001f49Smrg	break;
88332001f49Smrg      case 'o':
88432001f49Smrg        if (genericObject == cube) {
88532001f49Smrg          genericObject = cylinder;
88632001f49Smrg        }
88732001f49Smrg        else if (genericObject == cylinder) {
88832001f49Smrg          genericObject = torus;
88932001f49Smrg        }
89032001f49Smrg        else {
89132001f49Smrg          genericObject = cube;
89232001f49Smrg        }
89332001f49Smrg	ReInit();
89432001f49Smrg	break;
89532001f49Smrg      case 'd':
89632001f49Smrg	textureEnvironment = decal;
89732001f49Smrg	ReInit();
89832001f49Smrg	break;
89932001f49Smrg      case 'm':
90032001f49Smrg	textureEnvironment = modulate;
90132001f49Smrg	ReInit();
90232001f49Smrg	break;
90332001f49Smrg      case 'l':
90432001f49Smrg	isLit = !isLit;
90532001f49Smrg	ReInit();
90632001f49Smrg	break;
90732001f49Smrg      case 'f':
90832001f49Smrg	isFogged = !isFogged;
90932001f49Smrg	ReInit();
91032001f49Smrg	break;
91132001f49Smrg      case 't':
91232001f49Smrg        doTexture = !doTexture;
91332001f49Smrg	ReInit();
91432001f49Smrg	break;
91532001f49Smrg      case '0':
91632001f49Smrg	magFilter = nnearest;
91732001f49Smrg	ReInit();
91832001f49Smrg	break;
91932001f49Smrg      case '1':
92032001f49Smrg	magFilter = linear;
92132001f49Smrg	ReInit();
92232001f49Smrg	break;
92332001f49Smrg      case '2':
92432001f49Smrg	minFilter = nnearest;
92532001f49Smrg	ReInit();
92632001f49Smrg	break;
92732001f49Smrg      case '3':
92832001f49Smrg	minFilter = linear;
92932001f49Smrg	ReInit();
93032001f49Smrg	break;
93132001f49Smrg      case '4':
93232001f49Smrg	minFilter = nearest_mipmap_nearest;
93332001f49Smrg	ReInit();
93432001f49Smrg	break;
93532001f49Smrg      case '5':
93632001f49Smrg	minFilter = nearest_mipmap_linear;
93732001f49Smrg	ReInit();
93832001f49Smrg	break;
93932001f49Smrg      case '6':
94032001f49Smrg	minFilter = linear_mipmap_nearest;
94132001f49Smrg	ReInit();
94232001f49Smrg	break;
94332001f49Smrg      case '7':
94432001f49Smrg	minFilter = linear_mipmap_linear;
94532001f49Smrg	ReInit();
94632001f49Smrg	break;
94732001f49Smrg      default:
94832001f49Smrg	return;
94932001f49Smrg    }
95032001f49Smrg    glutPostRedisplay();
95132001f49Smrg}
95232001f49Smrg
95332001f49Smrgstatic GLenum Args(int argc, char **argv)
95432001f49Smrg{
95532001f49Smrg    GLint i;
95632001f49Smrg
95732001f49Smrg    doubleBuffer = GL_TRUE;
95832001f49Smrg
95932001f49Smrg    for (i = 1; i < argc; i++) {
96032001f49Smrg	if (strcmp(argv[i], "-sb") == 0) {
96132001f49Smrg	    doubleBuffer = GL_FALSE;
96232001f49Smrg	} else if (strcmp(argv[i], "-db") == 0) {
96332001f49Smrg	    doubleBuffer = GL_TRUE;
96432001f49Smrg	} else if (strcmp(argv[i], "-f") == 0) {
96532001f49Smrg	    if (i+1 >= argc || argv[i+1][0] == '-') {
96632001f49Smrg		printf("-f (No file name).\n");
96732001f49Smrg		return GL_FALSE;
96832001f49Smrg	    } else {
96932001f49Smrg		imageFileName = argv[++i];
97032001f49Smrg	    }
97132001f49Smrg	} else {
97232001f49Smrg	    printf("%s (Bad option).\n", argv[i]);
97332001f49Smrg	    return GL_FALSE;
97432001f49Smrg	}
97532001f49Smrg    }
97632001f49Smrg    return GL_TRUE;
97732001f49Smrg}
97832001f49Smrg
97932001f49Smrgint main(int argc, char **argv)
98032001f49Smrg{
98132001f49Smrg    GLenum type;
98232001f49Smrg
98332001f49Smrg    glutInit(&argc, argv);
98432001f49Smrg
98532001f49Smrg    if (Args(argc, argv) == GL_FALSE) {
98632001f49Smrg	exit(1);
98732001f49Smrg    }
98832001f49Smrg
98932001f49Smrg    if (imageFileName == 0) {
99032001f49Smrg	printf("No image file.\n");
99132001f49Smrg	exit(1);
99232001f49Smrg    }
99332001f49Smrg
99432001f49Smrg    glutInitWindowPosition(0, 0); glutInitWindowSize( W, H);
99532001f49Smrg
99632001f49Smrg    type = GLUT_RGB | GLUT_DEPTH;
99732001f49Smrg    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
99832001f49Smrg    glutInitDisplayMode(type);
99932001f49Smrg
100032001f49Smrg    if (glutCreateWindow("Texture Test") == GL_FALSE) {
100132001f49Smrg        exit(1);
100232001f49Smrg    }
100332001f49Smrg
100432001f49Smrg    Init();
100532001f49Smrg
100632001f49Smrg    glutReshapeFunc(Reshape);
100732001f49Smrg    glutKeyboardFunc(Key);
100832001f49Smrg    glutSpecialFunc(Key2);
100932001f49Smrg    glutDisplayFunc(Draw);
101032001f49Smrg    glutIdleFunc(Idle);
101132001f49Smrg
101232001f49Smrg    glutMainLoop();
101332001f49Smrg	return 0;
101432001f49Smrg}
1015