1 /* billard.c
2 **
3 **    code for positioning the balls
4 **    Copyright (C) 2001  Florian Berger
5 **    Email: harpin_floh@yahoo.de, florian.berger@jk.uni-linz.ac.at
6 **
7 **    This program is free software; you can redistribute it and/or modify
8 **    it under the terms of the GNU General Public License Version 2 as
9 **    published by the Free Software Foundation;
10 **
11 **    This program is distributed in the hope that it will be useful,
12 **    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 **    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 **    GNU General Public License for more details.
15 **
16 **    You should have received a copy of the GNU General Public License
17 **    along with this program; if not, write to the Free Software
18 **    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 */
21 
22 #define BILLARD_C
23 #include "billard.h"
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <math.h>
27 
28 
29 void (*create_scene)( BallsType * balls ) = create_8ball_scene;
30 void (*create_walls)( BordersType * walls ) = create_6hole_walls;
31 void * (*billard_malloc)( size_t size ) = malloc;
32 void (*billard_free)( void * ptr ) = free;
33 
setfunc_create_scene(void (* func)(BallsType * balls))34 void setfunc_create_scene( void (*func)( BallsType * balls ) )
35 {
36     create_scene=func;
37 }
38 
39 
setfunc_create_walls(void (* func)(BordersType * walls))40 void setfunc_create_walls( void (*func)( BordersType * walls ) )
41 {
42     create_walls=func;
43 }
44 
45 
setfunc_malloc_free(void * (* func_malloc)(size_t size),void (* func_free)(void * ptr))46 void setfunc_malloc_free( void * (*func_malloc)( size_t size ), void (*func_free)( void * ptr ) )
47 {
48     billard_malloc = func_malloc;
49     billard_free   = func_free;
50 }
51 
52 
53 /* positions:            */
54 /* ==========            */
55 /*   11  12  13  14  15  */
56 /*     07  08  09  10    */
57 /*       04  05  06      */
58 /*         02  03        */
59 /*           01          */
60 
place8ballnrs(BallsType * balls)61 void place8ballnrs( BallsType * balls )
62 {
63     int i,j,act;
64     int ok=1;
65 
66     do{
67         for(i=0;i<balls->nr;i++){
68             if(i==0){
69                 balls->ball[i].nr=0;
70             }else if(i==5){
71                 balls->ball[i].nr=8;
72             }else{
73                 int ok;
74                 act = rand() % balls->nr;
75                 do {
76                     ok=1;
77                     act = (act+1) % balls->nr;
78                     DPRINTF("   trying %d\n",act);
79                     for(j=0;j<i;j++){
80                         if( act==balls->ball[j].nr ){ ok=0; break; }
81                     }
82                     if( act == 8 || act == 0 ) ok=0;
83                 } while(!ok);
84                 balls->ball[i].nr=act;
85             }
86             DPRINTF("i=%d: ball#=%d\n",i,balls->ball[i].nr);
87         }
88     }while(!ok);
89     for(i=0;i<balls->nr;i++){
90         DPRINTF("i=%d: ball#=%d\n",i,balls->ball[i].nr);
91     }
92 }
93 
94 
create_6hole_walls(BordersType * walls)95 void create_6hole_walls( BordersType * walls )
96 {
97     int i;
98 
99     /* borders */
100 #ifdef USE_ADV_BORDER
101     /* borders */
102 //    walls->nr=30;
103     walls->nr=32;
104     if( walls->border != NULL ) billard_free( walls->border );
105     walls->border = billard_malloc( sizeof(BorderType)*walls->nr );
106 
107     /* bonds */
108     walls->border[0].pnr = 3;
109     walls->border[0].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
110     walls->border[0].r2 = vec_xyz( +TABLE_W/2.0,              +HOLE2_W/2.0, 0.0 );
111     walls->border[0].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
112     walls->border[0].n  = vec_xyz( -1.0, 0.0, 0.0 );
113 
114     walls->border[1].pnr = 3;
115     walls->border[1].r1 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
116     walls->border[1].r2 = vec_xyz( +TABLE_W/2.0,              -HOLE2_W/2.0, 0.0 );
117     walls->border[1].r3 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
118     walls->border[1].n  = vec_xyz( -1.0, 0.0, 0.0 );
119 
120     walls->border[2].pnr = 3;
121     walls->border[2].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
122     walls->border[2].r2 = vec_xyz( -TABLE_W/2.0,              +HOLE2_W/2.0, 0.0 );
123     walls->border[2].r3 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
124     walls->border[2].n  = vec_xyz( +1.0, 0.0, 0.0 );
125 
126     walls->border[3].pnr = 3;
127     walls->border[3].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
128     walls->border[3].r2 = vec_xyz( -TABLE_W/2.0,              -HOLE2_W/2.0, 0.0 );
129     walls->border[3].r3 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
130     walls->border[3].n  = vec_xyz( +1.0, 0.0, 0.0 );
131 
132     walls->border[4].pnr = 3;
133     walls->border[4].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
134     walls->border[4].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, 0.0 );
135     walls->border[4].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
136     walls->border[4].n  = vec_xyz( 0.0, -1.0, 0.0 );
137 
138     walls->border[5].pnr = 3;
139     walls->border[5].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
140     walls->border[5].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, 0.0 );
141     walls->border[5].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
142     walls->border[5].n  = vec_xyz( 0.0, +1.0, 0.0 );
143 
144     /* edges */
145     /* upper right */
146     walls->border[6].pnr = 2;
147     walls->border[6].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
148     walls->border[6].r2 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
149     walls->border[18].pnr = 3;
150     walls->border[18].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
151     walls->border[18].r2 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
152     walls->border[18].r3 = vec_xyz( +TABLE_W/2.0+1.0, +TABLE_L/2.0-HOLE1_W/SQR2+HOLE1_TAN, 0.0 );
153     walls->border[18].n  = vec_unit(vec_cross(vec_diff(walls->border[18].r2,walls->border[18].r1),vec_diff(walls->border[18].r3,walls->border[18].r1)));
154 
155     /* upper right */
156     walls->border[7].pnr = 2;
157     walls->border[7].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
158     walls->border[7].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
159     walls->border[19].pnr = 3;
160     walls->border[19].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
161     walls->border[19].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
162     walls->border[19].r3 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2+HOLE1_TAN, +TABLE_L/2.0+1.0, 0.0 );
163     walls->border[19].n  = vec_unit(vec_cross(vec_diff(walls->border[19].r1,walls->border[19].r2),vec_diff(walls->border[19].r3,walls->border[19].r1)));
164 
165     /* upper left */
166     walls->border[8].pnr = 2;
167     walls->border[8].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
168     walls->border[8].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
169     walls->border[20].pnr = 3;
170     walls->border[20].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
171     walls->border[20].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
172     walls->border[20].r3 = vec_xyz( -TABLE_W/2.0-1.0, +TABLE_L/2.0-HOLE1_W/SQR2+HOLE1_TAN, 0.0 );
173     walls->border[20].n  = vec_unit(vec_cross(vec_diff(walls->border[20].r1,walls->border[20].r2),vec_diff(walls->border[20].r3,walls->border[20].r1)));
174 
175     /* upper left */
176     walls->border[9].pnr = 2;
177     walls->border[9].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
178     walls->border[9].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
179     walls->border[21].pnr = 3;
180     walls->border[21].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
181     walls->border[21].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
182     walls->border[21].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2-HOLE1_TAN, +TABLE_L/2.0+1.0, 0.0 );
183     walls->border[21].n  = vec_unit(vec_cross(vec_diff(walls->border[21].r2,walls->border[21].r1),vec_diff(walls->border[21].r3,walls->border[21].r1)));
184 
185     /* lower right */
186     walls->border[10].pnr = 2;
187     walls->border[10].r1 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
188     walls->border[10].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
189     walls->border[22].pnr = 3;
190     walls->border[22].r1 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
191     walls->border[22].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
192     walls->border[22].r3 = vec_xyz( +TABLE_W/2.0+1.0, -TABLE_L/2.0+HOLE1_W/SQR2-HOLE1_TAN, 0.0 );
193     walls->border[22].n  = vec_unit(vec_cross(vec_diff(walls->border[22].r1,walls->border[22].r2),vec_diff(walls->border[22].r3,walls->border[22].r1)));
194 
195     /* lower right */
196     walls->border[11].pnr = 2;
197     walls->border[11].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
198     walls->border[11].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
199     walls->border[23].pnr = 3;
200     walls->border[23].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
201     walls->border[23].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
202     walls->border[23].r3 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2+HOLE1_TAN, -TABLE_L/2.0-1.0, 0.0 );
203     walls->border[23].n  = vec_unit(vec_cross(vec_diff(walls->border[23].r2,walls->border[23].r1),vec_diff(walls->border[23].r3,walls->border[23].r1)));
204 
205     /* lower left */
206     walls->border[12].pnr = 2;
207     walls->border[12].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
208     walls->border[12].r2 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
209     walls->border[24].pnr = 3;
210     walls->border[24].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
211     walls->border[24].r2 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
212     walls->border[24].r3 = vec_xyz( -TABLE_W/2.0-1.0, -TABLE_L/2.0+HOLE1_W/SQR2-HOLE1_TAN, 0.0 );
213     walls->border[24].n  = vec_unit(vec_cross(vec_diff(walls->border[24].r2,walls->border[24].r1),vec_diff(walls->border[24].r3,walls->border[24].r1)));
214 
215     /* lower left */
216     walls->border[13].pnr = 2;
217     walls->border[13].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
218     walls->border[13].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
219     walls->border[25].pnr = 3;
220     walls->border[25].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
221     walls->border[25].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
222     walls->border[25].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2-HOLE1_TAN, -TABLE_L/2.0-1.0, 0.0 );
223     walls->border[25].n  = vec_unit(vec_cross(vec_diff(walls->border[25].r1,walls->border[25].r2),vec_diff(walls->border[25].r3,walls->border[25].r1)));
224 
225     /* middle left */
226     walls->border[14].pnr = 2;
227     walls->border[14].r1 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
228     walls->border[14].r2 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
229     walls->border[26].pnr = 3;
230     walls->border[26].r1 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
231     walls->border[26].r2 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
232     walls->border[26].r3 = vec_xyz( -TABLE_W/2.0-1.0, HOLE2_W/2.0-HOLE2_TAN, 0.0 );
233     walls->border[26].n  = vec_unit(vec_cross(vec_diff(walls->border[26].r2,walls->border[26].r1),vec_diff(walls->border[26].r3,walls->border[26].r1)));
234 
235     /* middle left */
236     walls->border[15].pnr = 2;
237     walls->border[15].r1 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
238     walls->border[15].r2 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
239     walls->border[27].pnr = 3;
240     walls->border[27].r1 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
241     walls->border[27].r2 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
242     walls->border[27].r3 = vec_xyz( -TABLE_W/2.0-1.0, -HOLE2_W/2.0+HOLE2_TAN, 0.0 );
243     walls->border[27].n  = vec_unit(vec_cross(vec_diff(walls->border[27].r1,walls->border[27].r2),vec_diff(walls->border[27].r3,walls->border[27].r1)));
244 
245     /* middle right */
246     walls->border[16].pnr = 2;
247     walls->border[16].r1 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
248     walls->border[16].r2 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
249     walls->border[28].pnr = 3;
250     walls->border[28].r1 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
251     walls->border[28].r2 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
252     walls->border[28].r3 = vec_xyz( +TABLE_W/2.0+1.0, HOLE2_W/2.0-HOLE2_TAN, 0.0 );
253     walls->border[28].n  = vec_unit(vec_cross(vec_diff(walls->border[28].r1,walls->border[28].r2),vec_diff(walls->border[28].r3,walls->border[28].r1)));
254 
255     /* middle right */
256     walls->border[17].pnr = 2;
257     walls->border[17].r1 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
258     walls->border[17].r2 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
259     walls->border[29].pnr = 3;
260     walls->border[29].r1 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
261     walls->border[29].r2 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
262     walls->border[29].r3 = vec_xyz( +TABLE_W/2.0+1.0, -HOLE2_W/2.0+HOLE2_TAN, 0.0 );
263     walls->border[29].n  = vec_unit(vec_cross(vec_diff(walls->border[29].r2,walls->border[29].r1),vec_diff(walls->border[29].r3,walls->border[29].r1)));
264 
265     /* friction constants and loss factors */
266     for(i=0;i<walls->nr;i++){
267         walls->border[i].mu          = 0.1;
268         walls->border[i].loss0       = 0.2;
269         walls->border[i].loss_max    = 0.5;
270         walls->border[i].loss_wspeed = 4.0;  /* [m/s] */
271     }
272 
273     /* table surface */
274 #define TABLE_W2 (TABLE_W-BALL_D*0.9)
275 #define TABLE_L2 (TABLE_L-BALL_D*0.9)
276     walls->border[30].pnr = 3;
277     walls->border[30].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
278     walls->border[30].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
279     walls->border[30].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
280     walls->border[30].n  = vec_xyz( 0.0, 0.0, 1.0 );
281 
282     walls->border[31].pnr = 3;
283     walls->border[31].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
284     walls->border[31].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
285     walls->border[31].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
286     walls->border[31].n  = vec_xyz( 0.0, 0.0, 1.0 );
287 #undef TABLE_W2
288 #undef TABLE_L2
289 
290     walls->border[30].mu          = 0.2;
291     walls->border[30].loss0       = 0.6;
292     walls->border[30].loss_max    = 0.99;
293     walls->border[30].loss_wspeed = 1.5;
294     walls->border[31].mu          = 0.2;
295     walls->border[31].loss0       = 0.6;
296     walls->border[31].loss_max    = 0.99;
297     walls->border[31].loss_wspeed = 1.5;
298 
299 #else
300     /* borders */
301     walls->nr=4;
302     walls->border = billard_malloc(sizeof(BorderType)*walls->nr);
303     walls->border[0].r = vec_xyz( +TABLE_W/2.0, 0.0, 0.0 );
304     walls->border[0].n = vec_xyz( -1.0, 0.0, 0.0 );
305     walls->border[1].r = vec_xyz( -TABLE_W/2.0, 0.0, 0.0 );
306     walls->border[1].n = vec_xyz( +1.0, 0.0, 0.0 );
307     walls->border[2].r = vec_xyz( 0.0, +TABLE_L/2.0, 0.0 );
308     walls->border[2].n = vec_xyz( 0.0, -1.0, 0.0 );
309     walls->border[3].r = vec_xyz( 0.0, -TABLE_L/2.0, 0.0 );
310     walls->border[3].n = vec_xyz( 0.0, +1.0, 0.0 );
311 #endif
312 
313     /* holes */
314     walls->holenr = 6;
315     if( walls->hole != NULL ) billard_free( walls->hole );
316     walls->hole = billard_malloc(sizeof(HoleType)*walls->holenr);
317     /* middle right */
318     walls->hole[0].aim = vec_xyz( +TABLE_W/2.0-HOLE2_AIMOFFS, 0.0, 0.0 );
319     walls->hole[0].pos = vec_xyz( +TABLE_W/2.0+HOLE2_XYOFFS, 0.0, 0.0 );
320     walls->hole[0].r   = HOLE2_R;
321     /* middle left */
322     walls->hole[1].aim = vec_xyz( -TABLE_W/2.0+HOLE2_AIMOFFS, 0.0, 0.0 );
323     walls->hole[1].pos = vec_xyz( -TABLE_W/2.0-HOLE2_XYOFFS, 0.0, 0.0 );
324     walls->hole[1].r   = HOLE2_R;
325     /* upper right */
326     walls->hole[2].aim = vec_xyz( +TABLE_W/2.0-HOLE1_AIMOFFS, +TABLE_L/2.0-HOLE1_AIMOFFS, 0.0 );
327     walls->hole[2].pos = vec_xyz( +TABLE_W/2.0+HOLE1_XYOFFS, +TABLE_L/2.0+HOLE1_XYOFFS, 0.0 );
328     walls->hole[2].r   = HOLE1_R;
329     /* upper left */
330     walls->hole[3].aim = vec_xyz( -TABLE_W/2.0+HOLE1_AIMOFFS, +TABLE_L/2.0-HOLE1_AIMOFFS, 0.0 );
331     walls->hole[3].pos = vec_xyz( -TABLE_W/2.0-HOLE1_XYOFFS, +TABLE_L/2.0+HOLE1_XYOFFS, 0.0 );
332     walls->hole[3].r   = HOLE1_R;
333     /* lower left */
334     walls->hole[4].aim = vec_xyz( -TABLE_W/2.0+HOLE1_AIMOFFS, -TABLE_L/2.0-HOLE1_AIMOFFS, 0.0 );
335     walls->hole[4].pos = vec_xyz( -TABLE_W/2.0-HOLE1_XYOFFS, -TABLE_L/2.0-HOLE1_XYOFFS, 0.0 );
336     walls->hole[4].r   = HOLE1_R;
337     /* lower right */
338     walls->hole[5].aim = vec_xyz( +TABLE_W/2.0-HOLE1_AIMOFFS, -TABLE_L/2.0+HOLE1_AIMOFFS, 0.0 );
339     walls->hole[5].pos = vec_xyz( +TABLE_W/2.0+HOLE1_XYOFFS, -TABLE_L/2.0-HOLE1_XYOFFS, 0.0 );
340     walls->hole[5].r   = HOLE1_R;
341 }
342 
343 
create_6hole_walls_snooker(BordersType * walls)344 void create_6hole_walls_snooker( BordersType * walls )
345 {
346     int i;
347 
348     /* borders */
349 #ifdef USE_ADV_BORDER
350     /* borders */
351 //    walls->nr=30;
352     walls->nr=32;
353     if( walls->border != NULL ) billard_free( walls->border );
354     walls->border = billard_malloc( sizeof(BorderType)*walls->nr );
355 
356     /* bonds */
357     walls->border[0].pnr = 3;
358     walls->border[0].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
359     walls->border[0].r2 = vec_xyz( +TABLE_W/2.0,              +HOLE2_W/2.0, 0.0 );
360     walls->border[0].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
361     walls->border[0].n  = vec_xyz( -1.0, 0.0, 0.0 );
362 
363     walls->border[1].pnr = 3;
364     walls->border[1].r1 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
365     walls->border[1].r2 = vec_xyz( +TABLE_W/2.0,              -HOLE2_W/2.0, 0.0 );
366     walls->border[1].r3 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
367     walls->border[1].n  = vec_xyz( -1.0, 0.0, 0.0 );
368 
369     walls->border[2].pnr = 3;
370     walls->border[2].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
371     walls->border[2].r2 = vec_xyz( -TABLE_W/2.0,              +HOLE2_W/2.0, 0.0 );
372     walls->border[2].r3 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
373     walls->border[2].n  = vec_xyz( +1.0, 0.0, 0.0 );
374 
375     walls->border[3].pnr = 3;
376     walls->border[3].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
377     walls->border[3].r2 = vec_xyz( -TABLE_W/2.0,              -HOLE2_W/2.0, 0.0 );
378     walls->border[3].r3 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
379     walls->border[3].n  = vec_xyz( +1.0, 0.0, 0.0 );
380 
381     walls->border[4].pnr = 3;
382     walls->border[4].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
383     walls->border[4].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, 0.0 );
384     walls->border[4].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
385     walls->border[4].n  = vec_xyz( 0.0, -1.0, 0.0 );
386 
387     walls->border[5].pnr = 3;
388     walls->border[5].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
389     walls->border[5].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, 0.0 );
390     walls->border[5].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
391     walls->border[5].n  = vec_xyz( 0.0, +1.0, 0.0 );
392 
393     /* edges */
394     /* upper right */
395     walls->border[6].pnr = 2;
396     walls->border[6].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
397     walls->border[6].r2 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
398     walls->border[18].pnr = 3;
399     walls->border[18].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
400     walls->border[18].r2 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
401     walls->border[18].r3 = vec_xyz( +TABLE_W/2.0+1.0, +TABLE_L/2.0-HOLE1_W/SQR2+HOLE1_TAN, 0.0 );
402     walls->border[18].n  = vec_unit(vec_cross(vec_diff(walls->border[18].r2,walls->border[18].r1),vec_diff(walls->border[18].r3,walls->border[18].r1)));
403 
404     /* upper right */
405     walls->border[7].pnr = 2;
406     walls->border[7].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
407     walls->border[7].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
408     walls->border[19].pnr = 3;
409     walls->border[19].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
410     walls->border[19].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
411     walls->border[19].r3 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2+HOLE1_TAN, +TABLE_L/2.0+1.0, 0.0 );
412     walls->border[19].n  = vec_unit(vec_cross(vec_diff(walls->border[19].r1,walls->border[19].r2),vec_diff(walls->border[19].r3,walls->border[19].r1)));
413 
414     /* upper left */
415     walls->border[8].pnr = 2;
416     walls->border[8].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
417     walls->border[8].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
418     walls->border[20].pnr = 3;
419     walls->border[20].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, -BALL_D/2.0 );
420     walls->border[20].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0-HOLE1_W/SQR2, BALL_D/2.0 );
421     walls->border[20].r3 = vec_xyz( -TABLE_W/2.0-1.0, +TABLE_L/2.0-HOLE1_W/SQR2+HOLE1_TAN, 0.0 );
422     walls->border[20].n  = vec_unit(vec_cross(vec_diff(walls->border[20].r1,walls->border[20].r2),vec_diff(walls->border[20].r3,walls->border[20].r1)));
423 
424     /* upper left */
425     walls->border[9].pnr = 2;
426     walls->border[9].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
427     walls->border[9].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
428     walls->border[21].pnr = 3;
429     walls->border[21].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, -BALL_D/2.0 );
430     walls->border[21].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, +TABLE_L/2.0, BALL_D/2.0 );
431     walls->border[21].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2-HOLE1_TAN, +TABLE_L/2.0+1.0, 0.0 );
432     walls->border[21].n  = vec_unit(vec_cross(vec_diff(walls->border[21].r2,walls->border[21].r1),vec_diff(walls->border[21].r3,walls->border[21].r1)));
433 
434     /* lower right */
435     walls->border[10].pnr = 2;
436     walls->border[10].r1 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
437     walls->border[10].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
438     walls->border[22].pnr = 3;
439     walls->border[22].r1 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
440     walls->border[22].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
441     walls->border[22].r3 = vec_xyz( +TABLE_W/2.0+1.0, -TABLE_L/2.0+HOLE1_W/SQR2-HOLE1_TAN, 0.0 );
442     walls->border[22].n  = vec_unit(vec_cross(vec_diff(walls->border[22].r1,walls->border[22].r2),vec_diff(walls->border[22].r3,walls->border[22].r1)));
443 
444     /* lower right */
445     walls->border[11].pnr = 2;
446     walls->border[11].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
447     walls->border[11].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
448     walls->border[23].pnr = 3;
449     walls->border[23].r1 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
450     walls->border[23].r2 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
451     walls->border[23].r3 = vec_xyz( +TABLE_W/2.0-HOLE1_W/SQR2+HOLE1_TAN, -TABLE_L/2.0-1.0, 0.0 );
452     walls->border[23].n  = vec_unit(vec_cross(vec_diff(walls->border[23].r2,walls->border[23].r1),vec_diff(walls->border[23].r3,walls->border[23].r1)));
453 
454     /* lower left */
455     walls->border[12].pnr = 2;
456     walls->border[12].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
457     walls->border[12].r2 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
458     walls->border[24].pnr = 3;
459     walls->border[24].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, -BALL_D/2.0 );
460     walls->border[24].r2 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0+HOLE1_W/SQR2, BALL_D/2.0 );
461     walls->border[24].r3 = vec_xyz( -TABLE_W/2.0-1.0, -TABLE_L/2.0+HOLE1_W/SQR2-HOLE1_TAN, 0.0 );
462     walls->border[24].n  = vec_unit(vec_cross(vec_diff(walls->border[24].r2,walls->border[24].r1),vec_diff(walls->border[24].r3,walls->border[24].r1)));
463 
464     /* lower left */
465     walls->border[13].pnr = 2;
466     walls->border[13].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
467     walls->border[13].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
468     walls->border[25].pnr = 3;
469     walls->border[25].r1 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, -BALL_D/2.0 );
470     walls->border[25].r2 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2, -TABLE_L/2.0, BALL_D/2.0 );
471     walls->border[25].r3 = vec_xyz( -TABLE_W/2.0+HOLE1_W/SQR2-HOLE1_TAN, -TABLE_L/2.0-1.0, 0.0 );
472     walls->border[25].n  = vec_unit(vec_cross(vec_diff(walls->border[25].r1,walls->border[25].r2),vec_diff(walls->border[25].r3,walls->border[25].r1)));
473 
474     /* middle left */
475     walls->border[14].pnr = 2;
476     walls->border[14].r1 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
477     walls->border[14].r2 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
478     walls->border[26].pnr = 3;
479     walls->border[26].r1 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
480     walls->border[26].r2 = vec_xyz( -TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
481     walls->border[26].r3 = vec_xyz( -TABLE_W/2.0-1.0, HOLE2_W/2.0-HOLE2_TAN, 0.0 );
482     walls->border[26].n  = vec_unit(vec_cross(vec_diff(walls->border[26].r2,walls->border[26].r1),vec_diff(walls->border[26].r3,walls->border[26].r1)));
483 
484     /* middle left */
485     walls->border[15].pnr = 2;
486     walls->border[15].r1 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
487     walls->border[15].r2 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
488     walls->border[27].pnr = 3;
489     walls->border[27].r1 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
490     walls->border[27].r2 = vec_xyz( -TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
491     walls->border[27].r3 = vec_xyz( -TABLE_W/2.0-1.0, -HOLE2_W/2.0+HOLE2_TAN, 0.0 );
492     walls->border[27].n  = vec_unit(vec_cross(vec_diff(walls->border[27].r1,walls->border[27].r2),vec_diff(walls->border[27].r3,walls->border[27].r1)));
493 
494     /* middle right */
495     walls->border[16].pnr = 2;
496     walls->border[16].r1 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
497     walls->border[16].r2 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
498     walls->border[28].pnr = 3;
499     walls->border[28].r1 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, -BALL_D/2.0 );
500     walls->border[28].r2 = vec_xyz( +TABLE_W/2.0, HOLE2_W/2.0, BALL_D/2.0 );
501     walls->border[28].r3 = vec_xyz( +TABLE_W/2.0+1.0, HOLE2_W/2.0-HOLE2_TAN, 0.0 );
502     walls->border[28].n  = vec_unit(vec_cross(vec_diff(walls->border[28].r1,walls->border[28].r2),vec_diff(walls->border[28].r3,walls->border[28].r1)));
503 
504     /* middle right */
505     walls->border[17].pnr = 2;
506     walls->border[17].r1 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
507     walls->border[17].r2 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
508     walls->border[29].pnr = 3;
509     walls->border[29].r1 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, -BALL_D/2.0 );
510     walls->border[29].r2 = vec_xyz( +TABLE_W/2.0, -HOLE2_W/2.0, BALL_D/2.0 );
511     walls->border[29].r3 = vec_xyz( +TABLE_W/2.0+1.0, -HOLE2_W/2.0+HOLE2_TAN, 0.0 );
512     walls->border[29].n  = vec_unit(vec_cross(vec_diff(walls->border[29].r2,walls->border[29].r1),vec_diff(walls->border[29].r3,walls->border[29].r1)));
513 
514     /* friction constants and loss factors */
515     for(i=0;i<walls->nr;i++){
516         walls->border[i].mu          = 0.1;
517         walls->border[i].loss0       = 0.2;
518         walls->border[i].loss_max    = 0.5;
519         walls->border[i].loss_wspeed = 4.0;  /* [m/s] */
520     }
521 
522     /* table surface */
523 #define TABLE_W2 (TABLE_W-BALL_D*0.9)
524 #define TABLE_L2 (TABLE_L-BALL_D*0.9)
525     walls->border[30].pnr = 3;
526     walls->border[30].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
527     walls->border[30].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
528     walls->border[30].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
529     walls->border[30].n  = vec_xyz( 0.0, 0.0, 1.0 );
530 
531     walls->border[31].pnr = 3;
532     walls->border[31].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
533     walls->border[31].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
534     walls->border[31].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
535     walls->border[31].n  = vec_xyz( 0.0, 0.0, 1.0 );
536 #undef TABLE_W2
537 #undef TABLE_L2
538 
539     walls->border[30].mu          = 0.2;
540     walls->border[30].loss0       = 0.6;
541     walls->border[30].loss_max    = 0.99;
542     walls->border[30].loss_wspeed = 1.5;
543     walls->border[31].mu          = 0.2;
544     walls->border[31].loss0       = 0.6;
545     walls->border[31].loss_max    = 0.99;
546     walls->border[31].loss_wspeed = 1.5;
547 
548 #else
549     /* borders */
550     walls->nr=4;
551     walls->border = billard_malloc(sizeof(BorderType)*walls->nr);
552     walls->border[0].r = vec_xyz( +TABLE_W/2.0, 0.0, 0.0 );
553     walls->border[0].n = vec_xyz( -1.0, 0.0, 0.0 );
554     walls->border[1].r = vec_xyz( -TABLE_W/2.0, 0.0, 0.0 );
555     walls->border[1].n = vec_xyz( +1.0, 0.0, 0.0 );
556     walls->border[2].r = vec_xyz( 0.0, +TABLE_L/2.0, 0.0 );
557     walls->border[2].n = vec_xyz( 0.0, -1.0, 0.0 );
558     walls->border[3].r = vec_xyz( 0.0, -TABLE_L/2.0, 0.0 );
559     walls->border[3].n = vec_xyz( 0.0, +1.0, 0.0 );
560 #endif
561 
562     /* holes */
563     walls->holenr = 6;
564     if( walls->hole != NULL ) billard_free( walls->hole );
565     walls->hole = billard_malloc(sizeof(HoleType)*walls->holenr);
566     /* middle right */
567     walls->hole[0].aim = vec_xyz( +TABLE_W/2.0-HOLE2_AIMOFFS, 0.0, 0.0 );
568     walls->hole[0].pos = vec_xyz( +TABLE_W/2.0+HOLE2_XYOFFS, 0.0, 0.0 );
569     walls->hole[0].r   = HOLE2_R;
570     /* middle left */
571     walls->hole[1].aim = vec_xyz( -TABLE_W/2.0+HOLE2_AIMOFFS, 0.0, 0.0 );
572     walls->hole[1].pos = vec_xyz( -TABLE_W/2.0-HOLE2_XYOFFS, 0.0, 0.0 );
573     walls->hole[1].r   = HOLE2_R;
574     /* upper right */
575     walls->hole[2].aim = vec_xyz( +TABLE_W/2.0-HOLE1_AIMOFFS, +TABLE_L/2.0-HOLE1_AIMOFFS, 0.0 );
576     walls->hole[2].pos = vec_xyz( +TABLE_W/2.0+HOLE1_XYOFFS, +TABLE_L/2.0+HOLE1_XYOFFS, 0.0 );
577     walls->hole[2].r   = HOLE1_R;
578     /* upper left */
579     walls->hole[3].aim = vec_xyz( -TABLE_W/2.0+HOLE1_AIMOFFS, +TABLE_L/2.0-HOLE1_AIMOFFS, 0.0 );
580     walls->hole[3].pos = vec_xyz( -TABLE_W/2.0-HOLE1_XYOFFS, +TABLE_L/2.0+HOLE1_XYOFFS, 0.0 );
581     walls->hole[3].r   = HOLE1_R;
582     /* lower left */
583     walls->hole[4].aim = vec_xyz( -TABLE_W/2.0+HOLE1_AIMOFFS, -TABLE_L/2.0-HOLE1_AIMOFFS, 0.0 );
584     walls->hole[4].pos = vec_xyz( -TABLE_W/2.0-HOLE1_XYOFFS, -TABLE_L/2.0-HOLE1_XYOFFS, 0.0 );
585     walls->hole[4].r   = HOLE1_R;
586     /* lower right */
587     walls->hole[5].aim = vec_xyz( +TABLE_W/2.0-HOLE1_AIMOFFS, -TABLE_L/2.0+HOLE1_AIMOFFS, 0.0 );
588     walls->hole[5].pos = vec_xyz( +TABLE_W/2.0+HOLE1_XYOFFS, -TABLE_L/2.0-HOLE1_XYOFFS, 0.0 );
589     walls->hole[5].r   = HOLE1_R;
590 }
591 
592 
create_0hole_walls(BordersType * walls)593 void create_0hole_walls( BordersType * walls )
594 {
595     int i;
596 
597     /* borders */
598     walls->nr=6;
599     if( walls->border != NULL ) billard_free( walls->border );
600     walls->border = billard_malloc( sizeof(BorderType)*walls->nr );
601 
602     /* bonds */
603 /*    walls->border[0].pnr = 3;
604     walls->border[0].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0 );
605     walls->border[0].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, 0.0 );
606     walls->border[0].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, BALL_D/2.0 );
607     walls->border[0].n  = vec_xyz( -1.0, 0.0, 0.0 );
608 
609     walls->border[1].pnr = 3;
610     walls->border[1].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, BALL_D/2.0 );
611     walls->border[1].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, 0.0 );
612     walls->border[1].r3 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0 );
613     walls->border[1].n  = vec_xyz( +1.0, 0.0, 0.0 );
614 
615     walls->border[2].pnr = 3;
616     walls->border[2].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0 );
617     walls->border[2].r2 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, 0.0 );
618     walls->border[2].r3 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, BALL_D/2.0 );
619     walls->border[2].n  = vec_xyz( 0.0, -1.0, 0.0 );
620 
621     walls->border[3].pnr = 3;
622     walls->border[3].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0 );
623     walls->border[3].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, 0.0 );
624     walls->border[3].r3 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, BALL_D/2.0 );
625     walls->border[3].n  = vec_xyz( 0.0, +1.0, 0.0 );*/
626 
627     walls->border[0].pnr = 2;
628     walls->border[0].r1 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
629     walls->border[0].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
630 
631     walls->border[1].pnr = 2;
632     walls->border[1].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
633     walls->border[1].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
634 
635     walls->border[2].pnr = 2;
636     walls->border[2].r1 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
637     walls->border[2].r2 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
638 
639     walls->border[3].pnr = 2;
640     walls->border[3].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
641     walls->border[3].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, options_jump_shots ? 0.14*BALL_D : 0.0 );
642 
643     for(i=0;i<walls->nr;i++){
644         walls->border[i].mu          = 0.12;
645         walls->border[i].loss0       = 0.2;
646         walls->border[i].loss_max    = 0.5;
647         walls->border[i].loss_wspeed = 4.0;  /* [m/s] */
648     }
649 
650     /* table surface */
651     walls->border[4].pnr = 3;
652     walls->border[4].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
653     walls->border[4].r2 = vec_xyz( +TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
654     walls->border[4].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
655     walls->border[4].n  = vec_xyz( 0.0, 0.0, 1.0 );
656 
657     walls->border[5].pnr = 3;
658     walls->border[5].r1 = vec_xyz( -TABLE_W/2.0, -TABLE_L/2.0, -BALL_D/2.0-0.0001 );
659     walls->border[5].r3 = vec_xyz( +TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
660     walls->border[5].r2 = vec_xyz( -TABLE_W/2.0, +TABLE_L/2.0, -BALL_D/2.0-0.0001 );
661     walls->border[5].n  = vec_xyz( 0.0, 0.0, 1.0 );
662 
663     walls->border[4].mu          = 0.2;
664     walls->border[4].loss0       = 0.6;
665     walls->border[4].loss_max    = 0.9;
666     walls->border[4].loss_wspeed = 2.0;
667     walls->border[5].mu          = 0.2;
668     walls->border[5].loss0       = 0.6;
669     walls->border[5].loss_max    = 0.9;
670     walls->border[5].loss_wspeed = 2.0;
671 
672     /* no holes */
673     walls->holenr = 0;
674     if( walls->hole != NULL ) billard_free( walls->hole );
675     walls->hole = billard_malloc(sizeof(HoleType)*walls->holenr);
676 }
677 
678 
create_8ball_scene(BallsType * balls)679 void create_8ball_scene( BallsType * balls )
680 {
681     int i;
682     myvec dball1, dball2, vdummy;
683 //    double poserr=0.002;
684     double poserr=0.007;
685 
686     balls->gametype=GAME_8BALL;
687     /* balls */
688     balls->nr=16;
689     if( balls->ball != NULL ) billard_free( balls->ball );
690     balls->ball = billard_malloc(sizeof(BallType)*balls->nr);
691 
692     place8ballnrs(balls);
693 
694     for(i=0;i<balls->nr;i++){
695         balls->ball[i].m=BALL_M;
696         /* I_kugel = (m.r^2)2/5 = (m.d^2)/10 */
697         balls->ball[i].I=BALL_M*BALL_D*BALL_D/10.0/**0.01*/;
698         balls->ball[i].d=BALL_D;
699         balls->ball[i].v=vec_xyz(0.0,0.0,0.0);
700         balls->ball[i].w=vec_xyz(0.0,0.0,0.0);
701         balls->ball[i].b[0]=vec_unit(vec_xyz(rand(),rand(),rand()));
702         vdummy=vec_xyz(rand(),rand(),rand());
703         balls->ball[i].b[1]=vec_unit(vec_diff(vdummy,vec_proj(vdummy,balls->ball[i].b[0])));
704         balls->ball[i].b[2]=vec_cross(balls->ball[i].b[0],balls->ball[i].b[1]);
705         balls->ball[i].in_game=1;
706         balls->ball[i].in_hole=0;
707     }
708 
709     dball1=vec_scale( vec_xyz(-0.5, 0.5*sqrt(3.0), 0.0), (1.0+2.0*poserr)*BALL_D );
710     dball2=vec_scale( vec_xyz( 1.0,           0.0, 0.0), (1.0+2.0*poserr)*BALL_D );
711     /* white ball */
712     balls->ball[0].r = vec_xyz(0.0,-TABLE_L/4.0,0.0);
713 //    balls->ball[0].w = vec_xyz(-M_PI*5.0,0.0,-M_PI*5.0);
714     balls->ball[0].w = vec_xyz(0.0,0.0,0.0);
715     /* other balls */
716     balls->ball[ 1].r = vec_xyz(0.0,TABLE_L/4.0,0.0);
717     balls->ball[ 2].r = vec_add( balls->ball[ 1].r, dball1 );
718     balls->ball[ 3].r = vec_add( balls->ball[ 2].r, dball2 );
719     balls->ball[ 4].r = vec_add( balls->ball[ 2].r, dball1 );
720     balls->ball[ 5].r = vec_add( balls->ball[ 4].r, dball2 );
721     balls->ball[ 6].r = vec_add( balls->ball[ 5].r, dball2 );
722     balls->ball[ 7].r = vec_add( balls->ball[ 4].r, dball1 );
723     balls->ball[ 8].r = vec_add( balls->ball[ 7].r, dball2 );
724     balls->ball[ 9].r = vec_add( balls->ball[ 8].r, dball2 );
725     balls->ball[10].r = vec_add( balls->ball[ 9].r, dball2 );
726     balls->ball[11].r = vec_add( balls->ball[ 7].r, dball1 );
727     balls->ball[12].r = vec_add( balls->ball[11].r, dball2 );
728     balls->ball[13].r = vec_add( balls->ball[12].r, dball2 );
729     balls->ball[14].r = vec_add( balls->ball[13].r, dball2 );
730     balls->ball[15].r = vec_add( balls->ball[14].r, dball2 );
731 //    balls->ball[15].r = vec_xyz( 0, -TABLE_L/4, 0 );
732 
733     /* add randomness to init positions */
734     for( i=1 ; i<balls->nr ; i++ ){
735         double ang, ampl;
736         myvec verr;
737         ang  = (double)rand()/(double)RAND_MAX*2.0*M_PI;
738         DPRINTF("ball_placemet_err:   angle=%f    ",ang);
739         ampl = (double)rand()/(double)RAND_MAX*(poserr*0.95)*BALL_D;
740         DPRINTF("amplitude=%f\n",ampl);
741         verr = vec_scale( vec_xyz(cos(ang),sin(ang),0.0), (poserr*0.95)*BALL_D );
742         balls->ball[i].r = vec_add( balls->ball[i].r, verr );
743     }
744     for( i=1 ; i<balls->nr ; i++ ){
745         int j;
746         for( j=i+1 ; j<balls->nr ; j++ ){
747             if (vec_abs(vec_diff(balls->ball[i].r,balls->ball[j].r))/BALL_D<1.5){
748                 DPRINTF("BALLLDISR(%d,%d)=%f\n",balls->ball[i].nr,balls->ball[j].nr,vec_abs(vec_diff(balls->ball[i].r,balls->ball[j].r))/BALL_D);
749             }
750         }
751     }
752 
753     for( i=0 ; i<balls->nr ; i++ ){
754         balls->ball[i].path=0;
755         balls->ball[i].pathcnt=0;
756         balls->ball[i].pathsize=0;
757     }
758 
759 //    balls->ball[0].v=vec_xyz(1.5,2.0,0.0);
760     balls->ball[0].v=vec_xyz(0.0,0.0,0.0);
761 }
762 
place9ballnrs(BallsType * balls)763 void place9ballnrs( BallsType * balls )
764 {
765     int i;
766 
767     for(i=0;i<balls->nr;i++){
768         balls->ball[i].nr=i;
769     }
770 }
771 
772 
create_9ball_scene(BallsType * balls)773 void create_9ball_scene( BallsType * balls )
774 {
775     int i;
776     myvec dball1, dball2, vdummy;
777 
778     balls->gametype=GAME_9BALL;
779     /* balls */
780     balls->nr=10;
781     if( balls->ball != NULL ) billard_free( balls->ball );
782     balls->ball = billard_malloc(sizeof(BallType)*balls->nr);
783 
784     place9ballnrs(balls);
785 
786     for(i=0;i<balls->nr;i++){
787         balls->ball[i].m=BALL_M;
788         /* I_kugel = (m.r^2)2/5 = (m.d^2)/10 */
789         balls->ball[i].I=BALL_M*BALL_D*BALL_D/10.0/**0.01*/;
790         balls->ball[i].d=BALL_D;
791         balls->ball[i].v=vec_xyz(0.0,0.0,0.0);
792         balls->ball[i].w=vec_xyz(0.0,0.0,0.0);
793         balls->ball[i].b[0]=vec_unit(vec_xyz(rand(),rand(),rand()));
794         vdummy=vec_xyz(rand(),rand(),rand());
795         balls->ball[i].b[1]=vec_unit(vec_diff(vdummy,vec_proj(vdummy,balls->ball[i].b[0])));
796         balls->ball[i].b[2]=vec_cross(balls->ball[i].b[0],balls->ball[i].b[1]);
797         balls->ball[i].in_game=1;
798         balls->ball[i].in_hole=0;
799     }
800 
801     dball1=vec_scale(vec_xyz(-0.5*1.01, 0.5*sqrt(3.0)*1.01,0.0),BALL_D);
802     dball2=vec_scale(vec_xyz(+0.5*1.01, 0.5*sqrt(3.0)*1.01,0.0),BALL_D);
803     /* white ball */
804     balls->ball[0].r = vec_xyz(0.0,-TABLE_L/4.0,0.0);
805 //    balls->ball[0].w = vec_xyz(-M_PI*5.0,0.0,-M_PI*5.0);
806     balls->ball[0].w = vec_xyz(0.0,0.0,0.0);
807     /* other balls */
808     balls->ball[ 1].r = vec_xyz(0.0,TABLE_L/4.0,0.0);
809     balls->ball[ 2].r = vec_add( balls->ball[1].r, vec_scale(dball2,2.0) );
810     balls->ball[ 3].r = vec_add( balls->ball[2].r, vec_scale(dball1,2.0) );
811     balls->ball[ 4].r = vec_add( balls->ball[1].r, vec_scale(dball1,2.0) );
812     balls->ball[ 5].r = vec_add( balls->ball[1].r, dball1 );
813     balls->ball[ 6].r = vec_add( balls->ball[1].r, dball2 );
814     balls->ball[ 7].r = vec_add( balls->ball[2].r, dball1 );
815     balls->ball[ 8].r = vec_add( balls->ball[4].r, dball2 );
816     balls->ball[ 9].r = vec_add( balls->ball[1].r, vec_add(dball1,dball2) );
817 
818     /* add randomness to init positions */
819     for( i=1 ; i<balls->nr ; i++ ){
820         double ang, ampl;
821         myvec verr;
822         ang  = rand();
823         ang  = (double)rand()/(double)RAND_MAX*2.0*M_PI;
824         ampl = (double)rand()/(double)RAND_MAX*0.0049*BALL_D;
825         verr = vec_scale( vec_xyz(cos(ang),sin(ang),0.0), ampl );
826         balls->ball[i].r = vec_add( balls->ball[i].r, verr );
827     }
828 
829     for( i=0 ; i<balls->nr ; i++ ){
830         balls->ball[i].path=0;
831         balls->ball[i].pathcnt=0;
832         balls->ball[i].pathsize=0;
833     }
834 //    balls->ball[0].v=vec_xyz(1.5,2.0,0.0);
835     balls->ball[0].v=vec_xyz(0.0,0.0,0.0);
836 }
837 
838 
placecarambolballnrs(BallsType * balls)839 void placecarambolballnrs( BallsType * balls )
840 {
841     int i;
842 
843     for(i=0;i<balls->nr;i++){
844         balls->ball[i].nr=i;
845     }
846 }
847 
848 
create_carambol_scene(BallsType * balls)849 void create_carambol_scene( BallsType * balls )
850 {
851     int i;
852     myvec vdummy;
853 
854     balls->gametype=GAME_CARAMBOL;
855     /* balls */
856     balls->nr=3;
857     if( balls->ball != NULL ) billard_free( balls->ball );
858     balls->ball = billard_malloc(sizeof(BallType)*balls->nr);
859 
860     placecarambolballnrs(balls);
861 
862     for(i=0;i<balls->nr;i++){
863         balls->ball[i].nr=i;
864     }
865 
866     for(i=0;i<balls->nr;i++){
867         balls->ball[i].m=BALL_M;
868         /* I_kugel = (m.r^2)2/5 = (m.d^2)/10 */
869         balls->ball[i].I=BALL_M*BALL_D*BALL_D/10.0/**0.01*/;
870         balls->ball[i].d=BALL_D;
871         balls->ball[i].v=vec_xyz(0.0,0.0,0.0);
872         balls->ball[i].w=vec_xyz(0.0,0.0,0.0);
873         balls->ball[i].b[0]=vec_unit(vec_xyz(rand(),rand(),rand()));
874         vdummy=vec_xyz(rand(),rand(),rand());
875         balls->ball[i].b[1]=vec_unit(vec_diff(vdummy,vec_proj(vdummy,balls->ball[i].b[0])));
876         balls->ball[i].b[2]=vec_cross(balls->ball[i].b[0],balls->ball[i].b[1]);
877         balls->ball[i].in_game=1;
878         balls->ball[i].in_hole=0;
879     }
880 
881     /* white ball */
882     balls->ball[0].r = vec_xyz( TABLE_W/4.0, -TABLE_L/4.0, 0.0 );
883     balls->ball[1].r = vec_xyz(         0.0, -TABLE_L/4.0, 0.0 );
884     balls->ball[2].r = vec_xyz(         0.0, +TABLE_L/4.0, 0.0 );
885 
886     for( i=0 ; i<balls->nr ; i++ ){
887         balls->ball[i].path=0;
888         balls->ball[i].pathcnt=0;
889         balls->ball[i].pathsize=0;
890     }
891 }
892 
893 
placesnookerballnrs(BallsType * balls)894 void placesnookerballnrs( BallsType * balls )
895 {
896     int i;
897 
898 /*    for(i=0;i<8;i++){
899         balls->ball[i].nr=i;
900     }*/
901     for(i=0;i<balls->nr;i++){
902         balls->ball[i].nr=i;
903     }
904 }
905 
try_snooker_spot(BallsType * balls,struct Vect spot)906 int try_snooker_spot(BallsType *balls,struct Vect spot)
907 {
908    int i,available=1;
909    for(i=0;i<22;i++)
910    {
911       if(balls->ball[i].in_game && vec_abs(vec_diff(spot,balls->ball[i].r)) < (balls->ball[i].d) + 0.001)
912       {
913          available=0;
914       }
915    }
916    return available;
917 }
918 
919 #define TABLE_SCALE (TABLE_L/(3.571042))
spot_snooker_ball(BallsType * balls,int nr)920 void spot_snooker_ball(BallsType *balls,int nr)
921 {
922 
923     int i,found=0;
924     struct Vect spots[8];
925     spots[0]=vec_xyz(0.1,-TABLE_L/2+TABLE_SCALE*0.737,0.0);/*white*/
926     spots[2]=vec_xyz(TABLE_SCALE*0.292,-TABLE_L/2+TABLE_SCALE*0.737,0.0);/*yellow*/
927     spots[3]=vec_xyz(-TABLE_SCALE*0.292,-TABLE_L/2+TABLE_SCALE*0.737,0.0);/*green*/
928     spots[4]=vec_xyz(0.0,-TABLE_L/2+TABLE_SCALE*0.737,0.0);/*brown*/
929     spots[5]=vec_xyz(0.0,0.0,0.0);/*blue*/
930     spots[6]=vec_xyz(0.0,TABLE_L/4.0,0.0);/*pink*/
931     spots[7]=vec_xyz(0.0,TABLE_L/2-TABLE_SCALE*0.324,0.0);/*black*/
932 
933     balls->ball[nr].in_game=0;
934 
935     if(try_snooker_spot(balls,spots[nr]))
936     {
937        balls->ball[nr].r=spots[nr];
938        found=1;
939     }
940     else
941     {
942        i=7;
943        while(i>=2 && !found)
944        {
945           if(try_snooker_spot(balls,spots[i]))
946           {
947              balls->ball[nr].r=spots[i];
948              found=1;
949           }
950           i--;
951        }
952     }
953     if(!found)
954     {
955         struct Vect try=spots[nr];
956         while(!try_snooker_spot(balls,try))
957         {
958            try.y-=0.001;
959         }
960         balls->ball[nr].r=try;
961     }
962     balls->ball[nr].in_game=1;
963     balls->ball[nr].in_hole=0;
964     balls->ball[nr].v=vec_xyz(0.0,0.0,0.0);
965     balls->ball[nr].w=vec_xyz(0.0,0.0,0.0);
966 }
967 
create_snooker_scene(BallsType * balls)968 void create_snooker_scene( BallsType * balls )
969 {
970     int i;
971     myvec dball1, dball2, vdummy;
972 
973     balls->gametype=GAME_SNOOKER;
974     /* balls */
975     balls->nr=22;
976     if( balls->ball != NULL ) billard_free( balls->ball );
977     balls->ball = billard_malloc(sizeof(BallType)*balls->nr);
978 
979     placesnookerballnrs(balls);
980 
981     for(i=0;i<balls->nr;i++){
982         balls->ball[i].m=BALL_M;
983         /* I_kugel = (m.r^2)2/5 = (m.d^2)/10 */
984         balls->ball[i].I=BALL_M*BALL_D*BALL_D/10.0/**0.01*/;
985         balls->ball[i].d=BALL_D;
986         balls->ball[i].r = vec_xyz(TABLE_L*3,TABLE_L*3,0.0); /* get balls out of the way */
987         balls->ball[i].v=vec_xyz(0.0,0.0,0.0);
988         balls->ball[i].w=vec_xyz(0.0,0.0,0.0);
989         balls->ball[i].b[0]=vec_unit(vec_xyz(rand(),rand(),rand()));
990         vdummy=vec_xyz(rand(),rand(),rand());
991         balls->ball[i].b[1]=vec_unit(vec_diff(vdummy,vec_proj(vdummy,balls->ball[i].b[0])));
992         balls->ball[i].b[2]=vec_cross(balls->ball[i].b[0],balls->ball[i].b[1]);
993         balls->ball[i].in_game=1;
994         balls->ball[i].in_hole=0;
995     }
996 
997     dball1=vec_scale(vec_xyz(-0.5*1.01, 0.5*sqrt(3.0)*1.01,0.0),BALL_D);
998     dball2=vec_scale(vec_xyz( 1.01,      0.0,     0.0),BALL_D);
999     /* red balls */
1000     balls->ball[ 1].r = vec_xyz(0.0,TABLE_L/4.0+1.1*BALL_D,0.0);
1001     balls->ball[ 8].r = vec_add( balls->ball[ 1].r, dball1 );
1002     balls->ball[ 9].r = vec_add( balls->ball[ 8].r, dball2 );
1003     balls->ball[10].r = vec_add( balls->ball[ 8].r, dball1 );
1004     balls->ball[11].r = vec_add( balls->ball[10].r, dball2 );
1005     balls->ball[12].r = vec_add( balls->ball[11].r, dball2 );
1006     balls->ball[13].r = vec_add( balls->ball[10].r, dball1 );
1007     balls->ball[14].r = vec_add( balls->ball[13].r, dball2 );
1008     balls->ball[15].r = vec_add( balls->ball[14].r, dball2 );
1009     balls->ball[16].r = vec_add( balls->ball[15].r, dball2 );
1010     balls->ball[17].r = vec_add( balls->ball[13].r, dball1 );
1011     balls->ball[18].r = vec_add( balls->ball[17].r, dball2 );
1012     balls->ball[19].r = vec_add( balls->ball[18].r, dball2 );
1013     balls->ball[20].r = vec_add( balls->ball[19].r, dball2 );
1014     balls->ball[21].r = vec_add( balls->ball[20].r, dball2 );
1015 
1016     /* color balls */
1017     for(i=7;i>=2;i--)
1018     {
1019         spot_snooker_ball(balls,i);
1020     }
1021     /* white ball */
1022     spot_snooker_ball(balls,0);
1023 
1024     /* add randomness to init positions */
1025     for( i=1 ; i<balls->nr ; i++ ){
1026         double ang, ampl;
1027         myvec verr;
1028         ang  = (double)rand()/(double)RAND_MAX*2.0*M_PI;
1029         ampl = (double)rand()/(double)RAND_MAX*0.0049*BALL_D;
1030         verr = vec_scale( vec_xyz(cos(ang),sin(ang),0.0), ampl );
1031         balls->ball[i].r = vec_add( balls->ball[i].r, verr );
1032     }
1033 
1034     for( i=0 ; i<balls->nr ; i++ ){
1035         balls->ball[i].path=0;
1036         balls->ball[i].pathcnt=0;
1037         balls->ball[i].pathsize=0;
1038     }
1039 //    balls->ball[0].v=vec_xyz(1.5,2.0,0.0);
1040     balls->ball[0].v=vec_xyz(0.0,0.0,0.0);
1041 }
1042 
1043 
1044 
balls_in_game(BallsType * balls,int full_half)1045 int balls_in_game( BallsType * balls, int full_half )
1046 /* without white, 8 is neither full nor half */
1047 {
1048     int i;
1049     int nr=0;
1050     for(i=1;i<balls->nr;i++) {
1051         if( ( ( full_half==BALL_FULL && balls->ball[i].nr<8 ) ||
1052               ( full_half==BALL_HALF && balls->ball[i].nr>8 ) ||
1053               ( full_half==BALL_ANY ) ) &&
1054             balls->ball[i].in_game
1055           ) nr++;
1056     }
1057     return nr;
1058 }
1059