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