7414838fa84e8c9460579d740a88b9a057b0147d
[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         gluSphere(Quadratic, 2.0, 10, 5);
120         gluCylinder(Quadratic, 2.0, 0.0, 10.0, 10, 5);
121         glEndList();
122 }
123
124 #else
125 void
126 createDrawLists(BBox *bbox, GLuint *bboxList, GLuint *goalList, GLuint *fishList, Bool wire)
127 {
128         createBBoxList(bbox, bboxList, wire);
129
130         *goalList = glGenLists(1);
131         glNewList(*goalList, GL_COMPILE);
132         glScalef(10.0, 10.0, 10.0);
133         unit_sphere(10, 10, wire);
134         glEndList();
135
136         *fishList = glGenLists(1);
137         glNewList(*fishList, GL_COMPILE);
138         glScalef(2.0, 2.0, 2.0);
139         unit_sphere(10, 10, wire);
140         cone(0, 0, 0,
141                  0, 0, 5,
142                  1, 0, 10,
143                  True, False, wire);
144         glEndList();
145 }
146
147 #endif
148
149 void
150 initLights(void)
151 {
152         GLfloat         amb[4] = {0.1, 0.1, 0.1, 1.0};
153         GLfloat         dif[4] = {1.0, 1.0, 1.0, 1.0};
154         GLfloat         spc[4] = {1.0, 1.0, 1.0, 1.0};
155         GLfloat         pos[4] = {0.0, 50.0, -50.0, 1.0};
156
157         glMatrixMode(GL_MODELVIEW);
158         glLoadIdentity();
159
160         glLightfv(GL_LIGHT0, GL_POSITION, pos);
161         glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
162         glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
163         glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
164
165         glEnable(GL_LIGHT0);
166         glEnable(GL_LIGHTING);
167 }
168
169 void
170 initFog()
171 {
172         GLfloat         fog[4] = {0.0, 0.0, 0.15, 1.0};
173
174         glEnable(GL_FOG);
175         glFogi(GL_FOG_MODE, GL_EXP2);
176         glFogfv(GL_FOG_COLOR, fog);
177         glFogf(GL_FOG_DENSITY, .0025);
178         glFogf(GL_FOG_START, -100);
179 }
180
181 void
182 initGLEnv(Bool doFog)
183 {
184         GLfloat         spc[4] = {1.0, 1.0, 1.0, 1.0};
185
186         glClearColor(0.0, 0.0, 0.0, 0.0);
187         glClearDepth(1.0);
188         glDepthFunc(GL_LESS);
189
190         glEnable(GL_COLOR_MATERIAL);
191         glMateriali(GL_FRONT, GL_SHININESS, 128);
192         glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
193         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, spc);
194
195         glEnable(GL_NORMALIZE);
196         glEnable(GL_DEPTH_TEST);
197         glShadeModel(GL_SMOOTH);
198         glEnable(GL_CULL_FACE);
199
200         initLights();
201         if (doFog) initFog();
202
203         Quadratic = gluNewQuadric();
204 }
205
206 void
207 reshape(int width, int height)
208 {
209         GLfloat h = (GLfloat) width / (GLfloat) height;
210
211         glViewport (0, 0, (GLint) width, (GLint) height);
212
213         glMatrixMode(GL_PROJECTION);
214         glLoadIdentity();
215         gluPerspective(60.0, h, 0.1, 451.0);
216
217         glMatrixMode(GL_MODELVIEW);
218         glLoadIdentity();
219 }
220
221 void
222 getColorVect(XColor *colors, int index, double *colorVect)
223 {
224         colorVect[0] = colors[index].red / 65535.0;
225         colorVect[1] = colors[index].green / 65535.0;
226         colorVect[2] = colors[index].blue / 65535.0;
227 }
228
229 void
230 drawSchool(XColor *colors, School *s,
231                    GLuint bboxList, GLuint goalList, GLuint fishList,
232                    int rotCounter, Bool drawGoal_p, Bool drawBBox_p)
233 {
234         double                  xVect[3];
235         double                  colorVect[3];
236         int                             i = 0;
237         double                  rotTheta = 0.0;
238         double                  colTheta = 0.0;
239         Fish                    *f = (Fish *)0;
240         int                             nFish = SCHOOL_NFISH(s);
241         Fish                    *theFishes = SCHOOL_FISHES(s);
242
243         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
244
245         glMatrixMode(GL_MODELVIEW);
246         glLoadIdentity();
247
248         if (drawBBox_p) {
249                 glDisable(GL_LIGHTING);
250                 glCallList(bboxList);
251                 glEnable(GL_LIGHTING);
252         }
253
254         if (drawGoal_p) drawGoal(SCHOOL_GOAL(s), goalList);
255
256         for(i = 0, f = theFishes; i < nFish; i++, f++) {
257                 colTheta = computeNormalAndThetaToPlusZ(FISH_AVGVEL(f), xVect);
258                 rotTheta = computeNormalAndThetaToPlusZ(FISH_VEL(f), xVect);
259
260                 if (FISH_IAVGVEL(f,2) < 0.0) colTheta = 180.0 - colTheta;
261                 if (FISH_VZ(f) < 0.0) rotTheta = 180.0 - rotTheta;
262
263                 getColorVect(colors, (int)(colTheta+240)%360, colorVect);
264                 glColor3f(colorVect[0], colorVect[1], colorVect[2]);
265
266                 glPushMatrix();
267                 {
268                         glTranslatef(FISH_X(f), FISH_Y(f), FISH_Z(f));
269                         glRotatef(180.0+rotTheta, xVect[0], xVect[1], xVect[2]);
270                         glCallList(fishList);
271                 }
272                 glPopMatrix();
273         }
274
275         glFinish();
276 }