1 /* This is "gl.c", a part of the pool (billiards)-program
2
3 "Another Pool GL".
4
5 "gl.c" includes some procedures needed for the OpenGL-graphics-
6 system of the game. Therefore GL, GLU and SDL must be installed
7 on your system. (Documentation: see http://www.opengl.org and
8 http://www.libsdl.org)
9
10 Parts of the following code (texture loading, font output and loading
11 and parts of the initialization ) are based on NeHe's OpenGL Tutorials
12 (see http://nehe.gamedev.net).
13
14 Copyright (C) 1995,2002,2003 by Gerrit Jahn (http://www.planetjahn.de)
15
16 This file ist part of Another Pool / Another Pool GL (apool, apoolGL).
17
18 "Another Pool" is free software; you can redistribute it
19 and/or modify it under the terms of the GNU General Public License
20 as published by the Free Software Foundation; either version 2 of
21 the License, or (at your option) any later version.
22
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with GNU CC; see the file COPYING. If not, write to
30 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
31
32 /* ------------------------------ computer.c ----------------------------- */
33
34 #include <math.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <time.h>
38 #include <SDL.h>
39 #include <GL/gl.h>
40 #include <GL/glu.h>
41 #include <string.h>
42 #include "apool.h"
43 #include <sys/param.h>
44 #include <sys/time.h>
45
46 #ifndef M_PI
47 #define M_PI 3.141592654
48 #endif
49
50 #ifndef ABS
51 #define ABS(a) ((a) < 0 ? -(a) : a)
52 #endif
53
54 #define FALSE 0
55 #define TRUE 1
56
57 #define SIGN(a) ((a) > 0 ? 1 : -1)
58
59 /* L�ngeneinheit: Tisch ist in real life 8 Fu� lang, d.h. 244cm,
60 die im Spiel auf die L�nge 1.0 (von -0.5 - +0.5) verteilt sind */
61
62 /* liefert die "H�he" der Bande am Rand wieder - ergibt abgerundete Kante */
63 #define bfunc_max 60.0
64 #define BFUNC(m) ((m) > 1 ? (RADIUS*(4.0/3.0 - 4.0/3.0*exp(-1.0/5.0 * (bfunc_max-(m))))) : \
65 RADIUS*4.0/3.0 - (1-m)*0.0004)
66
67 #define BFUNC_new_geht_nicht(m) (((m)/1000.0 <= 0.06-4.0/3.0*RADIUS) ? 4.0/3.0*RADIUS : \
68 sqrt((16.0/9.0*RADIUS*RADIUS) - ((m)/1000.0-0.06+4.0/3.0*RADIUS)*((m)/1000.0-0.06+4.0/3.0*RADIUS)))
69
70 double angx=0.0,angy=0.0,angz=0.0;
71 double startx=0.0,starty=0.0,startz=-0.985;
72 double transx=0.0, transy = 0.0, transz = 0.0;
73
74 unsigned long poly = 0;
75
76 GLfloat LightAmbient3[] = { 0.9, 0.9, 0.8, 1.0 };
77 GLfloat LightAmbient[] = { 0.15, 0.15, 0.15, 1.0 };
78 GLfloat LightDiffuse3[] = { 0.5, 0.5, 0.5, 1.0 };
79 GLfloat LightDiffuse1[] = { 0.9, 0.9, 0.75, 1.0 };
80 GLfloat LightDiffuse2[] = { 0.9, 0.9, 0.75, 1.0 };
81 GLfloat LightSpecular[] = { 1.0, 1.0, 1.0, 1.0 };
82
83 GLfloat LightAmbient_multi[] = { 0.01, 0.01, 0.01, 0.1 };
84 GLfloat LightDiffuse_multi[] = { 0.4, 0.4, 0.4, 0.4 };
85 GLfloat LightSpecular_multi[] = { 0.01, 0.01, 0.01, 0.01};
86
87 GLfloat LightZero[] = { 0.0, 0.0, 0.0, 0.0 };
88
89 GLfloat LightPosition[][4] = {{ 0.25, 0.0, 0.25, 1.0 }, /* Tischbeleuchtung 1 */
90 { -0.25, 0.0, 0.25, 1.0 }, /* Tischbeleuchtung 2 */
91 { 0.0, 0.0, 1.5, 0.0 }}; /* Beleuchtung der Spin-Kugel und der Kugel links oben */
92
93 GLfloat MatAmb[] = {0.3, 0.3, 0.3, 0.2};
94 GLfloat MatAmbbright[] = {0.75, 0.75, 0.75, 1.0};
95 GLfloat MatDif[] = {0.9, 0.9, 0.9, 1.0};
96 GLfloat MatDifTransparent[] = {0.9, 0.9, 0.9, 0.7};
97 GLfloat MatDifballs[] = {0.7, 0.7, 0.7, 1.0};
98 GLfloat MatDifballs_multi[] = {0.6, 0.6, 0.6, 0.6};
99 GLfloat MatDifMetall[] = {0.1, 0.1, 0.125, 1.0};
100 GLfloat MatDifTablegreen[] = {0.0, 0.55, 0.00, 1.0};
101 GLfloat MatDifTableblue[] = {0.1, 0.1, 0.7, 1.0};
102 GLfloat MatDifTablered[] = {0.6, 0.1, 0.1, 1.0};
103 GLfloat MatDifTableTextgreen[] = {0.0, 0.55, 0.0, 1.0};
104 GLfloat MatDifTableTextblue[] = {0.1, 0.1, 0.7, 1.0};
105 GLfloat MatDifTableTextred[] = {0.6, 0.1, 0.1, 1.0};
106 GLfloat MatDifBorder[] = {0.0, 0.45, 0.0, 1.0};
107 /* GLfloat MatDifWood[] = {0.5, 0.2, 0.0, 1.0}; */
108 GLfloat MatDifWood[] = {0.6, 0.6, 0.6, 1.0};
109 GLfloat MatGummi[] = {0.03, 0.03, 0.03, 1.0};
110 GLfloat MatDifWooddark[] = {0.01, 0.005, 0.0, 1.0};
111 GLfloat MatAmbWooddark[] = {0.04, 0.02, 0.0, 1.0};
112 GLfloat MatDifDark[] = {0.1, 0.1, 0.1, -1.0};
113 GLfloat MatEm[] = {0.9, 0.0, 0.0, 0.1};
114
115 GLfloat MatSpc[] = { 1.0, 1.0, 1.0, 1.0 };
116 GLfloat MatSpc_multi[] = { 0.3, 0.3, 0.3, 0.3 };
117 GLfloat MatSpcWood[] = { 0.65, 0.65, 0.65, 0.5 };
118 GLfloat MatSpcLow[] = { 0.0, 0.01, 0.0, 0.1 };
119 GLfloat MatNull[] = { 0.0, 0.0, 0.0, 0.0 };
120
121 GLfloat MatRedDif[] = {1.0,0.0,0.0,1.0};
122 GLfloat MatYellowDif[] = {1.0,1.0,0.0,1.0};
123 GLfloat MatBlackDif[] = {0.0,0.0,0.0,1.0};
124 GLfloat MatWhiteDif[] = {1.0,1.0,1.0,1.0};
125
126 GLfloat MatShn = 64.0;
127 GLfloat MatShnsmall = 128.0;
128
129 GLuint base; /* f�r Fonts */
130
131 /* Ikosaeder mit Mathematica erzeugt, ist um einen Faktor 1.1755705045849463
132 zu gro�, wird unten auf 1 normiert */
133 double ico20[20*3*3] =
134 {0.0, 0.0, 1.1755705045849463, 0.3249196962329063, 1.0,
135 0.5257311121191336, 1.0514622242382672, 0.0, 0.5257311121191336,
136 0.0, 0.0, 1.1755705045849463, -0.8506508083520399,
137 0.6180339887498949, 0.5257311121191336, 0.3249196962329063, 1.0,
138 0.5257311121191336, 0.0, 0.0, 1.1755705045849463,
139 -0.8506508083520399, -0.6180339887498949, 0.5257311121191336,
140 -0.8506508083520399, 0.6180339887498949, 0.5257311121191336,
141 0.0, 0.0, 1.1755705045849463, 0.3249196962329063, -1.0,
142 0.5257311121191336, -0.8506508083520399, -0.6180339887498949,
143 0.5257311121191336, 0.0, 0.0, 1.1755705045849463,
144 1.0514622242382672, 0.0, 0.5257311121191336, 0.3249196962329063, -1.0,
145 0.5257311121191336,
146 1.0514622242382672, 0.0, 0.5257311121191336,
147 0.3249196962329063, 1.0, 0.5257311121191336,
148 0.8506508083520399, 0.6180339887498949, -0.5257311121191336,
149 0.3249196962329063, 1.0, 0.5257311121191336,
150 -0.8506508083520399, 0.6180339887498949, 0.5257311121191336,
151 -0.3249196962329063, 1.0, -0.5257311121191336,
152 -0.8506508083520399, 0.6180339887498949, 0.5257311121191336,
153 -0.8506508083520399, -0.6180339887498949, 0.5257311121191336,
154 -1.0514622242382672, 0.0, -0.5257311121191336,
155 -0.8506508083520399, -0.6180339887498949, 0.5257311121191336,
156 0.3249196962329063, -1.0, 0.5257311121191336,
157 -0.3249196962329063, -1.0, -0.5257311121191336,
158 0.3249196962329063, -1.0, 0.5257311121191336,
159 1.0514622242382672, 0.0, 0.5257311121191336,
160 0.8506508083520399, -0.6180339887498949, -0.5257311121191336,
161 0.8506508083520399, 0.6180339887498949, -0.5257311121191336,
162 0.3249196962329063, 1.0, 0.5257311121191336, -0.3249196962329063, 1.0,
163 -0.5257311121191336,
164 -0.3249196962329063, 1.0, -0.5257311121191336,
165 -0.8506508083520399, 0.6180339887498949, 0.5257311121191336,
166 -1.0514622242382672, 0.0, -0.5257311121191336,
167 -1.0514622242382672, 0.0, -0.5257311121191336,
168 -0.8506508083520399, -0.6180339887498949, 0.5257311121191336,
169 -0.3249196962329063, -1.0, -0.5257311121191336,
170 -0.3249196962329063, -1.0, -0.5257311121191336,
171 0.3249196962329063, -1.0, 0.5257311121191336,
172 0.8506508083520399, -0.6180339887498949, -0.5257311121191336,
173 0.8506508083520399, -0.6180339887498949, -0.5257311121191336,
174 1.0514622242382672, 0.0, 0.5257311121191336,
175 0.8506508083520399, 0.6180339887498949, -0.5257311121191336,
176 0.8506508083520399, 0.6180339887498949, -0.5257311121191336,
177 -0.3249196962329063, 1.0, -0.5257311121191336,
178 0.0, 0.0, -1.1755705045849463,
179 -0.3249196962329063, 1.0, -0.5257311121191336,
180 -1.0514622242382672, 0.0, -0.5257311121191336,
181 0.0, 0.0, -1.1755705045849463,
182 -1.0514622242382672, 0.0, -0.5257311121191336,
183 -0.3249196962329063, -1.0, -0.5257311121191336,
184 0.0, 0.0, -1.1755705045849463,
185 -0.3249196962329063, -1.0, -0.5257311121191336,
186 0.8506508083520399, -0.6180339887498949, -0.5257311121191336,
187 0.0, 0.0, -1.1755705045849463,
188 0.8506508083520399, -0.6180339887498949, -0.5257311121191336,
189 0.8506508083520399, 0.6180339887498949, -0.5257311121191336,
190 0.0, 0.0, -1.1755705045849463};
191
192 #define shadow_step 3
193 double shadow[BALLS][(360+shadow_step)/shadow_step][4][3];
194
195 #define DIFF_half(a,b,c)\
196 (a).x = ((c).x - (b).x)/2.0;\
197 (a).y = ((c).y - (b).y)/2.0;\
198 (a).z = ((c).z - (b).z)/2.0
199
200 #define ADD(a,b,c)\
201 (a).x = (b).x + (c).x;\
202 (a).y = (b).y + (c).y;\
203 (a).z = (b).z + (c).z
204
205 #define TRIANGLE(no,x1,x2,x3)\
206 ico[(no)*9+0*3+0] = (x1).x;\
207 ico[(no)*9+0*3+1] = (x1).y;\
208 ico[(no)*9+0*3+2] = (x1).z;\
209 \
210 ico[(no)*9+1*3+0] = (x2).x;\
211 ico[(no)*9+1*3+1] = (x2).y;\
212 ico[(no)*9+1*3+2] = (x2).z;\
213 \
214 ico[(no)*9+2*3+0] = (x3).x;\
215 ico[(no)*9+2*3+1] = (x3).y;\
216 ico[(no)*9+2*3+2] = (x3).z
217
218 #define NORMAL(p)\
219 if( (dummy = BETR3(p) ) )\
220 {\
221 (p).x /= dummy;\
222 (p).y /= dummy;\
223 (p).z /= dummy;\
224 }
225
226 /* Normiert den mit Mathematica erzeugen Icosaeder so, dass die �u�ersten
227 Punkte auf der Einheitskugel liegen. Mathematica hat den Ikosaeder "im
228 Mittel" auf 1 normiert */
normalize_ico20(double scale)229 void normalize_ico20(double scale)
230 {
231 int i,j,k;
232 if( scale == 0 ) return;
233 for(i=0;i<20;i++)
234 for(j=0;j<3;j++)
235 for(k=0;k<3;k++)
236 ico20[i*9+j*3+k] /= scale;
237 }
238
239 /* unterteilt teilt jedes Dreieck des �bergegebenen Polyhedrons "ico"
240 in vier Dreicke und zieht die neu entstandenen Punkte (die
241 Mittelpunkte der Verbindungslininen des urspr�nglichen Dreiecks)
242 auf die Einheitskugel */
splitpoly(double * ico,double * ico_small,int no)243 void splitpoly(double *ico, double *ico_small, int no)
244 {
245 int i;
246 struct vect3 x1,x2,x3,x4,x5,x6,v;
247 double dummy;
248 for(i=0;i<no;i++)
249 {
250 x1.x = ico_small[i*9+0*3+0];
251 x1.y = ico_small[i*9+0*3+1];
252 x1.z = ico_small[i*9+0*3+2];
253
254 x3.x = ico_small[i*9+1*3+0];
255 x3.y = ico_small[i*9+1*3+1];
256 x3.z = ico_small[i*9+1*3+2];
257
258 x5.x = ico_small[i*9+2*3+0];
259 x5.y = ico_small[i*9+2*3+1];
260 x5.z = ico_small[i*9+2*3+2];
261
262 DIFF_half(v,x1,x3);
263 ADD(x2,x1,v);
264 NORMAL(x2);
265
266 DIFF_half(v,x3,x5);
267 ADD(x4,x3,v);
268 NORMAL(x4);
269
270 DIFF_half(v,x5,x1);
271 ADD(x6,x5,v);
272 NORMAL(x6);
273
274 TRIANGLE(i*4, x1, x2, x6);
275 TRIANGLE(i*4+1, x2, x3, x4);
276 TRIANGLE(i*4+2, x6, x4, x5);
277 TRIANGLE(i*4+3, x6, x2, x4);
278 }
279 }
280
281 /* ruft die Displaylisten f�r die entsprechenden Ikosaeder-Kugeln auf */
icoball(int no)282 void icoball(int no)
283 {
284 switch(no)
285 {
286 case 20: glCallList(400); break;
287 case 80: glCallList(401); break;
288 case 320: glCallList(402); break;
289 case 1280: glCallList(403); break;
290 case 5120: glCallList(404); break;
291 case 20480: glCallList(405); break;
292 default: glCallList(403); break;
293 }
294 #ifdef DEBUG
295 poly += no;
296 #endif
297 }
298
299 /* malt Kugel mit angegebenem Kugeldatensatz "ico" mit "no" Polygonen
300 und Radius=radius */
icosphere(double * ico,int no,double radius)301 void icosphere(double *ico, int no, double radius)
302 {
303 int i, sign;
304 glCullFace(GL_FRONT);
305 glBegin(GL_TRIANGLES);
306 for(i=0;i<no;i++)
307 { /* damit auf der R�ckseite die Textur um 180 Grad gedreht, */
308 sign = (ico[i*9+0*3+2] >= 0 ? 1 : -1 ); /* aber nicht gespiegelt ist! */
309
310 glTexCoord2d( (ico[i*9+0*3+0]+1.0)/2, sign * (ico[i*9+0*3+1]+1.0)/2.0);
311 glNormal3f(ico[i*9+0*3+0],ico[i*9+0*3+1],ico[i*9+0*3+2]);
312 glVertex3f(ico[i*9+0*3+0] * radius, ico[i*9+0*3+1] * radius, ico[i*9+0*3+2] * radius);
313
314 glTexCoord2d( (ico[i*9+1*3+0]+1.0)/2, sign * (ico[i*9+1*3+1]+1.0)/2.0);
315 glNormal3f(ico[i*9+1*3+0],ico[i*9+1*3+1],ico[i*9+1*3+2]);
316 glVertex3f(ico[i*9+1*3+0] * radius ,ico[i*9+1*3+1] * radius, ico[i*9+1*3+2] * radius);
317
318 glTexCoord2d( (ico[i*9+2*3+0]+1.0)/2, sign * (ico[i*9+2*3+1]+1.0)/2.0);
319 glNormal3f(ico[i*9+2*3+0],ico[i*9+2*3+1],ico[i*9+2*3+2]);
320 glVertex3f(ico[i*9+2*3+0] * radius, ico[i*9+2*3+1] * radius, ico[i*9+2*3+2] * radius);
321
322 }
323 glEnd();
324 glCullFace(GL_BACK);
325 }
326
327 /* von NeHe �bernommen und an den verwendeten Zeichensatz angepasst
328 NeHe verwendet eine Textur mit zwei Zeichens�tzen. Hier wird
329 nur ein Zeichensatz verwendet, der daf�r den vollen ASCII-Satz
330 enth�lt */
BuildFont(GLvoid)331 GLvoid BuildFont(GLvoid) /* Build Our Font Display List */
332 {
333 double cx; /* Holds Our X Character Coord */
334 double cy; /* Holds Our Y Character Coord */
335 int loop;
336
337 base=glGenLists(256); /* Creating 256 Display Lists */
338 glBindTexture(GL_TEXTURE_2D, texture[32]); /* Select Our Font Texture */
339 for (loop=0; loop<256; loop++) /* Loop Through All 256 Lists */
340 {
341 cx=(double)(loop%16)/16.0; /* X Position Of Current Character */
342 cy=(double)(loop/16)/16.0; /* Y Position Of Current Character */
343
344 glNewList(base+loop,GL_COMPILE); /* Start Building A List */
345 glBegin(GL_QUADS); /* Use A Quad For Each Character */
346 glTexCoord2d(cx+0.15/16.0,1-cy-0.0625); /* Texture Coord (Bottom Left) */
347 glVertex2i(0,0); /* Vertex Coord (Bottom Left) */
348 glTexCoord2d(cx+0.0625-0.15/16.0,1-cy-0.0625); /* Texture Coord (Bottom Right) */
349 glVertex2i(16,0); /* Vertex Coord (Bottom Right) */
350 glTexCoord2d(cx+0.0625-0.15/16.0,1-cy); /* Texture Coord (Top Right) */
351 glVertex2i(16,16); /* Vertex Coord (Top Right) */
352 glTexCoord2d(cx+0.15/16.0,1-cy); /* Texture Coord (Top Left) */
353 glVertex2i(0,16); /* Vertex Coord (Top Left) */
354 glEnd(); /* Done Building Our Quad (Character) */
355 glTranslated(10,0,0); /* Move To The Right Of The Character */
356 glEndList(); /* Done Building The Display List */
357 } /* Loop Until All 256 Are Built */
358 }
359
KillFont(GLvoid)360 GLvoid KillFont(GLvoid) /* Delete The Font From Memory */
361 {
362 glDeleteLists(base,256); /* Delete All 256 Display Lists */
363 }
364
365 /* ebenfalls von Nehe �bernommen und an obige Modifkation f�r einen
366 Zeichensatz angepasst. Weiterhin Skalierung und Farbe eingebaut */
367 /* malt Strings an die Position x,y (in Bildschirmkoordinaten, bezogen auf
368 1024x768! charset=0,1; Farben klar, scale: Skalierung */
glPrint(GLint x,GLint y,char * string,int charset,double red,double green,double blue,double alpha,double scale)369 GLvoid glPrint(GLint x, GLint y, char *string, int charset,
370 double red, double green, double blue, double alpha, double scale)
371 {
372 double xp = x * SCREENRESX/1024.0, yp = y * SCREENRESX/1024.0;
373 if (charset>1) charset=1;
374 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
375 glDisable(GL_LIGHTING);
376 glEnable(GL_BLEND);
377 glDisable(GL_FOG);
378 glColor4d(red,green,blue,alpha);
379 glEnable(GL_TEXTURE_2D);
380 glBindTexture(GL_TEXTURE_2D, texture[32]); /* Select Our Font Texture */
381 glDisable(GL_DEPTH_TEST); /* Disables Depth Testing */
382 glMatrixMode(GL_PROJECTION); /* Select The Projection Matrix */
383 glPushMatrix(); /* Store The Projection Matrix */
384 glLoadIdentity(); /* Reset The Projection Matrix */
385 glOrtho(0,SCREENRESX,0,SCREENRESY,-1,1); /* Set Up An Ortho Screen */
386 glMatrixMode(GL_MODELVIEW); /* Select The Modelview Matrix */
387 glPushMatrix(); /* Store The Modelview Matrix */
388 glLoadIdentity(); /* Reset The Modelview Matrix */
389 glTranslated(xp,yp,-1.00); /* Position The Text (0,0 - Bottom Left) */
390 glListBase(base+(128*charset)); /* Choose The Font Set (0 or 1) */
391 glScaled(1.5*SCREENRESX/1024.0, 1.5*SCREENRESX/1024.0, 1.0);
392 glScaled(scale,scale,1.0);
393 glCallLists(strlen(string),GL_UNSIGNED_BYTE,string); /* Write The Text To The Screen */
394 glMatrixMode(GL_PROJECTION); /* Select The Projection Matrix */
395 glPopMatrix(); /* Restore The Old Projection Matrix */
396 glMatrixMode(GL_MODELVIEW); /* Select The Modelview Matrix */
397 glPopMatrix(); /* Restore The Old Projection Matrix */
398 glEnable(GL_DEPTH_TEST); /* Enables Depth Testing */
399 glDisable(GL_TEXTURE_2D);
400 glDisable(GL_BLEND);
401 glEnable(GL_LIGHTING);
402 glEnable(GL_FOG);
403 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
404 }
405
LoadBMP(char * filename)406 SDL_Surface *LoadBMP(char *filename) /* Von Nehe �bernommen */
407 {
408 Uint8 *rowhi, *rowlo;
409 Uint8 *tmpbuf, tmpch;
410 SDL_Surface *image;
411 int i, j;
412
413 image = SDL_LoadBMP(filename);
414 if ( image == NULL )
415 {
416 fprintf(stderr, "Unable to load %s: %s\n", filename, SDL_GetError());
417 return(NULL);
418 }
419
420 /* GL surfaces are upsidedown and RGB, not BGR :-) */
421 tmpbuf = (Uint8 *)malloc(image->pitch);
422 if ( tmpbuf == NULL )
423 {
424 fprintf(stderr, "Out of memory\n");
425 return(NULL);
426 }
427 rowhi = (Uint8 *)image->pixels;
428 rowlo = rowhi + (image->h * image->pitch) - image->pitch;
429 for ( i=0; i<image->h/2; ++i )
430 {
431 for ( j=0; j<image->w; ++j )
432 {
433 tmpch = rowhi[j*3];
434 rowhi[j*3] = rowhi[j*3+2];
435 rowhi[j*3+2] = tmpch;
436 tmpch = rowlo[j*3];
437 rowlo[j*3] = rowlo[j*3+2];
438 rowlo[j*3+2] = tmpch;
439 }
440 memcpy(tmpbuf, rowhi, image->pitch);
441 memcpy(rowhi, rowlo, image->pitch);
442 memcpy(rowlo, tmpbuf, image->pitch);
443 rowhi += image->pitch;
444 rowlo -= image->pitch;
445 }
446 free(tmpbuf);
447 return(image);
448 }
449
450 #define cube_txt_size 128
451
LoadGLTextures(void)452 int LoadGLTextures( void ) /* ebenfalls basierend auf einem Nehe Tutorial */
453 { /* aber f�r mehrere Texturen angepasst und erweitert f. Mipmapping, Cube-Textures, usw.*/
454 int i;
455 char txt[PATH_MAX];
456 SDL_Surface *TextureImage[ANZ_TEXTURES];
457 memset(TextureImage,0,sizeof(void *)*ANZ_TEXTURES);
458 texture = malloc((sizeof(int) * ANZ_TEXTURES));
459
460 for(i=0;i<BALLS;i++)
461 {
462 sprintf(txt,DATADIR"/textures-hi/%d.bmp",i);
463 if( !(TextureImage[i]=LoadBMP(txt)) )
464 {
465 printf("can't find %d of hd textures\n",i);
466 return FALSE;
467 }
468 }
469
470 for(i=BALLS;i<2*BALLS;i++)
471 {
472 sprintf(txt,DATADIR"/textures-lo/%d.bmp",i-BALLS);
473 if( !(TextureImage[i]=LoadBMP(txt)) )
474 {
475 printf("can't find %d of ld textures\n",i-BALLS);
476 return FALSE;
477 }
478 }
479
480 if( !(TextureImage[i++]=LoadBMP(DATADIR"/textures-hi/Font.bmp")) ) return FALSE;
481 if( !(TextureImage[i++]=LoadBMP(DATADIR"/textures-hi/Holz.bmp")) ) return FALSE;
482 if( !(TextureImage[i++]=LoadBMP(DATADIR"/textures-hi/Marmor.bmp")) ) return FALSE;
483 if( !(TextureImage[i++]=LoadBMP(DATADIR"/textures-hi/Tuch.bmp")) ) return FALSE;
484 if( !(TextureImage[i++]=LoadBMP(DATADIR"/textures-hi/Env.bmp")) ) return FALSE;
485
486 glGenTextures(ANZ_TEXTURES, &texture[0]);
487 for (i=0; i<ANZ_TEXTURES; i++)
488 {
489 if( i < 32 ) /* Balltexturen mipmappen */
490 {
491 glBindTexture(GL_TEXTURE_2D, texture[i]);
492 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
493 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR );
494 if( i == 0 || i == 16 ) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); /* Weisse nicht repeaten! */
495 else glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
496
497 /* glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0); /\* funktioniert, bringts was ?! *\/ */
498
499 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB5, TextureImage[i]->w, TextureImage[i]->h,
500 GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->pixels);
501 }
502 else /* Rest (Holz z.B.) nicht mipmappen, sah nicht gut aus */
503 {
504 glBindTexture(GL_TEXTURE_2D, texture[i]);
505 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
506 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
507 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, TextureImage[i]->w, TextureImage[i]->h, 0,
508 GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->pixels);
509 }
510 }
511
512 for(i=0;i<BALLS;i++)
513 {
514 glGenTextures(1,&cube_texture[i]);
515 glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, cube_texture[i]);
516
517 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
518 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
519
520 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
521 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
522 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
523
524 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
525
526 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,0,GL_RGB5,cube_txt_size,cube_txt_size,0,GL_RGB,GL_UNSIGNED_BYTE, NULL);
527 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,0,GL_RGB5,cube_txt_size,cube_txt_size,0,GL_RGB,GL_UNSIGNED_BYTE, NULL);
528 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,0,GL_RGB5,cube_txt_size,cube_txt_size,0,GL_RGB,GL_UNSIGNED_BYTE, NULL);
529 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,0,GL_RGB5,cube_txt_size,cube_txt_size,0,GL_RGB,GL_UNSIGNED_BYTE, NULL);
530 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,0,GL_RGB5,cube_txt_size,cube_txt_size,0,GL_RGB,GL_UNSIGNED_BYTE, NULL);
531 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,0,GL_RGB5,cube_txt_size,cube_txt_size,0,GL_RGB,GL_UNSIGNED_BYTE, NULL);
532 }
533
534 for (i=0; i<ANZ_TEXTURES; i++)
535 if (TextureImage[i]) SDL_FreeSurface(TextureImage[i]);
536
537 return TRUE;
538 }
539
540 /* Makros/Funktionen zum Malen des Tischtuchs */
541 #ifdef DEBUG
542 #define tuch(x1,y1,x2,y2,tx1,ty1,tx2,ty2)\
543 {\
544 glTexCoord2d(tx1, ty1);\
545 glVertex3d( x1, y1, 0.0 );\
546 glTexCoord2d(tx2, ty1);\
547 glVertex3d( x2, y1, 0.0 );\
548 glTexCoord2d(tx2, ty2);\
549 glVertex3d( x2, y2, 0.0 );\
550 glTexCoord2d(tx1, ty2);\
551 glVertex3d( x1, y2, 0.0 );\
552 poly++;\
553 }
554 #else
555 #define tuch(x1,y1,x2,y2,tx1,ty1,tx2,ty2)\
556 {\
557 glTexCoord2d(tx1, ty1);\
558 glVertex3d( x1, y1, 0.0 );\
559 glTexCoord2d(tx2, ty1);\
560 glVertex3d( x2, y1, 0.0 );\
561 glTexCoord2d(tx2, ty2);\
562 glVertex3d( x2, y2, 0.0 );\
563 glTexCoord2d(tx1, ty2);\
564 glVertex3d( x1, y2, 0.0 );\
565 }
566 #endif
567
568 #ifdef DEBUG
569 #define tuch_strips(x1,y1,x2,y2,tx1,ty1,tx2,ty2) \
570 glTexCoord2d(tx1, ty1);\
571 glVertex3d( x2, y2, 0.0 );\
572 glTexCoord2d(tx2, ty2);\
573 glVertex3d( x1, y1, 0.0 );\
574 poly++
575 #else
576 #define tuch_strips(x1,y1,x2,y2,tx1,ty1,tx2,ty2) \
577 glTexCoord2d(tx1, ty1);\
578 glVertex3d( x2, y2, 0.0 );\
579 glTexCoord2d(tx2, ty2);\
580 glVertex3d( x1, y1, 0.0)
581 #endif
582
583
calc_normal_ez(struct vect3 * res,struct vect3 * v)584 void calc_normal_ez( struct vect3 *res, struct vect3 *v )
585 {
586 struct vect3 ez;
587 double dummy;
588 ez.x = 0; ez.y = 0; ez.z = 1.0;
589 res->x = v->y * ez.z - v->z * ez.y;
590 res->y = v->z * ez.x - v->x * ez.z;
591 res->z = v->x * ez.y - v->y * ez.x;
592 dummy = sqrt(res->x*res->x + res->y*res->y + res->z*res->z );
593 if( dummy > 0 )
594 {
595 res->x /= dummy;
596 res->y /= dummy;
597 res->z /= dummy;
598 }
599 }
600
601 /* Normalenvektor berechnen, Ergebnis steht im ersten �bergabeparameter */
calc_normal(double * n,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3)602 void calc_normal( double *n, double x1, double y1, double z1, double x2, double y2, double z2,
603 double x3, double y3, double z3 )
604 {
605 double v1x=x2-x1, v1y=y2-y1, v1z=z2-z1, v2x=x3-x1, v2y=y3-y1, v2z=z3-z1;
606 double dummy;
607 n[0] = v1y * v2z - v1z * v2y;
608 n[1] = v1z * v2x - v1x * v2z;
609 n[2] = v1x * v2y - v1y * v2x;
610 dummy = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2] );
611 if( dummy > 0 )
612 {
613 n[0] /= dummy;
614 n[1] /= dummy;
615 n[2] /= dummy;
616 }
617 if( n[2] < 0 ) { n[0] = -n[0]; n[1] = -n[1]; n[2] = -n[2]; }
618 }
619
holz_strip(double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3,double txt_x1,double txt_y1,double txt_x2,double txt_y2)620 void holz_strip(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3,
621 double txt_x1, double txt_y1, double txt_x2, double txt_y2 )
622 {
623 double norm[3];
624 calc_normal(norm, x1, y1, z1, x2, y2, z2, x3, y3, z3);
625 glNormal3dv( norm );
626 glTexCoord2d(txt_x2, txt_y2);
627 glVertex3d( x2, y2, z2 );
628 glTexCoord2d(txt_x1, txt_y1);
629 glVertex3d( x1, y1, z1 );
630 }
631
632 /* hintere Innenseite der Taschen */
gummi(double x1,double y1,double x2,double y2)633 void gummi( double x1, double y1, double x2, double y2)
634 {
635 glVertex3d( x1, y1, 4.0/3.0 * RADIUS);
636 glVertex3d( x2, y2, 4.0/3.0 * RADIUS);
637 glVertex3d( x2, y2, -9.0/3.0 * RADIUS );
638 glVertex3d( x1, y1, -9.0/3.0 * RADIUS );
639 }
640
641 /* gummitop malt die Gummiverkleidungen der L�cher "auf" dem Metall */
642 /* 1,2: im Abstand RADIUS, 3,4: im Abstand 1.25 * RADIUS, 5,6: im Abstand 0.90*RADIUS */
gummitop(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4,double x5,double y5,double x6,double y6,int stat)643 void gummitop( double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4,
644 double x5, double y5, double x6, double y6, int stat)
645 {
646 /* hinten */
647
648 glNormal3d(x3-x1,y3-y1,0.0);
649 glColor3d(0.1, 0.1, 0.1);
650 glVertex3d( x5, y5, 4.0/3.0 * RADIUS + 0.002);
651 glVertex3d( x6, y6, 4.0/3.0 * RADIUS + 0.002);
652 glVertex3d( x6, y6, 3.0/3.0 * RADIUS );
653 glVertex3d( x5, y5, 3.0/3.0 * RADIUS );
654
655 glNormal3d(0.0,0.0,1.0);
656
657 /* oben */
658 glColor3d(0.4, 0.4, 0.4);
659 glVertex3d( x1, y1, 4.0/3.0 * RADIUS + 0.002 );
660 glColor3d(0.4, 0.4, 0.4);
661 glVertex3d( x2, y2, 4.0/3.0 * RADIUS + 0.002 );
662 glColor3d(0.1, 0.1, 0.1);
663 glVertex3d( x6, y6, 4.0/3.0 * RADIUS + 0.002 );
664 glColor3d(0.1, 0.1, 0.1);
665 glVertex3d( x5, y5, 4.0/3.0 * RADIUS + 0.002 );
666
667 /* vorne schr�g */
668 glNormal3d(0.0,0.0,1.0);
669 glColor3d(0.4, 0.4, 0.4);
670 glVertex3d( x1, y1, 4.0/3.0 * RADIUS + 0.002 );
671 glColor3d(0.1, 0.1, 0.1);
672 glVertex3d( x4, y4, 3.5/3.0 * RADIUS);
673 glColor3d(0.1, 0.1, 0.1);
674 glVertex3d( x3, y3, 3.5/3.0 * RADIUS);
675 glColor3d(0.4, 0.4, 0.4);
676 glVertex3d( x2, y2, 4.0/3.0 * RADIUS + 0.002 );
677
678 if( stat ) /* Endkappen malen. Im Moment wird ein Polygon ins Nirwana gemalt */
679 {
680 glColor3d(0.4, 0.4, 0.4);
681 glVertex3d(x1, y1, 4.0/3.0 * RADIUS + 0.002);
682 glColor3d(0.1, 0.1, 0.1);
683 glVertex3d(x5, y5, 4.0/3.0 * RADIUS + 0.002);
684 glColor3d(0.1, 0.1, 0.1);
685 glVertex3d(x5, y5, 4.0/3.0 * RADIUS);
686 glColor3d(0.1, 0.1, 0.1);
687 glVertex3d(x3, y3, 3.5/3.0 * RADIUS);
688
689 glColor3d(0.4, 0.4, 0.4);
690 glVertex3d(x2, y2, 4.0/3.0 * RADIUS + 0.002);
691 glColor3d(0.1, 0.1, 0.1);
692 glVertex3d(x4, y4, 3.5/3.0 * RADIUS);
693 glColor3d(0.1, 0.1, 0.1);
694 glVertex3d(x6, y6, 4.0/3.0 * RADIUS);
695 glColor3d(0.1, 0.1, 0.1);
696 glVertex3d(x6, y6, 4.0/3.0 * RADIUS + 0.002);
697 }
698 #ifdef DEBUG
699 poly+=4;
700 #endif
701 }
702
703 /* Tisch au�en */
outside(double x1,double y1,double x2,double y2)704 void outside(double x1, double y1, double x2, double y2 )
705 {
706 struct vect3 n, v;
707 v.x = x2-x1;
708 v.y = y2-y1;
709 v.z = 0;
710 calc_normal_ez(&n, &v);
711 glNormal3f(n.x, n.y, n.z);
712 glVertex3d( x1, y1, BFUNC(bfunc_max) );
713 glVertex3d( x1, y1, -9.0/3.0*RADIUS-0.0011 );
714 glVertex3d( x2, y2, -9.0/3.0*RADIUS-0.0011 );
715 glVertex3d( x2, y2, BFUNC(bfunc_max) );
716 #ifdef DEBUG
717 poly++;
718 #endif
719 }
720
721 /* malt einen "Metallstreifen" der Mittel- und Ecktaschenverkleidung */
metal_strip(double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3)722 void metal_strip( double x1, double y1, double z1, double x2, double y2, double z2,
723 double x3, double y3, double z3)
724 {
725 double norm[3];
726 calc_normal(norm, x1, y1, z1, x2, y2, z2, x3, y3, z3);
727 glNormal3dv( norm );
728 glVertex3d( x1, y1, z1 );
729 glVertex3d( x2, y2, z2 );
730 #ifdef DEBUG
731 poly++;
732 #endif
733 }
734
metal_strip_b(double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3,double x4,double y4,double z4)735 void metal_strip_b( double x1, double y1, double z1, double x2, double y2, double z2,
736 double x3, double y3, double z3, double x4, double y4, double z4 )
737 {
738 double norm[3], dum1,dum2;
739 norm[0] = x3-x1;
740 norm[1] = y3-y1;
741 norm[2] = z3-z1;
742 dum1 = sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
743 if( dum1 ) { norm[0] /= dum1; norm[1] /= dum1; norm[2] /= dum1;}
744 dum1 = norm[2];
745 dum2 = sqrt(norm[0]*norm[0]+norm[1]*norm[1]);
746 if( dum2 == 0 ) {norm[0] = norm[1] = 0; norm[2] = 1;}
747 else
748 {
749 norm[2] = dum2;
750 norm[0] *= ABS(dum1);
751 norm[1] *= ABS(dum1);
752 }
753
754 glNormal3dv( norm );
755 glVertex3d( x1, y1, z1 );
756
757 norm[0] = x4-x2;
758 norm[1] = y4-y2;
759 norm[2] = z4-z2;
760
761 dum1 = sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
762 if( dum1 ) { norm[0] /= dum1; norm[1] /= dum1; norm[2] /= dum1;}
763 dum1 = norm[2];
764 dum2 = sqrt(norm[0]*norm[0]+norm[1]*norm[1]);
765 if( dum2 == 0 ) {norm[0] = norm[1] = 0; norm[2] = 1;}
766 else
767 {
768 norm[2] = dum2;
769 norm[0] *= ABS(dum1);
770 norm[1] *= ABS(dum1);
771 }
772
773 glNormal3dv( norm );
774 glVertex3d( x2, y2, z2 );
775 #ifdef DEBUG
776 poly++;
777 #endif
778 }
779
780 /* Metall-Verblendung des Tisches au�en (Ecktaschen) */
metal_edge(double x1,double y1,double x2,double y2,double mx,double my,double * n1,double * n2,int stat)781 void metal_edge( double x1, double y1, double x2, double y2, double mx, double my, double *n1, double *n2, int stat )
782 {
783 double dummy;
784 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
785 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
786 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifMetall);
787 if( (dummy = sqrt(n1[0]*n1[0] + n1[1]*n1[1] + n1[2]*n1[2])) )
788 {n1[0] /= dummy; n1[1] /= dummy; }
789 if( (dummy = sqrt(n2[0]*n2[0] + n2[1]*n2[1] + n2[2]*n2[2] )) )
790 {n2[0] /= dummy; n2[1] /= dummy; }
791
792 /* Rand des Tisches */
793 glBegin(GL_QUADS);
794 glNormal3dv(n1);
795 glVertex3d( x1, y1, BFUNC(bfunc_max) );
796 glNormal3dv(n1);
797 glVertex3d( x1, y1, -9.0/3.0*RADIUS-0.0011 );
798 glNormal3dv(n2);
799 glVertex3d( x2, y2, -9.0/3.0*RADIUS-0.0011 );
800 glNormal3dv(n2);
801 glVertex3d( x2, y2, BFUNC(bfunc_max) );
802 glEnd();
803
804 glLightfv(GL_LIGHT1, GL_SPECULAR, LightZero);
805 glLightfv(GL_LIGHT2, GL_SPECULAR, LightZero);
806
807 /* unter dem Tisch */
808 if( stat )
809 {
810 glDisable(GL_CULL_FACE);
811 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifDark);
812 glBegin(GL_TRIANGLES);
813 glNormal3d(0,0,-1.0);
814 glVertex3d( mx, my, -9.0/3.0*RADIUS-0.001 );
815 glVertex3d( x1, y1, -9.0/3.0*RADIUS-0.001 );
816 glVertex3d( x2, y2, -9.0/3.0*RADIUS-0.001 );
817 glEnd();
818 glEnable(GL_CULL_FACE);
819 }
820 #ifdef DEBUG
821 poly+=2;
822 #endif
823 }
824
825 /* Metall-Verblendung des Tisches au�en (Mitteltaschen) */
metal_mid(double x1,double y1,double x2,double y2)826 void metal_mid( double x1, double y1, double x2, double y2 )
827 {
828 glVertex3d( x1, y1, BFUNC(bfunc_max) );
829 glVertex3d( x1, y1, -9.0/3.0*RADIUS-0.0011 );
830 glVertex3d( x2, y2, -9.0/3.0*RADIUS-0.0011 );
831 glVertex3d( x2, y2, BFUNC(bfunc_max) );
832 #ifdef DEBUG
833 poly++;
834 #endif
835 }
836
837 /* ;-) Unterseite des kompletten Tisches */
underside(double x1,double y1,double x2,double y2)838 void underside( double x1, double y1, double x2, double y2 )
839 {
840 /* glTexCoord2d( 0.0,1.0 ); */
841 glVertex3d( x1, y1, -3.0 * RADIUS -0.001);
842 /* glTexCoord2d( 1.0,1.0 ); */
843 glVertex3d( x1, y2, -3.0 * RADIUS -0.001);
844 /* glTexCoord2d( 1.0,0.0 ); */
845 glVertex3d( x2, y2, -3.0 * RADIUS -0.001);
846 /* glTexCoord2d( 0.0,0.0 ); */
847 glVertex3d( x2, y1, -3.0 * RADIUS -0.001);
848 #ifdef DEBUG
849 poly++;
850 #endif
851 }
852
853 #define TABLE_COLOR(add) \
854 switch( table_color ) \
855 {\
856 case TABLE_BLUE: glColor4f( 0.2+(add)/3.0, 0.2+(add)/3.0, 0.4+(add), 1.0); break;\
857 case TABLE_GREEN: glColor4f( 0.0, 0.4+(add), 0.0, 1.0); break;\
858 case TABLE_RED: glColor4f( 0.4+(add), 0.1, 0.1, 1.0); break;\
859 }
860
861 /* Displaylisten f�r den Tisch */
gl_init_lists(void)862 void gl_init_lists(void)
863 {
864 double x1, y1, x2, y2, xo1=0, xo2=0, yo1=0, yo2=0;
865 double rad = 28.0 / 1000.0; /* exakt w�re eigentlich rad = 27.841;*/ /* gemalter Radius der Taschen-"R�ckseite" */
866 double rad_outer = 64.00/1000.0; /* stimmt exakt! */
867 double ls, lsstep, ms, msstep, ns, nsstep;
868 double n1[3], n2[3];
869 int i,j,l,m,n,step=1,stepouter=1, stat, dum_int;
870 double r_Kante = 0.0045, dummy, txtstep=500.0;
871 struct vect3 norm;
872 poly = 0;
873
874 glNewList(400,GL_COMPILE);
875 icosphere(ico20,20,RADIUS);
876 glEndList();
877
878 glNewList(401,GL_COMPILE);
879 icosphere(ico80,80,RADIUS);
880 glEndList();
881
882 glNewList(402,GL_COMPILE);
883 icosphere(ico320,320,RADIUS);
884 glEndList();
885
886 glNewList(403,GL_COMPILE);
887 icosphere(ico1280,1280,RADIUS);
888 glEndList();
889
890 glNewList(404,GL_COMPILE);
891 icosphere(ico5120,5120,RADIUS);
892 glEndList();
893
894 glNewList(405,GL_COMPILE);
895 icosphere(ico20480,20480,RADIUS);
896 glEndList();
897
898 glNewList(257, GL_COMPILE );
899
900 if( shadows != STENCIL_SHADOWS2 )
901 {
902 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
903 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
904 }
905 else
906 {
907 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular_multi);
908 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular_multi);
909 }
910
911 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpcLow);
912 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);
913
914 if( display_floor_textures )
915 {
916 glColor4d(1.0, 1.0, 1.0, 1.0);
917 switch(table_color)
918 {
919 case TABLE_GREEN: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTableTextgreen); break;
920 case TABLE_RED: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTableTextred); break;
921 case TABLE_BLUE: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTableTextblue); break;
922 }
923 }
924 else
925 {
926 glColor4d(1.0, 1.0, 1.0, 1.0);
927 switch(table_color)
928 {
929 case TABLE_GREEN: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTablegreen); break;
930 case TABLE_RED: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTablered); break;
931 case TABLE_BLUE: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTableblue); break;
932 }
933 }
934
935 glNormal3d( 0.0, 0.0, 1.0);
936
937 if( display_floor_textures ) /* Tischtextur */
938 {
939 glEnable(GL_TEXTURE_2D);
940 glBindTexture(GL_TEXTURE_2D, texture[35]);
941 }
942
943 /* Tischtuch malen */
944 switch(geo_detail)
945 {
946 case DETAIL_VERYHIGH: step = 5; stepouter=10; txtstep=125.0; break;
947 case DETAIL_HIGH: step = 25; stepouter=20; txtstep=125.0; break;
948 case DETAIL_MED: step = 50; stepouter=40; txtstep=250.0; break;
949 case DETAIL_LOW: step = 125; stepouter=80; txtstep=250.0; break;
950 case DETAIL_VERYLOW: step = 250; stepouter=240; txtstep=500.0; break;
951 }
952 for(j=-250;j<250;j+=step)
953 {
954 glBegin(GL_QUAD_STRIP);
955 tuch_strips( (double)-485.0/1000.0, (double)j/1000.0, (double)-485.0/1000.0, (double)(j+step)/1000.0,
956 (-485.0)/txtstep, (j+step)/txtstep, (-485.0)/txtstep, ((j))/txtstep);
957 for( i=-480;i<=480;i+=stepouter)
958 { tuch_strips( (double)i/1000.0, (double)j/1000.0, (double)i/1000.0, (double)(j+step)/1000.0,
959 (i)/txtstep, (j+step)/txtstep, (i)/txtstep, ((j))/txtstep); }
960 tuch_strips( (double)485.0/1000.0, (double)j/1000.0, (double)485.0/1000.0, (double)(j+step)/1000.0,
961 (485.0)/txtstep, (j+step)/txtstep, (485.0)/txtstep, ((j))/txtstep);
962 glEnd();
963 }
964
965 switch(geo_detail)
966 {
967 case DETAIL_VERYHIGH: step = 5; stepouter=10; break;
968 case DETAIL_HIGH: step = 20; stepouter=15; break;
969 case DETAIL_MED: step = 20; stepouter=30; break;
970 case DETAIL_LOW: step = 20; stepouter=30; break;
971 case DETAIL_VERYLOW: step = 20; stepouter=30; break;
972 }
973
974 /* fehlendes Tuch an den langen Banden zwischen Eck- und Mitteltaschen */
975 for(j=250;j<270;j+=step)
976 {
977 glBegin(GL_QUAD_STRIP);
978 for( i=30;i<=480;i+=stepouter)
979 { tuch_strips( (double)i/1000.0, (double)j/1000.0, (double)i/1000.0, (double)(j+step)/1000.0,
980 (i)/txtstep, (j+step)/txtstep, (i)/txtstep, (j)/txtstep); }
981 tuch_strips( (double)485.0/1000.0, (double)j/1000.0, (double)485.0/1000.0, (double)(j+step)/1000.0,
982 (485.0)/txtstep, (j+step)/txtstep, (485.0)/txtstep, (j)/txtstep);
983
984 glEnd();
985 }
986 for(j=250;j<270;j+=step)
987 {
988 glBegin(GL_QUAD_STRIP);
989 for( i=30;i<=480;i+=stepouter)
990 { tuch_strips( -(double)i/1000.0, -(double)j/1000.0, -(double)i/1000.0, -(double)(j+step)/1000.0,
991 (-i)/txtstep, -(j+step)/txtstep, (-i)/txtstep, -j/txtstep); }
992 tuch_strips( -(double)485.0/1000.0, -(double)j/1000.0, -(double)485.0/1000.0, -(double)(j+step)/1000.0,
993 (-485.0)/txtstep, -(j+step)/txtstep, (-485.0)/txtstep, -j/txtstep);
994 glEnd();
995 }
996 for(j=250;j<270;j+=step)
997 {
998 glBegin(GL_QUAD_STRIP);
999 for( i=30;i<=480;i+=stepouter)
1000 { tuch_strips( -(double)i/1000.0, (double)(j+step)/1000.0, -(double)i/1000.0, (double)j/1000.0,
1001 (-i)/txtstep, (j)/txtstep, (-i)/txtstep, (j+step)/txtstep); }
1002 tuch_strips( -(double)485.0/1000.0, (double)(j+step)/1000.0, -(double)485.0/1000.0, (double)j/1000.0,
1003 (-485.0)/txtstep, (j)/txtstep, (-485.0)/txtstep, (j+step)/txtstep);
1004 glEnd();
1005 }
1006 for(j=250;j<270;j+=step)
1007 {
1008 glBegin(GL_QUAD_STRIP);
1009 for( i=30;i<=480;i+=stepouter)
1010 { tuch_strips( (double)i/1000.0, -(double)(j+step)/1000.0, (double)i/1000.0, -(double)j/1000.0,
1011 (i)/txtstep, -(j)/txtstep, (i)/txtstep, -(j+step)/txtstep); }
1012 tuch_strips( (double)485.0/1000.0, -(double)(j+step)/1000.0, (double)485.0/1000.0, -(double)j/1000.0,
1013 (485.0)/txtstep, -(j)/txtstep, (485.0)/txtstep, -(j+step)/txtstep);
1014 glEnd();
1015 }
1016
1017 switch(geo_detail)
1018 {
1019 case DETAIL_VERYHIGH: stepouter=10; break;
1020 case DETAIL_HIGH: stepouter=20; break;
1021 case DETAIL_MED: stepouter=20; break;
1022 case DETAIL_LOW: stepouter=20; break;
1023 case DETAIL_VERYLOW: stepouter=230; break;
1024 }
1025
1026 /* fehlendes Tuch an den kurzen Banden */
1027 for(i=-520;i<-480;i+=step)
1028 {
1029 glBegin(GL_QUAD_STRIP);
1030 tuch_strips( (double)i/1000.0, (double)235.0/1000.0, (double)(i+step)/1000.0, (double)235.0/1000.0,
1031 (i+step)/txtstep, (235.0)/txtstep, (i)/txtstep, (235.0)/txtstep);
1032 for(j=-230;j<=230;j+=stepouter)
1033 {
1034 tuch_strips( (double)i/1000.0, -(double)j/1000.0, (double)(i+step)/1000.0, -(double)j/1000.0,
1035 (i+step)/txtstep, (-j)/txtstep, (i)/txtstep, (-j)/txtstep);
1036 }
1037 tuch_strips( (double)i/1000.0, -(double)235.0/1000.0, (double)(i+step)/1000.0, -(double)235.0/1000.0,
1038 (i+step)/txtstep, (-235.0)/txtstep, (i)/txtstep, (-235.0)/txtstep);
1039 glEnd();
1040 }
1041 for(i=480;i<520;i+=step)
1042 {
1043 glBegin(GL_QUAD_STRIP);
1044 tuch_strips( (double)(i+step)/1000.0, (double)-235.0/1000.0, (double)i/1000.0, (double)-235.0/1000.0,
1045 (i)/txtstep, (-235.0)/txtstep, (i+step)/txtstep, (-235.0)/txtstep);
1046 for(j=-230;j<=230;j+=stepouter)
1047 {
1048 tuch_strips( (double)(i+step)/1000.0, (double)j/1000.0, (double)i/1000.0, (double)j/1000.0,
1049 (i)/txtstep, (j)/txtstep, (i+step)/txtstep, (j)/txtstep);
1050 }
1051 tuch_strips( (double)(i+step)/1000.0, (double)235.0/1000.0, (double)i/1000.0, (double)235.0/1000.0,
1052 (i)/txtstep, (235.0)/txtstep, (i+step)/txtstep, (235.0)/txtstep);
1053 glEnd();
1054 }
1055
1056 /* Ausschnitte der Ecktaschen und Abrundung der Kante */
1057
1058 switch(geo_detail)
1059 {
1060 case DETAIL_VERYHIGH: step = 1; break;
1061 case DETAIL_HIGH: step = 3; break;
1062 case DETAIL_MED: step = 9; break;
1063 case DETAIL_LOW: step = 18; break;
1064 case DETAIL_VERYLOW: step = 45; break;
1065 }
1066
1067 for(i=-1;i<=1;i+=2)
1068 {
1069 glPushMatrix();
1070 glTranslatef((posl[1].p.x-0.5)*i,0.0,0.0);
1071 for(j=-1;j<=1;j+=2)
1072 {
1073 glPushMatrix();
1074 glTranslatef(0.0,j*(posl[1].p.y-0.25) ,0.0);
1075 if( i == -1 && j == -1 ) glRotatef(180,0.0,0.0,1.0);
1076 else if( i == 1 && j == -1 ) glRotatef(-90,0.0,0.0,1.0);
1077 else if( i == -1 && j == 1 ) glRotatef(+90,0.0,0.0,1.0);
1078
1079 glNormal3d( 0.0, 0.0, 1.0);
1080
1081 glBegin(GL_TRIANGLE_FAN);
1082 glTexCoord2d(((posl[1].p.x-0.5)+0.04125)*1000.0/txtstep,((posl[1].p.y-0.25)+0.04125)*1000.0/txtstep);
1083 glVertex3d(0.04125,0.04125,0);
1084 for(l=90;l>=0;l-=step ) /* malt die Rundung der Taschen "in" der Tischplatte, 0-90 Grad */
1085 { /* und f�llt den Bereich bis dorthin aus */
1086 x1 = posl[1].r/DIFFX * cos((double)l*M_PI/180.0);
1087 y1 = posl[1].r/DIFFX * sin((double)l*M_PI/180.0);
1088 glTexCoord2d(((posl[1].p.x-0.5)+x1)*1000/txtstep,((posl[1].p.y-0.25)+y1)*1000/txtstep);
1089 glVertex3d(x1,y1,0);
1090 #ifdef DEBUG
1091 poly++;
1092 #endif
1093 }
1094 glEnd();
1095 for(n=0;n<90;n+=step) /* Hier wird die Abrundung der Kante gemalt. (Radius 1/4-1/2 Zoll) */
1096 {
1097 yo1 = -r_Kante * (1.0-cos((double)n*M_PI/180.0));
1098 yo2 = -r_Kante * (1.0-cos((double)(n+step)*M_PI/180.0));
1099 glBegin(GL_QUAD_STRIP);
1100 for(l=0;l<=90;l+=step )
1101 {
1102 x1 = (posl[1].r/DIFFX-r_Kante*sin((n+step)*M_PI/180.0)) * cos((double)l*M_PI/180.0);
1103 y1 = (posl[1].r/DIFFX-r_Kante*sin((n+step)*M_PI/180.0)) * sin((double)l*M_PI/180.0);
1104 dummy = sqrt(x1*x1+y1*y1);
1105 norm.x = -x1/dummy * (1.0-cos((n+step)*M_PI/180.0));
1106 norm.y = -y1/dummy * (1.0-cos((n+step)*M_PI/180.0));
1107 norm.z = (1.0-sin((n+step)*M_PI/180.0));
1108 glNormal3f(norm.x, norm.y, norm.z);
1109 glVertex3d( x1, y1, yo2);
1110 x1 = (posl[1].r/DIFFX-r_Kante*sin(n*M_PI/180.0)) * cos((double)l*M_PI/180.0);
1111 y1 = (posl[1].r/DIFFX-r_Kante*sin(n*M_PI/180.0)) * sin((double)l*M_PI/180.0);
1112 dummy = sqrt(x1*x1+y1*y1);
1113 norm.x = -x1/dummy * (1.0-cos(n*M_PI/180.0));
1114 norm.y = -y1/dummy * (1.0-cos(n*M_PI/180.0));
1115 norm.z = (1.0-sin(n*M_PI/180.0));
1116 glNormal3f(norm.x, norm.y, norm.z);
1117 glVertex3d(x1, y1, yo1); ;
1118 #ifdef DEBUG
1119 poly++;
1120 #endif
1121 }
1122 glEnd();
1123 }
1124 glPopMatrix();
1125 }
1126 glPopMatrix();
1127 }
1128
1129 /* jetzt das gleiche f�r die Mitteltaschen. Erst die Ausschnitte */
1130 /* und dann die Abrundung der Kante, Radius wie oben 1/4-1/2 Zoll so etwa */
1131 for(i=-1;i<=1;i+=2)
1132 {
1133 glPushMatrix();
1134 glTranslatef((posl[5].p.x-0.5),i*(posl[5].p.y-0.25),0.0);
1135 glRotatef((i-1)/2*180.0,0.0,0.0,1.0);
1136
1137 glNormal3d( 0.0, 0.0, 1.0);
1138 glBegin(GL_QUAD_STRIP);
1139 for(l=-180;l<=0;l+=step)
1140 {
1141 x1 = posl[5].r/DIFFX * cos((double)l*M_PI/180.0);
1142 y1 = posl[5].r/DIFFX * sin((double)l*M_PI/180.0);
1143 glTexCoord2d(((posl[5].p.x-0.5)+x1)*1000/txtstep,((posl[5].p.y-0.25)+y1)*1000/txtstep);
1144 glVertex3d(x1,y1,0.0);
1145 glTexCoord2d(((posl[5].p.x-0.5)+x1)*1000/txtstep,((posl[5].p.y-0.25)-0.03575)*1000/txtstep);
1146 glVertex3d(x1,-0.03575,0.0);
1147 #ifdef DEBUG
1148 poly++;
1149 #endif
1150 }
1151 glEnd();
1152 for(n=0;n<90;n+=step)
1153 {
1154 yo1 = -r_Kante * (1.0-cos((double)n*M_PI/180.0));
1155 yo2 = -r_Kante * (1.0-cos((double)(n+step)*M_PI/180.0));
1156 glBegin(GL_QUAD_STRIP);
1157 for(l=0;l>=-180;l-=step )
1158 {
1159 x1 = (posl[5].r/DIFFX-r_Kante*sin(n*M_PI/180.0)) * cos((double)l*M_PI/180.0);
1160 y1 = (posl[5].r/DIFFX-r_Kante*sin(n*M_PI/180.0)) * sin((double)l*M_PI/180.0);
1161 dummy = sqrt(x1*x1+y1*y1);
1162 norm.x = -x1/dummy * (1.0-cos(n*M_PI/180.0));
1163 norm.y = -y1/dummy * (1.0-cos(n*M_PI/180.0));
1164 norm.z = (1.0-sin(n*M_PI/180.0));
1165 glNormal3f(norm.x, norm.y, norm.z);
1166 glVertex3d(x1, y1, yo1); ;
1167 x1 = (posl[5].r/DIFFX-r_Kante*sin((n+step)*M_PI/180.0)) * cos((double)l*M_PI/180.0);
1168 y1 = (posl[5].r/DIFFX-r_Kante*sin((n+step)*M_PI/180.0)) * sin((double)l*M_PI/180.0);
1169 dummy = sqrt(x1*x1+y1*y1);
1170 norm.x = -x1/dummy * (1.0-cos((n+step)*M_PI/180.0));
1171 norm.y = -y1/dummy * (1.0-cos((n+step)*M_PI/180.0));
1172 norm.z = (1.0-sin((n+step)*M_PI/180.0));
1173 glNormal3f(norm.x, norm.y, norm.z);
1174 glVertex3d(x1, y1, yo2);
1175 #ifdef DEBUG
1176 poly++;
1177 #endif
1178 }
1179 glEnd();
1180 }
1181 glPopMatrix();
1182 }
1183
1184 if( display_textures || display_floor_textures ) glDisable(GL_TEXTURE_2D); /* Ende der "floor-texture" */
1185
1186 /* Schatten der Bande muss vor den ganzen "Aufbauten" gemalt werden
1187 wegen abgeschaltetem z-Buffer */
1188 glDisable(GL_LIGHTING);
1189 glEnable(GL_BLEND);
1190 glDisable(GL_DEPTH_TEST);
1191
1192 for(j=-1;j<=1;j+=2)
1193 for(i=-1;i<=1;i+=2)
1194 {
1195 glBegin(GL_QUADS);
1196 if( i*j == -1 ) glFrontFace(GL_CW);
1197 else glFrontFace(GL_CCW);
1198 glColor4f( 0.0, 0.0, 0.0, 0.5);
1199 glVertex3d( 0.490*j, 0.270*i, 0.0 );
1200 glVertex3d( 0.027*j, 0.270*i, 0.0 );
1201 glColor4f( 0.0, 0.0, 0.0, 0.0);
1202 glVertex3d( 0.032*j, 0.250*i, 0.0 );
1203 glVertex3d( 0.460*j, 0.250*i, 0.0 );
1204 glEnd();
1205 #ifdef DEBUG
1206 poly++;
1207 #endif
1208 }
1209 for(i=-1;i<=1;i+=2)
1210 {
1211 if( i==1 ) glFrontFace(GL_CCW);
1212 else glFrontFace(GL_CW);
1213 glBegin(GL_QUADS);
1214 glColor4f( 0.0, 0.0, 0.0, 0.5);
1215 glVertex3d( 0.520*i, -0.240, 0.0 );
1216 glVertex3d( 0.520*i, 0.240, 0.0 );
1217 glColor4f( 0.0, 0.0, 0.0, 0.0);
1218 glVertex3d( 0.500*i, 0.210, 0.0 );
1219 glVertex3d( 0.500*i, -0.210, 0.0 );
1220 glEnd();
1221 #ifdef DEBUG
1222 poly++;
1223 #endif
1224 }
1225 glFrontFace(GL_CCW);
1226
1227 /* Fussfeldlinie ebenfalls vor den Aufbauten malen, z-Buffer
1228 weiterhin ausgeschaltet */
1229
1230 glBegin(GL_QUAD_STRIP);
1231 glColor4f( 0.9, 0.9, 0.9, 0.0);
1232 glVertex3d( -0.2485, -0.280, 0.001);
1233 glVertex3d( -0.2485, 0.280, 0.001);
1234 glColor4f( 0.9, 0.9, 0.9, 0.8);
1235 glVertex3d( -0.250, -0.280, 0.001);
1236 glVertex3d( -0.250, 0.280, 0.001);
1237 glColor4f( 0.9, 0.9, 0.9, 0.001);
1238 glVertex3d( -0.2515, -0.280, 0.001);
1239 glVertex3d( -0.2515, 0.280, 0.001);
1240 glEnd();
1241 #ifdef DEBUG
1242 poly++;
1243 #endif
1244
1245 glEnable(GL_DEPTH_TEST);
1246 glEnable(GL_LIGHTING);
1247
1248 glEndList();
1249
1250 /* Tischholz und Banden */
1251
1252 glNewList(258, GL_COMPILE );
1253
1254 if( display_textures )
1255 {
1256 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
1257 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
1258
1259 glMaterialf(GL_FRONT, GL_SHININESS, MatShn);
1260 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);
1261 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifWood);
1262 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpcWood);
1263 glColor4d(0.5, 0.3, 0.1,1.0);
1264
1265 glEnable(GL_TEXTURE_2D);
1266 switch(table_color)
1267 {
1268 case TABLE_GREEN: glBindTexture(GL_TEXTURE_2D, texture[33]); break;
1269 case TABLE_BLUE: glBindTexture(GL_TEXTURE_2D, texture[34]); break;
1270 case TABLE_RED:
1271 glDisable(GL_TEXTURE_2D);
1272 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatNull);
1273 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
1274 break;
1275 }
1276 }
1277 else
1278 {
1279 glLightfv(GL_LIGHT2, GL_SPECULAR, MatNull);
1280 glLightfv(GL_LIGHT1, GL_SPECULAR, MatNull);
1281 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifWood);
1282 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpcWood);
1283
1284 glColor4d(0.5, 0.3, 0.1,1.0);
1285 }
1286
1287 /* Holz: lange Banden */
1288 /* Rasterung der Kante nach au�en hin, seitlich gesehen*/
1289 switch(geo_detail)
1290 {
1291 case DETAIL_VERYHIGH: step = 1; stepouter = 5; break;
1292 case DETAIL_HIGH: step = 2; stepouter = 10; break;
1293 case DETAIL_MED: step = 5; stepouter = 25; break;
1294 case DETAIL_LOW: step = 5; stepouter = 50; break;
1295 case DETAIL_VERYLOW: step = 10; stepouter = 50; break;
1296 }
1297
1298 for(i=-489;i<=39;i+=528)
1299 {
1300 for(j=0;j<=180;j+=180)
1301 {
1302 glPushMatrix();
1303 glRotatef(j,0.0,0.0,1.0);
1304 glTranslatef(i/1000.0,0.0,0.0);
1305 for( l=0;l<450;l+=stepouter)
1306 {
1307 ls = l/1000.0;
1308 lsstep=ls + step/1000.0;
1309 glBegin(GL_QUAD_STRIP);
1310 for(m=bfunc_max;m>=0;m-=step)
1311 {
1312 ms=m/1000.0;
1313 msstep=ms + step/1000.0;
1314 holz_strip( ls, 0.270+ms, BFUNC(m),
1315 (ls+stepouter/1000.0), 0.270+ms, BFUNC(m),
1316 ls, 0.270+msstep, BFUNC(m+step),
1317 (l)/450.0, (50.0-m)/50.0, (l+stepouter)/450.0, (50.0-m)/50.0);
1318 }
1319 glEnd();
1320 }
1321 glPopMatrix();
1322 }
1323 }
1324
1325 /* Holz: kurze Banden, erst den "mittleren" Teil */
1326 for(i=0;i<=180;i+=180)
1327 {
1328 glPushMatrix();
1329 glRotatef(i,0.0,0.0,1.0);
1330 for(l=-200;l<200;l+=stepouter)
1331 {
1332 ls = l/1000.0;
1333 glBegin(GL_QUAD_STRIP);
1334 for(m=bfunc_max;m>=0;m-=step)
1335 {
1336 ms=m/1000.0;
1337 msstep=ms + step/1000.0;
1338 holz_strip( (0.520+ms), ls+stepouter/1000.0, BFUNC(m),
1339 (0.520+ms), ls, BFUNC(m),
1340 (0.520+msstep), ls, BFUNC(m+step),
1341 (240.0+l+stepouter)/480.0, (bfunc_max-m)/bfunc_max, (240.0+l)/480.0, (bfunc_max-m)/bfunc_max);
1342 }
1343 glEnd();
1344 }
1345
1346 /* seitliche fehlende St�cke zur kurzen Bande */
1347 glBegin(GL_QUAD_STRIP);
1348 for(m=bfunc_max;m>=0;m-=step)
1349 {
1350 ms=m/1000.0;
1351 msstep=ms + step/1000.0;
1352 holz_strip( (0.520+ms), 0.239, BFUNC(m),
1353 (0.520+ms), 0.200, BFUNC(m),
1354 (0.520+msstep), 0.200, BFUNC(m+step),
1355 (240.0+240)/480.0, (bfunc_max-m)/bfunc_max, (240.0+200)/480.0, (bfunc_max-m)/bfunc_max);
1356 }
1357 glEnd();
1358 glBegin(GL_QUAD_STRIP);
1359 for(m=bfunc_max;m>=0;m-=step)
1360 {
1361 ms=m/1000.0;
1362 msstep=ms + step/1000.0;
1363 holz_strip( (0.520+ms), -0.200, BFUNC(m),
1364 (0.520+ms), -0.239, BFUNC(m),
1365 (0.520+msstep), -0.200, BFUNC(m+step),
1366 -(240.0+200)/480.0, (bfunc_max-m)/bfunc_max, -(240.0+240)/480.0, (bfunc_max-m)/bfunc_max);
1367 }
1368 glEnd();
1369 glPopMatrix();
1370 }
1371 glEnd(); /* End of Quads for the "rail-wood" */
1372
1373 if( display_textures ) glDisable(GL_TEXTURE_2D);
1374
1375 for(l=-1;l<=1;l+=2)
1376 {
1377 glPushMatrix();
1378 glTranslatef(0.516*l,0.0,0.0);
1379 for( m=-1; m<=1; m+=2)
1380 {
1381 glPushMatrix();
1382 glTranslatef(0.0,m*0.266,0.0);
1383 if( l == -1 && m == -1 ) glRotatef(180,0.0,0.0,1.0);
1384 else if( l == 1 && m == -1 ) glRotatef(-90,0.0,0.0,1.0);
1385 else if( l == -1 && m == 1 ) glRotatef(+90,0.0,0.0,1.0);
1386
1387 /* stepouter: Rasterung des Kreises der Gummiverkleidung der Ecktaschen von oben gesehen ;-), GoodQ:10 */
1388 switch(geo_detail)
1389 {
1390 case DETAIL_VERYHIGH: stepouter = 2; break;
1391 case DETAIL_HIGH: stepouter = 5; break;
1392 case DETAIL_MED: stepouter = 10; break;
1393 case DETAIL_LOW: stepouter = 25; break;
1394 case DETAIL_VERYLOW: stepouter = 50; break;
1395 }
1396
1397 for(i=280;i<530;i+=stepouter)
1398 {
1399 x1 = rad * cos( (double)i* M_PI / 180.0 );
1400 y1 = rad * sin( (double)i* M_PI / 180.0 );
1401 x2 = rad * cos( (double)(i+stepouter) * M_PI / 180.0 );
1402 y2 = rad * sin( (double)(i+stepouter) * M_PI / 180.0 );
1403
1404 /* zuerst die Taschenhinterseiten*/
1405 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatGummi);
1406 glMaterialfv(GL_FRONT, GL_SPECULAR, MatNull);
1407 glMaterialf(GL_FRONT, GL_SHININESS, 0.0);
1408
1409 glNormal3d(-x1/sqrt(x1*x1+y1*y1),-y1/sqrt(x1*x1+y1*y1),0.0);
1410 glDisable(GL_CULL_FACE);
1411 glBegin(GL_QUADS);
1412 gummi( x1, y1, x2, y2 );
1413 glEnd();
1414 glEnable(GL_CULL_FACE);
1415 glDisable(GL_LIGHTING);
1416 glBegin(GL_QUADS);
1417 if( i==280 || i >= 530-stepouter ) stat=1; /* f. Gummi-Endkappen */
1418 else stat=0;
1419 /* dann die Gummiverkleidung "auf" den Taschen */
1420 if( env_map) /* sph�risches Env-Mapping wieder ausschalten */
1421 {
1422 glDisable(GL_TEXTURE_GEN_R);
1423 glDisable(GL_TEXTURE_GEN_S);
1424 glDisable(GL_TEXTURE_GEN_T);
1425 glDisable(GL_TEXTURE_2D);
1426 }
1427
1428 gummitop( (rad*0.85 * cos( (double)(i+stepouter)* M_PI / 180.0 )),
1429 (rad*0.85 * sin( (double)(i+stepouter)* M_PI / 180.0 )),
1430 (rad*0.85 * cos( (double)i* M_PI / 180.0 )),
1431 (rad*0.85 * sin( (double)i* M_PI / 180.0 )),
1432 x1, y1, x2, y2,
1433 (rad*1.15 * cos( (double)(i+stepouter)* M_PI / 180.0 )),
1434 (rad*1.15 * sin( (double)(i+stepouter)* M_PI / 180.0 )),
1435 (rad*1.15 * cos( (double)i* M_PI / 180.0 )),
1436 (rad*1.15 * sin( (double)i* M_PI / 180.0 )), stat);
1437 glEnd();
1438 glEnable(GL_LIGHTING);
1439 }
1440
1441 /* "Metall" Taschenverblendungen */
1442
1443 /* stepouter: Rasterung der Ecktaschenradien au�en, von oben gesehen 1,2,4 sind vern�ndtige Werte, 3 nicht!, GoodQ:2*/
1444 /* step_: Rasterung der Neigung der Metallverblendung der Ecktaschen nach au�en hin, seitlich gesehen ;-) GoodQ:5*/
1445
1446 switch(geo_detail)
1447 {
1448 case DETAIL_VERYHIGH: step = 1; stepouter = 1; break;
1449 case DETAIL_HIGH: step = 2; stepouter = 2; break;
1450 case DETAIL_MED: step = 3; stepouter = 5; break;
1451 case DETAIL_LOW: step = 5; stepouter = 5; break;
1452 case DETAIL_VERYLOW: step = 10; stepouter = 10; break;
1453 }
1454
1455 for(i=280;i<530;i+=stepouter)
1456 {
1457 struct vect v1,v2;
1458 /* Punkte auf innerem Radius berechnen */
1459 x1 = rad * cos( (double)i* M_PI / 180.0 );
1460 y1 = rad * sin( (double)i* M_PI / 180.0 );
1461 x2 = rad * cos( (double)(i+stepouter) * M_PI / 180.0 );
1462 y2 = rad * sin( (double)(i+stepouter) * M_PI / 180.0 );
1463
1464 /* Punkte auf �u�erem Radius berechnen */
1465 xo1 = rad_outer * cos( (double)i* M_PI / 180.0 );
1466 yo1 = rad_outer * sin( (double)i* M_PI / 180.0 );
1467 xo2 = rad_outer * cos( (double)(i+stepouter) * M_PI / 180.0 );
1468 yo2 = rad_outer * sin( (double)(i+stepouter) * M_PI / 180.0 );
1469
1470 /* Verbindungsvektoren bestimmen */
1471 v1.x = xo1-x1;
1472 v1.y = yo1-y1;
1473 v2.x = xo2-x2;
1474 v2.y = yo2-y2;
1475
1476 if( display_textures )
1477 {
1478 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
1479 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
1480
1481 glMaterialf(GL_FRONT, GL_SHININESS, MatShn);
1482 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
1483
1484 if( env_map ) /* sph�risches Environment-Mapping anschalten */
1485 {
1486 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
1487 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
1488 glEnable(GL_TEXTURE_GEN_S);
1489 glEnable(GL_TEXTURE_GEN_T);
1490 glBindTexture(GL_TEXTURE_2D, texture[36]);
1491 glEnable(GL_TEXTURE_2D);
1492 }
1493 }
1494 else
1495 {
1496 glLightfv(GL_LIGHT2, GL_SPECULAR, MatNull);
1497 glLightfv(GL_LIGHT1, GL_SPECULAR, MatNull);
1498 }
1499 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifMetall);
1500
1501 if( i >= 360 && i < 450 ) /* der 90-Grad Bereich der Ecken */
1502 {
1503 glBegin(GL_QUAD_STRIP);
1504 for(n=bfunc_max;n>=24;n-=step)
1505 {
1506 /* Metalleckkappenteil malen entlang der Verbindungsvektoren
1507 ausgehend von einem inneren Punkt */
1508 metal_strip_b( (x1+v1.x/36.0*(n-24)), (y1+v1.y/36.0*(n-24)), BFUNC(n),
1509 (x2+v2.x/36.0*(n-24)), (y2+v2.y/36.0*(n-24)), BFUNC(n),
1510 (x1+v1.x/36.0*(n-24+step)), (y1+v1.y/36.0*(n-24+step)), BFUNC(n+step),
1511 (x2+v2.x/36.0*(n-24+step)), (y2+v2.y/36.0*(n-24+step)), BFUNC(n+step));
1512 }
1513 glEnd();
1514 n1[0] = xo1-x1;
1515 n1[1] = yo1-y1;
1516 n1[2] = 0;
1517 n2[0] = xo2-x2;
1518 n2[1] = yo2-y2;
1519 n2[2] = 0;
1520 metal_edge(xo1, yo1, xo2, yo2, 0, 0, n1, n2, 1);
1521
1522 }
1523 else if( i < 360 ) /* Kopfbandenteil */
1524 {
1525 glBegin(GL_QUAD_STRIP);
1526 for(n=bfunc_max;n>=(x2-0.004)*1000.0;n-=step)
1527 {
1528 ns = n/1000.0;
1529 nsstep=ns + step/1000.0;
1530 metal_strip_b( (0.004+ns), -0.027, BFUNC(n),
1531 (0.004+ns), y2, BFUNC(n),
1532 (0.004+nsstep), -0.027, BFUNC(n+step),
1533 (0.004+nsstep), y2, BFUNC(n+step));
1534 }
1535 glEnd();
1536 xo1=rad_outer; yo1=y1;
1537 xo2=rad_outer; yo2=y2;
1538 n1[0] = xo1-x1;
1539 n1[1] = yo1-y1;
1540 n1[2] = 0;
1541 n2[0] = xo2-x2;
1542 n2[1] = yo2-y2;
1543 n2[2] = 0;
1544 metal_edge(xo1, yo1, xo2, yo2, 0, 0, n1, n2, 0);
1545 }
1546 else if( i >= 450 ) /* Rest der Metallverblendung an der langen Bande */
1547 {
1548 dum_int = (y2-0.004)*1000.0;
1549 glBegin(GL_QUAD_STRIP);
1550 for(n=bfunc_max;n>=dum_int;n-=step)
1551 {
1552 ns = n/1000.0;
1553 nsstep=ns + step/1000.0;
1554 metal_strip_b( x1, (0.004+ns), BFUNC(n),
1555 -0.027, (0.004+ns), BFUNC(n),
1556 x1, (0.004+nsstep), BFUNC(n+step),
1557 -0.027, (0.004+nsstep), BFUNC(n+step));
1558 }
1559 glEnd();
1560 xo1=x1; yo1=rad_outer; /* f. metal_edge */
1561 xo2=x2; yo2=rad_outer;
1562 n1[0] = xo1-x1;
1563 n1[1] = yo1-y1;
1564 n1[2] = 0;
1565 n2[0] = xo2-x2;
1566 n2[1] = yo2-y2;
1567 n2[2] = 0;
1568 metal_edge(xo1, yo1, xo2, yo2, 0, 0, n1, n2, 0);
1569 }
1570 }
1571 glPopMatrix();
1572 }
1573 glPopMatrix();
1574 }
1575
1576 if( env_map) /* sph�risches Env-Mapping wieder ausschalten */
1577 {
1578 glDisable(GL_TEXTURE_GEN_R);
1579 glDisable(GL_TEXTURE_GEN_S);
1580 glDisable(GL_TEXTURE_GEN_T);
1581 glDisable(GL_TEXTURE_2D);
1582 }
1583
1584 glColor4d(0.5,0.5,0.5,1.0);
1585 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatGummi);
1586
1587 /* step: Innenkreise der Mitteltaschen, Gummiverblendung von oben gesehen
1588 (Metallverblendung nicht!!) ;-) */
1589
1590 switch(geo_detail)
1591 {
1592 case DETAIL_VERYHIGH: step = 2; break;
1593 case DETAIL_HIGH: step = 5; break;
1594 case DETAIL_MED: step = 10; break;
1595 case DETAIL_LOW: step = 15; break;
1596 case DETAIL_VERYLOW: step = 30; break;
1597 }
1598
1599 for(j=-1;j<=1;j+=2)
1600 {
1601 glPushMatrix();
1602 glTranslatef(0.0,j*0.2775,0.0);
1603 glRotatef(180.0*(j-1)/2,0.0,0.0,1.0);
1604
1605 for(i=-15;i<195;i+=step)
1606 {
1607 x1 = rad * cos( (double)i* M_PI / 180.0 );
1608 y1 = rad * sin( (double)i* M_PI / 180.0 );
1609 glBegin(GL_QUADS); /* KANN MAN NOCH DURCH QUAD_STRIPS ERSETZEN */
1610 glNormal3d(-x1/sqrt(x1*x1+y1*y1),-y1/sqrt(x1*x1+y1*y1),0.0);
1611
1612 gummi( x1, y1,
1613 (x2 = rad * cos( (double)(i+step) * M_PI / 180.0 )),
1614 (y2 = rad * sin( (double)(i+step) * M_PI / 180.0 )) );
1615 glEnd();
1616 if( i==-15 || i>=195-step) stat = 1;
1617 else stat=0;
1618 glDisable(GL_LIGHTING);
1619 glBegin(GL_QUADS);
1620 gummitop( (rad*0.85 * cos( (double)(i+step)* M_PI / 180.0 )),
1621 (rad*0.85 * sin( (double)(i+step)* M_PI / 180.0 )),
1622 (rad*0.85 * cos( (double)i* M_PI / 180.0 )),
1623 (rad*0.85 * sin( (double)i* M_PI / 180.0 )),
1624 x1, y1, x2, y2,
1625 (rad*1.15 * cos( (double)(i+step)* M_PI / 180.0 )),
1626 (rad*1.15 * sin( (double)(i+step)* M_PI / 180.0 )),
1627 (rad*1.15 * cos( (double)i* M_PI / 180.0 )),
1628 (rad*1.15 * sin( (double)i* M_PI / 180.0 )), stat);
1629 glEnd();
1630 glEnable(GL_LIGHTING);
1631 }
1632 glPopMatrix();
1633 }
1634
1635 if( display_textures )
1636 {
1637 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
1638 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
1639
1640 glMaterialf(GL_FRONT, GL_SHININESS, MatShn);
1641 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
1642
1643 if( env_map )
1644 {
1645 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
1646 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
1647 glEnable(GL_TEXTURE_GEN_S);
1648 glEnable(GL_TEXTURE_GEN_T);
1649 glEnable(GL_TEXTURE_2D);
1650 glBindTexture(GL_TEXTURE_2D, texture[36]);
1651 }
1652 }
1653 else
1654 {
1655 glLightfv(GL_LIGHT2, GL_SPECULAR, MatNull);
1656 glLightfv(GL_LIGHT1, GL_SPECULAR, MatNull);
1657 }
1658 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifMetall);
1659
1660 /* stepouter: Rasterung des Innenkreises der Mitteltaschen f�r die Metallverblendung! von oben gesehen, GoodQ:5 */
1661 /* step: Rasterung der "Metall-Kante" nach au�en hin, seitlich gesehen, GoodQ:5 */
1662
1663 switch(geo_detail)
1664 {
1665 case DETAIL_VERYHIGH: step = 1; stepouter = 1; break;
1666 case DETAIL_HIGH: step = 2; stepouter = 1; break;
1667 case DETAIL_MED: step = 5; stepouter = 5; break;
1668 case DETAIL_LOW: step = 5; stepouter = 10; break;
1669 case DETAIL_VERYLOW: step = 10; stepouter = 20; break;
1670 }
1671
1672 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
1673 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
1674
1675 glMaterialf(GL_FRONT, GL_SHININESS, MatShn);
1676 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
1677
1678 for(j=-1;j<=1;j+=2)
1679 {
1680 glPushMatrix();
1681 glRotatef((j+1)/2*180.0,0.0,0.0,1.0);
1682 glTranslatef(0.0,0.2775,0.0);
1683 for(i=0;i<180-stepouter;i+=stepouter)
1684 {
1685 x1 = rad * cos( (double)i* M_PI / 180.0 );
1686 y1 = rad * sin( (double)i* M_PI / 180.0 );
1687 x2 = rad * cos( (double)(i+stepouter) * M_PI / 180.0 );
1688 y2 = rad * sin( (double)(i+stepouter) * M_PI / 180.0 );
1689
1690 dum_int=y2*1000+7.5;
1691 glBegin(GL_QUAD_STRIP);
1692 for(m=bfunc_max;m>=dum_int;m-=step)
1693 {
1694 ms = m/1000.0;
1695 msstep = ms + step/1000.0;
1696 metal_strip(x1, (-0.0075+ms), BFUNC(m),
1697 x2, (-0.0075+ms), BFUNC(m),
1698 x2, (-0.0075+msstep), BFUNC(m+step));
1699 }
1700 glEnd();
1701 }
1702 /* die beiden seitlichen Streifen */
1703 glBegin(GL_QUAD_STRIP);
1704 for(m=bfunc_max;m>=0;m-=step)
1705 {
1706 ms = m/1000.0;
1707 msstep = ms + step/1000.0;
1708 metal_strip( 0.039, (-0.0075+ms), BFUNC(m),
1709 0.027, (-0.0075+ms), BFUNC(m),
1710 0.039, (-0.0075+msstep), BFUNC(m+step));
1711 }
1712 glEnd();
1713 glBegin(GL_QUAD_STRIP);
1714 for(m=bfunc_max;m>=0;m-=step)
1715 {
1716 ms = m/1000.0;
1717 msstep = ms + step/1000.0;
1718 metal_strip( -0.027, (-0.0075+ms), BFUNC(m),
1719 -0.039, (-0.0075+ms), BFUNC(m),
1720
1721 -0.039, (-0.0075+msstep), BFUNC(m+step));
1722 }
1723 glEnd();
1724 glPopMatrix();
1725 }
1726
1727 /* Metallverkleidung der Mitteltaschen */
1728 glBegin(GL_QUADS);
1729
1730 glNormal3d(0,1.0,0.0);
1731 metal_mid( 0.039, 0.330, -0.039, 0.330);
1732 glNormal3d(0,-1.0,0.0);
1733 metal_mid(-0.039, -0.330, 0.039, -0.330);
1734
1735 glEnd();
1736 if( env_map )
1737 {
1738 glDisable(GL_TEXTURE_GEN_S);
1739 glDisable(GL_TEXTURE_GEN_T);
1740 glDisable(GL_TEXTURE_2D);
1741 }
1742
1743 glBegin(GL_QUADS);
1744 /* Unterseite des Tisches*/
1745 glLightfv(GL_LIGHT1, GL_SPECULAR, LightZero);
1746 glLightfv(GL_LIGHT2, GL_SPECULAR, LightZero);
1747
1748 glColor4d(0.1, 0.1, 0.1,1.0);
1749 glNormal3d( 0, 0, -1.0);
1750
1751 /* glEnable(GL_TEXTURE_2D); */
1752 /* glBindTexture(GL_TEXTURE_2D, texture[3]); */
1753 underside(-0.516, -0.33, 0.516, 0.33 );
1754 /* glDisable(GL_TEXTURE_2D); */
1755 underside(0.515, -0.266, 0.58, 0.266 );
1756 underside(-0.58, -0.266, -0.515, 0.266 );
1757
1758 /* Au�enseite des Tisches */
1759
1760 glColor4d(0.1, 0.1, 0.1,1.0);
1761
1762 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifWooddark);
1763 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmbWooddark);
1764
1765 outside( 0.489, 0.330, 0.039, 0.330 );
1766 outside( -0.489, -0.330, -0.039, -0.330 );
1767 outside( -0.039, 0.330, -0.489, 0.330 );
1768 outside( 0.039, -0.330, 0.489, -0.330 );
1769
1770 outside( 0.580, -0.239, 0.580, 0.239 );
1771 outside( -0.580, 0.239, -0.580, -0.239 );
1772
1773 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifDark);
1774 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);
1775
1776 glEnd();
1777
1778 glEndList(); /* Ende Aufbauten (L�cher Verblendungen, Holz, die tuchfarbenen Banden kommen mit 259 */
1779
1780 glNewList(259, GL_COMPILE);
1781
1782 /* Banden malen: Erstmal die seitlichen St�cke */
1783 glColor4d(1.0, 1.0, 1.0, 1.0);
1784 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpcLow);
1785 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);
1786 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifBorder);
1787
1788 glDisable(GL_LIGHTING);
1789
1790 glBegin(GL_QUADS);
1791 for(i=0;i<18;i+=3)
1792 {
1793 glNormal3d( ban[i].n.x, ban[i].n.y, -0.1);
1794 TABLE_COLOR(0.0);
1795 glVertex3d( (double)ban[i].p0.x-0.5, ((double)ban[i].p0.y-0.25), -0.001);
1796 TABLE_COLOR(0.0);
1797 glVertex3d( (double)ban[i].p0.x-0.5, ((double)ban[i].p0.y-0.25), 4.0/3.0*RADIUS);
1798 TABLE_COLOR(0.3);
1799 glVertex3d( (double)ban[i].p1.x-0.5, ((double)ban[i].p1.y-0.25), 635/1000.0 * 2.0*RADIUS);
1800 TABLE_COLOR(0.3);
1801 glVertex3d( (double)ban[i].p1.x-0.5, ((double)ban[i].p1.y-0.25), 635/1000.0 * 2.0*RADIUS);
1802 #ifdef DEBUG
1803 poly++;
1804 #endif
1805 }
1806
1807 for(i=2;i<18;i+=3)
1808 {
1809 glNormal3d( ban[i].n.x, ban[i].n.y, -0.1);
1810 TABLE_COLOR(0.0);
1811 glVertex3d( (double)ban[i].p1.x-0.5, ((double)ban[i].p1.y-0.25), -0.001);
1812 TABLE_COLOR(0.2);
1813 glVertex3d( (double)ban[i].p0.x-0.5, ((double)ban[i].p0.y-0.25), 635/1000.0 * 2.0*RADIUS);
1814 TABLE_COLOR(0.2);
1815 glVertex3d( (double)ban[i].p0.x-0.5, ((double)ban[i].p0.y-0.25), 635/1000.0 * 2.0*RADIUS);
1816 TABLE_COLOR(0.0);
1817 glVertex3d( (double)ban[i].p1.x-0.5, ((double)ban[i].p1.y-0.25), 4.0/3.0*RADIUS);
1818 #ifdef DEBUG
1819 poly++;
1820 #endif
1821 }
1822
1823 for(i=1;i<18;i+=3)
1824 {
1825 glNormal3d( ban[i].n.x, ban[i].n.y, -0.1);
1826 TABLE_COLOR(0.2);
1827 glVertex3d( (double)ban[i].p1.x-0.5, ((double)ban[i].p1.y-0.25), 635/1000.0 * 2.0*RADIUS);
1828 TABLE_COLOR(0.2);
1829 glVertex3d( (double)ban[i+1].p1.x-0.5, ((double)ban[i+1].p1.y-0.25), -0.001);
1830 TABLE_COLOR(0.0);
1831 glVertex3d( (double)ban[i-1].p0.x-0.5, ((double)ban[i-1].p0.y-0.25), -0.001);
1832 TABLE_COLOR(0.0);
1833 glVertex3d( (double)ban[i].p0.x-0.5, ((double)ban[i].p0.y-0.25), 635/1000.0 * 2.0*RADIUS);
1834 #ifdef DEBUG
1835 poly++;
1836 #endif
1837 }
1838
1839 /* Banden malen: Oberseite */
1840 for(i=0;i<6;i++)
1841 {
1842 glNormal3d( 0.0, 0.0, 1.0);
1843 TABLE_COLOR(0.2);
1844 glVertex3d( (double)ban[i*3+2].p1.x-0.5, (double)ban[i*3+2].p1.y-0.25, 4.0/3.0*RADIUS);
1845 TABLE_COLOR(0.5);
1846 glVertex3d( (double)ban[i*3+2].p0.x-0.5, (double)ban[i*3+2].p0.y-0.25, 635/1000.0 * 2.0*RADIUS);
1847 TABLE_COLOR(0.5);
1848 glVertex3d( (double)ban[i*3].p1.x-0.5, (double)ban[i*3].p1.y-0.25, 635/1000.0 * 2.0*RADIUS);
1849 TABLE_COLOR(0.2);
1850 glVertex3d( (double)ban[i*3].p0.x-0.5, (double)ban[i*3].p0.y-0.25, 4.0/3.0*RADIUS);
1851 #ifdef DEBUG
1852 poly++;
1853 #endif
1854 }
1855 glEnd();
1856
1857 glEnable(GL_LIGHTING);
1858
1859 glEndList(); /* Ende Bandenaufbauten */
1860
1861 switch(geo_detail) /* Rasterung des Schattenkreises */
1862 {
1863 case DETAIL_VERYHIGH: step = 5; break;
1864 case DETAIL_HIGH: step = 10; break;
1865 case DETAIL_MED: step = 20; break;
1866 case DETAIL_LOW: step = 20; break;
1867 case DETAIL_VERYLOW: step = 30; break;
1868 }
1869 glNewList(280, GL_COMPILE ); /* Liste f�r Schatten der Kugeln */
1870 glBegin(GL_TRIANGLE_FAN);
1871 glColor4f(0.0,0.0,0.0,0.08);
1872 glVertex3d(0.0,0.0,0.0);
1873 for(i=360;i>=00;i-=step)
1874 glVertex3d(0.8*RADIUS * sin((double)i*M_PI/180.0), 0.8*RADIUS * cos((double)i*M_PI/180.0), 0.001);
1875 glEnd();
1876 glBegin(GL_QUAD_STRIP);
1877 for(i=0;i<=360;i+=step)
1878 {
1879 glColor4f(0.0,0.0,0.0,0.0);
1880 glVertex3d(RADIUS*1.1 * sin((double)i*M_PI/180.0), RADIUS*1.1 * cos((double)i*M_PI/180.0), 0.001);
1881 glColor4f(0.0,0.0,0.0,0.08);
1882 glVertex3d(0.8*RADIUS * sin((double)i*M_PI/180.0), 0.8*RADIUS * cos((double)i*M_PI/180.0), 0.001);
1883 #ifdef DEBUG
1884 poly++;
1885 #endif
1886 }
1887 glEnd();
1888 glEndList();
1889
1890 /* Displaylisten f�r Kugeln inkl. Texturen */
1891 for(i=0;i<BALLS;i++)
1892 {
1893 glNewList(290+i, GL_COMPILE );
1894 if( display_textures )
1895 {
1896 glBindTexture(GL_TEXTURE_2D, texture[i + (txt_detail < TEXTURE_HIGH ? 16 : 0)]);
1897 }
1898 else /* switch �ber k[i].col hat nicht funktioniert... ?! */
1899 {
1900 if( i == 0 ) glMaterialfv(GL_FRONT, GL_DIFFUSE, MatWhiteDif);
1901 if( i == 8 ) glMaterialfv(GL_FRONT, GL_DIFFUSE, MatBlackDif);
1902 if( i > 0 && i < 8 ) glMaterialfv(GL_FRONT, GL_DIFFUSE, MatRedDif);
1903 if( i > 8 ) glMaterialfv(GL_FRONT, GL_DIFFUSE, MatYellowDif);
1904 }
1905 switch(geo_detail)
1906 {
1907 case DETAIL_VERYHIGH: icoball(20480); break;
1908 case DETAIL_HIGH: icoball(5120); break;
1909 case DETAIL_MED: icoball(1280); break;
1910 case DETAIL_LOW: icoball(320); break;
1911 case DETAIL_VERYLOW: icoball(80); break;
1912 }
1913 glEndList();
1914 }
1915 #ifdef DEBUG
1916 printf("In init_lists: Polygone: %ld\n",poly);
1917 #endif
1918 }
1919
InitGL(int width,int height)1920 void InitGL(int width, int height)
1921 {
1922 char out[128];
1923 SDL_Init(SDL_INIT_VIDEO); /* wird ben�tigt vor SetVideoMode; ohne muss ein Extra SDL-Fenster ge�ffnet werden */
1924 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,8); /* Sicherstellen, dass stencil-buffer vorhanden ist! */
1925
1926 if ( SDL_SetVideoMode(width, height, 0, SDL_OPENGL|GLOPT) == NULL )
1927 {
1928 fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError());
1929 SDL_Quit();
1930 exit(1);
1931 }
1932 sprintf(out,"Another Pool GL V %s, (c) 1995 and 2002-2003,2005 by Gerrit Jahn",VERSION);
1933 SDL_WM_SetCaption(out, NULL);
1934
1935 LoadGLTextures(); /* wichtig: erst GL-VideoMode erzeugen, DANN Texturen laden ! ;-)) */
1936 BuildFont();
1937
1938 glViewport(0, 0, width, height);
1939 glClearColor(0.0, 0.0, 0.0, 0.0); /* Clear Screen mit angegebenen Farben */
1940 glClearDepth(1.0); /* Z-Buffer l�schen */
1941 glDepthFunc(GL_LEQUAL);
1942
1943 glFogf(GL_FOG_MODE, GL_EXP2); /* "Nebel" */
1944 glFogf(GL_FOG_DENSITY, 0.5);
1945 glEnable(GL_FOG);
1946
1947 glCullFace(GL_BACK);
1948 glEnable(GL_CULL_FACE);
1949
1950 glEnable(GL_DEPTH_TEST); /* Z-Buffer anschalten */
1951 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1952 glDisable(GL_POLYGON_SMOOTH); /* sonst treten bei MESA an den Polygonkanten Linienartefakte auf */
1953
1954 glShadeModel(GL_SMOOTH);
1955
1956 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
1957
1958 glLightModelf(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); /* f�r die sch�nenen Glanzlichter ;-) */
1959
1960 glMatrixMode(GL_PROJECTION); /* Perspektive am Anfang festlegen */
1961 glLoadIdentity();
1962 gluPerspective(45.0,(GLdouble)width/(GLdouble)height,0.01,100.0);
1963
1964 glMatrixMode(GL_MODELVIEW);
1965 glLoadIdentity();
1966
1967 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); /* LIGHT1,2 sind die beiden Hauptlichter �ber dem Tisch */
1968 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse1);
1969 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
1970 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition[0]);
1971 glEnable(GL_LIGHT1);
1972
1973 glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient);
1974 glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2);
1975 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
1976 glLightfv(GL_LIGHT2, GL_POSITION,LightPosition[1]);
1977 glEnable(GL_LIGHT2);
1978
1979 glLightfv(GL_LIGHT3, GL_AMBIENT, LightAmbient3); /* LIGHT3 wird nur ben�tigt, um Spin-Kugel usw. zu beleuchten */
1980 glLightfv(GL_LIGHT3, GL_DIFFUSE, LightDiffuse3);
1981 glLightfv(GL_LIGHT3, GL_SPECULAR, LightSpecular);
1982 glLightfv(GL_LIGHT3, GL_POSITION,LightPosition[2]);
1983
1984 oldang.x = angx; /* die "letzte Ansicht" (GL-Mode: "l" dr�cken) initialisieren */
1985 oldang.y = angy;
1986 oldang.z = angz;
1987 oldstart.x = startx;
1988 oldstart.y = starty;
1989 oldstart.z = startz;
1990
1991 /* Ikosaeder umnormieren, so dass die �u�ersten Punkt auf
1992 der Einheitskugel liegen. Im Moment liegen die mittleren
1993 Verbindungslinien der Dreiecke auf der 1 */
1994 normalize_ico20(1.1755705045849463);
1995
1996 /* Kugeln aus dem Ikosaeder erzeugen durch Aufteilen der
1997 vorhandenen Dreicke in 4 Dreiecke - mehrfach */
1998 splitpoly(ico80, ico20, 20);
1999 splitpoly(ico320, ico80, 80);
2000 splitpoly(ico1280, ico320, 320);
2001 splitpoly(ico5120, ico1280, 1280);
2002 splitpoly(ico20480, ico5120, 5120);
2003 }
2004
2005 /* malt den Schatten der Kugeln mittels Alpha-Blendung auf das Tischtuch */
gl_planar_shadows(void)2006 void gl_planar_shadows(void)
2007 {
2008 int i,j;
2009 double dummy, tangens, scale=1.0, alpha=0.06;
2010 struct vect3 diff, ez={0.0,0.0,1.0}, trans;
2011 glDisable(GL_LIGHTING);
2012 glEnable(GL_BLEND);
2013 glLightfv(GL_LIGHT2, GL_SPECULAR, LightZero);
2014 glLightfv(GL_LIGHT1, GL_SPECULAR, LightZero);
2015 glMaterialfv(GL_FRONT, GL_SPECULAR, MatNull);
2016 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatNull);
2017
2018 glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_ALPHA);
2019 glDisable(GL_DEPTH_TEST);
2020
2021 for(i=0;i<BALLS;i++)
2022 {
2023 if( k[i].stat & ONTABLE )
2024 {
2025 for(j=0;j<2;j++)
2026 {
2027 glPushMatrix();
2028 glTranslated((double)k[i].p.x-0.5, (double)k[i].p.y-0.25, 0.0);
2029 diff.x = LightPosition[j][0] - (k[i].p.x-0.5);
2030 diff.y = LightPosition[j][1] - (k[i].p.y-0.25);
2031 diff.z = LightPosition[j][2] - 2.0*RADIUS;
2032 alpha = 0.02 + 1.0 / (1000.0 * SKALP3(diff,diff) );
2033 if( ABS(diff.x) > 1E-10 || ABS(diff.y) > 1E-10 )
2034 {
2035 dummy = sqrt(diff.x*diff.x + diff.y*diff.y);
2036 tangens = diff.z / dummy;
2037 scale = 1.0 + 1.0 / tangens;
2038 dummy = BETR3(diff);
2039 diff.x /= dummy;
2040 diff.y /= dummy;
2041 diff.z /= dummy;
2042 dummy = SKALP3(diff, ez);
2043 trans.x = diff.x - dummy * ez.x;
2044 trans.y = diff.y - dummy * ez.y;
2045 trans.z = diff.z - dummy * ez.z;
2046 glTranslated(-RADIUS*scale * trans.x, -RADIUS*scale*trans.y, 0.0);
2047
2048 glRotated(atan(trans.y/trans.x) * 180.0/M_PI, 0.0,0.0,1.0);
2049 glScaled(scale, 1.0,1.0);
2050 }
2051 else glScaled(1.0,1.0,1.0);
2052 glCallList(280); /* Schattenkreise malen */
2053 glPopMatrix();
2054 }
2055 }
2056 }
2057 glEnable(GL_DEPTH_TEST);
2058 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2059 glDisable(GL_BLEND);
2060 glEnable(GL_LIGHTING);
2061 }
2062
2063 /* malt die Kugeln */
gl_plotballs(int stencilrun,int create_cubemaps_flag)2064 void gl_plotballs(int stencilrun, int create_cubemaps_flag)
2065 {
2066 int i;
2067 double angle;
2068 if( display_textures )
2069 {
2070 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
2071 glMaterialf(GL_FRONT, GL_SHININESS, MatShnsmall);
2072 }
2073 else
2074 {
2075 glLightfv(GL_LIGHT2, GL_SPECULAR, LightZero);
2076 glLightfv(GL_LIGHT1, GL_SPECULAR, LightZero);
2077 glMaterialfv(GL_FRONT, GL_SPECULAR, MatNull);
2078 glMaterialf(GL_FRONT, GL_SHININESS, 0.0);
2079 }
2080
2081 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmbbright);
2082
2083 if( stencilrun != 2 )
2084 {
2085 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifballs);
2086 if( ball_env_map != 1 ) glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
2087 else glMaterialfv(GL_FRONT, GL_SPECULAR, MatNull);
2088 }
2089 else
2090 {
2091 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifballs_multi);
2092 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc_multi);
2093 }
2094
2095 glColor4d(1.0, 1.0, 1.0, 1.0);
2096
2097 if( display_textures ) glEnable(GL_TEXTURE_2D);
2098
2099 /* In der for-Schleife f�r die Kugeln werden die ruhenden Kugeln in Displaylisten gesteckt */
2100 /* Bei sich bewegenden Kugeln wird nur der statische Anteil (Sphere und Texturemapping */
2101 /* aus einer Liste geholt */
2102
2103 for(i=0;i<BALLS;i++)
2104 {
2105 if( !( k[i].stat & DELETED) )
2106 {
2107 if( ball_env_map || (k[i].stat & MOVING) ) /* Kugel bewegt sich noch, also nur einen Teil aus Liste holen */
2108 {
2109 glPushMatrix();
2110
2111 glTranslated((double)k[i].p.x-0.5, (double)k[i].p.y-0.25, (double)k[i].p.z);
2112 if( display_textures )
2113 {
2114 angle = sqrt( k[i].rot.x*k[i].rot.x + k[i].rot.y*k[i].rot.y /* + k[i].rot.z*k[i].rot.z */ );
2115 glRotated(angle, k[i].rot.x, k[i].rot.y, 0.0 /* k[i].rot.z */ );
2116 glMultMatrixd(k[i].mrot);
2117 }
2118 glCallList((290+k[i].no));
2119
2120 if( display_textures )
2121 {
2122 if( ball_env_map && create_cubemaps_flag )
2123 {
2124 glDisable(GL_LIGHTING);
2125 glColor4f(0.2,0.2,0.2,1.0);
2126 glEnable(GL_BLEND);
2127 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
2128
2129 if( ball_env_map == 2 )
2130 {
2131 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
2132 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
2133 glEnable(GL_TEXTURE_GEN_S);
2134 glEnable(GL_TEXTURE_GEN_T);
2135 glBindTexture(GL_TEXTURE_2D, texture[36]);
2136 }
2137 else if( ball_env_map == 1 )
2138 {
2139 glDisable(GL_TEXTURE_2D);
2140
2141 /* die Cube-Environment-Textur wird immer unrotiert auf die das
2142 Objekt gemappt (unabh. davon, wie die Modelview-Matrix
2143 aktuell rotiert ist. Daher muss die Textur-Matrix das
2144 Inverse der Modelview Matrix sein bzgl. Rotationen. Also
2145 einfach Textur-Matrix mit negativen Winkeln in umgekehrter
2146 Reihenfolge rotieren, damit sich die Cube-Env-Textur nicht
2147 mitdreht, der Raum um die Kugeln also "stabil" bleibt: */
2148 glMatrixMode(GL_TEXTURE);
2149 glPushMatrix();
2150 glLoadIdentity();
2151 glRotatef(-angz,0.0,0.0,1.0);
2152 glRotatef(-angy,0.0,1.0,0.0);
2153 glRotatef(-angx,1.0,0.0,0.0);
2154
2155 glEnable(GL_TEXTURE_CUBE_MAP_EXT);
2156
2157 glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, cube_texture[WHITE]);
2158 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2159 glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2160 glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2161
2162 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
2163 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
2164 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
2165 glEnable(GL_TEXTURE_GEN_S);
2166 glEnable(GL_TEXTURE_GEN_T);
2167 glEnable(GL_TEXTURE_GEN_R);
2168 }
2169 }
2170
2171 switch(geo_detail)
2172 {
2173 case DETAIL_VERYHIGH: icoball(20480); break;
2174 case DETAIL_HIGH: icoball(5120); break;
2175 case DETAIL_MED: icoball(1280); break;
2176 case DETAIL_LOW: icoball(320); break;
2177 case DETAIL_VERYLOW: icoball(80); break;
2178 }
2179
2180 if( ball_env_map == 1 )
2181 {
2182 glPopMatrix();
2183 glMatrixMode(GL_MODELVIEW);
2184 glDisable(GL_TEXTURE_GEN_R);
2185 glDisable(GL_TEXTURE_CUBE_MAP_EXT);
2186 glEnable(GL_TEXTURE_2D);
2187 }
2188 glDisable(GL_TEXTURE_GEN_S);
2189 glDisable(GL_TEXTURE_GEN_T);
2190 glDisable(GL_BLEND);
2191 glEnable(GL_LIGHTING);
2192 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2193 }
2194 glPopMatrix();
2195 }
2196 else
2197 {
2198 if( k[i].stat & GL_LISTED_NOT_MOVING )
2199 {
2200 glCallList(260+i); /* falls schon in Liste, Liste aufrufen */
2201 }
2202 else /* sonst Liste erstellen */
2203 {
2204 glNewList(260+i,GL_COMPILE_AND_EXECUTE);
2205
2206 glPushMatrix();
2207
2208 angle = sqrt( k[i].rot.x*k[i].rot.x + k[i].rot.y*k[i].rot.y /* + k[i].rot.z*k[i].rot.z */ );
2209
2210 glTranslated((double)k[i].p.x-0.5, (double)k[i].p.y-0.25, (double)k[i].p.z);
2211 glRotated(angle, k[i].rot.x, k[i].rot.y, 0.0 /* k[i].rot.z */ );
2212 glMultMatrixd(k[i].mrot);
2213
2214 glCallList((290+k[i].no));
2215
2216 glPopMatrix();
2217 glEndList();
2218 k[i].stat |= GL_LISTED_NOT_MOVING;
2219 }
2220 }
2221 }
2222 }
2223 if( display_textures )
2224 {
2225 glDisable(GL_TEXTURE_2D);
2226 }
2227 }
2228
2229 /* gibt den aktuellen Spieler und die kleine Kugel links oben aus */
gl_plotplayer(void)2230 void gl_plotplayer(void)
2231 {
2232 char out[256];
2233 if( !new_game )
2234 {
2235 glDisable(GL_FOG);
2236 glEnable(GL_BLEND);
2237 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifTransparent);
2238 glDisable(GL_LIGHT1);
2239 glDisable(GL_LIGHT2);
2240 glEnable(GL_LIGHT3);
2241
2242 glMatrixMode(GL_PROJECTION);
2243 glPushMatrix();
2244 glLoadIdentity();
2245 glOrtho(-0.5,0.5,-0.4,0.4,1.0,0);
2246 glMatrixMode(GL_MODELVIEW);
2247 glPushMatrix();
2248 glLoadIdentity();
2249
2250 glColor4d(1.0, 1.0, 1.0, 0.4);
2251 glTranslated(-0.45, 0.35, -1.0);
2252
2253 if( display_textures )
2254 {
2255 glEnable(GL_TEXTURE_2D);
2256 switch( ply[cur].col)
2257 {
2258 case COL_RED: glBindTexture(GL_TEXTURE_2D, texture[2 + (txt_detail < TEXTURE_HIGH ? 16 : 0)]);break;
2259 case COL_YELLOW: glBindTexture(GL_TEXTURE_2D, texture[10 + (txt_detail < TEXTURE_HIGH ? 16 : 0)]); break;
2260 case COL_BLACK: glBindTexture(GL_TEXTURE_2D, texture[8 + (txt_detail < TEXTURE_HIGH ? 16 : 0)]); break;
2261 default: glBindTexture(GL_TEXTURE_2D, texture[0 + (txt_detail < TEXTURE_HIGH ? 16 : 0)]); break;
2262 }
2263 }
2264 else
2265 {
2266 switch( ply[cur].col)
2267 {
2268 case COL_RED: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatRedDif); break;
2269 case COL_YELLOW: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatYellowDif); break;
2270 case COL_BLACK: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatBlackDif);break;
2271 default: glMaterialfv(GL_FRONT, GL_DIFFUSE, MatWhiteDif); break;
2272 }
2273 }
2274 icosphere(ico320,320,RADIUS*2); /* displaylist */
2275
2276 if( display_textures ) glDisable(GL_TEXTURE_2D);
2277
2278 glMatrixMode(GL_PROJECTION);
2279 glPopMatrix();
2280 glMatrixMode(GL_MODELVIEW);
2281 glPopMatrix();
2282 glEnable(GL_LIGHT1);
2283 glEnable(GL_LIGHT2);
2284 glDisable(GL_LIGHT3);
2285 glEnable(GL_FOG);
2286
2287 sprintf(out,"Player: %d %s",cur+1,(extra_shot==1 || freeball == 1)?"(xS)":"");
2288 glPrint(100,768-55,out,0,0.5,0.5,0.8,0.8, 1.0);
2289 }
2290 }
2291
2292 /* Frames/s und aktuellen Spieler ausgeben */
gl_plotfps(void)2293 void gl_plotfps(void)
2294 {
2295 char out[256];
2296 sprintf(out,"%d",(int)(frames_per_second+0.5));
2297 glPrint(1024-60,22,out,0,0.5,0.5,0.8,0.8, 1.0);
2298 }
2299
initshadow(double xL,double yL,double zL)2300 void initshadow(double xL, double yL, double zL)
2301 { /* z-Werte des Schattenvolumens sind falsch. Sollten nicht konstant sein! */
2302 int i,j;
2303 float x1,y1,z1,x2,y2,z2;
2304 struct vect3 v,e1,e2;
2305 double dummy, dummysin, dummycos;
2306
2307 for(j=0;j<BALLS;j++)
2308 {
2309 if( !( k[j].stat & DELETED) )
2310 {
2311 /* Verbindungslinie Licht - Mittelpunkt der Kugel */
2312 v.x = xL - (k[j].p.x-0.5);
2313 v.y = yL - (k[j].p.y-0.25);
2314 v.z = zL - k[j].p.z;
2315
2316 /* zwei Vektoren senkrecht zueinander und senkrecht auf v bestimmen */
2317 e1.x = 0;
2318 e1.y = v.z;
2319 e1.z = -v.y;
2320
2321 if( (dummy = BETR3(e1)) )
2322 {
2323 e1.x /= dummy;
2324 e1.y /= dummy;
2325 e1.z /= dummy;
2326 }
2327
2328 e2.x = v.y * e1.z - v.z * e1.y;
2329 e2.y = v.z * e1.x - v.x * e1.z;
2330 e2.z = v.x * e1.y - v.y * e1.x;
2331
2332 if( (dummy = BETR3(e2)) )
2333 {
2334 e2.x /= dummy;
2335 e2.y /= dummy;
2336 e2.z /= dummy;
2337 }
2338
2339 for(i=0;i<360;i+=shadow_step)
2340 {
2341 dummysin = sin(i*M_PI/180.0);
2342 dummycos = cos(i*M_PI/180.0);
2343 x1= RADIUS * dummysin * e1.x + RADIUS * dummycos * e2.x;
2344 y1= RADIUS * dummysin * e1.y + RADIUS * dummycos * e2.y;
2345 z1= RADIUS * dummysin * e1.z + RADIUS * dummycos * e2.z;
2346
2347 /* Mittelpunktkoordinaten dazuaddieren (Translation des Schattenvolumens
2348 an die Kugelposition) */
2349 x1 += k[j].p.x-0.5;
2350 y1 += k[j].p.y-0.25;
2351 z1 += k[j].p.z;
2352
2353 /* Verl�ngerungsvektor berechnen, Scheibenrand - Licht */
2354 x2 = x1 - xL;
2355 y2 = y1 - yL;
2356 z2 = z1 - zL;
2357
2358 dummy = sqrt(x2*x2+y2*y2+z2*z2);
2359 x2 /= dummy;
2360 y2 /= dummy;
2361 z2 /= dummy;
2362
2363 /* nach "unendlich" verl�ngerte Punkte des Zylinders berechnen */
2364
2365 x2 = x1 + x2;
2366 y2 = y1 + y2;
2367 z2 = z1 + z2;
2368
2369 /* QUAD_STRIP-Koordinaten des Schattenzylinders abspeichern */
2370 shadow[j][i/shadow_step][0][0] = x2;
2371 shadow[j][i/shadow_step][0][1] = y2;
2372 shadow[j][i/shadow_step][0][2] = z2;
2373 shadow[j][i/shadow_step][1][0] = x1;
2374 shadow[j][i/shadow_step][1][1] = y1;
2375 shadow[j][i/shadow_step][1][2] = z1;
2376 }
2377 /* Den "Zylinder" schlie�en: */
2378 shadow[j][i/shadow_step][0][0] = shadow[j][0][0][0];
2379 shadow[j][i/shadow_step][0][1] = shadow[j][0][0][1];
2380 shadow[j][i/shadow_step][0][2] = shadow[j][0][0][2];
2381 shadow[j][i/shadow_step][1][0] = shadow[j][0][1][0];
2382 shadow[j][i/shadow_step][1][1] = shadow[j][0][1][1];
2383 shadow[j][i/shadow_step][1][2] = shadow[j][0][1][2];
2384 }
2385 }
2386 }
2387
gl_plotshadow(void)2388 void gl_plotshadow(void)
2389 {
2390 int i,j;
2391 glDisable(GL_LIGHTING);
2392 glEnable(GL_BLEND);
2393 glColor4f(0.9,0.9,0.9,0.5);
2394 for(i=0;i<BALLS;i++)
2395 {
2396 if( !( k[i].stat & DELETED) )
2397 {
2398 glBegin(GL_QUAD_STRIP);
2399 for(j=0;j<=360/shadow_step;j++)
2400 {
2401 glVertex3d(shadow[i][j][0][0],shadow[i][j][0][1],shadow[i][j][0][2]);
2402 glVertex3d(shadow[i][j][1][0],shadow[i][j][1][1],shadow[i][j][1][2]);
2403 }
2404 glEnd();
2405 }
2406 }
2407 glDisable(GL_BLEND);
2408 glEnable(GL_LIGHTING);
2409 }
2410
position_lights(void)2411 void position_lights(void)
2412 {
2413 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition[0]); /* Licht positionieren */
2414 glLightfv(GL_LIGHT2, GL_POSITION,LightPosition[1]);
2415 }
2416
create_cubemaps(int which)2417 void create_cubemaps(int which)
2418 {
2419 glPushMatrix();
2420 glMatrixMode(GL_PROJECTION); /* Perspektive am Anfang festlegen */
2421 glPushMatrix();
2422 glLoadIdentity();
2423 gluPerspective(90.0,1.0,0.01,2.0);
2424
2425 glViewport(0,0,cube_txt_size, cube_txt_size); /* Viewport auf Texturgr��e setzen */
2426
2427 glMatrixMode(GL_MODELVIEW); /* Am Anfang einmal MODELVIEW initialisieren */
2428
2429 glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, cube_texture[which]);
2430
2431 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2432 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2433 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2434 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2435 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
2436 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2437
2438 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2439 glLoadIdentity();
2440
2441 glRotated(180.0,1.0,0.0,0.0); /* nach "oben" schauen */
2442 glTranslated(-(k[which].p.x-0.5),-(k[which].p.y-0.25),-RADIUS);
2443 glDisable(GL_LIGHTING); /* Licht ausschalten und virtuelle Lichter in Buffer rendern */
2444 glMaterialfv(GL_FRONT,GL_DIFFUSE,MatWhiteDif);
2445 glColor3f(1.0,1.0,1.0);
2446 glBegin(GL_QUADS);
2447 glVertex3f(-0.4,-0.1,0.5);
2448 glVertex3f(-0.4,0.1,0.5);
2449 glVertex3f(-0.03,0.1,0.5);
2450 glVertex3f(-0.03,-0.1,0.5);
2451 glVertex3f(0.4,-0.1,0.5);
2452 glVertex3f(0.03,-0.1,0.5);
2453 glVertex3f(0.03,0.1,0.5);
2454 glVertex3f(0.4,0.1,0.5);
2455 glEnd();
2456 glEnable(GL_LIGHTING);
2457
2458 glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,0,0,0,0,0,cube_txt_size,cube_txt_size); /* Buffer -> Textur */
2459
2460 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2461 glLoadIdentity(); /* nach "unten" schauen, Drehung um 0 Grad... */
2462
2463 glTranslated(-(k[which].p.x-0.5),-(k[which].p.y-0.25),-RADIUS);
2464 position_lights();
2465
2466 glCallList(257);
2467
2468 gl_planar_shadows();
2469
2470 glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT,0,0,0,0,0,cube_txt_size,cube_txt_size); /* Buffer -> Textur */
2471
2472 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2473 glLoadIdentity();
2474
2475 glRotated(-90.0,1.0,0.0,0.0); /* nach "rechts" schauen */
2476 glTranslated(-(k[which].p.x-0.5),-(k[which].p.y-0.25),-RADIUS);
2477 position_lights();
2478
2479 glCallList(257);
2480 /* gl_planar_shadows(); */
2481 gl_plotballs(0,0);
2482 glCallList(259);
2483
2484 glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,0,0,0,0,0,cube_txt_size,cube_txt_size); /* Buffer -> Textur */
2485
2486 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2487 glLoadIdentity();
2488
2489 glRotated(90.0,1.0,0.0,0.0); /* nach "links" schauen */
2490 glTranslated(-(k[which].p.x-0.5),-(k[which].p.y-0.25),-RADIUS);
2491 position_lights();
2492
2493 glCallList(257);
2494 /* gl_planar_shadows(); */
2495 gl_plotballs(0,0);
2496 glCallList(259);
2497
2498 glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,0,0,0,0,0,cube_txt_size,cube_txt_size); /* Buffer -> Textur */
2499
2500 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2501 glLoadIdentity();
2502
2503 glRotated(180.0,1.0,0.0,0.0); /* nach "vorne" schauen */
2504 glRotated(-90.0,0.0,1.0,0.0);
2505 glTranslated(-(k[which].p.x-0.5),-(k[which].p.y-0.25),-RADIUS);
2506 position_lights();
2507
2508 glCallList(257);
2509 /* gl_planar_shadows(); */
2510 gl_plotballs(0,0);
2511 glCallList(259);
2512
2513 glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,0,0,0,0,0,cube_txt_size,cube_txt_size); /* Buffer -> Textur */
2514
2515 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2516 glLoadIdentity();
2517
2518 glRotated(180,1.0,0.0,0.0); /* nach "hinten" schauen */
2519 glRotated(90.0,0.0,1.0,0.0);
2520 glTranslated(-(k[which].p.x-0.5),-(k[which].p.y-0.25),-RADIUS);
2521 position_lights();
2522
2523 glCallList(257);
2524 /* gl_planar_shadows(); */
2525 gl_plotballs(0,0);
2526 glCallList(259);
2527
2528 glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,0,0,0,0,0,cube_txt_size,cube_txt_size); /* Buffer -> Textur */
2529
2530 glMatrixMode(GL_PROJECTION); /* Perspektive wieder zur�ckdrehen */
2531 glPopMatrix();
2532 glViewport(0,0,SCREENRESX, SCREENRESY);
2533 glMatrixMode(GL_MODELVIEW);
2534 glPopMatrix();
2535 }
2536
2537 #define stencilrun 2
2538 #define stencilstep 45
gl_plotall(int paintall)2539 void gl_plotall( int paintall ) /* ruft die andern plot-Funktionen auf */
2540 {
2541 int l,m,n;
2542
2543 if( ball_env_map == 1 )
2544 {
2545 /* cube-maps updaten */
2546 for(l=WHITE;l<BALLS;l++) create_cubemaps(l);
2547 }
2548
2549 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Buffer l�schen */
2550
2551 glMatrixMode(GL_MODELVIEW); /* Am Anfang einmal MODELVIEW initialisieren */
2552 glLoadIdentity();
2553
2554 glTranslated(startx,starty,startz); /* "Kamera" verschieben und rotieren */
2555 glRotated(angx,1.0,0.0,0.0);
2556 glRotated(angy,0.0,1.0,0.0);
2557 glRotated(angz,0.0,0.0,1.0);
2558 glTranslated(transx,transy,transz);
2559
2560 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition[0]); /* Licht positionieren */
2561 glLightfv(GL_LIGHT2, GL_POSITION,LightPosition[1]);
2562
2563 glEnable(GL_LIGHTING);
2564 glDisable(GL_BLEND);
2565
2566 if( shadows < STENCIL_SHADOWS )
2567 {
2568 /*************************************************************************************/
2569 /* ersten Teil des Tisches malen. Muss gemalt werden, BEVOR die planaren Schatten */
2570 /* der Kugeln gemalt werden, da dabei dann der Z-Buffer ausgeschaltet ist */
2571 /*************************************************************************************/
2572
2573 glCallList(257); /* Tischtuch, Rundung an Taschenkanten, Bandenschatten */
2574
2575 /* planare Schatten malen? */
2576 if( display_textures && shadows == PLANAR_SHADOWS ) gl_planar_shadows();
2577
2578 /* Kugeln malen */
2579 if( display_textures )
2580 {
2581 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular);
2582 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
2583 }
2584
2585 gl_plotballs(shadows,1);
2586
2587 /* zweiter Teil des Tisches (Aufbauten) */
2588 glCallList(258); /* Banden, Taschen+Gummi- und Metallverkleidung, Rand, Unterseite */
2589 glCallList(259); /* Banden, Taschen+Gummi- und Metallverkleidung, Rand, Unterseite */
2590 }
2591 else /* if shadows == STENCIL_SHADOWS */
2592 {
2593 if( shadows == STENCIL_SHADOWS2 )
2594 {
2595 glLightfv(GL_LIGHT1, GL_SPECULAR, LightZero );
2596 glLightfv(GL_LIGHT2, GL_SPECULAR, LightZero );
2597 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightZero);
2598 glLightfv(GL_LIGHT2, GL_DIFFUSE, LightZero);
2599 glLightfv(GL_LIGHT1, GL_AMBIENT, LightZero);
2600 glLightfv(GL_LIGHT2, GL_AMBIENT, LightZero);
2601
2602 glCallList(257); /* Tischtuch, Rundung an Taschenkanten, Bandenschatten */
2603 gl_plotballs( 4,1 ); /* Kugeln malen ohne specular light usw. */
2604 glCallList(258); /* Banden,Taschen+Gummi- und Metallverkleidung,Rand,Unterseite */
2605 glCallList(259); /* Banden,Taschen+Gummi- und Metallverkleidung,Rand,Unterseite */
2606
2607 /* initshadow(LightPosition[0][0],LightPosition[0][1],LightPosition[0][2]); */
2608 /* glDisable(GL_CULL_FACE); */
2609 /* gl_plotshadow(); */
2610 /* glEnable(GL_CULL_FACE); */
2611
2612 /* initshadow(LightPosition[1][0],LightPosition[1][1],LightPosition[1][2]); */
2613 /* glDisable(GL_CULL_FACE); */
2614 /* gl_plotshadow(); */
2615 /* glEnable(GL_CULL_FACE); */
2616
2617 glLightfv(GL_LIGHT1, GL_AMBIENT, LightZero); /* ambientes Licht aus */
2618 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightZero); /* diffuses Licht an */
2619 glLightfv(GL_LIGHT2, GL_AMBIENT, LightZero); /* ambientes Licht aus */
2620 glLightfv(GL_LIGHT2, GL_DIFFUSE, LightZero); /* diffuses Licht an */
2621 }
2622 else
2623 {
2624 glCallList(257); /* Tischtuch, Rundung an Taschenkanten, Bandenschatten */
2625 gl_plotballs( 4,1 ); /* Kugeln malen ohne specular light usw. */
2626 glCallList(258); /* Banden,Taschen+Gummi- und Metallverkleidung,Rand,Unterseite */
2627 glCallList(259); /* Banden,Taschen+Gummi- und Metallverkleidung,Rand,Unterseite */
2628 }
2629
2630 l=0;
2631 m=0;
2632 /* for(l=0;l<=5;l++) */
2633 /* for(m=1;m<=(l+1)*(l+1);m++) */
2634 for(n=0;n<2;n++) /* Schleife �ber die beiden Lichtquellen */
2635 {
2636 double r = (double)l*0.01;
2637 double x = r * cos(((double)m/(l*l+1)*360.0)*M_PI/180.0);
2638 double y = r * sin(((double)m/(l*l+1)*360.0)*M_PI/180.0);
2639 if( n == 0 ) { glEnable(GL_LIGHT1); glDisable(GL_LIGHT2);}
2640 else if( n == 1 ) { glEnable(GL_LIGHT2); glDisable(GL_LIGHT1);}
2641
2642 glClear(GL_STENCIL_BUFFER_BIT);
2643
2644 initshadow(LightPosition[n][0]+x, LightPosition[n][1]+y, LightPosition[n][2]);
2645
2646 glDisable( GL_LIGHTING ); /* Licht aus */
2647 glDisable( GL_BLEND ); /* Blending aus */
2648
2649 glColorMask(0,0,0,0); /* bedeutet, dass kein Farb-Bit im Framebuffer �berschrieben
2650 werden kann */
2651
2652 glDepthMask(0); /* 0 bedeutet: in den Z-Buffer kann nicht reingeschrieben werden!
2653 andere Werte: schreiben ist m�glich */
2654
2655 glDepthFunc( GL_LEQUAL ); /* aktuelles "Fragment" (Pixel) besteht nur, wenn es kleinere
2656 z_W-Wert hat als das im Buffer hat... -- je nachdem ob der
2657 z-Buffer-Test fehlschl�gt oder nicht, k�nnen bei der Stencil-Op
2658 entsprechende Flags gesetzt werden !*/
2659
2660 glEnable( GL_STENCIL_TEST ); /* Stencil-Buffer Test anschalten */
2661
2662 glStencilFunc( GL_ALWAYS, 0, ~0); /* glStencilFunc(func,ref,mask): ref ist der Referenzwert,
2663 mask wird verANDed mit dem Refernzwert und dem im Buffer
2664 gespeicherten Wert, ALWAYS: Stencil-Test wird immer
2665 "bestanden", d.h. alle Pixel werden "durchgelassen" */
2666
2667 glStencilMask(~0); /* was ist ~0? jedenfalls: Stencil Buffer beschreibbar machen! */
2668
2669 /*********************************************************/
2670 /* Schatteneintritte malen und z�hlen */
2671 /*********************************************************/
2672
2673 glCullFace(GL_BACK); /* nur vordere Seiten malen */
2674
2675 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); /* Ergebnisse des Stencil-Tests egal, bei bestandenem z-Buffer-Test
2676 wird das aktuelle Byte im Stencil-Buffer um eins erh�ht,
2677 z-Test nicht best.: egal */
2678
2679 gl_plotshadow(); /* R�ckseiten des Schattenvolumens malen */
2680
2681 /*********************************************************/
2682 /* Schattenaustritte malen und z�hlen */
2683 /*********************************************************/
2684
2685 glCullFace(GL_FRONT); /* nur hintere Seiten malen */
2686
2687 glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); /* Ergebnisse des Stencil-Tests egal, bei bestandenem z-Buffer-Test
2688 wird das aktuelle Byte im Stencil-Buffer um eins erniedrigt,
2689 z-Test nicht best.: egal */
2690
2691 gl_plotshadow(); /* Vorderseiten des Schattenvolumens malen */
2692
2693 /*********************************************************/
2694 /* nochmal Objecte mit angeschalteten Stencil-Test malen */
2695 /*********************************************************/
2696 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2697
2698 glColorMask(1,1,1,1); /* Framebuffer wieder beschreibbar */
2699 glDepthMask(1); /* z-Buffer beschreiben ist wieder m�glich, warum hier schon? */
2700
2701 if( shadows == STENCIL_SHADOWS2 )
2702 {
2703 glStencilFunc(GL_EQUAL, 0, ~0); /* Stencil Test wird nur dann bestanden, wenn Buffer-Wert == 0 */
2704 glEnable(GL_LIGHTING); /* Licht an */
2705 if( n == 0 )
2706 {
2707 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse_multi); /* diffuses Licht "hell" an */
2708 glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular_multi); /* specular Light an */
2709 }
2710 else if( n == 1 )
2711 {
2712 glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse_multi); /* diffuses Licht "hell" an */
2713 glLightfv(GL_LIGHT2, GL_SPECULAR, LightSpecular_multi); /* specular Light an */
2714 }
2715 glCullFace(GL_BACK); /* f�r die komplette Szene nochmal nur die nach vorne geneigten
2716 Polygone malen (schneller) */
2717 glEnable(GL_BLEND);
2718
2719 glCallList(257); /* Tischtuch, Rundung an Taschenkanten, Bandenschatten */
2720 gl_plotballs( STENCIL_SHADOWS,1 ); /* Kugeln malen ohne specular light usw. */
2721 glCallList(258); /* Banden,Taschen+Gummi- und Metallverkleidung,Rand,Unterseite */
2722 glCallList(259); /* Banden,Taschen+Gummi- und Metallverkleidung,Rand,Unterseite */
2723 }
2724 else
2725 {
2726 glStencilFunc(GL_NOTEQUAL, 0, ~0); /* Stencil Test wird nur dann bestanden, wenn Buffer-Wert != 0 */
2727
2728 glDisable(GL_LIGHTING);
2729 glEnable(GL_BLEND);
2730 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2731 /* glColor4f(0.0,0.0,0.0,0.2/(60.0)); */ /* 60, falls die beiden for-Schleife oben unkommentiert sind ... */
2732 glColor4f(0.0,0.0,0.0,0.1);
2733
2734 glMatrixMode(GL_PROJECTION); /* um alpha-geblendetes Polygon zu malen, wird zuerst Parallel- */
2735 glPushMatrix(); /* projektion angeschaltet und danach eben ein Polygon �ber den */
2736 glLoadIdentity(); /* kompletten Bildschirm gemalt. Durch den Stencil-Test */
2737 glOrtho(0,0,1,1,0,1); /* wird effektiv nur in beschatteten Regionen gemalt */
2738 glMatrixMode(GL_MODELVIEW);
2739 glPushMatrix();
2740 glLoadIdentity();
2741
2742 glDisable(GL_DEPTH_TEST);
2743
2744 glBegin(GL_QUADS);
2745 glVertex2f(-1,-1);
2746 glVertex2f(-1,1);
2747 glVertex2f(1,1);
2748 glVertex2f(1,-1);
2749 glEnd();
2750 glEnable(GL_DEPTH_TEST);
2751
2752 glMatrixMode(GL_PROJECTION);
2753 glPopMatrix();
2754 glMatrixMode(GL_MODELVIEW);
2755 glPopMatrix();
2756 }
2757
2758 glDisable(GL_BLEND);
2759 glDisable(GL_STENCIL_TEST); /* Stencil-Test wieder ausschalten */
2760 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2761 }
2762
2763 glEnable(GL_LIGHT1);
2764 glEnable(GL_LIGHT2);
2765 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse1);
2766 glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2);
2767 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightSpecular);
2768 glLightfv(GL_LIGHT2, GL_DIFFUSE, LightSpecular);
2769 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
2770 glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient);
2771 glMaterialf(GL_FRONT, GL_SHININESS, MatShn);
2772 }
2773
2774 /* aktuellen Spieler und zu spielende Kugel-"Art" malen */
2775 gl_plotplayer();
2776
2777 if( timer() < err2_endtime ) gl_print_err2();
2778 if( timer() < foul_endtime ) gl_print_foul();
2779
2780 if( showfps ) gl_plotfps();
2781
2782 if( paintall != -1 ) SDL_GL_SwapBuffers();
2783 }
2784
2785 /* berechnet die Rotationsmatrix f�r die Kugeln */
calc_rotation(int n)2786 void calc_rotation(int n)
2787 {
2788 double angle = sqrt( k[n].rot.x*k[n].rot.x + k[n].rot.y*k[n].rot.y /* + k[n].rot.z*k[n].rot.z */ );
2789 glPushMatrix();
2790 glLoadIdentity();
2791 glRotated( angle, k[n].rot.x, k[n].rot.y, /* k[n].rot.z */ 0.0 );
2792 glMultMatrixd(k[n].mrot);
2793 k[n].rot.x = 0.0;
2794 k[n].rot.y = 0.0;
2795 k[n].rot.z = 0.0;
2796 glGetDoublev(GL_MODELVIEW_MATRIX,k[n].mrot);
2797 glPopMatrix();
2798 }
2799
calc_rotation_inkl_z(int n)2800 void calc_rotation_inkl_z(int n)
2801 {
2802 double angle = sqrt( k[n].rot.x*k[n].rot.x + k[n].rot.y*k[n].rot.y + k[n].rot.z*k[n].rot.z );
2803 glPushMatrix();
2804 glLoadIdentity();
2805 glRotated( angle, k[n].rot.x, k[n].rot.y, k[n].rot.z );
2806 glMultMatrixd(k[n].mrot);
2807 k[n].rot.x = 0.0;
2808 k[n].rot.y = 0.0;
2809 k[n].rot.z = 0.0;
2810 glGetDoublev(GL_MODELVIEW_MATRIX,k[n].mrot);
2811 glPopMatrix();
2812 }
2813
2814 /* Einheitsmatrix f�r Kugel[n] erzeugen */
clear_rotation_matrix(int n)2815 void clear_rotation_matrix(int n) /* wird nur zum Initilisieren ben�tigt, nicht geschwindigkeitsrelevant */
2816 {
2817 int i;
2818 for(i=0;i<16;i++) k[n].mrot[i] = (i % 5 ? 0 : 1);
2819 }
2820
gl_move_table(double x,double y,double z,double sx,double sy,double sz,double step,double tx,double ty,double tz)2821 void gl_move_table(double x, double y, double z, double sx, double sy, double sz, double step,
2822 double tx, double ty, double tz)
2823 {
2824 double stepx, stepy, stepz, stepstartx, stepstarty, stepstartz, steptransx, steptransy, steptransz;
2825 int i;
2826 struct timeval tp_start,tp_cur;
2827 double time_cur, time_start;
2828
2829 angx = (double)((int)(angx+0.5) % 360); /* bissle unh�bsch, aber was solls ;-) */
2830 angy = (double)((int)(angy+0.5) % 360); /* vermeidet jetzt jedenfalls Mehrfachdrehungen */
2831 angz = (double)((int)(angz+0.5) % 360);
2832 if( angx > 180.0 ) angx -= 360.0;
2833 if( angy > 180.0 ) angy -= 360.0;
2834 if( angz > 180.0 ) angz -= 360.0;
2835 if( angx < -180.0 ) angx += 360.0;
2836 if( angy < -180.0 ) angy += 360.0;
2837 if( angz < -180.0 ) angz += 360.0;
2838 if( x > 180.0 ) x -= 360.0;
2839 if( y > 180.0 ) y -= 360.0;
2840 if( z > 180.0 ) z -= 360.0;
2841 if( x < -180.0 ) x += 360.0;
2842 if( y < -180.0 ) y += 360.0;
2843 if( z < -180.0 ) z += 360.0;
2844 oldang.x = angx;
2845 oldang.y = angy;
2846 oldang.z = angz;
2847 oldstart.x = startx;
2848 oldstart.y = starty;
2849 oldstart.z = startz;
2850 oldtrans.x = transx;
2851 oldtrans.y = transy;
2852 oldtrans.z = transz;
2853 /* Abfrage, ob angx-x > 180 oder < -180 */
2854 stepx = (angx - x)/step;
2855 stepy = (angy - y)/step;
2856 stepz = (angz - z)/step;
2857 stepstartx = (startx - sx)/step;
2858 stepstarty = (starty - sy)/step;
2859 stepstartz = (startz - sz)/step;
2860 steptransx = (transx - tx)/step;
2861 steptransy = (transy - ty)/step;
2862 steptransz = (transz - tz)/step;
2863 init_timer();
2864
2865 for( i=0;i<(int)step;i++ )
2866 {
2867 angx -= stepx;
2868 angy -= stepy;
2869 angz -= stepz;
2870 startx -= stepstartx;
2871 starty -= stepstarty;
2872 startz -= stepstartz;
2873 transx -= steptransx;
2874 transy -= steptransy;
2875 transz -= steptransz;
2876 gettimeofday(&tp_start,NULL);
2877 time_start = tp_start.tv_sec * 1000000 + tp_start.tv_usec;
2878 gl_plotall(1);
2879 gettimeofday(&tp_cur,NULL);
2880 time_cur = tp_cur.tv_sec * 1000000 + tp_cur.tv_usec;
2881
2882 if( time_cur - time_start < 20000 ) SDL_Delay(20+(time_cur - time_start)/1000);
2883 }
2884 angx=x; angy=y; angz=z;
2885 startx=sx; starty=sy; startz=sz;
2886 transx = tx; transy = ty; transz = tz;
2887 gl_plotall(1);
2888 }
2889
glPrintCentered(int y,char * out,int charset,float r,float g,float b,float alpha,float scale)2890 void glPrintCentered(int y, char *out, int charset, float r, float g, float b, float alpha, float scale)
2891 {
2892 glPrint(1024/2 - strlen(out)*1024/132*scale,y,out,charset,r,g,b,alpha,scale);
2893 }
2894
title_screen(void)2895 void title_screen( void )
2896 {
2897 long ende = 0, pressed=0;
2898 double dummy;
2899 char out[80];
2900 struct timeval tp_start,tp_cur;
2901 Uint8 *keys;
2902 SDL_Event event;
2903 Uint8 buttons;
2904 frames_per_second=0.0;
2905 angx = -60;
2906 startz = -1.3;
2907 k[WHITE].stat = (ONTABLE|MOVING);
2908 k[WHITE].p.x = 0.22; k[WHITE].p.y = 0.25;
2909 k[WHITE].p.z = RADIUS;
2910 glFogf(GL_FOG_DENSITY, 0.9);
2911 angz=180.0;
2912 do
2913 {
2914 gettimeofday(&tp_start,NULL);
2915 gl_plotall(-1);
2916 glPrintCentered(768/3*2.0,"Another Pool GL",0,0.7,0.7,1.0,1.0,4.0);
2917 sprintf(out,"Version %s - %s",VERSION, DATE);
2918 glPrintCentered(768/3*2.0-30,out,0,0.7,0.7,1.0,1.0,sqrt(2.0));
2919 if( SCREENRESX > 600 )
2920 {
2921 glPrintCentered(768/3*2.4,";-) ",0,0.7,0.7,1.0,1.0,6.0);
2922 glPrintCentered(768/3*2.0-60,"(c) 1995,2002,2003,2005 by Gerrit Jahn",0,0.7,0.7,1.0,1.0,1.0);
2923 glPrintCentered(768/3*2.0-90,"http://www.planetjahn.de/apool",0,0.7,0.7,1.0,1.0,1.0);
2924 }
2925 msg("press left mouse button or SPACE to start ApoolGL...");
2926 SDL_GL_SwapBuffers();
2927
2928 gettimeofday(&tp_cur,NULL);
2929 dummy = (tp_cur.tv_usec + tp_cur.tv_sec * 1000000 - tp_start.tv_usec - tp_start.tv_sec * 1000000);
2930 if( dummy > 0 )
2931 {
2932 frames_per_second = 19.0*frames_per_second + 1000000.0 / (double)dummy;
2933 frames_per_second /= 20.0;
2934 }
2935 else frames_per_second = 1000.0;
2936 angz += 20.0/1000000.0 * dummy;
2937 if( angz > 360.0 ) angz -= 360.0;
2938 SDL_PollEvent(&event);
2939 keys = SDL_GetKeyState(NULL);
2940 buttons = SDL_GetRelativeMouseState(NULL, NULL);
2941 if( keys[SDLK_SPACE] ) ende = 1;
2942 if( keys[SDLK_ESCAPE] ) stop_it();
2943 if( buttons & SDL_BUTTON(1) ) pressed = 1;
2944 if( pressed && !( buttons & SDL_BUTTON(1) ) ) ende = 1;
2945 }
2946 while( !ende );
2947 glFogf(GL_FOG_DENSITY, 0.5);
2948
2949 k[WHITE].stat = DELETED;
2950 }
2951