From http://www.jwz.org/xscreensaver/xscreensaver-5.16.tar.gz
[xscreensaver] / hacks / glx / glschool_gl.c
1 /* glschool_gl.c, Copyright (c) 2005-2012 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 "sphere.h"
15 #include "tube.h"
16
17 void
18 drawGoal(double *goal, GLuint goalList)
19 {
20         glColor3f(1.0, 0.0, 0.0);
21         glPushMatrix();
22         {
23                 glTranslatef(goal[0], goal[1], goal[2]);
24                 glColor3f(1.0, 0.0, 0.0);
25                 glCallList(goalList);
26         }
27         glPopMatrix();
28 }
29
30 int
31 drawBoundingBox(BBox *bbox, Bool wire)
32 {
33   int polys = 0;
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         polys++;
53         glEnd();
54
55         /* left */
56         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
57         glColor3f(0.0, 0.0, .2);
58         glVertex3f(xMin, yMin, zMax);
59         glVertex3f(xMin, yMin, zMin);
60         glVertex3f(xMin, yMax, zMin);
61         glVertex3f(xMin, yMax, zMax);
62         polys++;
63         glEnd();
64
65         /* right */
66         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
67         glColor3f(0.0, 0.0, .2);
68         glVertex3f(xMax, yMin, zMin);
69         glVertex3f(xMax, yMin, zMax);
70         glVertex3f(xMax, yMax, zMax);
71         glVertex3f(xMax, yMax, zMin);
72         polys++;
73         glEnd();
74
75         /* top */
76         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
77         glColor3f(0.0, 0.0, .1);
78         glVertex3f(xMax, yMax, zMax);
79         glVertex3f(xMin, yMax, zMax);
80         glVertex3f(xMin, yMax, zMin);
81         glVertex3f(xMax, yMax, zMin);
82         polys++;
83         glEnd();
84
85         /* bottom */
86         glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
87         glColor3f(0.0, 0.0, .3);
88         glVertex3f(xMin, yMin, zMax);
89         glVertex3f(xMax, yMin, zMax);
90         glVertex3f(xMax, yMin, zMin);
91         glVertex3f(xMin, yMin, zMin);
92         polys++;
93         glEnd();
94
95         if (wire) glLineWidth(1.0);
96
97         return polys;
98 }
99
100 int
101 createBBoxList(BBox *bbox, GLuint *bboxList, int wire)
102 {
103   int polys = 0;
104         *bboxList = glGenLists(1);
105         glNewList(*bboxList, GL_COMPILE);
106         polys = drawBoundingBox(bbox, wire);
107         glEndList();
108         return polys;
109 }
110
111 void
112 createDrawLists(BBox *bbox, GLuint *bboxList, GLuint *goalList, GLuint *fishList, int *fish_polys, int *box_polys, int wire)
113 {
114
115         int faces = 16;
116
117         *box_polys = 0;
118         *fish_polys = 0;
119
120         *box_polys +=   createBBoxList(bbox, bboxList, wire);
121
122         *box_polys = 0;
123         *fish_polys = 0;
124
125         *goalList = glGenLists(1);
126         glNewList(*goalList, GL_COMPILE);
127         glScalef (5, 5, 5);
128         *box_polys += unit_sphere (10, 10, wire);
129         glEndList();
130
131         *fishList = glGenLists(1);
132         glNewList(*fishList, GL_COMPILE);
133         *fish_polys += cone (0, 0, 0,
134                              0, 0, 10,
135                              2, 0,
136                              faces, True, (faces <= 3), /* cap */
137                              wire);
138         glTranslatef (0, 0, -0.3);
139         glScalef (2, 2, 2);
140         glRotatef (90, 1, 0, 0);
141         if (faces > 3)
142           *fish_polys += unit_sphere (faces, faces, wire);
143         glEndList();
144 }
145
146
147 void
148 initLights(void)
149 {
150         GLfloat         amb[4] = {0.1, 0.1, 0.1, 1.0};
151         GLfloat         dif[4] = {1.0, 1.0, 1.0, 1.0};
152         GLfloat         spc[4] = {1.0, 1.0, 1.0, 1.0};
153         GLfloat         pos[4] = {0.0, 50.0, -50.0, 1.0};
154
155         glMatrixMode(GL_MODELVIEW);
156         glLoadIdentity();
157
158         glLightfv(GL_LIGHT0, GL_POSITION, pos);
159         glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
160         glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
161         glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
162
163         glEnable(GL_LIGHT0);
164         glEnable(GL_LIGHTING);
165 }
166
167 void
168 initFog()
169 {
170         GLfloat         fog[4] = {0.0, 0.0, 0.15, 1.0};
171
172         glEnable(GL_FOG);
173         glFogi(GL_FOG_MODE, GL_EXP2);
174         glFogfv(GL_FOG_COLOR, fog);
175         glFogf(GL_FOG_DENSITY, .0025);
176         glFogf(GL_FOG_START, -100);
177 }
178
179 void
180 initGLEnv(Bool doFog)
181 {
182         GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
183
184         glClearDepth(1.0);
185         glDepthFunc(GL_LESS);
186
187         glEnable(GL_COLOR_MATERIAL);
188         glMateriali(GL_FRONT, GL_SHININESS, 128);
189         glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
190         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, spc);
191
192         glEnable(GL_NORMALIZE);
193         glEnable(GL_DEPTH_TEST);
194         glShadeModel(GL_SMOOTH);
195         glEnable(GL_CULL_FACE);
196
197         initLights();
198         if (doFog) initFog();
199 }
200
201 void
202 reshape(int width, int height)
203 {
204         GLfloat h = (GLfloat) width / (GLfloat) height;
205
206         glViewport (0, 0, (GLint) width, (GLint) height);
207
208         glMatrixMode(GL_PROJECTION);
209         glLoadIdentity();
210         gluPerspective(60.0, h, 0.1, 451.0);
211
212         glMatrixMode(GL_MODELVIEW);
213         glLoadIdentity();
214 }
215
216 void
217 getColorVect(XColor *colors, int index, double *colorVect)
218 {
219         colorVect[0] = colors[index].red / 65535.0;
220         colorVect[1] = colors[index].green / 65535.0;
221         colorVect[2] = colors[index].blue / 65535.0;
222 }
223
224 void
225 drawSchool(XColor *colors, School *s,
226                    GLuint bboxList, GLuint goalList, GLuint fishList,
227                    int rotCounter, Bool drawGoal_p, Bool drawBBox_p,
228            int fish_polys, int box_polys, unsigned long *polys)
229 {
230         double                  xVect[3];
231         double                  colorVect[3];
232         int                             i = 0;
233         double                  rotTheta = 0.0;
234         double                  colTheta = 0.0;
235         Fish                    *f = (Fish *)0;
236         int                             nFish = SCHOOL_NFISH(s);
237         Fish                    *theFishes = SCHOOL_FISHES(s);
238
239         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
240
241         glMatrixMode(GL_MODELVIEW);
242         glLoadIdentity();
243
244         if (drawBBox_p) {
245                 glDisable(GL_LIGHTING);
246                 glCallList(bboxList);
247                 glEnable(GL_LIGHTING);
248                 *polys += box_polys;
249         }
250
251         if (drawGoal_p) drawGoal(SCHOOL_GOAL(s), goalList);
252
253         for(i = 0, f = theFishes; i < nFish; i++, f++) {
254                 colTheta = computeNormalAndThetaToPlusZ(FISH_AVGVEL(f), xVect);
255                 rotTheta = computeNormalAndThetaToPlusZ(FISH_VEL(f), xVect);
256
257                 if (FISH_IAVGVEL(f,2) < 0.0) colTheta = 180.0 - colTheta;
258                 if (FISH_VZ(f) < 0.0) rotTheta = 180.0 - rotTheta;
259
260                 getColorVect(colors, (int)(colTheta+240)%360, colorVect);
261                 glColor3f(colorVect[0], colorVect[1], colorVect[2]);
262
263                 glPushMatrix();
264                 {
265                         glTranslatef(FISH_X(f), FISH_Y(f), FISH_Z(f));
266                         glRotatef(180.0+rotTheta, xVect[0], xVect[1], xVect[2]);
267                         glCallList(fishList);
268                         *polys += fish_polys;
269                 }
270                 glPopMatrix();
271         }
272
273         glFinish();
274 }