3afe91bdb7725be4d7b68e9ede690e87836d9030
[xscreensaver] / hacks / glx / glschool_gl.c
1 /* glschool_gl.c, Copyright (c) 2005-2006 David C. Lambert <dcl@panix.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 #include "sphere.h"
13 #include "glschool_gl.h"
14 #include "tube.h"
15
16 static GLUquadricObj    *Quadratic;
17
18 void
19 drawGoal(double *goal, GLuint goalList)
20 {
21         glColor3f(1.0, 0.0, 0.0);
22         glPushMatrix();
23         {
24                 glTranslatef(goal[0], goal[1], goal[2]);
25                 glColor3f(1.0, 0.0, 0.0);
26                 glCallList(goalList);
27         }
28         glPopMatrix();
29 }
30
31 void
32 drawBoundingBox(BBox *bbox, Bool wire)
33 {
34         double          xMin = BBOX_XMIN(bbox);
35         double          yMin = BBOX_YMIN(bbox);
36         double          zMin = BBOX_ZMIN(bbox);
37
38         double          xMax = BBOX_XMAX(bbox);
39         double          yMax = BBOX_YMAX(bbox);
40         double          zMax = BBOX_ZMAX(bbox);
41
42         glFrontFace(GL_CCW);
43         if (wire) glLineWidth(5.0);
44
45         /*  back */
46         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
47         glColor3f(0.0, 0.0, .15);
48         glVertex3f(xMin, yMin, zMin);
49         glVertex3f(xMax, yMin, zMin);
50         glVertex3f(xMax, yMax, zMin);
51         glVertex3f(xMin, yMax, zMin);
52         glEnd();
53
54         /* left */
55         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
56         glColor3f(0.0, 0.0, .2);
57         glVertex3f(xMin, yMin, zMax);
58         glVertex3f(xMin, yMin, zMin);
59         glVertex3f(xMin, yMax, zMin);
60         glVertex3f(xMin, yMax, zMax);
61         glEnd();
62
63         /* right */
64         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
65         glColor3f(0.0, 0.0, .2);
66         glVertex3f(xMax, yMin, zMin);
67         glVertex3f(xMax, yMin, zMax);
68         glVertex3f(xMax, yMax, zMax);
69         glVertex3f(xMax, yMax, zMin);
70         glEnd();
71
72         /* top */
73         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
74         glColor3f(0.0, 0.0, .1);
75         glVertex3f(xMax, yMax, zMax);
76         glVertex3f(xMin, yMax, zMax);
77         glVertex3f(xMin, yMax, zMin);
78         glVertex3f(xMax, yMax, zMin);
79         glEnd();
80
81         /* bottom */
82         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
83         glColor3f(0.0, 0.0, .3);
84         glVertex3f(xMin, yMin, zMax);
85         glVertex3f(xMax, yMin, zMax);
86         glVertex3f(xMax, yMin, zMin);
87         glVertex3f(xMin, yMin, zMin);
88         glEnd();
89
90         if (wire) glLineWidth(1.0);
91 }
92
93 void
94 createBBoxList(BBox *bbox, GLuint *bboxList, int wire)
95 {
96         *bboxList = glGenLists(1);
97         glNewList(*bboxList, GL_COMPILE);
98         drawBoundingBox(bbox, wire);
99         glEndList();
100 }
101
102 #if 1
103 void
104 createDrawLists(BBox *bbox, GLuint *bboxList, GLuint *goalList, GLuint *fishList, int wire)
105 {
106         if (Quadratic == (GLUquadricObj *)0) return;
107
108         gluQuadricDrawStyle(Quadratic, (wire ? GLU_LINE : GLU_FILL));
109
110         createBBoxList(bbox, bboxList, wire);
111
112         *goalList = glGenLists(1);
113         glNewList(*goalList, GL_COMPILE);
114         gluSphere(Quadratic, 5.0, 10, 10);
115         glEndList();
116
117         *fishList = glGenLists(1);
118         glNewList(*fishList, GL_COMPILE);
119 #if 0
120         gluSphere(Quadratic, 2.0, 10, 5);
121         gluCylinder(Quadratic, 2.0, 0.0, 10.0, 10, 5);
122 #else
123         gluSphere(Quadratic, 2.0, 3, 2);
124         gluCylinder(Quadratic, 2.0, 0.0, 10.0, 3, 2);
125 #endif
126         glEndList();
127 }
128
129 #else
130 void
131 createDrawLists(BBox *bbox, GLuint *bboxList, GLuint *goalList, GLuint *fishList, Bool wire)
132 {
133         createBBoxList(bbox, bboxList, wire);
134
135         *goalList = glGenLists(1);
136         glNewList(*goalList, GL_COMPILE);
137         glScalef(10.0, 10.0, 10.0);
138         unit_sphere(10, 10, wire);
139         glEndList();
140
141         *fishList = glGenLists(1);
142         glNewList(*fishList, GL_COMPILE);
143         glScalef(2.0, 2.0, 2.0);
144         unit_sphere(10, 10, wire);
145         cone(0, 0, 0,
146                  0, 0, 5,
147                  1, 0, 10,
148                  True, False, wire);
149         glEndList();
150 }
151
152 #endif
153
154 void
155 initLights(void)
156 {
157         GLfloat         amb[4] = {0.1, 0.1, 0.1, 1.0};
158         GLfloat         dif[4] = {1.0, 1.0, 1.0, 1.0};
159         GLfloat         spc[4] = {1.0, 1.0, 1.0, 1.0};
160         GLfloat         pos[4] = {0.0, 50.0, -50.0, 1.0};
161
162         glMatrixMode(GL_MODELVIEW);
163         glLoadIdentity();
164
165         glLightfv(GL_LIGHT0, GL_POSITION, pos);
166         glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
167         glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
168         glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
169
170         glEnable(GL_LIGHT0);
171         glEnable(GL_LIGHTING);
172 }
173
174 void
175 initFog()
176 {
177         GLfloat         fog[4] = {0.0, 0.0, 0.15, 1.0};
178
179         glEnable(GL_FOG);
180         glFogi(GL_FOG_MODE, GL_EXP2);
181         glFogfv(GL_FOG_COLOR, fog);
182         glFogf(GL_FOG_DENSITY, .0025);
183         glFogf(GL_FOG_START, -100);
184 }
185
186 void
187 initGLEnv(Bool doFog)
188 {
189         GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
190
191         glClearDepth(1.0);
192         glDepthFunc(GL_LESS);
193
194         glEnable(GL_COLOR_MATERIAL);
195         glMateriali(GL_FRONT, GL_SHININESS, 128);
196         glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
197         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, spc);
198
199         glEnable(GL_NORMALIZE);
200         glEnable(GL_DEPTH_TEST);
201         glShadeModel(GL_SMOOTH);
202         glEnable(GL_CULL_FACE);
203
204         initLights();
205         if (doFog) initFog();
206
207         Quadratic = gluNewQuadric();
208 }
209
210 void
211 reshape(int width, int height)
212 {
213         GLfloat h = (GLfloat) width / (GLfloat) height;
214
215         glViewport (0, 0, (GLint) width, (GLint) height);
216
217         glMatrixMode(GL_PROJECTION);
218         glLoadIdentity();
219         gluPerspective(60.0, h, 0.1, 451.0);
220
221         glMatrixMode(GL_MODELVIEW);
222         glLoadIdentity();
223 }
224
225 void
226 getColorVect(XColor *colors, int index, double *colorVect)
227 {
228         colorVect[0] = colors[index].red / 65535.0;
229         colorVect[1] = colors[index].green / 65535.0;
230         colorVect[2] = colors[index].blue / 65535.0;
231 }
232
233 void
234 drawSchool(XColor *colors, School *s,
235                    GLuint bboxList, GLuint goalList, GLuint fishList,
236                    int rotCounter, Bool drawGoal_p, Bool drawBBox_p)
237 {
238         double                  xVect[3];
239         double                  colorVect[3];
240         int                             i = 0;
241         double                  rotTheta = 0.0;
242         double                  colTheta = 0.0;
243         Fish                    *f = (Fish *)0;
244         int                             nFish = SCHOOL_NFISH(s);
245         Fish                    *theFishes = SCHOOL_FISHES(s);
246
247         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
248
249         glMatrixMode(GL_MODELVIEW);
250         glLoadIdentity();
251
252         if (drawBBox_p) {
253                 glDisable(GL_LIGHTING);
254                 glCallList(bboxList);
255                 glEnable(GL_LIGHTING);
256         }
257
258         if (drawGoal_p) drawGoal(SCHOOL_GOAL(s), goalList);
259
260         for(i = 0, f = theFishes; i < nFish; i++, f++) {
261                 colTheta = computeNormalAndThetaToPlusZ(FISH_AVGVEL(f), xVect);
262                 rotTheta = computeNormalAndThetaToPlusZ(FISH_VEL(f), xVect);
263
264                 if (FISH_IAVGVEL(f,2) < 0.0) colTheta = 180.0 - colTheta;
265                 if (FISH_VZ(f) < 0.0) rotTheta = 180.0 - rotTheta;
266
267                 getColorVect(colors, (int)(colTheta+240)%360, colorVect);
268                 glColor3f(colorVect[0], colorVect[1], colorVect[2]);
269
270                 glPushMatrix();
271                 {
272                         glTranslatef(FISH_X(f), FISH_Y(f), FISH_Z(f));
273                         glRotatef(180.0+rotTheta, xVect[0], xVect[1], xVect[2]);
274                         glCallList(fishList);
275                 }
276                 glPopMatrix();
277         }
278
279         glFinish();
280 }