1 /* billard3d.c
2 **
3 **    drawing all with OpenGL
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 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <sys/endian.h>
28 
29 #ifndef USE_SDL
30 #include <GL/glut.h>
31 #else
32 #include <GL/glu.h>
33 #include <GL/gl.h>
34 #endif
35 
36 //#include <sys/timeb.h>  /* my_time */
37 #ifndef _WIN32
38    #include <sys/time.h>    // us time measure
39    #include <getopt.h>
40 #else
41    #include <sys/timeb.h>   // us time measure
42 #endif
43 
44 #include "billard.h"
45 #include "ball.h"
46 #include "table.h"
47 #include "queue.h"
48 #include "png_loader.h"
49 #include "aiplayer.h"
50 #include "options.h"
51 #include "player.h"
52 #include "evaluate_move.h"
53 #include "helpscreen.h"
54 
55 #ifdef options_use_freetype
56 #include "font.h"
57 #include "textobj.h"
58 #endif
59 
60 #ifdef XMESA
61 #include <GL/xmesa.h>
62 #endif
63 
64 
65 #include "sys_stuff.h"
66 
67 #include "net_socket.h"
68 
69 #include "sound_stuff.h"
70 
71 
72 #include "menu.h"
73 #include "gamemenu.h"
74 
75 
76 
77 #define LIT 1
78 #define TEXTURED 2
79 #define REFLECT 3
80 #define ANIMATE 10
81 #define POINT_FILTER 20
82 #define LINEAR_FILTER 21
83 #define QUIT 100
84 
85 #define CUE_BALL_IND (player[act_player].cue_ball)
86 #define CUE_BALL_POS (balls.ball[CUE_BALL_IND].r)
87 #define CUE_BALL_XYPOS (vec_xyz(CUE_BALL_POS.x,CUE_BALL_POS.y,0.0))
88 
89 #define CUEBALL_MAXSPEED 7.0
90 
91 //#define strcpy_whtspace_2_uscore(dst,src) {int _i_; for(_i_=0;(dst[_i_]=src[_i_])!=0;_i_++) if(dst[_i_]==' ') dst[_i_]='_';}
92 //#define strcpy_uscore_2_whtspace(dst,src) {int _i_; for(_i_=0;(dst[_i_]=src[_i_])!=0;_i_++) if(dst[_i_]=='_') dst[_i_]=' ';}
93 #define strcpy_uscore_2_whtspace(d,s) {int i; for(i=0;(d[i]=(s[i]!='_'?s[i]:' '))!=0;i++);}
94 #define strcpy_whtspace_2_uscore(d,s) {int i; for(i=0;(d[i]=(s[i]!=' '?s[i]:'_'))!=0;i++);}
95 
96 /* control-flags */
97 int control__updated=0;  /* just activated */
98 int control__active=0;   /* one conrol is active */
99 /* the controls */
100 int control__english=0;
101 int control__cue_butt_updown=0;
102 int control__mouse_shoot=0;
103 int control__place_cue_ball=0;
104 
105 //#define WIDTH   1280
106 //#define HEIGHT  1024
107 //#define WIDTH   1024
108 //#define HEIGHT   768
109 
110 int win_width = 800;
111 int win_height = 600;
112 
113 //int win_width = 1024;
114 //int win_height = 768;
115 
116 #define WIDTH    win_width
117 #define HEIGHT   win_height
118 
119 //#define TIME_INTERPOLATE
120 
121 double scr_dpi = 80.0;
122 
123 BallsType balls;
124 BallsType bakballs;
125 BordersType walls;
126 
127 
128 static int frametime_ms_min = 10;
129 static int frametime_ms_max = 200;
130 static int frametime_ms = 40;
131 
132 
133 static int fullscreen=0;  /* this is not updated during runtime - its only for startup */
134 
135 static GLuint table_obj = 0;
136 static GLboolean Animate = GL_TRUE;
137 
138 static GLfloat Xrot = -70.0, Yrot = 0.0, Zrot = 0.0;
139 static GLfloat Xque = -83.0, Zque = 0.0;
140 static GLfloat Xrot_offs=0.0, Yrot_offs=0.0, Zrot_offs=0.0;
141 static GLfloat scale = 1.0;
142 
143 
144 
145 int b1_hold = 0;
146 int start_x, start_y;
147 int mouse_moved_after_b1_dn = 0;
148 
149 int b2_hold = 0;
150 int scaling_start, scaling_start2;
151 int b2_b1_hold = 0;
152 
153 
154 GLfloat cam_dist_aim = 2.5;
155 GLfloat cam_dist;
156 GLfloat cam_FOV=40.0;
157 
158 
159 VMvect  free_view_pos_aim;
160 VMvect  free_view_pos;
161 #define FREE_VIEW  ((!queue_view) && options_free_view_on)
162 
163 
164 static int  vline_on=1;
165 //static int  key_modifiers;
166 static int  queue_view=1;
167 static int  old_queue_view=1;
168 
169 static double queue_anim=0.0;
170 static GLfloat queue_offs=0.06;
171 #define queue_point_x  (player[act_player].cue_x)
172 #define queue_point_y  (player[act_player].cue_y)
173 #define queue_strength (player[act_player].strength)
174 
175 static int  balls_moving=0;
176 
177 /* reflection map */
178 static int    spheretexw,spheretexh;
179 static char * spheretexdata;
180 static GLuint spheretexbind;
181 static char * lightspheretexdata;
182 static GLuint lightspheretexbind;
183 static GLuint reftexbind;
184 static GLuint placecueballtexbind;
185 static GLuint blendetexbind;
186 static GLuint lightflaretexbind;
187 
188 static GLuint halfsymboltexbind;
189 static GLuint fullsymboltexbind;
190 static GLuint fullhalfsymboltexbind;
191 
192 static GLuint fblogotexbind;
193 
194 static int  show_fps=0;
195 
196 static int  helpscreen_on=0;
197 
198 /* cubemap reflection stuff */
199 //#define MAX_BALLS 22
200 //static int   cuberef_res=128;
201 #define cuberef_res options_cuberef_res
202 //static int   cubereftexbind=0;
203 static int   cuberef_allballs_texbind_nr = 0;
204 static int * cuberef_allballs_texbind = 0;
205 
206 
207 
208 VMvect comp_dir;
209 
210 static int  human_human_mode=0;
211 static int  act_player=0;   /* 0 or 1 */
212 static char * player_names[]={"Human Player","AI Player","Human Player 2","AI Player 2"};
213 static char * half_full_names[]={"any","full","half"};
214 static int  b1_b2_hold=0;
215 
216 /*
217 static struct Player{
218     int is_AI;
219     int half_full;
220     int queue_view;
221     double Zque;
222     double Xque;
223     double cue_x;
224     double cue_y;
225     double strength;
226     char *name;
227 } player[2];
228 */
229 static struct Player player[2];
230 
231 VMvect lightpos[10];
232 int    lightnr=3;
233 
234 enum gameType gametype = GAME_8BALL;
235 
236 
237 static int  g_socket=0;
238 static int  g_network_play=0;
239 static int  g_is_host=0;
240 
241 
242 
243 //static int  g_lookballnr;
244 
245 
246 static menuType  * g_act_menu;
247 static menuType  * g_main_menu;
248 static menuType  * g_options_menu;
249 static int menu_on=0;
250 
251 int   g_shot_due=1;  /* a shot to be due at the beginning */
252 float g_motion_ratio=1.0;  /* a shot to be due at the beginning */
253 
254 typedef enum
255 {
256   NET_STATE_REQ,
257   NET_STATE_ACK,
258   NET_STATE_DATA
259 } NetState;
260 
261 NetState g_net_state=NET_STATE_REQ;
262 
263 typedef struct
264 {
265     double Xrot;
266     double Zrot;
267     double white_x;
268     double white_y;
269     double cue_x;
270     double cue_y;
271     double strength;
272     int    shoot;
273 } NetData;
274 NetData g_net_data;
275 
276 
277 //#define Xque (player[act_player].X_que)
278 //#define Zque (player[act_player].Z_que)
279 //#define queue_view (player[act_player].queueview)
280 
281 
282 #ifdef USE_SOUND
283 static TSound ball_ball_snd;
284 static TSound ball_wall_snd;
285 static TSound ball_cue_snd;
286 #define SOUND_NULLOFFS 10000
287 #endif
288 
289 /*#define TIME_INTERPOLATE*/
290 
291 #ifdef TIME_INTERPOLATE
292 int g_frametime_laststep;
293 int g_frametime_fromlast;
294 BallsType g_lastballs;
295 BallsType g_drawballs;
296 #endif
297 
298 
299 #define ROSTER_MAX_NUM 128
300 struct PlayerRoster{
301     int             nr;       /* number of players */
302     struct Player   player[ROSTER_MAX_NUM];   /* players */
303 } human_player_roster;
304 
305 
306 #define TOURNAMENT_ROUND_NUM 4
307 static struct TournamentState_ {
308 
309     int round_num;
310 
311     int game_ind;
312     int round_ind;
313 
314     int wait_for_next_match; /* show status meanwhile */
315     int wait_for_next_round; /* show status meanwhile */
316     int overall_winner;
317     int tournament_over;
318     double ai_fast_motion;
319 
320     struct {
321         int roster_player1;
322         int roster_player2;
323         int winner;
324     } game[TOURNAMENT_ROUND_NUM/*rounds*/][1<<(TOURNAMENT_ROUND_NUM-1)/*games*/];
325 
326     struct PlayerRoster roster;
327 
328 } tournament_state;
329 
330 static textObj * winner_name_text_obj;
331 static textObj * winner_text_obj;
332 
333 #ifndef _WIN32
334 
335 enum optionType
336 {
337     OPT_PLAYER1,
338     OPT_PLAYER2,
339     OPT_NAME1,
340     OPT_NAME2,
341     OPT_HELP,
342     OPT_8BALL,
343     OPT_9BALL,
344     OPT_CARAMBOL,
345     OPT_SNOOKER,
346     OPT_TABLECOL,
347     OPT_EDGECOL,
348     OPT_FRAMECOL,
349     OPT_CHROMEBLUE,
350     OPT_GOLDGREEN,
351     OPT_GOLDRED,
352     OPT_BLACKWHITE,
353     OPT_BLACKBEIGE,
354     OPT_TABLESIZE,
355     OPT_LENSFLARE,
356     OPT_NOLENSFLARE,
357     OPT_POSLIGHT,
358     OPT_DIRLIGHT,
359     OPT_AI1ERR,
360     OPT_AI2ERR,
361     OPT_BALLDETAIL,
362     OPT_RGSTEREO,
363     OPT_RGAIM,
364 /*    OPT_NETGAME,
365     OPT_HOST,*/
366     OPT_HOSTADDR,
367     OPT_PORTNUM,
368     OPT_GEOMETRY,
369     OPT_FULLSCREEN,
370     OPT_FREEMOVE,
371     OPT_CUBEREF,
372     OPT_CUBERES,
373     OPT_BUMPREF,
374     OPT_BUMPWOOD,
375     OPT_BALLTRACE,
376     OPT_GAMEMODE,
377     OPT_BALL_FRESNEL,
378     OPT_AVATAR,
379     OPT_TOURFAST,
380     OPT_CLOTHTEX,
381     OPT_DUMMY
382 };
383 
384 
385 static char * appname_str="foobillard";
386 
387 
388 static struct option long_options[] =
389 {
390     {"player1",      required_argument, (int *)"arg=ai|human set player1 ai/human", OPT_PLAYER1},
391     {"player2",      required_argument, (int *)"arg=ai|human set player2 ai/human", OPT_PLAYER2},
392     {"p1",           required_argument, (int *)"arg=ai|human set player1 ai/human", OPT_PLAYER1},
393     {"p2",           required_argument, (int *)"arg=ai|human set player2 ai/human", OPT_PLAYER2},
394     {"name1",        required_argument, (int *)"set name of player1",               OPT_NAME1},
395     {"name2",        required_argument, (int *)"set name of player2",               OPT_NAME2},
396     {"8ball",        no_argument,       (int *)"8ball pool game",                   OPT_8BALL},
397     {"9ball",        no_argument,       (int *)"9ball pool game",                   OPT_9BALL},
398     {"carambol",     no_argument,       (int *)"carambol billard game",             OPT_CARAMBOL},
399     {"snooker",      no_argument,       (int *)"snooker billard game",              OPT_SNOOKER},
400     {"tablecolor",   required_argument, (int *)"table color in C-style hex notation <0xrrggbb>",  OPT_TABLECOL},
401     {"edgecolor",    required_argument, (int *)"edge color in C-style hex notation <0xrrggbb>",   OPT_EDGECOL},
402     {"framecolor",   required_argument, (int *)"frame color in C-style hex notation <0xrrggbb>",  OPT_FRAMECOL},
403     {"chromeblue",   no_argument,       (int *)"blue table with chrome edges",      OPT_CHROMEBLUE},
404     {"goldgreen",    no_argument,       (int *)"green table with gold edges",       OPT_GOLDGREEN},
405     {"goldred",      no_argument,       (int *)"red table with gold edges",         OPT_GOLDRED},
406     {"blackwhite",   no_argument,       (int *)"balck table with white frame",      OPT_BLACKWHITE},
407     {"blackbeige",   no_argument,       (int *)"beige table with balck metal",      OPT_BLACKBEIGE},
408     {"tablesize",    required_argument, (int *)"table size (length) in foot (default=7.0)",       OPT_TABLESIZE},
409     {"lensflare",    no_argument,       (int *)"turn on lensfare",                  OPT_LENSFLARE},
410     {"nolensflare",  no_argument,       (int *)"turn off lensfare",                 OPT_NOLENSFLARE},
411     {"poslight",     no_argument,       (int *)"use positional light",              OPT_POSLIGHT},
412     {"dirlight",     no_argument,       (int *)"use directional light",             OPT_DIRLIGHT},
413     {"ai1err",       required_argument, (int *)"to err is artificial (player1 error 0..1)",       OPT_AI1ERR},
414     {"ai2err",       required_argument, (int *)"to err is artificial (player2 error 0..1)",       OPT_AI2ERR},
415     {"balldetail",   required_argument, (int *)"set ball detail l[ow] m[edium] h[igh] or v[eryhigh]", OPT_BALLDETAIL},
416     {"rgstereo",     no_argument,       (int *)"start in stereo mode (red-green(cyan))",          OPT_RGSTEREO},
417     {"rgaim",        required_argument, (int *)"arg=left|right|middle for aiming eye position",   OPT_RGAIM},
418 //    {"netgame",      no_argument,       (int *)"host a networkgame (player2=client)",             OPT_NETGAME},
419 //    {"host",         required_argument, (int *)"arg=IP play network game with IP as host",        OPT_HOST},
420     {"hostaddr",     required_argument, (int *)"arg=IP-address for TCP/IP connection",            OPT_HOSTADDR},
421     {"portnum",      required_argument, (int *)"arg=port# for TCP/IP connection",                 OPT_PORTNUM},
422     {"geometry",     required_argument, (int *)"<width>x<height> window geometry",  OPT_GEOMETRY},
423     {"fullscreen",   no_argument,       (int *)"play in fullscreen mode",           OPT_FULLSCREEN},
424     {"freemove",     required_argument, (int *)"arg=on|off free move in external view mode",      OPT_FREEMOVE},
425     {"cuberef",      required_argument, (int *)"arg=on|off rendered cubemep reflections",         OPT_CUBEREF},
426     {"cuberes",      required_argument, (int *)"arg=<texture size for cuberef> (must be power of 2)",  OPT_CUBERES},
427     {"bumpref",      required_argument, (int *)"arg=on|off bumpmap reflections of edges",              OPT_BUMPREF},
428     {"bumpwood",     required_argument, (int *)"arg=on|off bumpmap of wood covers",                    OPT_BUMPWOOD},
429     {"balltraces",   required_argument, (int *)"arg=on|off trace lines of balls",                 OPT_BALLTRACE},
430     {"gamemode",     required_argument, (int *)"arg=match|training|tournament",                   OPT_GAMEMODE},
431     {"fresnel",      required_argument, (int *)"arg=on|off fresnel ball reflections",             OPT_BALL_FRESNEL},
432     {"avatar",       required_argument, (int *)"arg=on|off enable/disable avatar",                OPT_AVATAR},
433     {"tourfast",     required_argument, (int *)"arg=1.0..10.0 AI fast motion ratio for tournament",    OPT_TOURFAST},
434     {"clothtex",     required_argument, (int *)"arg=on|off for table detail map",   OPT_CLOTHTEX},
435     {"help",         no_argument,       (int *)"this help",                         OPT_HELP},
436     {NULL,           0,                 NULL, 0}
437 };
438 
439 
440 void set_gametype( int gtype );
441 
442 
443 
process_option(enum optionType act_option)444 void process_option(enum optionType act_option)
445 {
446        switch(act_option){
447        case OPT_PLAYER1:
448            human_player_roster.player[0].is_AI=(optarg[0]=='a')?1:0;
449            human_player_roster.player[0].queue_view=(optarg[0]=='a')?0:1;
450            // FIXME
451            queue_view=human_player_roster.player[0].queue_view;
452        break;
453        case OPT_PLAYER2:
454            human_player_roster.player[1].is_AI=(optarg[0]=='a')?1:0;
455            human_player_roster.player[1].queue_view=(optarg[0]=='a')?0:1;
456        break;
457        case OPT_NAME1:       strcpy_uscore_2_whtspace(human_player_roster.player[0].name,optarg); break;
458        case OPT_NAME2:       strcpy_uscore_2_whtspace(human_player_roster.player[1].name,optarg); break;
459        case OPT_8BALL:       set_gametype( GAME_8BALL );   break;
460        case OPT_9BALL:       set_gametype( GAME_9BALL );   break;
461        case OPT_CARAMBOL:    set_gametype( GAME_CARAMBOL );   break;
462        case OPT_SNOOKER:     set_gametype( GAME_SNOOKER );   break;
463        case OPT_TABLECOL:    sscanf(optarg,"%x",&options_table_color);   break;
464        case OPT_EDGECOL:     sscanf(optarg,"%x",&options_diamond_color); break;
465        case OPT_FRAMECOL:    sscanf(optarg,"%x",&options_frame_color);   break;
466        case OPT_CHROMEBLUE:  options_diamond_color=options_diamond_color_chrome; options_table_color=options_table_color_blue;   options_frame_tex_var=1; break;
467        case OPT_GOLDGREEN:   options_diamond_color=options_diamond_color_gold;   options_table_color=options_table_color_green;  options_frame_tex_var=1; break;
468        case OPT_GOLDRED:     options_diamond_color=options_diamond_color_gold;   options_table_color=options_table_color_red;    options_frame_tex_var=1; break;
469        case OPT_BLACKBEIGE:  options_diamond_color=options_diamond_color_black;  options_table_color=options_table_color_beige;  options_frame_tex_var=1; break;
470        case OPT_BLACKWHITE:  options_diamond_color=options_diamond_color_black;  options_table_color=options_table_color_black;  options_frame_tex_var=0;   options_frame_color=options_frame_color_white;  break;
471        case OPT_TABLESIZE:   sscanf(optarg,"%lf",&options_table_size); options_table_size*=0.3048; break;
472        case OPT_LENSFLARE:   options_lensflare=1; break;
473        case OPT_NOLENSFLARE: options_lensflare=0; break;
474        case OPT_POSLIGHT:    options_positional_light=1; break;
475        case OPT_DIRLIGHT:    options_positional_light=0; break;
476        case OPT_AI1ERR:      sscanf(optarg,"%lf",&(human_player_roster.player[0].err)); break;
477        case OPT_AI2ERR:      sscanf(optarg,"%lf",&(human_player_roster.player[1].err)); break;
478        case OPT_BALLDETAIL:  switch(optarg[0]){
479                              case 'l':
480                                  options_max_ball_detail     = options_max_ball_detail_LOW;
481                                  options_ball_detail_nearmax = options_ball_detail_nearmax_LOW;
482                                  options_ball_detail_farmin  = options_ball_detail_farmin_LOW;
483                                  break;
484                              case 'm':
485                                  options_max_ball_detail     = options_max_ball_detail_MED;
486                                  options_ball_detail_nearmax = options_ball_detail_nearmax_MED;
487                                  options_ball_detail_farmin  = options_ball_detail_farmin_MED;
488                                  break;
489                              case 'h':
490                                  options_max_ball_detail     = options_max_ball_detail_HIGH;
491                                  options_ball_detail_nearmax = options_ball_detail_nearmax_HIGH;
492                                  options_ball_detail_farmin  = options_ball_detail_farmin_HIGH;
493                                  break;
494                              case 'v':
495                                  options_max_ball_detail     = options_max_ball_detail_VERYHIGH;
496                                  options_ball_detail_nearmax = options_ball_detail_nearmax_VERYHIGH;
497                                  options_ball_detail_farmin  = options_ball_detail_farmin_VERYHIGH;
498                                  break;
499                              }
500                              break;
501        case OPT_RGSTEREO:    options_rgstereo_on=1; break;
502        case OPT_RGAIM:       if(optarg[0]=='l') options_rgaim=1;
503                              if(optarg[0]=='r') options_rgaim=2;
504                              if(optarg[0]=='m') options_rgaim=0;
505                              break;
506 /*       case OPT_NETGAME:     player[1].is_net=1;    player[0].is_net=0;
507                              g_is_host=1;
508                              g_network_play=1;
509                              break;
510        case OPT_HOST:        player[1].is_net=0;    player[0].is_net=1;
511                              g_is_host=0;
512                              g_network_play=1;
513                              options_net_hostname = optarg;
514                              break;*/
515        case OPT_HOSTADDR:    strcpy(options_net_hostname,optarg);
516                              break;
517        case OPT_PORTNUM:     sscanf(optarg,"%d",&options_net_portnum);
518                              break;
519        case OPT_GEOMETRY:    sscanf(optarg,"%dx%d",&win_width,&win_height); break;
520        case OPT_FULLSCREEN:  fullscreen=1; break;
521        case OPT_FREEMOVE:    switch(optarg[1]){
522                              case 'f': /* off */
523                                  options_free_view_on=0; break;
524                              case 'n': /* on  */
525                                  options_free_view_on=1; break;
526                              }
527                              break;
528        case OPT_CUBEREF:     switch(optarg[1]){
529                              case 'f': /* off */
530                                  options_cuberef=0; break;
531                              case 'n': /* on  */
532                                  options_cuberef=1; break;
533                              }
534                              break;
535        case OPT_CUBERES:     sscanf(optarg,"%d", &options_cuberef_res);
536                              break;
537        case OPT_BUMPREF:     switch(optarg[1]){
538                              case 'f': /* off */
539                                  options_bumpref=0; break;
540                              case 'n': /* on  */
541                                  options_bumpref=1; break;
542                              }
543                              break;
544        case OPT_BUMPWOOD:    switch(optarg[1]){
545                              case 'f': /* off */
546                                  options_bumpwood=0; break;
547                              case 'n': /* on  */
548                                  options_bumpwood=1; break;
549                              }
550                              break;
551        case OPT_BALLTRACE:   switch(optarg[1]){
552                              case 'f': /* off */
553                                  options_balltrace=0; break;
554                              case 'n': /* on  */
555                                  options_balltrace=1; break;
556                              }
557                              break;
558        case OPT_GAMEMODE:    if       (strncasecmp("match",optarg,5)==0){
559                                  options_gamemode=options_gamemode_match;
560                              } else if(strncasecmp("train",optarg,5)==0){
561                                  options_gamemode=options_gamemode_training;
562                              } else if(strncasecmp("tourn",optarg,5)==0){
563                                  options_gamemode=options_gamemode_tournament;
564                              }
565                              break;
566        case OPT_BALL_FRESNEL:switch(optarg[1]){
567                              case 'f': /* off */
568                                  options_ball_fresnel_refl=0; break;
569                              case 'n': /* on  */
570                                  options_ball_fresnel_refl=1; break;
571                              }
572                              break;
573        case OPT_AVATAR:      switch(optarg[1]){
574                              case 'f': /* off */
575                                  options_avatar_on=0; break;
576                              case 'n': /* on  */
577                                  options_avatar_on=1; break;
578                              }
579                              break;
580        case OPT_TOURFAST:    sscanf(optarg,"%lf",&options_tourfast); break;
581        case OPT_CLOTHTEX:    switch(optarg[1]){
582                              case 'f': /* off */
583                                  options_cloth_tex=0; break;
584                              case 'n': /* on  */
585                                  options_cloth_tex=1; break;
586                              }
587                              break;
588        case OPT_HELP:        exit(1);   break;
589        case OPT_DUMMY:       break;
590        }
591 }
592 
593 
print_help(struct option * opt,char * appname,FILE * io)594 void print_help(struct option * opt, char *appname, FILE * io)
595 {
596     int i;
597 
598     fprintf(io,"usage: %s [--option [<arg>]]\n",appname);
599     fprintf(io,"  options:\n");
600     for(i=0;opt[i].name!=0;i++){
601         fprintf(io,"--%s %s\n",opt[i].name,opt[i].has_arg?"<arg>":"");
602         fprintf(io,"     %s\n",(char *)(opt[i].flag));
603         opt[i].flag=NULL;
604     }
605     printf("the color <0xrrggbb> means one byte for each red, green, blue\n");
606 //  printf("the transparency specification is optional e.g. <0xrrggbb>\n");
607     fprintf(io,"\n");
608 }
609 
610 
load_config(char *** confv,int * confc,char ** argv,int argc)611 int load_config( char *** confv, int * confc, char ** argv, int argc )
612 {
613     FILE * f;
614     int c,i;
615     char * str;
616     char allstr[64000];
617     char filename[512];
618 
619     *confc=1;
620     str=allstr;
621 
622     sprintf(filename,"%s/.foobillardrc",getenv("HOME"));
623 
624     if( (f=fopen(filename,"rb")) != NULL ){
625 
626         do{
627             str[0]='-'; str[1]='-';
628             for( i=2 ; (c=fgetc(f))!='\n' && c!=EOF ; i++ ){
629                 if( c!=' ' && c!=0x13 && c!=0x0A ) str[i]=c;
630                 else {
631                     str[i]=0;
632                     (*confc)++;
633 //                    while((c=fgetc(f))==' ' && c!=EOF);
634                 }
635             }
636             str[i]=0;
637             if( str[2]!=0 ){
638                 (*confc)++;
639 /*           fprintf(stderr,"confstring:<%s> confc=%d\n",str,*confc);*/
640                 str+=i+1;
641             }
642         } while( c!=EOF );
643 
644         *confv = malloc( (argc+*confc)*sizeof(char *) );
645         str=allstr;
646 /*    fprintf(stderr,"allstr:<%s>\n",allstr);*/
647         (*confv)[0]=argv[0];
648         for(i=1;i<*confc;i++){
649             (*confv)[i]=str;
650 /*        fprintf(stderr,"confstring2:<%s>\n",(*confv)[i]);*/
651             if( i!=(*confc)-1 ){ for(;(*str)!=0;str++); str++; }
652         }
653         for(i=1;i<argc;i++){
654             (*confv)[*confc+i-1]=argv[i];
655         }
656         (*confc)+=argc-1;
657     } else {
658         (*confv)=argv;
659         *confc=argc;
660 /*      fprintf(stderr,"no rc file found\n");*/
661     }
662 
663 /*    printf("number of args = %d\n",*confc);
664     for(i=0;i<*confc;i++){
665         printf("arg %d = %s\n",i,(*confv)[i]);
666     }*/
667 
668     return (f!=NULL);
669 }
670 
671 
write_rc(FILE * f,int opt,char * arg)672 void write_rc(FILE * f, int opt, char * arg)
673 {
674     int i;
675     for( i=0; i<OPT_DUMMY && long_options[i].val!=opt ; i++ );
676 
677     if( arg!=NULL ){
678 //        int j;
679         char argstr[256];
680 //        for(j=0;(argstr[j]=arg[j])!=0;j++) if(argstr[j]==' ') argstr[j]=='_';
681         strcpy_whtspace_2_uscore(argstr,arg);
682         fprintf(f,"%s=%s\n",long_options[i].name,argstr);
683     } else {
684         fprintf(f,"%s\n",long_options[i].name);
685     }
686 }
687 
688 
save_config()689 void save_config()
690 {
691     int opt;
692     FILE * f;
693     char filename[512];
694     char str[256];
695 
696     sprintf(filename,"%s/.foobillardrc",getenv("HOME"));
697     if((f=fopen(filename,"wb"))==NULL){
698         fprintf(stderr,"can't write to %s - check rights\n",filename);
699         return;
700     }
701 
702     for(opt=0;opt<OPT_DUMMY;opt++){
703         DPRINTF("save_config: writing option %d\n",opt);
704         switch(opt){
705         case OPT_PLAYER1:     write_rc(f,opt,(human_player_roster.player[0].is_AI)?"ai":"human"); break;
706         case OPT_PLAYER2:     write_rc(f,opt,(human_player_roster.player[1].is_AI)?"ai":"human"); break;
707         case OPT_NAME1:       write_rc(f,opt,human_player_roster.player[0].name); break;
708         case OPT_NAME2:       write_rc(f,opt,human_player_roster.player[1].name); break;
709         case OPT_8BALL:       if(gametype==GAME_8BALL)    write_rc(f,opt,NULL);  break;
710         case OPT_9BALL:       if(gametype==GAME_9BALL)    write_rc(f,opt,NULL);  break;
711         case OPT_CARAMBOL:    if(gametype==GAME_CARAMBOL) write_rc(f,opt,NULL);  break;
712         case OPT_SNOOKER:     if(gametype==GAME_SNOOKER)  write_rc(f,opt,NULL);  break;
713 /*       case OPT_TABLECOL:    sprintf(str,"0x%06X",&options_table_color);   write_rc(OPT_TABCOL,str);  break;
714        case OPT_EDGECOL:     sprintf(str,"0x%06X",&options_diamond_color); write_rc(OPT_EDGECOL,str);  break;
715        case OPT_FRAMECOL:    sprintf(str,"0x%06X",&options_frame_color);   write_rc(OPT_FRAMECOL,str);  break;*/
716         case OPT_CHROMEBLUE:  if( options_diamond_color==options_diamond_color_chrome && options_table_color==options_table_color_blue  && options_frame_tex_var==1 ) write_rc(f,opt,NULL); break;
717         case OPT_GOLDGREEN:   if( options_diamond_color==options_diamond_color_gold   && options_table_color==options_table_color_green && options_frame_tex_var==1 ) write_rc(f,opt,NULL); break;
718         case OPT_GOLDRED:     if( options_diamond_color==options_diamond_color_gold   && options_table_color==options_table_color_red   && options_frame_tex_var==1 ) write_rc(f,opt,NULL); break;
719         case OPT_BLACKBEIGE:  if( options_diamond_color==options_diamond_color_black  && options_table_color==options_table_color_beige && options_frame_tex_var==1 ) write_rc(f,opt,NULL); break;
720         case OPT_BLACKWHITE:  if( options_diamond_color==options_diamond_color_black  && options_table_color==options_table_color_black && options_frame_tex_var==0 && options_frame_color==options_frame_color_white ) write_rc(f,opt,NULL);   break;
721         case OPT_TABLESIZE:   sprintf(str,"%f",options_table_size/0.3048); write_rc(f,opt,str); break;
722         case OPT_LENSFLARE:   if (options_lensflare) write_rc(f,opt,NULL); break;
723 /*       case OPT_POSLIGHT:    options_positional_light=1; break;
724        case OPT_DIRLIGHT:    options_positional_light=0; break;*/
725         case OPT_AI1ERR:      sprintf(str,"%f",human_player_roster.player[0].err); write_rc(f,opt,str); break;
726         case OPT_AI2ERR:      sprintf(str,"%f",human_player_roster.player[1].err); write_rc(f,opt,str); break;
727         case OPT_BALLDETAIL:
728             if       ( options_max_ball_detail == options_max_ball_detail_LOW ){
729                 write_rc(f,opt,"l"); break;
730             } else if( options_max_ball_detail == options_max_ball_detail_MED ){
731                 write_rc(f,opt,"m"); break;
732             } else if( options_max_ball_detail == options_max_ball_detail_HIGH ){
733                 write_rc(f,opt,"h"); break;
734             } else if( options_max_ball_detail == options_max_ball_detail_VERYHIGH ){
735                 write_rc(f,opt,"v"); break;
736             }
737             break;
738         case OPT_RGSTEREO:    if(options_rgstereo_on) write_rc(f,opt,NULL); break;
739         case OPT_RGAIM:
740             if( options_rgaim==1 ) write_rc(f,opt,"l");
741             if( options_rgaim==2 ) write_rc(f,opt,"r");
742             if( options_rgaim==0 ) write_rc(f,opt,"m");
743             break;
744         case OPT_HOSTADDR:    write_rc(f,opt,options_net_hostname); break;
745         case OPT_PORTNUM:     sprintf(str,"%d",options_net_portnum); write_rc(f,opt,str); break;
746         case OPT_GEOMETRY:    sprintf(str,"%dx%d",win_width,win_height); write_rc(f,opt,str); break;
747         case OPT_FULLSCREEN:  if (sys_get_fullscreen()) write_rc(f,opt,NULL); break;
748         case OPT_FREEMOVE:    write_rc(f,opt, options_free_view_on?"on":"off"); break;
749         case OPT_CUBEREF:     write_rc(f,opt, options_cuberef?"on":"off"); break;
750         case OPT_CUBERES:     sprintf(str,"%d", options_cuberef_res); write_rc(f,opt,str); break;
751         case OPT_BUMPREF:     write_rc(f,opt, options_bumpref?"on":"off"); break;
752         case OPT_BUMPWOOD:    write_rc(f,opt, options_bumpwood?"on":"off"); break;
753         case OPT_BALLTRACE:   write_rc(f,opt, options_balltrace?"on":"off"); break;
754         case OPT_GAMEMODE:    switch(options_gamemode){
755                                  case options_gamemode_match:
756                                          write_rc(f,opt,"match"); break;
757                                  case options_gamemode_training:
758                                          write_rc(f,opt,"training"); break;
759                                  case options_gamemode_tournament:
760                                          write_rc(f,opt,"tournament"); break;
761                               }
762                               break;
763         case OPT_BALL_FRESNEL:write_rc(f,opt, options_ball_fresnel_refl?"on":"off"); break;
764         case OPT_AVATAR:      write_rc(f,opt, options_avatar_on?"on":"off"); break;
765         case OPT_TOURFAST:    sprintf(str,"%f",options_tourfast); write_rc(f,opt,str); break;
766         case OPT_CLOTHTEX:    write_rc(f,opt, options_cloth_tex?"on":"off"); break;
767 /*      case OPT_HELP:        exit(1);   break;
768       case OPT_DUMMY:       break;*/
769        }
770     }
771 
772     fclose(f);
773 
774 }
775 
776 
777 #endif  // not WIN32
778 
779 
780 
781 /*
782 int my_time(void)
783 {struct timeb ts;
784       ftime(&ts);
785       return(ts.time*1000+ts.millitm);
786 }*/
787 
set_gametype(int gtype)788 void set_gametype( int gtype )
789 {
790     gametype=gtype;
791     if       ( gametype==GAME_8BALL ){
792         setfunc_evaluate_last_move( evaluate_last_move_8ball );
793         setfunc_create_scene( create_8ball_scene );
794         setfunc_create_walls( create_6hole_walls );
795         setfunc_ai_get_stroke_dir( ai_get_stroke_dir_8ball );
796         player[0].cue_ball=0;   player[1].cue_ball=0;
797         player[act_player].place_cue_ball=1;
798         human_player_roster.player[0].cue_ball=0;   human_player_roster.player[1].cue_ball=0;
799         human_player_roster.player[act_player].place_cue_ball=1;
800     } else if( gametype==GAME_9BALL ){
801         setfunc_evaluate_last_move( evaluate_last_move_9ball );
802         setfunc_create_scene( create_9ball_scene );
803         setfunc_create_walls( create_6hole_walls );
804         setfunc_ai_get_stroke_dir( ai_get_stroke_dir_9ball );
805         player[0].cue_ball=0;   player[1].cue_ball=0;
806         player[act_player].place_cue_ball=1;
807         human_player_roster.player[0].cue_ball=0;   human_player_roster.player[1].cue_ball=0;
808         human_player_roster.player[act_player].place_cue_ball=1;
809     } else if( gametype==GAME_CARAMBOL ){
810         setfunc_evaluate_last_move( evaluate_last_move_carambol );
811         setfunc_create_scene( create_carambol_scene );
812         setfunc_create_walls( create_0hole_walls );
813         setfunc_ai_get_stroke_dir( ai_get_stroke_dir_carambol );
814         player[0].cue_ball=0;   player[1].cue_ball=1;
815         player[act_player].place_cue_ball=0;
816         human_player_roster.player[0].cue_ball=0;   human_player_roster.player[1].cue_ball=1;
817         human_player_roster.player[act_player].place_cue_ball=0;
818     } else if( gametype==GAME_SNOOKER ){
819         setfunc_evaluate_last_move( evaluate_last_move_snooker );
820         setfunc_create_scene( create_snooker_scene );
821         setfunc_create_walls( create_6hole_walls );
822         setfunc_ai_get_stroke_dir( ai_get_stroke_dir_snooker );
823 /*        options_table_size = 9.0*2.54*12.0/100.0;
824         if( table_obj!=0 )  table_obj=create_table( spheretexbind, &walls );*/
825         player[0].cue_ball=0;   player[1].cue_ball=0;
826         player[act_player].place_cue_ball=1;
827         human_player_roster.player[0].cue_ball=0;   human_player_roster.player[1].cue_ball=0;
828         human_player_roster.player[act_player].place_cue_ball=1;
829     }
830 }
831 
832 
833 
angle_pm180(double ang)834 double angle_pm180(double ang)
835 {
836     while ( ang >  180.0 ) ang-=360.0;
837     while ( ang < -180.0 ) ang+=360.0;
838     return ang;
839 }
840 
841 
842 
toggle_queue_view()843 void toggle_queue_view()
844 {
845     queue_view = (queue_view==0)?1:0;
846     if( queue_view ){
847         Xrot_offs=angle_pm180(Xrot-Xque);  Xrot=Xque;
848         Zrot_offs=angle_pm180(Zrot-Zque);  Zrot=Zque;
849     } else {
850         double th=Xrot/180.0*M_PI;
851         double ph=Zrot/180.0*M_PI;
852         free_view_pos_aim = vec_scale(vec_xyz(sin(th)*sin(ph),sin(th)*cos(ph),cos(th)), cam_dist);
853         free_view_pos_aim = vec_add( free_view_pos_aim, CUE_BALL_XYPOS );
854         free_view_pos = free_view_pos_aim ;
855     }
856 }
857 
birdview()858 void birdview()
859 {
860         if(options_free_view_on==0) options_free_view_on=1;
861         if(queue_view) toggle_queue_view();
862 
863         if( (!queue_view) && options_free_view_on ){
864             double Xoffs=0.0-Xrot;
865             double Zoffs=-90.0-Zrot;
866             free_view_pos_aim = vec_xyz(0,0,3.5*options_table_size/2.1336);
867             free_view_pos = free_view_pos_aim ;
868             Xrot += Xoffs;
869             Zrot += Zoffs;
870             Xrot_offs -= Xoffs;
871             Zrot_offs -= Zoffs;
872             Xrot = 0.0;
873             Zrot = -90.0;
874             Xrot_offs = 0.0;
875             Zrot_offs = 0.0;
876         }
877         old_queue_view = queue_view;
878 }
879 
880 
player_copy(struct Player * player,struct Player src)881 void player_copy(struct Player * player, struct Player src)
882 {
883     player->is_AI          = src.is_AI;
884     player->is_net         = src.is_net;
885     player->half_full      = src.half_full;
886     printf("player_copy1\n");
887     strcpy(player->name,src.name);
888     printf("player_copy2\n");
889     player->Xque           = src.Xque;
890     player->Zque           = src.Zque;
891     player->cue_x          = src.cue_x;
892     player->cue_y          = src.cue_y;
893     player->strength       = src.strength;
894     player->queue_view     = src.queue_view;
895     player->place_cue_ball = src.place_cue_ball;
896     player->winner         = src.winner;
897     player->err            = src.err;
898     printf("player_copy3\n");
899     printf("%s\n", player->name);
900     if(player->text) textObj_setText(player->text, player->name);
901     printf("player_copy3.5\n");
902     if(player->score_text) textObj_setText(player->score_text, "0");
903     printf("player_copy4\n");
904     player->snooker_on_red = src.snooker_on_red;
905     player->score          = src.score;
906     player->cue_ball       = src.cue_ball;
907 }
908 
909 
init_player(struct Player * player,int ai)910 void init_player(struct Player * player, int ai)
911 {
912     player->is_AI=ai;
913     player->is_net=0;
914     player->half_full=BALL_ANY;
915     strcpy(player->name,ai?"AI-Player":"Human");
916     player->Xque=-83.0;
917     player->Zque=0.0;
918     player->cue_x=0.0;
919     player->cue_y=0.0;
920     player->strength=0.7;
921     player->queue_view=ai?0:1;
922     player->place_cue_ball=0;
923     player->winner=0;
924     player->err=0;
925     player->text = 0;
926     player->score_text = 0;
927     player->snooker_on_red=1;
928     player->score=0;
929     player->cue_ball=0;
930 //    player[0].free_view_pos=vec_xyz(0,-1.0,1.5);
931 //    player[1].free_view_pos=vec_xyz(0,-1.0,1.5);
932 }
933 
init_players()934 void init_players()
935 {
936     init_player(&player[0],0);
937     init_player(&player[1],human_human_mode?0:1);
938 /*    player[0].is_AI=0;
939     player[1].is_AI=human_human_mode?0:1;
940     player[0].is_net=0;
941     player[1].is_net=0;
942     player[0].half_full=BALL_ANY;
943     player[1].half_full=BALL_ANY;*/
944     strcpy(player[0].name,player_names[0]);
945     strcpy(player[1].name,player_names[human_human_mode?2:1]);
946 /*    player[0].Xque=-83.0;
947     player[1].Xque=-83.0;
948     player[0].Zque=0.0;
949     player[1].Zque=0.0;
950     player[0].cue_x=0.0;
951     player[1].cue_x=0.0;
952     player[0].cue_y=0.0;
953     player[1].cue_y=0.0;
954     player[0].strength=0.7;
955     player[1].strength=0.7;
956     player[0].queue_view=1;
957     player[1].queue_view=human_human_mode?1:0;
958     player[0].place_cue_ball=0;
959     player[1].place_cue_ball=0;
960     player[0].winner=0;
961     player[1].winner=0;
962     player[0].err=0;
963     player[1].err=0;
964     player[0].text = 0;
965     player[1].text = 0;
966     player[0].score_text = 0;
967     player[1].score_text = 0;
968     player[0].snooker_on_red=1;
969     player[1].snooker_on_red=1;
970     player[0].score=0;
971     player[1].score=0;
972     player[0].cue_ball=0;
973     player[1].cue_ball=0;*/
974 //    player[0].free_view_pos=vec_xyz(0,-1.0,1.5);
975 //    player[1].free_view_pos=vec_xyz(0,-1.0,1.5);
976 }
977 
init_ai_player_roster(struct PlayerRoster * roster)978 void init_ai_player_roster(struct PlayerRoster * roster)
979 {
980     int i;
981 
982     for(i=0;i<roster->nr;i++){
983 
984         init_player(&(roster->player[i]),1);
985 
986         if (i==roster->nr-1) { /* human player */
987             roster->player[i]=human_player_roster.player[0];
988         } else if (i==0){
989             strcpy(roster->player[i].name,"billardo bill");
990             roster->player[i].err=0.0;
991         } else if (i==1) {
992             strcpy(roster->player[i].name,"suzy cue");
993             roster->player[i].err=0.02;
994         } else if (i==2) {
995             strcpy(roster->player[i].name,"pooledo pete");
996             roster->player[i].err=0.05;
997         } else if (i==3) {
998             strcpy(roster->player[i].name,"billie ball");
999             roster->player[i].err=0.1;
1000         } else if (i==4) {
1001             strcpy(roster->player[i].name,"snookie");
1002             roster->player[i].err=0.2;
1003         } else if (i==5) {
1004             strcpy(roster->player[i].name,"diamond dan");
1005             roster->player[i].err=0.4;
1006         } else if (i==6) {
1007             strcpy(roster->player[i].name,"tom tuxedo");
1008             roster->player[i].err=0.6;
1009         } else if (i==7) {
1010             strcpy(roster->player[i].name,"sally silver");
1011             roster->player[i].err=0.7;
1012         } else if (i==8) {
1013             strcpy(roster->player[i].name,"wicked wendy");
1014             roster->player[i].err=0.8;
1015         } else if (i==9) {
1016             strcpy(roster->player[i].name,"bald ben");
1017             roster->player[i].err=0.9;
1018         } else if (i==10) {
1019             strcpy(roster->player[i].name,"badino buck");
1020             roster->player[i].err=0.10;
1021         } else if (i==11) {
1022             strcpy(roster->player[i].name,"worse will");
1023             roster->player[i].err=0.11;
1024         } else if (i==12) {
1025             strcpy(roster->player[i].name,"rita rookie");
1026             roster->player[i].err=0.12;
1027         } else if (i==13) {
1028             strcpy(roster->player[i].name,"don dumb");
1029             roster->player[i].err=0.15;
1030         } else if (i==14) {
1031             strcpy(roster->player[i].name,"dana dummy");
1032             roster->player[i].err=0.19;
1033         } else {
1034             char str[256];
1035             sprintf(str,"dumb for %d",i-13);
1036             strcpy(roster->player[i].name,str);
1037             roster->player[i].err=0.1*(double)(i-13);
1038         }
1039         roster->player[i].text = textObj_new(roster->player[i].name, options_roster_fontname, 28);
1040     }
1041 }
1042 
init_human_player_roster(struct PlayerRoster * roster)1043 void init_human_player_roster(struct PlayerRoster * roster)
1044 {
1045     int i;
1046 
1047     roster->nr=2;
1048 
1049     for(i=0;i<roster->nr;i++){
1050 
1051         init_player(&(roster->player[i]),0);
1052 
1053         {
1054             char str[256];
1055             sprintf(str,"human player %d",i+1);
1056             strcpy(roster->player[i].name,str);
1057             roster->player[i].err=(double)i/10.0;
1058         }
1059         roster->player[i].text = 0;
1060     }
1061 }
1062 
create_human_player_roster_text(struct PlayerRoster * roster)1063 void create_human_player_roster_text(struct PlayerRoster * roster)
1064 {
1065     int i;
1066 
1067     for(i=0;i<roster->nr;i++){
1068         if(roster->player[i].text == 0){
1069             roster->player[i].text = textObj_new(roster->player[i].name, options_roster_fontname, 28);
1070         } else {
1071             textObj_setText(roster->player[i].text, roster->player[i].name);
1072         }
1073     }
1074 }
1075 
init_tournament_state(struct TournamentState_ * ts)1076 void init_tournament_state( struct TournamentState_ * ts )
1077 {
1078     static int init_me=1;
1079     int i,j,k, dummy, game;
1080     int players[100];
1081 
1082     ts->round_num=TOURNAMENT_ROUND_NUM;
1083     ts->game_ind=0;
1084     ts->round_ind=0;
1085     ts->wait_for_next_match=1;
1086     ts->tournament_over=0;
1087     ts->overall_winner=-1;
1088     ts->ai_fast_motion=options_tourfast;
1089     for( i=0 ; i<(1<<ts->round_num) ; i++ ) players[i]=i;
1090     /* mix players for tournament */
1091     for( k=0 ; k<1000 ; k++ ){
1092         i =   k   %(1<<ts->round_num);
1093         j = rand()%(1<<ts->round_num);
1094         dummy=players[i];
1095         players[i]=players[j];
1096         players[j]=dummy;
1097     }
1098     /* set up pairings */
1099     for( game=0 ; game<(1<<(ts->round_num-1)) ; game++ ){
1100         ts->game[0][game].roster_player1 = players[(game*2)];
1101         ts->game[0][game].roster_player2 = players[(game*2)+1];
1102         ts->game[0][game].winner = -1;
1103     }
1104     ts->roster.nr = 1<<ts->round_num;
1105 
1106     if(init_me){
1107         DPRINTF("init_tournament_state: initializing player roster\n");
1108         init_ai_player_roster(&(ts->roster));
1109         init_me=0;
1110     }
1111 }
1112 
1113 void restart_game_common();
1114 
tournament_state_setup_next_round(struct TournamentState_ * ts)1115 void tournament_state_setup_next_round( struct TournamentState_ * ts )
1116 {
1117     int i;
1118     int players[100];
1119 
1120     printf("tournament_state_setup_next_round\n");
1121 
1122     (ts->round_ind)++;
1123     if( ts->round_ind == ts->round_num ){ /* tournament over ? */
1124         ts->tournament_over=1;
1125         ts->round_ind = ts->round_num-1;
1126         if(ts->game[ts->round_ind][0].winner==0){
1127             ts->overall_winner=ts->game[ts->round_ind][0].roster_player1;
1128         } else if(ts->game[ts->round_ind][0].winner==1){
1129             ts->overall_winner=ts->game[ts->round_ind][0].roster_player2;
1130         } else {
1131             fprintf(stderr,"error: nobody won the tournament !?\n");
1132             exit(1);
1133         }
1134     } else {
1135         for(i=0;i<(1<<(ts->round_num-ts->round_ind));i++){
1136             if(ts->game[ts->round_ind-1][i].winner==0){
1137                 players[i]=ts->game[ts->round_ind-1][i].roster_player1;
1138             } else if(ts->game[ts->round_ind-1][i].winner==1){
1139                 players[i]=ts->game[ts->round_ind-1][i].roster_player2;
1140             } else {
1141                 fprintf(stderr,"error: sbdy didnt win one of the last matches !?\n");
1142                 exit(1);
1143             }
1144         }
1145         printf("Pairings:\n");
1146         for(i=0;i<(1<<(ts->round_num-ts->round_ind-1));i++){
1147             ts->game[ts->round_ind][i].roster_player1=players[2*i];
1148             ts->game[ts->round_ind][i].roster_player2=players[2*i+1];
1149             ts->game[ts->round_ind][i].winner = -1;
1150             printf("%d vs. %d\n",
1151                    ts->game[ts->round_ind][i].roster_player1,
1152                    ts->game[ts->round_ind][i].roster_player2
1153                   );
1154             printf("%s vs. %s\n",
1155                    ts->roster.player[ts->game[ts->round_ind][i].roster_player1].name,
1156                    ts->roster.player[ts->game[ts->round_ind][i].roster_player2].name
1157                   );
1158         }
1159     }
1160 }
1161 
tournament_evaluate_last_match(struct TournamentState_ * ts)1162 void tournament_evaluate_last_match( struct TournamentState_ * ts )
1163 {
1164     printf("tournament_evaluate_last_match 1\n");
1165     if( player[0].winner ){
1166         ts->game[ts->round_ind][ts->game_ind].winner=0;
1167     } else if( player[1].winner ){
1168         ts->game[ts->round_ind][ts->game_ind].winner=1;
1169     } else {
1170         ts->game[ts->round_ind][ts->game_ind].winner=-1;
1171     }
1172     printf("tournament_evaluate_last_match 2\n");
1173     ts->game_ind++;
1174     printf("tournament_evaluate_last_match 3\n");
1175     if( ts->game_ind >= (1<<(ts->round_num-ts->round_ind-1)) ){
1176         printf("tournament_evaluate_last_match 4\n");
1177         tournament_state_setup_next_round(ts);
1178         ts->game_ind=0;
1179 /*        if(ts->round_ind>=ts->round_num){
1180             ts->tournament_over=1;
1181             if( ts->game[ts->round_num-1][0].winner == 0 ){
1182                 ts->overall_winner = ts->game[ts->round_num-1][0].roster_player1;
1183             } else {
1184                 ts->overall_winner = ts->game[ts->round_num-1][0].roster_player2;
1185             }
1186         }*/
1187     }
1188     printf("tournament_evaluate_last_match 5\n");
1189 }
1190 
tournament_state_setup_next_match(struct TournamentState_ * ts)1191 void tournament_state_setup_next_match( struct TournamentState_ * ts )
1192 {
1193     printf("tournament_state_setup_next_match 1\n");
1194     printf("ts->game[ts->round_ind][ts->game_ind].roster_player1=%d\n",ts->game[ts->round_ind][ts->game_ind].roster_player1);
1195     player_copy(&(player[0]),ts->roster.player[ts->game[ts->round_ind][ts->game_ind].roster_player1]);
1196     printf("tournament_state_setup_next_match 2\n");
1197     printf("ts->game[ts->round_ind][ts->game_ind].roster_player2=%d\n",ts->game[ts->round_ind][ts->game_ind].roster_player2);
1198     player_copy(&(player[1]),ts->roster.player[ts->game[ts->round_ind][ts->game_ind].roster_player2]);
1199     printf("tournament_state_setup_next_match 3\n");
1200     player[0].winner=0;
1201     player[1].winner=0;
1202     printf("tournament_state_setup_next_match 4\n");
1203     if( player[0].is_AI && player[1].is_AI ){
1204         g_motion_ratio=ts->ai_fast_motion;
1205         printf("ts->ai_fast_motion=%f\n",g_motion_ratio);
1206         printf("tournament_state_setup_next_match 4-1\n");
1207     } else {
1208         g_motion_ratio=1.0;
1209         printf("g_motion_ratio=%f\n",g_motion_ratio);
1210         printf("tournament_state_setup_next_match 4-2\n");
1211     }
1212     printf("tournament_state_setup_next_match 5\n");
1213     restart_game_common();
1214     printf("tournament_state_setup_next_match 6\n");
1215     act_player=0;
1216     printf("tournament_state_setup_next_match 7\n");
1217     queue_view=player[act_player].queue_view;
1218     printf("tournament_state_setup_next_match 8\n");
1219 }
1220 
create_players_text()1221 void create_players_text()
1222 {
1223     player[0].text = textObj_new(player[0].name, options_player_fontname, 28);
1224     player[1].text = textObj_new(player[1].name, options_player_fontname, 28);
1225 //    player[0].text = textObj3D_new(player[0].name, options_player_fontname, 28, 1.0, 3);
1226 //    player[1].text = textObj3D_new(player[1].name, options_player_fontname, 28, 1.0, 3);
1227     player[0].score_text = textObj_new("0", options_score_fontname, 20);
1228     player[1].score_text = textObj_new("0", options_score_fontname, 20);
1229 }
1230 
copy_balls(BallsType * balls1,BallsType * balls2)1231 void copy_balls( BallsType * balls1, BallsType * balls2 )
1232 {
1233     int i;
1234     if ( balls2->nr != balls1->nr ){
1235         balls2->nr = balls1->nr;
1236         free( balls2->ball );
1237         balls2->ball=(BallType *)malloc(balls2->nr*sizeof(BallType));
1238     }
1239     for(i=0;i<balls1->nr;i++){
1240         balls2->ball[i] = balls1->ball[i];
1241     }
1242     balls2->gametype = balls1->gametype;
1243 }
1244 
1245 
queue_shot()1246 void queue_shot()
1247 {
1248     VMvect dir, nx, ny, hitpoint;
1249 
1250     if( !balls_moving ){
1251         int other_player;
1252 
1253         /* backup actual ball setup */
1254         copy_balls(&balls,&bakballs);
1255 
1256         other_player=(act_player==1)?0:1;
1257         if( player[other_player].is_net ){
1258             socket_write(g_socket,(char *)&(Zque),sizeof(Zque));
1259             socket_write(g_socket,(char *)&(Xque),sizeof(Xque));
1260         }
1261 //        player[act_player].place_cue_ball=0;
1262 
1263         dir = vec_xyz(sin(Zque*M_PI/180.0)*sin(Xque*M_PI/180.0),
1264                       cos(Zque*M_PI/180.0)*sin(Xque*M_PI/180.0),
1265                       cos(Xque*M_PI/180.0));
1266         nx = vec_unit(vec_cross(vec_ez(),dir));  /* parallel to table */
1267         ny = vec_unit(vec_cross(nx,dir));        /* orthogonal to dir and nx */
1268         hitpoint = vec_add(vec_scale(nx,queue_point_x),vec_scale(ny,queue_point_y));
1269 //        fprintf(stderr,"queue_shot: Zque=%f\n",Zque);
1270 //        Zque=-137.020020;
1271         balls.ball[CUE_BALL_IND].v =  vec_scale(dir,-CUEBALL_MAXSPEED*queue_strength);
1272 #if options_jump_shots
1273 #else
1274         balls.ball[CUE_BALL_IND].v.z =  0.0;
1275 #endif
1276 /*        balls.ball[CUE_BALL_IND].v.x =  -CUEBALL_MAXSPEED*queue_strength*sin(Xque*M_PI/180.0)*sin(Zque*M_PI/180.0);
1277         balls.ball[CUE_BALL_IND].v.y =  -CUEBALL_MAXSPEED*queue_strength*sin(Xque*M_PI/180.0)*cos(Zque*M_PI/180.0);*/
1278 //        balls.ball[0].w.x = -2.0/balls.ball[0].d/2.0*balls.ball[0].v.y;
1279 //        balls.ball[0].w.y = +2.0/balls.ball[0].d/2.0*balls.ball[0].v.x;
1280 //        balls.ball[0].w.z = -2.0/balls.ball[0].d/2.0;
1281         if(vec_abssq(hitpoint)==0.0){
1282             balls.ball[CUE_BALL_IND].w = vec_xyz(0.0,0.0,0.0);
1283         } else {
1284             /* w = roll speed if hit 1/3of radius above center */
1285 //            balls.ball[CUE_BALL_IND].w = vec_scale(vec_cross(dir,hitpoint),4.0*3.0*CUEBALL_MAXSPEED*queue_strength/balls.ball[CUE_BALL_IND].d/balls.ball[CUE_BALL_IND].d);
1286             /* hmm, this one works better */
1287             balls.ball[CUE_BALL_IND].w = vec_scale(vec_cross(dir,hitpoint),2.0*3.0*CUEBALL_MAXSPEED*queue_strength/balls.ball[CUE_BALL_IND].d/balls.ball[CUE_BALL_IND].d);
1288         }
1289 
1290 #ifdef USE_SOUND
1291         PlaySound(&ball_cue_snd,options_snd_volume*queue_strength/2.0);
1292 #endif
1293 
1294         /* clear recorded ballpaths */
1295         {int i;
1296             for( i=0 ; i<balls.nr ; i++ ){
1297                 BM_clearpath( &balls.ball[i] );
1298             }
1299         }
1300 
1301         /* reset offset parameters */
1302         queue_point_x=0.0;
1303         queue_point_y=0.0;
1304 
1305     }
1306 }
1307 
1308 
1309 
1310 void shoot( int ani );
1311 
1312 
do_computer_move(int doit)1313 void do_computer_move( int doit )
1314 {
1315     VMvect dir;
1316 
1317     DPRINTF("do_computermove: begin ai_get_strike_dir\n");
1318 
1319     ai_set_err(player[act_player].err);
1320     dir = ai_get_stroke_dir(&balls,&walls,&player[act_player]);
1321 
1322     DPRINTF("do_computermove: end ai_get_strike_dir\n");
1323 
1324     Zque = atan2(dir.x,dir.y)/M_PI*180.0;
1325 //    Xque = atan2(sqrt(dir.x*dir.x+dir.y*dir.y),dir.z)/M_PI*180.0;
1326     if(doit){
1327         shoot( !queue_view );
1328 /*        if(!queue_view){
1329             queue_anim=30.0;
1330         } else {
1331             queue_shot();
1332         }*/
1333     }
1334     comp_dir=dir;
1335 }
1336 
do_net_move(void)1337 int do_net_move( void )
1338 {
1339     int nbytes;
1340 
1341     DPRINTF("do_net_move: start\n");
1342 
1343     nbytes=socket_read(g_socket,(char *)&(Zque),sizeof(Zque));
1344     if( nbytes==0 ) return 0;
1345     nbytes=socket_read(g_socket,(char *)&(Xque),sizeof(Xque));
1346     if( nbytes==0 ) return 0;
1347     DPRINTF("do_net_move: %d bytes read\n",nbytes);
1348     DPRINTF("Zque = %f\n",Zque);
1349 
1350     if(!queue_view){
1351         queue_anim=30.0;
1352     } else {
1353         queue_shot();
1354     }
1355     DPRINTF("do_net_move: end\n");
1356 
1357     return 1;
1358 }
1359 
1360 
queue_offs_func1(double t)1361 double queue_offs_func1( double t )
1362 {
1363     return( 1.0-cos(t*2.0*M_PI) );
1364 }
1365 
1366 
queue_offs_func2(double t)1367 double queue_offs_func2( double t )
1368 {
1369     return( sin(t*M_PI) );
1370 }
1371 
1372 
queue_offs_func(double t)1373 double queue_offs_func( double t )
1374 {
1375     double tx6, rval, dt1, dt2, dt3, dt4, dt5, dt6, t1,t2,t3,t4,t5,t6;
1376     rval=0.0;
1377     dt1=1.0;
1378     dt2=0.4;
1379     dt3=1.0;
1380     dt4=0.4;
1381     dt5=1.0;
1382     dt6=0.7;
1383     t1=dt1;
1384     t2=t1+dt2;
1385     t3=t2+dt3;
1386     t4=t3+dt4;
1387     t5=t4+dt5;
1388     t6=t5+dt6;
1389     tx6=t*t6;
1390     if       ( tx6 >= 0.0 && tx6 < t1  ){
1391         rval = 1.0*queue_offs_func1(tx6);
1392     } else if( tx6 >= t1 && tx6 < t2  ){
1393         rval = 0.0;
1394     } else if( tx6 >= t2 && tx6 < t3  ){
1395         rval = 1.0*queue_offs_func1((tx6-t2)/dt3);
1396     } else if( tx6 >= t3 && tx6 < t4  ){
1397         rval = 0.0;
1398     } else if( tx6 >= t4 && tx6 < t5  ){
1399         rval = 1.3*queue_offs_func1((tx6-t4)/dt5);
1400     } else if( tx6 >= t5 && tx6 < t6  ){
1401         rval = 6.0*queue_offs_func2((tx6-t5)/dt6*1.06);
1402     }
1403     return 0.5*(0.7+rval);
1404 //    return( 1.0+t*t*sin(t*(10.0+M_PI)) );
1405 }
1406 
1407 
net_get_send_req()1408 int net_get_send_req()
1409 {
1410     char c;
1411     if( socket_read(g_socket,&c,1)==1 && c=='R' ){
1412         return 1;
1413     }
1414     return 0;
1415 }
1416 
1417 
net_get_ack()1418 int net_get_ack()
1419 {
1420     char c;
1421     if( socket_read(g_socket,&c,1)==1 && c=='A' ){
1422         return 1;
1423     }
1424     return 0;
1425 }
1426 
1427 
net_get_data()1428 int net_get_data()
1429 {
1430     if( socket_read(g_socket,(char *)&g_net_data,sizeof(NetData))==sizeof(NetData) ){
1431         Xque=g_net_data.Xrot;
1432         Zque=g_net_data.Zrot;
1433         player[act_player].cue_x=g_net_data.cue_x;
1434         player[act_player].cue_y=g_net_data.cue_y;
1435         player[act_player].strength=g_net_data.strength;
1436         balls.ball[CUE_BALL_IND].r.x=g_net_data.white_x;
1437         balls.ball[CUE_BALL_IND].r.y=g_net_data.white_y;
1438         return 1;
1439     }
1440     return 0;
1441 }
1442 
1443 
net_send_send_req()1444 void net_send_send_req()
1445 {
1446     char c='R';
1447     socket_write(g_socket,&c,1);
1448 }
1449 
1450 
net_send_ack()1451 void net_send_ack()
1452 {
1453     char c='A';
1454     socket_write(g_socket,&c,1);
1455 }
1456 
1457 
net_send_data()1458 void net_send_data()
1459 {
1460     g_net_data.Xrot=Xque;
1461     g_net_data.Zrot=Zque;
1462     g_net_data.cue_x=player[act_player].cue_x;
1463     g_net_data.cue_y=player[act_player].cue_y;
1464     g_net_data.strength=player[act_player].strength;
1465     g_net_data.white_x=balls.ball[CUE_BALL_IND].r.x;
1466     g_net_data.white_y=balls.ball[CUE_BALL_IND].r.y;
1467     socket_write(g_socket,(char *)&g_net_data,sizeof(NetData));
1468 }
1469 
1470 
shoot(int ani)1471 void shoot( int ani )
1472 {
1473     int other_player;
1474 
1475     other_player = (act_player==0) ? 1 : 0 ;
1476     if ( player[other_player].is_net ){
1477         DPRINTF("shoot: handling unresolved net request\n");
1478         switch(g_net_state){
1479         case NET_STATE_ACK:
1480             while( !net_get_ack() );
1481         case NET_STATE_DATA:
1482             g_net_data.shoot=0;
1483             net_send_data();
1484         case NET_STATE_REQ: break;
1485         }
1486         fprintf(stderr,"shoot: sending new data with shot\n");
1487         net_send_send_req();
1488         while( !net_get_ack() );
1489         g_net_data.shoot=1;
1490         net_send_data();
1491         g_net_data.shoot=0;
1492         g_net_state=NET_STATE_REQ;
1493     }
1494 
1495     if( ani ){
1496         DPRINTF("shoot: ani-shot\n");
1497         queue_anim=30;
1498     } else {
1499         DPRINTF("shoot: direct shot\n");
1500         queue_shot();
1501     }
1502 }
1503 
1504 
1505 int
in_cue_ball_region(VMvect pos)1506 in_cue_ball_region( VMvect pos )
1507 {
1508     int in_region=1;
1509 
1510     switch(gametype){
1511     case GAME_8BALL:
1512     case GAME_9BALL:
1513         if( pos.x >  (TABLE_W-BALL_D)/2.0 )  in_region=0 ;
1514         if( pos.x < -(TABLE_W-BALL_D)/2.0 )  in_region=0 ;
1515         if( pos.y > -TABLE_L/4.0          )  in_region=0 ;
1516         if( pos.y < -(TABLE_L-BALL_D)/2.0 )  in_region=0 ;
1517         break;
1518     case GAME_CARAMBOL:
1519         break;
1520     case GAME_SNOOKER:
1521 #define TABLE_SCALE (TABLE_L/(3.571042))
1522         if( pos.y > -TABLE_L/2.0+TABLE_SCALE*0.737 ) in_region=0 ;
1523         if( vec_abs(vec_diff(pos,vec_xyz(0,-TABLE_L/2.0+TABLE_SCALE*0.737,0))) > TABLE_SCALE*0.292 ) in_region=0 ;
1524 #undef TABLE_SCALE
1525         break;
1526     }
1527 
1528     return(in_region);
1529 }
1530 
1531 int
in_table_region(VMvect pos)1532 in_table_region( VMvect pos )
1533 {
1534     int in_region=1;
1535 
1536     if( pos.x >  (TABLE_W-BALL_D)/2.0 )  in_region=0 ;
1537     if( pos.x < -(TABLE_W-BALL_D)/2.0 )  in_region=0 ;
1538     if( pos.y >  (TABLE_L-BALL_D)/2.0 )  in_region=0 ;
1539     if( pos.y < -(TABLE_L-BALL_D)/2.0 )  in_region=0 ;
1540 
1541     return(in_region);
1542 }
1543 
1544 
ball_free_place(int ind,BallsType * pballs)1545 static void ball_free_place( int ind, BallsType * pballs )
1546 {
1547         int i,exitloop;
1548         double x,y, x0,y0, r,phi;
1549         x=pballs->ball[ind].r.x; y=pballs->ball[ind].r.y;
1550         x0=x; y0=y;
1551         phi=0.0;
1552         do{
1553             exitloop=1;
1554             r=floor(phi/2.0/M_PI)*0.01;
1555             x=x0+r*cos(phi);
1556             y=y0+r*sin(phi);
1557             DPRINTF("phi=%f\n", phi);
1558             DPRINTF("ind=%d, CUE_BALL_IND=%d\n", ind, CUE_BALL_IND);
1559             if( ( ind==CUE_BALL_IND && in_cue_ball_region(vec_xyz(x,y,0)) && player[act_player].place_cue_ball ) ||
1560                 in_table_region(vec_xyz(x,y,0))
1561               )
1562             {
1563             } else exitloop=0;
1564             DPRINTF("1:exitloop=%d\n", exitloop);
1565             for(i=0;i<pballs->nr;i++) if( i!=ind && pballs->ball[i].in_game ){
1566                 if ( vec_abs(vec_diff(vec_xyz(x,y,0),pballs->ball[i].r)) <
1567                      (pballs->ball[ind].d+pballs->ball[i].d)/2.0 )
1568                 { exitloop=0; break; }
1569             }
1570             DPRINTF("2:exitloop=%d\n", exitloop);
1571             phi+=0.01;
1572         } while(!exitloop);
1573         pballs->ball[ind].r.x=x;
1574         pballs->ball[ind].r.y=y;
1575 }
1576 
all_balls_free_place(BallsType * pballs)1577 static void all_balls_free_place(BallsType * pballs)
1578 {
1579     int i;
1580     for(i=0;i<pballs->nr;i++) if( pballs->ball[i].in_game ){
1581         ball_free_place( i, pballs );
1582     }
1583 }
1584 
1585 
1586 //static void Idle_timer( int value )
Idle_timer(void)1587 static void Idle_timer( void )
1588 {
1589     int i;
1590 //    static int balls_moving=0;
1591     static int balls_were_moving=0;
1592     static int first_time=1;
1593     int t_act;
1594     static int dt;
1595     static int t_prev=-1;
1596     static int frametime_rest=0;
1597 //    static int frametime_fromlast=0;
1598 //    static int framestep=0;
1599     static int dt_rest=0;
1600     static int count=0;
1601     static double dt_s_rest=0.0;
1602 //    static int waiting_for_net_data=0;
1603     int other_player;
1604     double fact;
1605 
1606     count++;
1607     t_act   = time_us();
1608     if (t_prev==-1)  t_prev=t_act;
1609     dt     += t_act-t_prev;
1610     dt_s_rest += (double)(t_act-t_prev)/1000000.0;
1611     t_prev  = t_act;
1612     if(count==1){
1613         count=0;
1614         frametime_ms=(int)((double)dt/1000.0);
1615         if( frametime_ms<1 ) frametime_ms=1;
1616 //        if( frametime_ms<frametime_ms_min ) frametime_ms=frametime_ms_min;
1617         if( frametime_ms>frametime_ms_max ) frametime_ms=frametime_ms_max;
1618         dt=0;
1619         dt_rest+=frametime_ms;
1620 //        frametime_ms=frametime_ms_min;
1621     }
1622 
1623 //    glutTimerFunc( frametime_ms*0.8,       /* -5 for assuring framerate increase */
1624 //                   Idle_timer, value );  /* assure a framerate of max ... fps */
1625 
1626 //    glutTimerFunc( frametime_ms_min, Idle_timer, value );
1627     sys_set_timer( frametime_ms_min, Idle_timer) ;
1628 
1629 #ifdef USE_SOUND
1630 #ifndef USE_SDL
1631     mixaudio();
1632 #endif
1633 #endif
1634 
1635 //    fprintf(stderr,"dt=%d\n",dt);
1636     fact=pow(0.85,(double)frametime_ms/50.0);
1637 //    fact=0.85;
1638     Xrot_offs *= fact;
1639     Zrot_offs *= fact;
1640     fact=pow(0.94,(double)frametime_ms/50.0);
1641 //    fact=0.94;
1642     cam_dist = (cam_dist*fact)+(cam_dist_aim+vec_abs(balls.ball[CUE_BALL_IND].v)*0.4)*(1.0-fact);
1643 
1644     free_view_pos = vec_add( vec_scale( free_view_pos, fact ), vec_scale( free_view_pos_aim, 1.0-fact ) );
1645 
1646 
1647     if (Animate) {
1648 //        int bhit=0;
1649 //        int whit=0;
1650         double bhitstrength=0.0;
1651         double whitstrength=0.0;
1652         double toffs=0.0;
1653 
1654 //      Xrot += DXrot;
1655 //      Yrot += DYrot;
1656 
1657 #if 0
1658         first_time=1; /* to get into loop when balls not moving */
1659         for(i=0;
1660             (balls_moving || first_time ) &&
1661             (
1662              i<(frametime_ms+frametime_rest)/(int)(10.0/g_motion_ratio) /* assure constant time flow */
1663             );
1664             i++)
1665 #else
1666        while(dt_s_rest>0.0) /* assure constant time flow */
1667 #endif
1668        {
1669         first_time=0; /* to get into loop when balls not moving */
1670 //       for(i=0;i<(frametime_ms+frametime_rest)/3;i++){   /* assure constant time flow */
1671 //       for(i=0;i<(frametime_ms+5)/10;i++){   /* assure constant time flow */
1672 //           balls_moving = proceed_dt( &balls, &walls, 0.01 );
1673 #ifdef TIME_INTERPOLATE
1674            copy_balls(&balls,&g_lastballs);
1675 #endif
1676 #define TIMESTEP 0.0075
1677            dt_s_rest-=TIMESTEP/0.75/g_motion_ratio;
1678 //           printf("g_motion_ratio=%f\n",g_motion_ratio);
1679            balls_moving = proceed_dt( &balls, &walls, TIMESTEP );
1680            if(balls_moving) balls_were_moving = 1;
1681            /* 0.0075 instead of 0.01 - finetuning */
1682 /*           bhitstrength+=BM_get_balls_hit_strength_last();
1683            whitstrength+=BM_get_walls_hit_strength_last();*/
1684 //           fprintf(stderr,"whitstrength=%f\n",whitstrength);
1685 //           fprintf(stderr,"bhitstrength=%f\n",bhitstrength);
1686 #ifdef USE_SOUND
1687            {
1688            int index;
1689            index=0;
1690            do{
1691                BM_get_balls_hit_strength_last_index( index++ ,&bhitstrength, &toffs );
1692                bhitstrength = 1.75 * (0.3 * bhitstrength / CUEBALL_MAXSPEED +
1693                                       0.7 * bhitstrength*bhitstrength / CUEBALL_MAXSPEED / CUEBALL_MAXSPEED);
1694                if(bhitstrength!=0.0){
1695                    if( toffs>TIMESTEP || toffs<0.0 ){
1696                        exit(0);
1697                    }else{
1698 //                       printf("toffs/TIMESTEP=%f\n",toffs/TIMESTEP);
1699                    }
1700                    PlaySound_offs(&ball_ball_snd,options_snd_volume*((bhitstrength>1.0)?1.0:bhitstrength), SOUND_NULLOFFS-(TIMESTEP-toffs)*22050);
1701                }
1702            } while(bhitstrength!=0.0);
1703            index=0;
1704            do{
1705                BM_get_walls_hit_strength_last_index( index++ ,&whitstrength, &toffs );
1706                whitstrength = 0.4 * (0.3 * whitstrength / CUEBALL_MAXSPEED +
1707                                      0.7 * whitstrength*whitstrength / CUEBALL_MAXSPEED / CUEBALL_MAXSPEED);
1708                if(whitstrength!=0.0){
1709                   PlaySound_offs(&ball_wall_snd,options_snd_volume*((whitstrength>1.0)?1.0:whitstrength), SOUND_NULLOFFS-(TIMESTEP-toffs)*22050);
1710 //                  PlaySound(&ball_wall_snd,(whitstrength*0.125>1.0)?1.0:whitstrength*0.125);
1711                }
1712            } while(whitstrength!=0.0);
1713            }
1714 #endif
1715         if (!balls_moving) break;
1716        }
1717        if (dt_s_rest>0.0) dt_s_rest=0.0; /* to move on if last move was completely in last simulation step */
1718 #ifdef TIME_INTERPOLATE
1719        if((frametime_ms+frametime_rest)/10>0)
1720            g_frametime_laststep = (frametime_ms+frametime_rest)/10*10;
1721        g_frametime_fromlast = frametime_rest;
1722 #endif
1723        frametime_rest = (frametime_ms+frametime_rest) % 10;
1724 
1725        if(options_balltrace){
1726            for(i=0;i<balls.nr;i++) if( balls.ball[i].in_game ){
1727                BM_add2path( &balls.ball[i] );
1728            }
1729        }
1730 
1731 /*#ifdef USE_SDL
1732        if(bhitstrength!=0.0){
1733            PlaySound(&ball_ball_snd,(bhitstrength*0.25>1.0)?1.0:bhitstrength*0.25);
1734        }
1735        if(whitstrength!=0.0){
1736            PlaySound(&ball_wall_snd,(whitstrength*0.125>1.0)?1.0:whitstrength*0.125);
1737        }
1738 #endif*/
1739 /*       for(;dt_rest>=10;dt_rest-=10){
1740            balls_moving = proceed_dt( &balls, &walls, 0.0075 );
1741        }*/
1742        if( (!balls_moving) && balls_were_moving ){
1743            int i;
1744            int old_queue_view;
1745 
1746            /* allways a shot to be due when balls just stopped moving */
1747            g_shot_due=1;
1748            balls_were_moving=0;
1749 
1750            //           evaluate_last_move();
1751            old_queue_view=queue_view;
1752            if(options_gamemode!=options_gamemode_training){
1753                evaluate_last_move( player, &act_player, &balls, &queue_view, &Xque );
1754                if(!tournament_state.wait_for_next_match &&
1755                   options_gamemode==options_gamemode_tournament &&
1756                   (player[0].winner || player[1].winner) )
1757                {
1758                    tournament_evaluate_last_match( &tournament_state );
1759                    tournament_state.wait_for_next_match=1;
1760                }
1761            } else {
1762                int old_cueball_ind;
1763                player[act_player].place_cue_ball=1;
1764                /* find a ball still in game */
1765                old_cueball_ind=CUE_BALL_IND;
1766                while(!balls.ball[CUE_BALL_IND].in_game){
1767                    CUE_BALL_IND++;
1768                    if(CUE_BALL_IND==balls.nr) CUE_BALL_IND=0;
1769                    if(CUE_BALL_IND==old_cueball_ind) break;
1770                }
1771            }
1772            if( old_queue_view==1 && queue_view==0  ) /* this is sloppy and ugly */
1773            { /* set free_view_pos to actual view */
1774                double th=Xrot/180.0*M_PI;
1775                double ph=Zrot/180.0*M_PI;
1776                free_view_pos_aim = vec_scale(vec_xyz(sin(th)*sin(ph),sin(th)*cos(ph),cos(th)), cam_dist);
1777                free_view_pos_aim = vec_add( free_view_pos_aim, CUE_BALL_XYPOS );
1778                free_view_pos = free_view_pos_aim ;
1779            }
1780 
1781            /* no balls should overlap */
1782            all_balls_free_place(&balls);
1783 
1784            /* score text */
1785            for(i=0;i<2;i++){
1786                char str[256];
1787                switch(gametype){
1788                case GAME_8BALL: strcpy(str,"0"); break;
1789                case GAME_9BALL:
1790                    {
1791                        int j;
1792                        int minballnr=15;
1793                        for(j=0;j<balls.nr;j++){
1794                            if(balls.ball[j].nr<minballnr && balls.ball[j].nr!=0 && balls.ball[j].in_game)
1795                                minballnr=balls.ball[j].nr;
1796                        }
1797                        player[i].next_9ball = minballnr;
1798                        sprintf( str, "next:%d", minballnr );
1799                    }
1800                    break;
1801                case GAME_CARAMBOL:
1802                    sprintf( str, "%d", player[i].score );
1803                    break;
1804                case GAME_SNOOKER:
1805                    sprintf( str, "%c%03d  %s", (player[i].score<0)?'-':'+', abs(player[i].score), player[i].snooker_on_red ? "red":"col" );
1806                    break;
1807                }
1808                textObj_setText( player[i].score_text, str );
1809            }
1810        }
1811        if(g_shot_due &&
1812           !( options_gamemode==options_gamemode_tournament &&
1813             (tournament_state.wait_for_next_match || tournament_state.tournament_over)
1814            )
1815 /*          g_act_menu==0 &&
1816           !helpscreen_on*/
1817          )
1818        {
1819 //           first_time=0;
1820            g_shot_due=0;
1821            if( player[act_player].is_AI && !(player[act_player].winner || player[(act_player+1)%2].winner) ){
1822                do_computer_move(1);
1823            }
1824            if( (!player[act_player].is_AI) && player[act_player].is_net ){
1825                fprintf(stderr,"waiting for net move----------------------------------------------\n");
1826                //               do_net_move();
1827            }
1828        }
1829        other_player = (act_player==0) ? 1 : 0 ;
1830        if( !balls_moving && queue_anim==0.0 ){
1831 #if 1
1832            if      ( player[act_player].is_net ){
1833                switch(g_net_state){
1834                case NET_STATE_REQ:
1835 //                   fprintf(stderr,"NET_STATE_REQ\n");
1836                    if( net_get_send_req() )  g_net_state=NET_STATE_ACK;
1837                    break;
1838                case NET_STATE_ACK:
1839 //                   fprintf(stderr,"NET_STATE_ACK\n");
1840                    net_send_ack();           g_net_state=NET_STATE_DATA;
1841                    break;
1842                case NET_STATE_DATA:
1843 //                   fprintf(stderr,"NET_STATE_DATA\n");
1844                    if( net_get_data() )      g_net_state=NET_STATE_REQ;
1845                    if (g_net_data.shoot){
1846                        g_net_data.shoot=0;
1847                        shoot( !queue_view );
1848                    }
1849                    break;
1850                }
1851            } else if ( player[other_player].is_net ){
1852                switch(g_net_state){
1853                case NET_STATE_REQ:
1854 //                   fprintf(stderr,"NET_STATE_REQ\n");
1855                    net_send_send_req();      g_net_state=NET_STATE_ACK;
1856                    break;
1857                case NET_STATE_ACK:
1858 //                   fprintf(stderr,"NET_STATE_ACK\n");
1859                    if( net_get_ack() )       g_net_state=NET_STATE_DATA;
1860                    break;
1861                case NET_STATE_DATA:
1862 //                   fprintf(stderr,"NET_STATE_DATA\n");
1863                    g_net_data.shoot=0;
1864                    net_send_data();          g_net_state=NET_STATE_REQ;
1865                    break;
1866                }
1867            }//    glutPostRedisplay();
1868 #endif
1869        }
1870 //       balls_moving = 1;
1871        if ( queue_anim > 0.0 ){
1872 //           fprintf(stderr,"frametime_ms=%f",frametime_ms);
1873 //           queue_anim-=(double)frametime_ms*frametime_ms/40.0/40.0;
1874            queue_anim-=(double)frametime_ms/120.0*g_motion_ratio;
1875 //           queue_anim-=40.0/(double)frametime_ms;
1876            if (queue_anim<0.0) queue_anim=0.0;
1877 //           queue_offs=0.16+( 0.16*(30.0-queue_anim)*(30.0-queue_anim)/30.0/30.0*sin((30.0-queue_anim)/3.0) );
1878            queue_offs=0.16*queue_offs_func((30.0-queue_anim)/30.0);
1879            if( queue_anim==0.0 ){
1880                queue_shot();
1881                queue_offs=0.06;
1882            }
1883        }
1884 //       glutPostRedisplay();
1885        sys_redisplay();
1886    } else {
1887 //       glutPostRedisplay();
1888        sys_redisplay();
1889    }
1890 }
1891 
1892 
1893 
1894 
1895 /*static void Display_timer( int value )
1896 {
1897     glutTimerFunc( frametime_ms_max, Display_timer, value );
1898     glutPostRedisplay();
1899 }*/
1900 
1901 
1902 
strength01(double value)1903 double strength01( double value )
1904 {
1905     if( value > 1.0 ) value=1.0;
1906     if( value < 0.0 ) value=0.0;
1907     return value;
1908 }
1909 
1910 
1911 void
MouseEvent(MouseButtonEnum button,MouseButtonState state,int x,int y,int key_modifiers)1912 MouseEvent(MouseButtonEnum button,MouseButtonState  state, int x, int y,int key_modifiers)
1913 //MouseEvent(int button, int state, int x, int y)
1914 {
1915 //    key_modifiers=glutGetModifiers();
1916 
1917     if ( g_act_menu != 0 ) {
1918 
1919 //        fprintf(stderr,"x,y=%d,%d\n",x,y);
1920         menu_select_by_coord( g_act_menu, x-win_width/2, -y+win_height/2 );
1921         if ( button==MOUSE_LEFT_BUTTON && state==MOUSE_DOWN ) menu_choose(&g_act_menu);
1922 
1923 /*    } else if (options_gamemode==options_gamemode_tournament && tournament_state.wait_for_next_match) {
1924         if (button == MOUSE_MIDDLE_BUTTON && state == MOUSE_UP) {
1925             tournament_state_setup_next_match(&tournament_state);
1926             tournament_state.wait_for_next_match=0;
1927         }*/
1928     } else {
1929 
1930         if (button == MOUSE_LEFT_BUTTON) {
1931             if (state == MOUSE_DOWN) {
1932                 if(b2_hold){
1933                     b2_b1_hold = 1;
1934                 } else {
1935                     b1_hold = 1;
1936                     start_x = x;
1937                     start_y = y;
1938                 }
1939             }
1940             if (state == MOUSE_UP) {
1941                 b1_hold = 0;
1942                 b2_b1_hold = 0;
1943             }
1944         }
1945         if (button == MOUSE_RIGHT_BUTTON){
1946             if (state == MOUSE_DOWN) {
1947                 mouse_moved_after_b1_dn = 0;
1948                 if ( b1_hold ){
1949                     b1_b2_hold = 1;
1950                 } else {
1951                     b2_hold = 1;
1952                     scaling_start = y;
1953                     scaling_start2 = x;
1954                 }
1955             }
1956             if (state == MOUSE_UP) {
1957                 if(b1_b2_hold && !mouse_moved_after_b1_dn) toggle_queue_view();
1958                 b1_b2_hold = 0;
1959                 b2_hold = 0;
1960             }
1961         }
1962         if (button == MOUSE_MIDDLE_BUTTON) {
1963             if (state == MOUSE_UP) {
1964                 /* this has to be the same as enter,space key !!! - maybe put it in a function some day  */
1965                 if (options_gamemode==options_gamemode_tournament && tournament_state.wait_for_next_match) {
1966                     tournament_state_setup_next_match(&tournament_state);
1967                     tournament_state.wait_for_next_match=0;
1968                 } else if((!player[act_player].is_net) && (!player[act_player].is_AI)){
1969                     g_shot_due=0;
1970                     shoot( !queue_view );
1971                 }
1972             }
1973         }
1974         if (button == MOUSE_WHEEL_UP_BUTTON) {
1975             if(!player[act_player].is_AI && !balls_moving)
1976                 queue_strength = strength01( queue_strength+0.01 );
1977         }
1978         if (button == MOUSE_WHEEL_DOWN_BUTTON) {
1979             if(!player[act_player].is_AI && !balls_moving)
1980                 queue_strength = strength01( queue_strength-0.01 );
1981         }
1982 
1983     }
1984 //    fprintf(stderr,"button=%d\n", button);
1985 //    glutPostRedisplay();
1986     sys_redisplay();
1987 }
1988 
1989 
1990 void
ball_displace_clip(VMvect * cue_pos,VMvect offs)1991 ball_displace_clip( VMvect * cue_pos, VMvect offs )
1992 {
1993     VMvect newpos;
1994 
1995     newpos = vec_add( *cue_pos, offs );
1996 
1997     if(options_gamemode==options_gamemode_training){
1998 
1999         if( newpos.x >  (TABLE_W-BALL_D)/2.0 ) newpos.x= (TABLE_W-BALL_D)/2.0 ;
2000         if( newpos.x < -(TABLE_W-BALL_D)/2.0 ) newpos.x=-(TABLE_W-BALL_D)/2.0 ;
2001         if( newpos.y >  (TABLE_L-BALL_D)/2.0 ) newpos.y= (TABLE_L-BALL_D)/2.0 ;
2002         if( newpos.y < -(TABLE_L-BALL_D)/2.0 ) newpos.y=-(TABLE_L-BALL_D)/2.0 ;
2003 
2004     } else {
2005 
2006         switch(gametype){
2007         case GAME_8BALL:
2008         case GAME_9BALL:
2009             if( newpos.x >  (TABLE_W-BALL_D)/2.0 ) newpos.x= (TABLE_W-BALL_D)/2.0 ;
2010             if( newpos.x < -(TABLE_W-BALL_D)/2.0 ) newpos.x=-(TABLE_W-BALL_D)/2.0 ;
2011             if( newpos.y > -TABLE_L/4.0          ) newpos.y= -TABLE_L/4.0 ;
2012             if( newpos.y < -(TABLE_L-BALL_D)/2.0 ) newpos.y=-(TABLE_L-BALL_D)/2.0 ;
2013             break;
2014         case GAME_CARAMBOL:
2015             break;
2016         case GAME_SNOOKER:
2017 #define TABLE_SCALE (TABLE_L/(3.571042))
2018             if( newpos.y > -TABLE_L/2.0+TABLE_SCALE*0.737 ) newpos.y= -TABLE_L/2.0+TABLE_SCALE*0.737 ;
2019             newpos = vec_diff(newpos,vec_xyz(0,-TABLE_L/2.0+TABLE_SCALE*0.737,0));
2020             if( vec_abs(newpos) > TABLE_SCALE*0.292 ) newpos = vec_scale( vec_unit(newpos), TABLE_SCALE*0.292 ) ;
2021             newpos = vec_add(newpos,vec_xyz(0,-TABLE_L/2+TABLE_SCALE*0.737,0));
2022 #undef TABLE_SCALE
2023             break;
2024         }
2025     }
2026 
2027     *cue_pos=newpos;
2028 }
2029 
2030 
2031 void
MouseMotion(int x,int y,int key_modifiers)2032 MouseMotion(int x, int y, int key_modifiers)
2033 {
2034     static double acc;
2035     int place_cue_ball=0;
2036 //    int other_player;
2037 
2038     if (control__updated) {
2039         printf("updated\n");
2040         start_x = x;
2041         start_y = y;
2042         scaling_start = y;
2043         scaling_start2 = x;
2044         control__updated=0;
2045     }
2046 
2047     mouse_moved_after_b1_dn = 1;
2048 
2049     if( g_act_menu != 0 ){
2050 //        fprintf(stderr,"x,y=%d,%d\n",x,y);
2051         menu_select_by_coord( g_act_menu, x-win_width/2, -y+win_height/2 );
2052     } else {
2053 
2054     acc=1.0;
2055 
2056     if(control__active){
2057         if        ( control__place_cue_ball ){
2058             if( player[act_player].place_cue_ball && !balls_moving  && !player[act_player].is_AI && !player[act_player].is_net ){
2059                 VMvect xv,yv, whitepos;
2060                 double dx,dy;
2061                 int i, move_ok;
2062 
2063                 dx=(double)(x-start_x);
2064                 dx=dx*0.0001+fabs(dx)*dx*0.0002;
2065                 dy=(double)(y-start_y);
2066                 dy=dy*0.0001+fabs(dy)*dy*0.0002;
2067                 xv=vec_xyz(+dx*cos(Zrot/180.0*M_PI),-dx*sin(Zrot/180.0*M_PI),0.0);
2068                 yv=vec_xyz(-dy*sin(Zrot/180.0*M_PI),-dy*cos(Zrot/180.0*M_PI),0.0);
2069                 whitepos=balls.ball[CUE_BALL_IND].r;
2070                 ball_displace_clip( &(balls.ball[CUE_BALL_IND].r), vec_add(xv,yv) );
2071                 move_ok=1;
2072                 for(i=0;i<balls.nr;i++){
2073                     if(i!=CUE_BALL_IND){
2074                         move_ok = move_ok &&
2075                             ( vec_abs(vec_diff(balls.ball[CUE_BALL_IND].r,balls.ball[i].r))>(balls.ball[CUE_BALL_IND].d+balls.ball[i].d)/2.0 ||
2076                              (!balls.ball[i].in_game) );
2077                     }
2078                 }
2079                 if(!move_ok) balls.ball[CUE_BALL_IND].r=whitepos;
2080             }
2081         } else if ( control__mouse_shoot ){
2082             if( (!queue_view) && (!balls_moving) &&
2083                !player[act_player].is_AI && !player[act_player].is_net ) {  /* dynamic cue shot */
2084                 queue_offs+=(double)(y-start_y)*0.002;
2085                 //        if( queue_offs < balls.ball[0].d/2.0 ) shoot();
2086                 queue_strength=strength01( -0.02*(double)(y-start_y) );
2087                 if( queue_offs < balls.ball[CUE_BALL_IND].d/2.0 ){
2088                     queue_offs=0.04;
2089                     //                queue_shot();
2090                     shoot(0);
2091                 }
2092                 start_x = x;
2093                 start_y = y;
2094             }
2095         } else if ( control__english ){
2096             if( !player[act_player].is_AI && !player[act_player].is_net ){
2097                 double queue_point_abs;
2098                 queue_point_y +=  (y-scaling_start)*0.0005;
2099                 queue_point_x +=  (x-scaling_start2)*0.0005;
2100                 queue_point_abs=sqrt(queue_point_y*queue_point_y+queue_point_x*queue_point_x);
2101                 if( queue_point_abs>(BALL_D-QUEUE_D2)/2.0 ){
2102                     queue_point_x=queue_point_x/queue_point_abs*(BALL_D-QUEUE_D2)/2.0;
2103                     queue_point_y=queue_point_y/queue_point_abs*(BALL_D-QUEUE_D2)/2.0;
2104                 }
2105                 scaling_start = y;
2106                 scaling_start2 = x;
2107             }
2108         } else if ( control__cue_butt_updown ){
2109             double Xoffs;
2110             Xoffs =  (double)(y-start_y)*0.02*acc;
2111             Xoffs +=  (double)(y-start_y)*fabs(y-start_y)*0.01*acc;
2112             if( Xque+Xoffs < -90.0  ) Xoffs=-90.0-Xque;
2113             if( Xque+Xoffs >   0.0  ) Xoffs=  0.0-Xque;
2114 //            Xrot += Xoffs;
2115 //            Xrot_offs -= Xoffs;
2116             Xque+=Xoffs;
2117 /*            if( queue_view ){
2118                 Xque=Xrot;
2119             }*/
2120         }
2121         start_x = x;
2122         start_y = y;
2123         scaling_start = y;
2124         scaling_start2 = x;
2125 
2126     }else if(b1_hold){
2127         if( (key_modifiers & KEY_MODIFIER_SHIFT) || b1_b2_hold )
2128             place_cue_ball=player[act_player].place_cue_ball;
2129         if( (key_modifiers & KEY_MODIFIER_CTRL) && (!queue_view) && (!balls_moving) &&
2130             !player[act_player].is_AI && !player[act_player].is_net ) {  /* dynamic cue shot */
2131             queue_offs+=(double)(y-start_y)*0.002;
2132             //        if( queue_offs < balls.ball[0].d/2.0 ) shoot();
2133             queue_strength=strength01( -0.02*(double)(y-start_y) );
2134             if( queue_offs < balls.ball[CUE_BALL_IND].d/2.0 ){
2135                 queue_offs=0.04;
2136                 //                queue_shot();
2137                 shoot(0);
2138             }
2139             start_x = x;
2140             start_y = y;
2141         }else if( !place_cue_ball && !(key_modifiers & KEY_MODIFIER_CTRL) ){
2142             double Xoffs,Zoffs;
2143 /*            Xrot +=  (double)(y-start_y)*acc;
2144             Zrot +=  (double)(x-start_x)*acc;
2145             if( Xrot < -90.0  ) Xrot=-90.0;
2146             if( Xrot >   0.0  ) Xrot= 0.0;*/
2147             Xoffs =  (double)(y-start_y)*0.02*acc;
2148             Zoffs =  (double)(x-start_x)*0.02*acc;
2149             Xoffs +=  (double)(y-start_y)*fabs(y-start_y)*0.01*acc;
2150             Zoffs +=  (double)(x-start_x)*fabs(x-start_x)*0.01*acc;
2151             if( Xrot+Xoffs < -90.0  ) Xoffs=-90.0-Xrot;
2152             if( Xrot+Xoffs >   0.0  ) Xoffs=  0.0-Xrot;
2153             Xrot += Xoffs;
2154             Zrot += Zoffs;
2155             Xrot_offs -= Xoffs;
2156             Zrot_offs -= Zoffs;
2157             if( queue_view ){
2158                 Xque=Xrot;
2159                 Zque=Zrot;
2160             }
2161         } else if( place_cue_ball && !balls_moving  && !player[act_player].is_AI && !player[act_player].is_net ){
2162             VMvect xv,yv, whitepos;
2163             double dx,dy;
2164             int i, move_ok;
2165 //            dx=(double)(x-start_x)*acc*0.005;
2166 //            dy=(double)(y-start_y)*acc*0.005;
2167             dx=(double)(x-start_x);
2168             dx=dx*0.0001+fabs(dx)*dx*0.0002;
2169             dy=(double)(y-start_y);
2170             dy=dy*0.0001+fabs(dy)*dy*0.0002;
2171 //            yv=vec_xyz(dx*cos(Zrot),-dx*sin(Zrot),0.0);
2172             xv=vec_xyz(+dx*cos(Zrot/180.0*M_PI),-dx*sin(Zrot/180.0*M_PI),0.0);
2173             yv=vec_xyz(-dy*sin(Zrot/180.0*M_PI),-dy*cos(Zrot/180.0*M_PI),0.0);
2174             whitepos=balls.ball[CUE_BALL_IND].r;
2175             ball_displace_clip( &(balls.ball[CUE_BALL_IND].r), vec_add(xv,yv) );
2176             /*
2177             balls.ball[CUE_BALL_IND].r = vec_add( balls.ball[CUE_BALL_IND].r, xv );
2178             balls.ball[CUE_BALL_IND].r = vec_add( balls.ball[CUE_BALL_IND].r, yv );
2179             if( balls.ball[CUE_BALL_IND].r.x >  (TABLE_W-BALL_D)/2.0 ) balls.ball[CUE_BALL_IND].r.x= (TABLE_W-BALL_D)/2.0 ;
2180             if( balls.ball[CUE_BALL_IND].r.x < -(TABLE_W-BALL_D)/2.0 ) balls.ball[CUE_BALL_IND].r.x=-(TABLE_W-BALL_D)/2.0 ;
2181             if( balls.ball[CUE_BALL_IND].r.y > -TABLE_L/4.0          ) balls.ball[CUE_BALL_IND].r.y= -TABLE_L/4.0 ;
2182             if( balls.ball[CUE_BALL_IND].r.y < -(TABLE_L-BALL_D)/2.0 ) balls.ball[CUE_BALL_IND].r.y=-(TABLE_L-BALL_D)/2.0 ;
2183             */
2184             move_ok=1;
2185             for(i=0;i<balls.nr;i++){
2186                 if(i!=CUE_BALL_IND){
2187                     move_ok = move_ok &&
2188                         ( vec_abs(vec_diff(balls.ball[CUE_BALL_IND].r,balls.ball[i].r))>(balls.ball[CUE_BALL_IND].d+balls.ball[i].d)/2.0 ||
2189                          (!balls.ball[i].in_game) );
2190                 }
2191             }
2192             if(!move_ok) balls.ball[CUE_BALL_IND].r=whitepos;
2193         }
2194         start_x = x;
2195         start_y = y;
2196     } else if(b2_hold){
2197         if( key_modifiers & KEY_MODIFIER_CTRL ){
2198             double old_FOV;
2199             old_FOV=cam_FOV;
2200             cam_FOV  +=  (y-scaling_start)*0.05;
2201             if( cam_FOV<10.0 ) cam_FOV=10.0;
2202             if( cam_FOV>110.0 ) cam_FOV=110.0;
2203             cam_dist_aim = cam_dist_aim*tan(old_FOV*M_PI/360.0)/tan(cam_FOV*M_PI/360.0);
2204             cam_dist = cam_dist_aim;
2205             scaling_start = y;
2206         } else if( ( (key_modifiers & KEY_MODIFIER_SHIFT) || b2_b1_hold ) && /*!queue_view &&*/
2207                    !player[act_player].is_AI && !player[act_player].is_net ){
2208             double queue_point_abs;
2209             queue_point_y +=  (y-scaling_start)*0.0005;
2210             queue_point_x +=  (x-scaling_start2)*0.0005;
2211             queue_point_abs=sqrt(queue_point_y*queue_point_y+queue_point_x*queue_point_x);
2212             if( queue_point_abs>(BALL_D-QUEUE_D2)/2.0 ){
2213                 queue_point_x=queue_point_x/queue_point_abs*(BALL_D-QUEUE_D2)/2.0;
2214                 queue_point_y=queue_point_y/queue_point_abs*(BALL_D-QUEUE_D2)/2.0;
2215             }
2216 //            fprintf(stderr,"queue_point_x: %f\n",queue_point_x);
2217 //            fprintf(stderr,"queue_point_y: %f\n",queue_point_y);
2218 //            if( cam_dist_aim<0.0 ) cam_dist_aim=0.0;
2219             scaling_start = y;
2220             scaling_start2 = x;
2221         } else {
2222             if(!FREE_VIEW){
2223                 cam_dist_aim +=  (y-scaling_start)*0.005;
2224                 if( cam_dist_aim<0.0 ) cam_dist_aim=0.0;
2225                 scaling_start = y;
2226             } else {
2227                 double th, ph;
2228                 VMvect dvec;
2229                 th=Xrot/180.0*M_PI;
2230                 ph=Zrot/180.0*M_PI;
2231                 dvec = vec_xyz(sin(th)*sin(ph),sin(th)*cos(ph),cos(th));
2232                 dvec = vec_scale( dvec , (y-scaling_start)*0.005 );
2233                 free_view_pos_aim = vec_add( free_view_pos_aim, dvec );
2234                 if( free_view_pos_aim.z < 0.1 ) free_view_pos_aim.z = 0.1;
2235                 scaling_start = y;
2236             }
2237         }
2238     }
2239 
2240     }
2241     sys_redisplay();
2242 }
2243 
2244 
myRect2D(double x1,double y1,double x2,double y2)2245 void myRect2D( double x1, double y1, double x2, double y2 )
2246 {
2247     glBegin(GL_QUADS);
2248     glVertex3f(x1,y1,-0.5);
2249     glVertex3f(x1,y2,-0.5);
2250     glVertex3f(x2,y2,-0.5);
2251     glVertex3f(x2,y1,-0.5);
2252     glEnd();
2253 }
2254 
2255 
2256 #ifdef TIME_INTERPOLATE
interpolate_balls(BallsType * balls1,BallsType * balls2,BallsType * newballs,double ratio)2257 void interpolate_balls( BallsType * balls1, BallsType * balls2, BallsType * newballs, double ratio )
2258 {
2259     int i,j;
2260 //    fprintf(stderr,"ratio=%f",ratio);
2261     for(i=0;i<balls2->nr;i++){
2262         newballs->ball[i]=balls2->ball[i];
2263         newballs->ball[i].r = vec_add(
2264                                       vec_scale(balls1->ball[i].r,1.0-ratio),
2265                                       vec_scale(balls2->ball[i].r,ratio)
2266                                      );
2267         for(j=0;j<3;j++)
2268             newballs->ball[i].b[j] = vec_unit(vec_add(
2269                                                       vec_scale(balls1->ball[i].b[j],1.0-ratio),
2270                                                       vec_scale(balls2->ball[i].b[j],ratio)
2271                                                      )
2272                                               );
2273     }
2274 }
2275 #endif
2276 
2277 
2278 #if 0
2279 void cull_balls( BallsType balls, myvec cam_pos, int win_width, int win_height, float cam_FOV, float th, float ph)
2280 {
2281     int ballnr;
2282     double d, ang, ang1, ang2;
2283     double cam_FOV2;
2284     VMvect dvec, ballvec, right, up, cam_pos_;
2285 
2286     cam_FOV2=2.0*180.0/M_PI*atan(tan(cam_FOV*M_PI/180.0/2.0)/win_width*win_height);
2287 
2288 //    th=(Xrot+Xrot_offs)/180.0*M_PI;
2289 //    ph=(Zrot+Zrot_offs)/180.0*M_PI;
2290     th=th/180.0*M_PI;
2291     ph=ph/180.0*M_PI;
2292     dvec  = vec_xyz(-sin(th)*sin(ph),-sin(th)*cos(ph),-cos(th));
2293     for(ballnr=0;ballnr<balls.ball[i];ballnr++){
2294         cam_pos_ = vec_diff( cam_pos, vec_scale(dvec,balls.ball[ballnr].d/2.0/sin(cam_FOV*M_PI/180.0/2.0)) );
2295         right = vec_unit(vec_xyz(dvec.y,-dvec.x,0));
2296         up    = vec_cross(right,dvec);
2297         ballvec = vec_diff(balls.ball[ballnr].r,cam_pos_);
2298         ang1  = atan2( vec_mul(ballvec, right), vec_mul(ballvec, dvec) );
2299         ang2  = atan2( vec_mul(ballvec, up),    vec_mul(ballvec, dvec) );
2300         d = vec_mul(vec_diff(balls.ball[ballnr].r,cam_pos_),dvec);
2301         ang = d/vec_abs(ballvec);
2302         ang = (fabs(ang)<1.0)?acos(ang):0.0;
2303         if(
2304            fabs(ang1) < cam_FOV*M_PI/180.0/2.0 &&
2305            fabs(ang2) < cam_FOV2*M_PI/180.0/2.0
2306           )
2307         {
2308             balls.ball[ballnr].in_fov=1;
2309         } else {
2310             balls.ball[ballnr].in_fov=1;
2311         }
2312     }
2313 }
2314 #endif
2315 
2316 
draw_3D_winner_text()2317 void draw_3D_winner_text()
2318 {
2319     static double ang=0.0;
2320     static double tprev=0.0;
2321     double t;
2322     double dt;
2323 
2324     t=time_us();
2325     dt=(t-tprev)/1000000.0;
2326     tprev=t;
2327 
2328     textObj_setText( winner_name_text_obj, player[player[0].winner?0:1].name );
2329     //           glDisable(GL_TEXTURE_2D);
2330     glDisable(GL_LIGHTING);
2331     glEnable(GL_TEXTURE_GEN_S);
2332     glEnable(GL_TEXTURE_GEN_T);
2333     glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
2334     glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
2335     glColor3f(1.0,1.0,1.0);
2336     glBindTexture(GL_TEXTURE_2D, spheretexbind);
2337     glPushMatrix();
2338     glRotatef(ang+=60.0*dt,0,0,1);
2339     glTranslatef(0,0,0.35);
2340     glRotatef(90,1,0,0);
2341     textObj_draw_centered(winner_text_obj);
2342     glTranslatef(0,0.3,0);
2343     glRotatef(-ang*2.0,0,1,0);
2344     textObj_draw_centered(winner_name_text_obj);
2345     glPopMatrix();
2346     glDisable(GL_TEXTURE_GEN_S);
2347     glDisable(GL_TEXTURE_GEN_T);
2348     glEnable(GL_LIGHTING);
2349     //           glEnable(GL_TEXTURE_2D);
2350 }
2351 
2352 
DisplayFunc_cubemap(int ballnr,int side,VMvect cam_pos,int cube_res)2353 void DisplayFunc_cubemap( int ballnr, int side, VMvect cam_pos, int cube_res )
2354 {
2355    GLfloat light_position[] = { 0.0, 0.0, 0.7, 1.0 };
2356 //   GLfloat light_diff[]     = { 0.3, 0.3, 0.3, 1.0 };
2357 //   GLfloat light_amb[]      = { 0.2, 0.2, 0.2, 1.0 };
2358    GLfloat light_diff[]     = { 0.2, 0.2, 0.2, 1.0 };
2359    GLfloat light_amb[]      = { 0.05, 0.05, 0.05, 1.0 };
2360 
2361    int i;
2362 
2363    float mv_matr[16];
2364 
2365 
2366    glDisable(GL_LIGHT1);
2367 
2368 #ifdef TIME_INTERPOLATE
2369    interpolate_balls( &g_lastballs, &balls, &g_drawballs, (double)g_frametime_fromlast/(double)g_frametime_laststep );
2370 #endif
2371 
2372    if(options_positional_light){
2373        /* always use directional light for reflections for better performance */
2374        light_position[3]=0.0;
2375    } else {
2376        light_position[3]=0.0;
2377    }
2378 
2379 
2380    glMatrixMode( GL_PROJECTION );
2381    {
2382        double znear, zfar;
2383        znear=0.01;
2384        zfar=3.0;
2385 //       glFrustum( left, right, bottom, top, zNear, zFar );
2386 /*       {
2387            float m[16];
2388            glLoadIdentity();
2389            glFrustum( -0.1, 0.2,  -0.1,0.2,  0.1,1.0 );
2390            glGetFloatv(GL_PROJECTION_MATRIX,m);
2391            printf("\nmatrix=\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n",
2392                   m[0],m[4],m[8],m[12],
2393                   m[1],m[5],m[9],m[13],
2394                   m[2],m[6],m[10],m[14],
2395                   m[3],m[7],m[11],m[15]
2396                  );
2397        }*/
2398        glLoadIdentity();
2399        glFrustum( -znear,+znear,  -znear,+znear,  znear,zfar );
2400    }
2401    glMatrixMode( GL_MODELVIEW );
2402    glLoadIdentity();
2403 
2404    for(i=0;i<16;i++) mv_matr[i]=0.0;
2405    mv_matr[15]=1.0;
2406 
2407 #define NEG (1.0)
2408    switch( side ){
2409    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:  /* (s,t)=(-z,-y) */
2410 //                                   -y*ey                   -z*ex
2411        mv_matr[0] = 0.0;  mv_matr[4] = 0.0*NEG;  mv_matr[ 8] =-1.0;
2412        mv_matr[1] = 0.0;  mv_matr[5] =-1.0*NEG;  mv_matr[ 9] = 0.0;
2413        mv_matr[2] =-1.0;  mv_matr[6] = 0.0*NEG;  mv_matr[10] = 0.0;
2414        break;
2415    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:  /* (s,t)=(+z,-y) */
2416 //                                   -y*ey                   +z*ex
2417        mv_matr[0] = 0.0;  mv_matr[4] = 0.0*NEG;  mv_matr[ 8] = 1.0;
2418        mv_matr[1] = 0.0;  mv_matr[5] =-1.0*NEG;  mv_matr[ 9] = 0.0;
2419        mv_matr[2] = 1.0;  mv_matr[6] = 0.0*NEG;  mv_matr[10] = 0.0;
2420        break;
2421    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:  /* (s,t)=(+x,+z) */
2422 //                +x*ex                                  +z*ey
2423        mv_matr[0] = 1.0;  mv_matr[4] = 0.0;  mv_matr[ 8] = 0.0*NEG;
2424        mv_matr[1] = 0.0;  mv_matr[5] = 0.0;  mv_matr[ 9] = 1.0*NEG;
2425        mv_matr[2] = 0.0;  mv_matr[6] =-1.0;  mv_matr[10] = 0.0*NEG;
2426        break;
2427    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:  /* (s,t)=(+x,-z) */
2428 //                +x*ex                                  -z*ey
2429        mv_matr[0] = 1.0;  mv_matr[4] = 0.0;  mv_matr[ 8] = 0.0*NEG;
2430        mv_matr[1] = 0.0;  mv_matr[5] = 0.0;  mv_matr[ 9] =-1.0*NEG;
2431        mv_matr[2] = 0.0;  mv_matr[6] = 1.0;  mv_matr[10] = 0.0*NEG;
2432        break;
2433    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:  /* (s,t)=(+x,-y) */
2434 //                +x*ex              -y*ey
2435        mv_matr[0] = 1.0;  mv_matr[4] = 0.0*NEG;  mv_matr[ 8] = 0.0;
2436        mv_matr[1] = 0.0;  mv_matr[5] =-1.0*NEG;  mv_matr[ 9] = 0.0;
2437        mv_matr[2] = 0.0;  mv_matr[6] = 0.0*NEG;  mv_matr[10] =-1.0;
2438        break;
2439    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:  /* (s,t)=(-x,-y) */
2440 //                -x*ex              -y*ey
2441        mv_matr[0] =-1.0;  mv_matr[4] = 0.0*NEG;  mv_matr[ 8] = 0.0;
2442        mv_matr[1] = 0.0;  mv_matr[5] =-1.0*NEG;  mv_matr[ 9] = 0.0;
2443        mv_matr[2] = 0.0;  mv_matr[6] = 0.0*NEG;  mv_matr[10] = 1.0;
2444        break;
2445    }
2446 #undef NEG
2447 
2448    glLoadMatrixf(mv_matr);
2449    glTranslatef( -balls.ball[ballnr].r.x,
2450                  -balls.ball[ballnr].r.y,
2451                  -balls.ball[ballnr].r.z );
2452    cam_pos=vec_scale(vec_unit(vec_diff(cam_pos,balls.ball[ballnr].r)),BALL_D/2.5);
2453    glTranslatef( -cam_pos.x, -cam_pos.y, -cam_pos.z );
2454 
2455    glPushMatrix();
2456 
2457 
2458    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diff);
2459    glLightfv(GL_LIGHT0, GL_AMBIENT,  light_amb);
2460 //   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
2461    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
2462 
2463 
2464    /* draw table */
2465    glCallList(table_obj);
2466 
2467    /* some whole-ball-culling might be of use here */
2468 
2469 
2470    /* draw balls with reflections and shadows */
2471 #ifdef TIME_INTERPOLATE
2472    draw_balls(g_drawballs,balls.ball[ballnr].r,90.0,cube_res,spheretexbind,lightpos,lightnr, (int *)0);
2473 #else
2474    draw_balls(balls,balls.ball[ballnr].r,90.0,cube_res,spheretexbind,lightpos,lightnr, (int *)0);
2475 #endif
2476 
2477    if( !balls_moving ){  /* draw queue */
2478        draw_queue( balls.ball[CUE_BALL_IND].r, Xque, Zque, queue_offs,
2479                    queue_point_x, queue_point_y,
2480                    spheretexbind, lightpos, lightnr );
2481    }
2482 
2483    if (options_place_cue_ball_tex && player[act_player].place_cue_ball && !balls_moving){
2484        int i;
2485         glDepthMask (GL_FALSE);
2486         glEnable(GL_BLEND);
2487         glDisable (GL_LIGHTING);
2488         glBlendFunc (GL_ONE, GL_ONE);
2489         glColor3f(0.25,0.25,0.25);
2490         glBindTexture(GL_TEXTURE_2D,placecueballtexbind);
2491 #define SH_SZ 0.087
2492         i=CUE_BALL_IND;
2493             glBegin( GL_QUADS );
2494             glNormal3f( 0.0,0.0,1.0 );
2495             glTexCoord2f(0.0,1.0);
2496             glVertex3f( balls.ball[i].r.x-SH_SZ, balls.ball[i].r.y+SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
2497             glTexCoord2f(1.0,1.0);
2498             glVertex3f( balls.ball[i].r.x+SH_SZ, balls.ball[i].r.y+SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
2499             glTexCoord2f(1.0,0.0);
2500             glVertex3f( balls.ball[i].r.x+SH_SZ, balls.ball[i].r.y-SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
2501             glTexCoord2f(0.0,0.0);
2502             glVertex3f( balls.ball[i].r.x-SH_SZ, balls.ball[i].r.y-SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
2503             glEnd();
2504         glDisable(GL_BLEND);
2505         glDepthMask (GL_TRUE);
2506 #undef SH_SZ
2507         glEnable (GL_LIGHTING);
2508    }
2509 
2510    if( (player[0].winner || player[1].winner) ){
2511        if(options_3D_winnertext){
2512            draw_3D_winner_text();
2513        }
2514    }
2515 
2516    /* light rects */
2517    {
2518        glDisable(GL_LIGHTING);
2519        glDisable(GL_TEXTURE_2D);
2520        glColor4f(1.0,1.0,1.0,1.0);
2521 
2522        glBegin( GL_QUADS );
2523        glNormal3f( 0.0,0.0,-1.0 );
2524 
2525        glVertex3f(  0.18, 0.15, 1.0 );
2526        glVertex3f(  0.18, 0.76, 1.0 );
2527        glVertex3f( -0.18, 0.76, 1.0 );
2528        glVertex3f( -0.18, 0.15, 1.0 );
2529 
2530        glVertex3f( -0.18, -0.15, 1.0 );
2531        glVertex3f( -0.18, -0.76, 1.0 );
2532        glVertex3f(  0.18, -0.76, 1.0 );
2533        glVertex3f(  0.18, -0.15, 1.0 );
2534 
2535        glEnd();
2536 
2537        glColor4f(0.6,0.6,0.6,1.0);
2538        glBegin( GL_QUADS );
2539 
2540        glVertex3f(  0.20, 0.13, 1.001 );
2541        glVertex3f(  0.20, 0.78, 1.001 );
2542        glVertex3f( -0.20, 0.78, 1.001 );
2543        glVertex3f( -0.20, 0.13, 1.001 );
2544 
2545        glVertex3f( -0.20, -0.13, 1.001 );
2546        glVertex3f( -0.20, -0.78, 1.001 );
2547        glVertex3f(  0.20, -0.78, 1.001 );
2548        glVertex3f(  0.20, -0.13, 1.001 );
2549 
2550        glEnd();
2551 
2552        glColor4f(0.3,0.3,0.3,1.0);
2553        glBegin( GL_QUADS );
2554        glVertex3f(  0.28,-0.86, 1.002 );
2555        glVertex3f(  0.28, 0.86, 1.002 );
2556        glVertex3f( -0.28, 0.86, 1.002 );
2557        glVertex3f( -0.28,-0.86, 1.002 );
2558        glEnd();
2559 
2560        glColor4f(0.15,0.2,0.15,1.0);
2561        glBegin( GL_QUADS );
2562        glVertex3f(  0.38,-0.96, 1.004 );
2563        glVertex3f(  0.38, 0.96, 1.004 );
2564        glVertex3f( -0.38, 0.96, 1.004 );
2565        glVertex3f( -0.38,-0.96, 1.004 );
2566        glEnd();
2567 
2568        glEnable(GL_LIGHTING);
2569        glEnable(GL_TEXTURE_2D);
2570    }
2571 
2572    glPopMatrix();
2573 
2574 //   glutSwapBuffers();
2575 }
2576 
2577 
create_cuberef_map(int ballnr,int texbind,VMvect cam_pos)2578 void create_cuberef_map(int ballnr, int texbind, VMvect cam_pos)
2579 {
2580     int i, w, h, target, level;
2581     double d, ang, ang1, ang2;
2582     double th, ph, cam_FOV2;
2583     VMvect dvec, ballvec, right, up, cam_pos_;
2584 
2585     glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texbind);
2586 
2587     /* calc necessary detail level */
2588 //    level=ballnr%5;
2589     //    level=vec_abs(vec_diff(balls.ball[ballnr].r,cam_pos))/2.5*5.0;
2590 
2591     cam_FOV2=2.0*180.0/M_PI*atan(tan(cam_FOV*M_PI/180.0/2.0)/win_width*win_height);
2592 
2593     th=(Xrot+Xrot_offs)/180.0*M_PI;
2594     ph=(Zrot+Zrot_offs)/180.0*M_PI;
2595     dvec  = vec_xyz(-sin(th)*sin(ph),-sin(th)*cos(ph),-cos(th));
2596     cam_pos_ = vec_diff( cam_pos, vec_scale(dvec,balls.ball[ballnr].d/2.0/sin(cam_FOV*M_PI/180.0/2.0)) );
2597     right = vec_unit(vec_xyz(dvec.y,-dvec.x,0));
2598     up    = vec_cross(right,dvec);
2599     ballvec = vec_diff(balls.ball[ballnr].r,cam_pos_);
2600     ang1  = atan2( vec_mul(ballvec, right), vec_mul(ballvec, dvec) );
2601     ang2  = atan2( vec_mul(ballvec, up),    vec_mul(ballvec, dvec) );
2602     d = vec_mul(vec_diff(balls.ball[ballnr].r,cam_pos_),dvec);
2603     ang = d/vec_abs(ballvec);
2604     ang = (fabs(ang)<1.0)?acos(ang):0.0;
2605 
2606 /*    if(ballnr==0)
2607         printf("ang2=%lf\n",ang2);*/
2608 //    if( ang < M_PI/4.0 ){
2609     if(
2610        fabs(ang1) < cam_FOV*M_PI/180.0/2.0 &&
2611        fabs(ang2) < cam_FOV2*M_PI/180.0/2.0
2612       ){
2613 
2614         level=log(d/0.2)/log(2.0)-1.0;
2615         if (level<0) level=0;
2616 /*        if(ballnr==0)
2617             printf("level==%d\n",level);*/
2618 
2619         w=cuberef_res>>level;
2620         h=w;
2621 
2622 /*        glScissor( 0, 0, 3*cuberef_res, 2*cuberef_res );
2623         glViewport( 0, 0, 3*cuberef_res, 2*cuberef_res );
2624         glEnable( GL_SCISSOR_TEST );
2625         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
2626         glDisable( GL_SCISSOR_TEST );*/
2627         for(i=0;i<6;i++){
2628 //        printf("   creating cubemap #%d\n",i);
2629             glViewport( (i%3)*cuberef_res/*+9*/, (i/3)*cuberef_res, w, h);
2630             switch(i){
2631             case 0: target=GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
2632                     DisplayFunc_cubemap( ballnr , GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, cam_pos, w );
2633                     break;
2634             case 1: target=GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
2635                     DisplayFunc_cubemap( ballnr , GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, cam_pos, w );
2636                     break;
2637             case 2: target=GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
2638                     DisplayFunc_cubemap( ballnr , GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, cam_pos, w );
2639                     break;
2640             case 3: target=GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
2641                     DisplayFunc_cubemap( ballnr , GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, cam_pos, w );
2642                     break;
2643             case 4: target=GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
2644                     DisplayFunc_cubemap( ballnr , GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, cam_pos, w );
2645                     break;
2646             case 5: target=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
2647                     DisplayFunc_cubemap( ballnr , GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, cam_pos, w );
2648                     break;
2649             }
2650             glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_BASE_LEVEL, level);
2651             glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAX_LEVEL, level);
2652             glCopyTexSubImage2D(target, level,
2653                                 0, 0,
2654                                 (i%3)*cuberef_res, (i/3)*cuberef_res/*+1*/,
2655                                 w, h );
2656         }
2657     }
2658 }
2659 
create_cuberef_maps(VMvect cam_pos)2660 void create_cuberef_maps(VMvect cam_pos)
2661 {
2662     int i;
2663     for(i=0;i<balls.nr;i++) if(balls.ball[i].in_game){
2664 //        printf("creating cubemaps for ball #%d\n",i);
2665         glColorMask(1, 1, 1, 1);
2666         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
2667         create_cuberef_map(i,cuberef_allballs_texbind[i],cam_pos);
2668     }
2669 }
2670 
2671 
Display_tournament_tree(struct TournamentState_ * ts)2672 void Display_tournament_tree( struct TournamentState_ * ts )
2673 {
2674     int i,j;
2675     static textObj * title=0;
2676     static textObj * bottom=0;
2677 
2678     DPRINTF("Display_tournament_tree: 1");
2679     if( title == 0 ){
2680         title=textObj_new("Tournament",options_menu_fontname,32);
2681     }
2682     if( bottom == 0 ){
2683         bottom=textObj_new("<fire> to continue",options_menu_fontname,16);
2684     }
2685 
2686     glDisable(GL_LIGHTING);
2687     glDisable(GL_DEPTH_TEST);
2688     glEnable(GL_BLEND);
2689     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2690 
2691     glPushMatrix();
2692     glLoadIdentity();
2693     glScalef(0.8,0.8,1.0);
2694 
2695     glColor4f(0.4,0.4,0.4,0.7);
2696     glDisable(GL_TEXTURE_2D);
2697     /* top line */
2698     glBegin(GL_QUAD_STRIP);
2699     glVertex3f(-1, 0.98, 0);
2700     glVertex3f( 1, 0.98, 0);
2701     glVertex3f(-1, 0.82, 0);
2702     glVertex3f( 1, 0.82, 0);
2703     glEnd();
2704     /* bottom line */
2705     glBegin(GL_QUAD_STRIP);
2706     glVertex3f(-1, -0.82, 0);
2707     glVertex3f( 1, -0.82, 0);
2708     glVertex3f(-1, -0.98, 0);
2709     glVertex3f( 1, -0.98, 0);
2710     glEnd();
2711 
2712     glColor4f(0.6,0.6,0.6,0.85);
2713     glBindTexture(GL_TEXTURE_2D,fblogotexbind);
2714     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2715     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2716     glEnable(GL_TEXTURE_2D);
2717     glBegin(GL_QUAD_STRIP);
2718     glTexCoord2f(-0.3-0.15, 0.06-0.15);
2719     glVertex3f(-1, 0.8, 0);
2720     glTexCoord2f( 1.3-0.15, 0.06-0.15);
2721     glVertex3f( 1, 0.8, 0);
2722     glTexCoord2f(-0.3+0.15, 0.94+0.15);
2723     glVertex3f(-1,-0.8, 0);
2724     glTexCoord2f( 1.3+0.15, 0.94+0.15);
2725     glVertex3f( 1,-0.8, 0);
2726     glEnd();
2727 
2728     glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR);
2729 //    glDisable(GL_CULL_FACE);
2730     glEnable(GL_TEXTURE_2D);
2731 
2732     glPushMatrix();
2733       glTranslatef(0,0.9,0);
2734       glPushMatrix();
2735         glScalef(0.004,0.005,1.0);
2736         textObj_draw_bound(title,HBOUND_CENTER,VBOUND_CENTER);
2737       glPopMatrix();
2738       glTranslatef(0,-1.8,0);
2739       glPushMatrix();
2740         glScalef(0.004,0.004,1.0);
2741         textObj_draw_bound(bottom,HBOUND_CENTER,VBOUND_CENTER);
2742       glPopMatrix();
2743     glPopMatrix();
2744 
2745     glTranslatef(-1.0,0.8,0);
2746     glTranslatef(0.5*2.0/ts->round_num,0,0);
2747 
2748     DPRINTF("Display_tournament_tree: 2");
2749     for(i=0;i<=ts->round_ind;i++){
2750         glPushMatrix();
2751         glTranslatef(0,-0.5*1.6/(float)(1<<(ts->round_num-i)),0);
2752         for(j=0;j<(1<<(ts->round_num-i-1));j++){
2753             DPRINTF("Display_tournament_tree: drawing player %s\n",ts->roster.player[ts->game[i][j].roster_player1].text->str);
2754             if(ts->roster.player[ts->game[i][j].roster_player1].text){
2755                 glPushMatrix();
2756                 glScalef(0.003,0.003,1.0);
2757                 if     (ts->game[i][j].winner==0) glColor3f(0.0,1.0,1.0);
2758                 else if(ts->game[i][j].winner==1) glColor3f(0.5,0.5,0.5);
2759                 else                              glColor3f(1.0,1.0,1.0);
2760                 textObj_draw_bound(ts->roster.player[ts->game[i][j].roster_player1].text,HBOUND_CENTER,VBOUND_CENTER);
2761                 glPopMatrix();
2762             }
2763             glTranslatef(0,-1.6/(float)(1<<(ts->round_num-i)),0);
2764             DPRINTF("Display_tournament_tree: drawing player %s\n",ts->roster.player[ts->game[i][j].roster_player2].text->str);
2765             if(ts->roster.player[ts->game[i][j].roster_player2].text){
2766                 glPushMatrix();
2767                 glScalef(0.003,0.003,1.0);
2768                 if     (ts->game[i][j].winner==1) glColor3f(0.0,1.0,1.0);
2769                 else if(ts->game[i][j].winner==0) glColor3f(0.5,0.5,0.5);
2770                 else                              glColor3f(1.0,1.0,1.0);
2771                 textObj_draw_bound(ts->roster.player[ts->game[i][j].roster_player2].text,HBOUND_CENTER,VBOUND_CENTER);
2772                 glPopMatrix();
2773             }
2774             glTranslatef(0,-1.6/(float)(1<<(ts->round_num-i)),0);
2775         }
2776         glPopMatrix();
2777         glTranslatef(2.0/ts->round_num,0,0);
2778     }
2779 
2780     glPopMatrix(); /* glScalef(0.8,0.8,1.0); */
2781 
2782     glEnable(GL_TEXTURE_2D);
2783     glEnable(GL_LIGHTING);
2784     glEnable(GL_DEPTH_TEST);
2785     glDisable(GL_BLEND);
2786 }
2787 
2788 
DisplayFunc(void)2789 void DisplayFunc( void )
2790 {
2791 //   int i;
2792    double th,ph;
2793    GLfloat light_position[] = { 0.0, 0.0, 0.7, 1.0 };
2794    GLfloat light0_position[] = { 0.0, 0.7, 0.7, 1.0 };
2795    GLfloat light0_diff[]     = { 0.6, 0.6, 0.6, 1.0 };
2796    GLfloat light0_amb[]      = { 0.35, 0.35, 0.35, 1.0 };
2797    GLfloat light1_position[] = { 0.0, -0.7, 0.7, 1.0 };
2798    GLfloat light1_diff[]     = { 0.6, 0.6, 0.6, 1.0 };
2799    GLfloat light1_amb[]      = { 0.35, 0.35, 0.35, 1.0 };
2800 //   GLfloat light_diff_r[]   = { 1.0, 0.0, 0.0, 1.0 };
2801 //   GLfloat light_amb_r[]    = { 0.5, 0.0, 0.0, 1.0 };
2802 //   GLfloat light_diff_g[]   = { 0.0, 0.7, 0.0, 1.0 };
2803 //   GLfloat light_amb_g[]    = { 0.0, 0.5*0.7, 0.0, 1.0 };
2804    myvec cam_pos;
2805    static GLfloat real_dist=0.0;
2806    static double fps;
2807    int i;
2808 //   int act_buffer;
2809    VMmatrix4 mv_matr;
2810    VMmatrix4 prj_matr;
2811 
2812    static GLfloat rg_eye_dist=0.05;
2813 //   static GLfloat rg_scrw=0.225;
2814    //   static GLfloat rg_scrh=0.165;
2815 
2816 
2817    if( old_queue_view==1 && queue_view==0  ) /* this is sloppy and ugly */
2818    { /* set free_view_pos to actual view */
2819        double th=Xrot/180.0*M_PI;
2820        double ph=Zrot/180.0*M_PI;
2821        free_view_pos_aim = vec_scale(vec_xyz(sin(th)*sin(ph),sin(th)*cos(ph),cos(th)), cam_dist);
2822        free_view_pos_aim = vec_add( free_view_pos_aim, CUE_BALL_XYPOS );
2823        free_view_pos = free_view_pos_aim ;
2824    }
2825    old_queue_view=queue_view;
2826 
2827 
2828    th=(Xrot+Xrot_offs)/180.0*M_PI;
2829    ph=(Zrot+Zrot_offs)/180.0*M_PI;
2830    if(!FREE_VIEW){
2831        cam_pos=vec_scale(vec_xyz(sin(th)*sin(ph),sin(th)*cos(ph),cos(th)),
2832                          real_dist);
2833        cam_pos=vec_add(cam_pos,balls.ball[CUE_BALL_IND].r);
2834    } else {
2835        cam_pos=free_view_pos;
2836    }
2837 
2838 
2839    if(options_cuberef){
2840        create_cuberef_maps(cam_pos);
2841    }
2842 
2843    glViewport( 0, 0, win_width, win_height);
2844 
2845 
2846 
2847 #ifdef TIME_INTERPOLATE
2848    interpolate_balls( &g_lastballs, &balls, &g_drawballs, (double)g_frametime_fromlast/(double)g_frametime_laststep );
2849 #endif
2850 
2851    if(options_positional_light){
2852        light_position[3]=1.0;
2853        light0_position[3]=1.0;
2854        light1_position[3]=1.0;
2855    } else {
2856        light_position[3]=0.0;
2857        light0_position[3]=0.0;
2858        light1_position[3]=0.0;
2859    }
2860 
2861 
2862    fps = 1000.0/frametime_ms;
2863 
2864 //   glScalef(100.0,100.0,100.0);
2865 
2866 //   my_glBox(cam_pos.x+0.01, cam_pos.y+0.01, cam_pos.z+0.01,
2867 //            cam_pos.x-0.01, cam_pos.y-0.01, cam_pos.z-0.01);
2868 
2869 
2870 
2871    if(!FREE_VIEW){
2872        glFogf (GL_FOG_START, (cam_dist/2.0>cam_dist-1.0) ? cam_dist/2.0 : cam_dist-1.0 );
2873        glFogf (GL_FOG_END, cam_dist+6.0);
2874    }else{
2875        double cam_dist0;
2876        cam_dist0 = vec_abs(cam_pos);
2877        glFogf (GL_FOG_START, (cam_dist0/2.0>cam_dist0-1.0) ? cam_dist0/2.0 : cam_dist0-1.0 );
2878        glFogf (GL_FOG_END, cam_dist0+6.0);
2879    }
2880 
2881    real_dist = cam_dist;
2882 
2883 //   glGetIntegerv(GL_DRAW_BUFFER, &act_buffer);
2884    if(options_rgstereo_on){
2885 //       glClearAccum(0.0, 0.0, 0.0, 0.0);
2886 //       glClear(GL_ACCUM_BUFFER_BIT);
2887        glColorMask(1, 1, 1, 1);
2888        glClear( GL_COLOR_BUFFER_BIT );
2889    }
2890    for(i=0;i<=options_rgstereo_on;i++){
2891 
2892    glMatrixMode( GL_MODELVIEW );
2893    glLoadIdentity();
2894    glMatrixMode( GL_PROJECTION );
2895    glLoadIdentity();
2896 
2897    if       (options_rgstereo_on){
2898        double znear, zfar;
2899        double eye_offs, zeye;
2900        znear=0.03;
2901        zfar=10.0;
2902        zeye = (double)win_width/2.0/scr_dpi*0.025/tan(cam_FOV*M_PI/360.0);
2903        eye_offs = rg_eye_dist/2.0*znear/zeye;
2904        glLoadIdentity();
2905        if       (i==0){
2906            double eye_offs0;
2907            if (options_rgaim == 0) eye_offs0 = -eye_offs;
2908            if (options_rgaim == 1) eye_offs0 = -2.0*eye_offs;
2909            if (options_rgaim == 2) eye_offs0 = 0.0;
2910            glColorMask(1, 0, 0, 1);
2911            glMatrixMode( GL_PROJECTION );
2912            glFrustum( -znear*tan(cam_FOV*M_PI/360.0)+eye_offs0, znear*tan(cam_FOV*M_PI/360.0)+eye_offs0,
2913                      -znear*tan(cam_FOV*M_PI/360.0)*(double)win_height/(double)win_width,
2914                      +znear*tan(cam_FOV*M_PI/360.0)*(double)win_height/(double)win_width, znear, zfar);
2915            glMatrixMode( GL_MODELVIEW );
2916            glTranslatef( eye_offs0/znear*zeye, 0.0, 0.0 );
2917 
2918        }else if (i==1){
2919            double eye_offs1;
2920            if (options_rgaim == 0) eye_offs1 = +eye_offs;
2921            if (options_rgaim == 1) eye_offs1 = 0.0;
2922            if (options_rgaim == 2) eye_offs1 = +2.0*eye_offs;
2923            glColorMask(0, 1, 1, 1);
2924            glMatrixMode( GL_PROJECTION );
2925            glFrustum( -znear*tan(cam_FOV*M_PI/360.0)+eye_offs1, znear*tan(cam_FOV*M_PI/360.0)+eye_offs1,
2926                      -znear*tan(cam_FOV*M_PI/360.0)*(double)win_height/(double)win_width,
2927                      +znear*tan(cam_FOV*M_PI/360.0)*(double)win_height/(double)win_width, znear, zfar);
2928            glMatrixMode( GL_MODELVIEW );
2929            glTranslatef( eye_offs1/znear*zeye, 0.0, 0.0 );
2930        }
2931    }else{
2932        double znear, zfar;
2933        znear=0.03;
2934        zfar=10.0;
2935 //       glFrustum( left, right, bottom, top, zNear, zFar );
2936        glMatrixMode( GL_PROJECTION );
2937        glFrustum( -znear*tan(cam_FOV*M_PI/360.0), znear*tan(cam_FOV*M_PI/360.0),
2938                   -znear*tan(cam_FOV*M_PI/360.0)*(double)win_height/(double)win_width,
2939                   +znear*tan(cam_FOV*M_PI/360.0)*(double)win_height/(double)win_width, znear, zfar);
2940 /*       {
2941            GLfloat m[16];
2942            glGetFloatv(GL_PROJECTION_MATRIX,m);
2943            printf("\nmatrix=\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n",
2944                   m[0],m[4],m[8],m[12],
2945                   m[1],m[5],m[9],m[13],
2946                   m[2],m[6],m[10],m[14],
2947                   m[3],m[7],m[11],m[15]
2948                  );
2949        }*/
2950        glMatrixMode( GL_MODELVIEW );
2951    }
2952 
2953    glMatrixMode( GL_MODELVIEW );
2954 
2955 /*   if       (i==0 && options_rgstereo_on){
2956        glTranslatef( -rg_eye_dist/2.0, 0.0, 0.0 );
2957    }else if (i==1 && options_rgstereo_on){
2958        glTranslatef( rg_eye_dist/2.0, 0.0, 0.0 );
2959    }else{
2960    }*/
2961 
2962 
2963    if(FREE_VIEW){
2964        glRotatef(Xrot+Xrot_offs, 1.0, 0.0, 0.0);
2965        glRotatef(Yrot+Yrot_offs, 0.0, 1.0, 0.0);
2966        glRotatef(Zrot+Zrot_offs, 0.0, 0.0, 1.0);
2967        glTranslatef( -free_view_pos.x, -free_view_pos.y, -free_view_pos.z );
2968 //       glTranslatef( 0.0, 0.0, -1.0 );
2969    }
2970 
2971    if(!FREE_VIEW){
2972        glTranslatef( 0.0, 0.0, -real_dist );
2973    }
2974 
2975    glPushMatrix();
2976 
2977    if(!FREE_VIEW){
2978        glRotatef(Xrot+Xrot_offs, 1.0, 0.0, 0.0);
2979        glRotatef(Yrot+Yrot_offs, 0.0, 1.0, 0.0);
2980        glRotatef(Zrot+Zrot_offs, 0.0, 0.0, 1.0);
2981 /*   if(g_lookballnr<balls.nr){
2982        BallType * ball;
2983 #ifdef TIME_INTERPOLATE
2984        ball=BM_get_ball_by_nr( g_lookballnr, &g_drawballs );
2985 #else
2986        ball=BM_get_ball_by_nr( g_lookballnr, &balls );
2987 #endif
2988 glTranslatef( -ball->r.x, -ball->r.y, -ball->r.z );*/
2989        glTranslatef( -balls.ball[CUE_BALL_IND].r.x,
2990                      -balls.ball[CUE_BALL_IND].r.y,
2991                      -balls.ball[CUE_BALL_IND].r.z );
2992 /*   }else{
2993    }*/
2994    }
2995 
2996 
2997    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light0_diff);
2998    glLightfv(GL_LIGHT0, GL_AMBIENT,  light0_amb);
2999    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
3000    glEnable(GL_LIGHT1);
3001    glLightfv(GL_LIGHT1, GL_DIFFUSE,  light1_diff);
3002    glLightfv(GL_LIGHT1, GL_AMBIENT,  light1_amb);
3003    glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
3004 
3005    if       (i==1 && options_rgstereo_on) {
3006        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
3007    } else if(i==0 && options_rgstereo_on) {
3008        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
3009    } else {
3010        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
3011    }
3012 
3013 
3014    /* draw table */
3015    glCallList(table_obj);
3016 
3017 /*   {
3018        float col_text[4]={1.0,1.0,1.0,1.0};
3019        glDisable(GL_TEXTURE_2D);
3020        glPushMatrix();
3021        glRotatef(90.0,1,0,0);
3022        glMaterialfv(GL_FRONT, GL_DIFFUSE, col_text);
3023        glCallList(g_test_list);
3024        glPopMatrix();
3025        glEnable(GL_TEXTURE_2D);
3026    }*/
3027 
3028 
3029    /* draw balls with reflections and shadows */
3030 #ifdef TIME_INTERPOLATE
3031    if(options_ball_reflections_blended){
3032        if( options_calc_ball_reflections ){
3033            draw_balls(g_drawballs,cam_pos,cam_FOV,win_width,reftexbind,lightpos,lightnr, (int *)0);
3034        }else if( options_cuberef ){
3035            draw_balls(g_drawballs,cam_pos,cam_FOV,win_width,spheretexbind,lightpos,lightnr, cuberef_allballs_texbind);
3036        }else{
3037            draw_balls(g_drawballs,cam_pos,cam_FOV,win_width,spheretexbind,lightpos,lightnr, (int *)0);
3038        }
3039    } else {
3040        draw_balls(g_drawballs,cam_pos,cam_FOV,win_width,lightspheretexbind,lightpos,lightnr, (int *)0);
3041    }
3042 #else
3043    if(options_ball_reflections_blended){
3044        if( options_calc_ball_reflections ){
3045            draw_balls(balls,cam_pos,cam_FOV,win_width,reftexbind,lightpos,lightnr, (int *)0);
3046        }else if( options_cuberef ){
3047            draw_balls(balls,cam_pos,cam_FOV,win_width,spheretexbind,lightpos,lightnr, cuberef_allballs_texbind);
3048        }else{
3049            draw_balls(balls,cam_pos,cam_FOV,win_width,spheretexbind,lightpos,lightnr, (int *)0);
3050        }
3051    } else {
3052        draw_balls(balls,cam_pos,cam_FOV,win_width,lightspheretexbind,lightpos,lightnr, (int *)0);
3053    }
3054 #endif
3055 
3056    if( !queue_view && !balls_moving ){  /* draw queue */
3057 /*       double dx,dy,dz,th,ph;
3058        ph=Zque/180.0*M_PI;
3059        th=Xque/180.0*M_PI;
3060        dy=+1.0*sin(th)*cos(ph);
3061        dx=+1.0*sin(th)*sin(ph);
3062        dz=+1.0*cos(th);
3063        glBegin( GL_LINES );
3064        glVertex3f(balls.ball[0].r.x,balls.ball[0].r.y,balls.ball[0].r.z);
3065        glVertex3f(balls.ball[0].r.x+dx,balls.ball[0].r.y+dy,balls.ball[0].r.z+dz);
3066        glEnd();*/
3067 /*       glBegin( GL_LINES );
3068        glVertex3f(balls.ball[0].r.x,balls.ball[0].r.y,balls.ball[0].r.z);
3069        glVertex3f(balls.ball[0].r.x+comp_dir.x,balls.ball[0].r.y+comp_dir.y,balls.ball[0].r.z+comp_dir.z);
3070        glEnd();*/
3071        draw_queue( balls.ball[CUE_BALL_IND].r, Xque, Zque, queue_offs,
3072                    queue_point_x, queue_point_y,
3073                    spheretexbind, lightpos, lightnr );
3074    }
3075 
3076    if (options_place_cue_ball_tex && player[act_player].place_cue_ball && !balls_moving){
3077        int i;
3078 //        glMaterialfv(GL_FRONT, GL_DIFFUSE, col_shad);
3079         glDepthMask (GL_FALSE);
3080         glEnable(GL_BLEND);
3081 //        glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
3082 //        glBlendFunc (GL_ONE, GL_SRC_ALPHA);
3083 //        glColor4f(0.5,0.5,0.5,1.0);
3084 //        glBlendFunc (GL_SRC_ALPHA, GL_ONE);
3085         glDisable (GL_LIGHTING);
3086         glBlendFunc (GL_ONE, GL_ONE);
3087         glColor3f(0.5,0.5,0.5);
3088 //        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3089         // glBlendFunc ( GL_ONE, GL_SRC_ALPHA );
3090 //        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3091         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3092         glBindTexture(GL_TEXTURE_2D,placecueballtexbind);
3093 //        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3094 #define SH_SZ 0.087
3095         i=CUE_BALL_IND;
3096             glBegin( GL_QUADS );
3097 //            glBegin(GL_POLYGON);
3098             glNormal3f( 0.0,0.0,1.0 );
3099             glTexCoord2f(0.0,1.0);
3100             glVertex3f( balls.ball[i].r.x-SH_SZ, balls.ball[i].r.y+SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
3101             glTexCoord2f(1.0,1.0);
3102             glVertex3f( balls.ball[i].r.x+SH_SZ, balls.ball[i].r.y+SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
3103             glTexCoord2f(1.0,0.0);
3104             glVertex3f( balls.ball[i].r.x+SH_SZ, balls.ball[i].r.y-SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
3105             glTexCoord2f(0.0,0.0);
3106             glVertex3f( balls.ball[i].r.x-SH_SZ, balls.ball[i].r.y-SH_SZ, balls.ball[i].r.z-balls.ball[i].d/2.02 );
3107             glEnd();
3108         glDisable(GL_BLEND);
3109         glDepthMask (GL_TRUE);
3110 #undef SH_SZ
3111         glEnable (GL_LIGHTING);
3112    }
3113 
3114    if( options_balltrace ){
3115        int i;
3116        for(i=0;i<balls.nr;i++){
3117           glDisable(GL_TEXTURE_2D);
3118           glDisable(GL_LIGHTING);
3119           draw_ballpath(&balls.ball[i]);
3120           glEnable(GL_LIGHTING);
3121           glEnable(GL_TEXTURE_2D);
3122        }
3123    }
3124 
3125 
3126    if( (player[0].winner || player[1].winner) ){
3127        if(options_3D_winnertext){
3128            draw_3D_winner_text();
3129        }
3130    }
3131 
3132 /*       if( vline_on && queue_view && !balls_moving ){
3133            glLineStipple( 1, 0xF0F0 );
3134            glEnable(GL_LINE_STIPPLE);
3135 
3136            glBegin( GL_LINES );
3137            glVertex3f(balls.ball[CUE_BALL_IND].r.x,balls.ball[CUE_BALL_IND].r.y,balls.ball[CUE_BALL_IND].r.z);
3138            glVertex3f(balls.ball[CUE_BALL_IND].r.x,balls.ball[CUE_BALL_IND].r.y,balls.ball[CUE_BALL_IND].r.z+1.0);
3139            glEnd();
3140 
3141            glDisable(GL_LINE_STIPPLE);
3142        }*/
3143 
3144    if( options_lensflare ){
3145        VMvect dpos,dpos1,actpos,centpos,right,up;
3146        int i,j;
3147 
3148        glDepthMask (GL_FALSE);
3149        glEnable(GL_BLEND);
3150        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3151 
3152 /*       glRasterPos3f(lightpos[0].x,lightpos[0].y,lightpos[0].z);
3153        fprintf(stderr,"lightpos =<%f,%f,%f>\n",lightpos[0].x,lightpos[0].y,lightpos[0].z);
3154        glGetFloatv(GL_CURRENT_RASTER_POSITION,pos);
3155        fprintf(stderr,"rasterpos=<%f,%f,%f>\n",pos[0],pos[1],pos[2]);*/
3156 
3157        for(i=0;i<1/*lightnr*/;i++){
3158            int k;
3159 //           glBlendFunc ( GL_ONE, GL_SRC_COLOR );
3160            glBlendFunc ( GL_ONE, GL_ONE );
3161 
3162            glBindTexture(GL_TEXTURE_2D,blendetexbind);
3163            glGetFloatv(GL_MODELVIEW_MATRIX,mv_matr.m);
3164            glGetFloatv(GL_PROJECTION_MATRIX,prj_matr.m);
3165 //           actpos  = matr4_rdot( matr4_mul(prj_matr,mv_matr), lightpos[i] );
3166 //           centpos = vec_add(balls.ball[0].r,vec_scale(vec_diff(cam_pos,balls.ball[0].r),0.5));
3167            //           centpos = matr_rdot( matr_mul(prj_matr,mv_matr,4), centpos, 4 );
3168 
3169            dpos1    = matr4_rdot( mv_matr, vec_xyz(0,0,0.77) );
3170 //           dpos1    = matr4_rdot( mv_matr, lightpos[i] );
3171            centpos = vec_xyz(0,0,-0.5);
3172            dpos    = vec_unit(vec_diff( dpos1, centpos ));
3173 
3174 /*           glMatrixMode(GL_PROJECTION_MATRIX);
3175            glPushMatrix();
3176            glLoadIdentity();*/
3177            glMatrixMode(GL_MODELVIEW);
3178            glPushMatrix();
3179            glLoadIdentity();
3180            glDisable(GL_LIGHTING);
3181 //           glDisable(GL_TEXTURE_2D);
3182 //           glDisable(GL_DEPTH_TEST);
3183 
3184            for(k=0;k<3;k++)
3185            for(j=-1;j<20;j++){
3186                VMfloat zact;
3187 
3188                if(!options_rgstereo_on){
3189                    glColor3f(1.0*(double)(k%3!=1),
3190                              1.0*(double)(k%3!=2),
3191                              1.0*(double)(k%3!=0));
3192                } else {
3193                    glColor3f(0.5+0.25*(double)(k%3),
3194                              0.5+0.25*(double)(k%3),
3195                              0.5+0.25*(double)(k%3));
3196                }
3197 
3198                if(j==-1 && k==0){
3199                    glColor3f(1.0,1.0,1.0);
3200                    glBindTexture(GL_TEXTURE_2D,lightflaretexbind);
3201                    zact = dpos1.z;
3202                    actpos = dpos1;
3203                    right = vec_xyz(0.02/0.4*(0.5-zact),0,0);
3204                    up    = vec_xyz(0,0.02/0.4*(0.5-zact),0);
3205                } else if(j>=0 && j<10){
3206                    glBindTexture(GL_TEXTURE_2D,blendetexbind);
3207                    zact = 0.32-0.25*exp((j-3)+k*1.4345);
3208                    actpos = vec_add( centpos , vec_scale(dpos,zact/dpos.z) );
3209                    right = vec_xyz(0.008*(1.0-k*0.23)/0.4*(0.5-zact),0,0);
3210                    up    = vec_xyz(0,0.008*(1.0-k*0.23)/0.4*(0.5-zact),0);
3211                } else {
3212                    glBindTexture(GL_TEXTURE_2D,blendetexbind);
3213                    zact = 0.282-0.127*exp((j-3-10)+k*1.2453);
3214                    actpos = vec_add( centpos , vec_scale(dpos,zact/dpos.z) );
3215                    right = vec_xyz(0.003*(1.0-k*0.23)/0.4*(0.5-zact),0,0);
3216                    up    = vec_xyz(0,0.003*(1.0-k*0.23)/0.4*(0.5-zact),0);
3217                }
3218 
3219                glBegin( GL_QUADS );
3220                glTexCoord2f(0.0,0.0);
3221                glVertex3f( actpos.x+up.x-right.x, actpos.y+up.y-right.y, actpos.z+up.z-right.z );
3222                glTexCoord2f(1.0,0.0);
3223                glVertex3f( actpos.x+up.x+right.x, actpos.y+up.y+right.y, actpos.z+up.z+right.z );
3224                glTexCoord2f(1.0,1.0);
3225                glVertex3f( actpos.x-up.x+right.x, actpos.y-up.y+right.y, actpos.z-up.z+right.z );
3226                glTexCoord2f(0.0,1.0);
3227                glVertex3f( actpos.x-up.x-right.x, actpos.y-up.y-right.y, actpos.z-up.z-right.z );
3228                glEnd();
3229            }
3230 
3231 //           glEnable(GL_TEXTURE_2D);
3232            glPushMatrix();
3233            glTranslatef( 0,0,-0.5 );
3234            glScalef(0.0005,0.0005,1.0);
3235 //           glCallList( create_string_quad( "Hallo-fagd",24 ) );
3236            glPopMatrix();
3237 
3238            glPopMatrix();
3239 /*           glMatrixMode(GL_PROJECTION);
3240            glPopMatrix();*/
3241            glMatrixMode(GL_MODELVIEW);
3242        }
3243        glDisable(GL_BLEND);
3244        glDepthMask (GL_TRUE);
3245    }
3246 
3247    if(1){   /* HUD stuff */
3248 /*       char str[200];
3249        if (gametype==GAME_8BALL){
3250            sprintf(str,"%s - %s",player[act_player].name,half_full_names[player[act_player].half_full]);
3251        }else if (gametype==GAME_9BALL){
3252            int i;
3253            int minballnr=15;
3254            for(i=0;i<balls.nr;i++){
3255                if(balls.ball[i].nr<minballnr && balls.ball[i].nr!=0 && balls.ball[i].in_game)
3256                    minballnr=balls.ball[i].nr;
3257            }
3258            sprintf(str,"%s next:%d",player[act_player].name,minballnr);
3259        }*/
3260 
3261 
3262        glDisable(GL_DEPTH_TEST);
3263        if( vline_on && queue_view && !balls_moving &&
3264           ((2-options_rgaim)==i || options_rgaim==0 || !options_rgstereo_on) ){
3265            VMvect bx, by, bz;
3266            VMvect p, p1, p2;
3267            bz=vec_unit(vec_diff(cam_pos,balls.ball[CUE_BALL_IND].r));
3268            bx=vec_unit(vec_xyz(-bz.y, bz.x, 0));
3269            by=vec_cross(bz,bx);
3270            p=vec_add(vec_scale(bx,queue_point_x),vec_scale(by,-queue_point_y));
3271            p=vec_add(p,balls.ball[CUE_BALL_IND].r);
3272            glLineStipple( 1, 0x3333 );
3273            glEnable(GL_LINE_STIPPLE);
3274 
3275            glBegin( GL_LINES );
3276                p1=vec_add(p,vec_scale(bx,-0.01));
3277                p2=vec_add(p,vec_scale(bx,+0.01));
3278                glVertex3f( p.x, p.y, p.z );
3279                glVertex3f( p1.x, p1.y, p1.z );
3280                glVertex3f( p.x, p.y, p.z );
3281                glVertex3f( p2.x, p2.y, p2.z );
3282                p1=vec_add(p,vec_scale(by,-0.01));
3283                p2=vec_add(p,vec_scale(by,+0.01));
3284                glVertex3f( p.x, p.y, p.z );
3285                glVertex3f( p1.x, p1.y, p1.z );
3286                glVertex3f( p.x, p.y, p.z );
3287                glVertex3f( p2.x, p2.y, p2.z );
3288            glEnd();
3289 
3290            glDisable(GL_LINE_STIPPLE);
3291        }
3292 
3293        glMatrixMode( GL_TEXTURE );
3294        glPushMatrix();
3295        glLoadIdentity();
3296 
3297        glMatrixMode( GL_PROJECTION );
3298        glPushMatrix();
3299        glLoadIdentity();
3300 
3301        glMatrixMode( GL_MODELVIEW );
3302        glPushMatrix();
3303        glLoadIdentity();
3304 
3305 //       glColor3f(0.5,1.0,0.7);
3306 //       glColor3f(1.0,1.0,1.0);
3307        glColor3f(1.0,1.0,1.0);
3308        glDisable(GL_LIGHTING);
3309        glDisable(GL_TEXTURE_2D);
3310        glDisable(GL_DEPTH_TEST);
3311        glDisable(GL_TEXTURE_GEN_S);
3312        glDisable(GL_TEXTURE_GEN_T);
3313 
3314        glEnable(GL_TEXTURE_2D);
3315        glEnable(GL_BLEND);
3316        glBlendFunc(GL_ONE,GL_ONE);
3317        /* act player */
3318        glPushMatrix();
3319        glTranslatef(-0.94,-0.94,-1.0);
3320        glScalef(2.0/win_width,2.0/win_height,1.0);
3321        if( player[act_player].text != 0 ){
3322            textObj_draw( player[act_player].text );
3323        }
3324        glTranslatef(0,30,0);
3325        if        (gametype==GAME_8BALL){
3326            switch(player[act_player].half_full){
3327            case BALL_HALF: glBindTexture(GL_TEXTURE_2D,halfsymboltexbind); break;
3328            case BALL_FULL: glBindTexture(GL_TEXTURE_2D,fullsymboltexbind); break;
3329            case BALL_ANY:  glBindTexture(GL_TEXTURE_2D,fullhalfsymboltexbind); break;
3330            }
3331            glBegin(GL_QUADS);
3332            glTexCoord2f(0,1);
3333            glVertex3f(0,0,0);
3334            glTexCoord2f(0,0);
3335            glVertex3f(0,48,0);
3336            glTexCoord2f(1,0);
3337            glVertex3f(48,48,0);
3338            glTexCoord2f(1,1);
3339            glVertex3f(48,0,0);
3340            glEnd();
3341        } else if (gametype==GAME_9BALL){
3342            int col;
3343            if( player[act_player].next_9ball != 8 ){
3344                col = options_col_ball[player[act_player].next_9ball];
3345            } else {
3346                col = 0x888888;
3347            }
3348            glColor3ub( col>>16, (col>>8)&0xFF, col&0xFF );
3349            textObj_draw( player[act_player].score_text );
3350        } else if (gametype==GAME_SNOOKER){
3351            textObj_draw( player[act_player].score_text );
3352        } else if (gametype==GAME_CARAMBOL){
3353            textObj_draw( player[act_player].score_text );
3354        }
3355        glPopMatrix();
3356        /* 2nd player */
3357        glPushMatrix();
3358        glColor3f(0.0,0.0,1.0);
3359        glTranslatef(0.94,-0.94,-1.0);
3360        glScalef(2.0/win_width,2.0/win_height,1.0);
3361        if( player[act_player].text != 0 ){
3362            textObj_draw_bound( player[act_player?0:1].text, HBOUND_RIGHT, VBOUND_BOTTOM );
3363        }
3364        glTranslatef(0,30,0);
3365        if (gametype==GAME_SNOOKER){
3366            textObj_draw_bound( player[act_player?0:1].score_text, HBOUND_RIGHT, VBOUND_BOTTOM );
3367        } else if (gametype==GAME_CARAMBOL){
3368            textObj_draw_bound( player[act_player?0:1].score_text, HBOUND_RIGHT, VBOUND_BOTTOM );
3369        }
3370        glPopMatrix();
3371 
3372 
3373        glDisable(GL_LIGHTING);
3374        glDisable(GL_TEXTURE_2D);
3375        glDisable(GL_BLEND);
3376 
3377        glEnable(GL_BLEND);
3378 //       glBlendFunc(GL_ONE_MINUS_SRC_COLOR,GL_ONE);
3379        glBlendFunc(GL_ONE,GL_ONE);
3380 
3381        /* strength bar */
3382        if( !(options_gamemode==options_gamemode_tournament && tournament_state.wait_for_next_match) )
3383        /* disable strength bar if tournament window active */
3384        {
3385            glColor3f(0.2,0.2,0.2);
3386            myRect2D( -0.5, -0.805,  0.5,                -0.725 );
3387            glColor3f(0.3,0.3,0.3);
3388            myRect2D( -0.5, -0.795, -0.5+queue_strength, -0.735 );
3389        }
3390 
3391        if( vline_on && queue_view && !balls_moving &&
3392           ((2-options_rgaim)==i || options_rgaim==0 || !options_rgstereo_on) ){
3393            glColor3f(0.3,0.3,0.3);
3394            glLineStipple( 1, 0xF0F0 );
3395            glEnable(GL_LINE_STIPPLE);
3396 
3397            glBegin( GL_LINES );
3398            glVertex3f( 0, 1.00, 0.5);
3399            glVertex3f( 0, 0.08, 0.5);
3400            glEnd();
3401 
3402            glDisable(GL_LINE_STIPPLE);
3403        }
3404 
3405 
3406        glDisable(GL_BLEND);
3407 
3408 //       glRasterPos3f(-0.9,-0.9,-0.5);
3409 //       for(i=0;str[i]!=0;i++){
3410 //            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,str[i]);
3411 ////            glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);
3412 //       }
3413 
3414 #ifndef USE_SDL
3415        if(show_fps){
3416            char str[256];
3417            glColor3f(1.0,1.0,1.0);
3418            sprintf(str,"fps=%f",fps);
3419            glRasterPos3f(0.5,-0.9,-0.5);
3420            for(i=0;str[i]!=0;i++){
3421                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,str[i]);
3422            }
3423        }
3424 #endif
3425 
3426 #if 0
3427        if(player[0].winner || player[1].winner)
3428        {
3429            int winner=0;
3430            int width=0;
3431            if( player[0].winner ) winner=0; else winner=1;
3432            sprintf(str,"%s  wins",player[winner].name);
3433            for(i=0;str[i]!=0;i++){
3434                width+=glutBitmapWidth(GLUT_BITMAP_TIMES_ROMAN_24,str[i]);
3435            }
3436            glColor3f(1.0,0.1,0.1);
3437            glRasterPos3f(-(double)width/(double)win_width,0,-0.5);
3438            for(i=0;str[i]!=0;i++){
3439                glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24,str[i]);
3440            }
3441        }
3442 #endif
3443 
3444        if(options_gamemode==options_gamemode_tournament &&
3445           tournament_state.overall_winner>=0)
3446        {
3447            printf("!!!!!!!!!!!! overall_winner=%d !!!!!!!!!!!!\n",tournament_state.overall_winner);
3448 //           textObj_draw(tournament_state.overal_winner_text);
3449        }
3450 
3451        if( (player[0].winner || player[1].winner) && g_act_menu==(menuType *)0 ){
3452            if(options_3D_winnertext){
3453            } else {
3454                glEnable(GL_TEXTURE_2D);
3455                glEnable(GL_BLEND);
3456                glBlendFunc(GL_ONE,GL_ONE);
3457                if( !options_rgstereo_on ){
3458                    glColor3f(1.0,1.0,0.0);
3459                } else {
3460                    glColor3f(1.0,1.0,1.0);
3461                }
3462                glPushMatrix();
3463                glTranslatef(0,0,-0.5);
3464                glScalef(2.0/win_width,2.0/win_height,1.0);
3465                glTranslatef( 0, 30,-0.5);
3466                //           textObj_draw_centered( player[player[0].winner?0:1].text );
3467                textObj_setText( winner_name_text_obj, player[player[0].winner?0:1].name );
3468                textObj_draw_centered( winner_name_text_obj );
3469                glTranslatef( 0,-60, 0.0);
3470                textObj_draw_centered( winner_text_obj );
3471                //           textObj_draw( winner_text_obj );
3472                glPopMatrix();
3473                glDisable(GL_BLEND);
3474            }
3475        }
3476 
3477 
3478        if(helpscreen_on){
3479            glColor3f(0.7,0.7,0.7);
3480            glEnable(GL_TEXTURE_2D);
3481            glEnable(GL_BLEND);
3482            glBlendFunc(GL_ONE,GL_ONE);
3483            glPushMatrix();
3484            draw_help_screen(win_width, win_height);
3485            glPopMatrix();
3486            glDisable(GL_LIGHTING);
3487            glDisable(GL_TEXTURE_2D);
3488            glDisable(GL_BLEND);
3489        }
3490 
3491        if(options_gamemode==options_gamemode_tournament &&
3492           tournament_state.wait_for_next_match)
3493        {
3494            int i;
3495            struct TournamentState_ * ts;
3496            ts = &tournament_state;
3497            Display_tournament_tree(&tournament_state);
3498 //           printf("Pairings: \n");
3499            for(i=0;i<(1<<(ts->round_num-ts->round_ind-1));i++){
3500 /*               printf("%s vs. %s\n",
3501                       ts->roster.player[ts->game[ts->round_ind][i].roster_player1].name,
3502                       ts->roster.player[ts->game[ts->round_ind][i].roster_player2].name
3503                      );*/
3504 /*               printf("%d vs. %d\n",
3505                       ts->game[ts->round_ind][i].roster_player1,
3506                       ts->game[ts->round_ind][i].roster_player2
3507                      );*/
3508            }
3509        }
3510 
3511        if( g_act_menu != (menuType *)0 ){
3512            //           glColor3f(0.7,0.7,0.7);
3513            glColor3f(1.0,1.0,1.0);
3514            glEnable(GL_TEXTURE_2D);
3515            glEnable(GL_BLEND);
3516            glDisable(GL_LIGHTING);
3517            glBlendFunc(GL_ONE,GL_ONE);
3518            glPushMatrix();
3519            glTranslatef(0.0,0.0,-1.0);
3520            glScalef(2.0/win_width,2.0/win_height,1.0);
3521            menu_draw( g_act_menu );
3522            glPopMatrix();
3523            glDisable(GL_BLEND);
3524        }
3525 
3526        glEnable(GL_DEPTH_TEST);
3527        glEnable(GL_LIGHTING);
3528        glEnable(GL_TEXTURE_2D);
3529        glPopMatrix();
3530 
3531        glMatrixMode( GL_PROJECTION );
3532        glPopMatrix();
3533        glMatrixMode( GL_MODELVIEW );
3534    }
3535 
3536    glPopMatrix();
3537    } /* rg stereo */
3538 
3539 //   glutSwapBuffers();
3540 }
3541 
3542 
ResizeWindow(int width,int height)3543 void ResizeWindow( int width, int height )
3544 {
3545 /*   if (width > WIDTH)
3546        width = WIDTH;
3547    if (height > HEIGHT)
3548        height = HEIGHT;*/
3549 
3550     win_width=width;
3551     win_height=height;
3552    glViewport( 0, 0, width, height );
3553    glMatrixMode( GL_PROJECTION );
3554    glLoadIdentity();
3555    //   glFrustum( -1.0, 1.0, -1.0, 1.0, 4.0, 1000.0 );
3556 
3557 //   gluPerspective(cam_FOV, /* field of view in degree */
3558 //     (GLfloat) width/(GLfloat) height, /* aspect ratio */
3559 //     0.1, /* Z near */
3560 //                  10.0); /* Z far */
3561 
3562 //   gluLookAt(0.0, 1.0, 380.0,  /* eye is at (0,8,60) */
3563 //     0.0, 0.0, 0.0,      /* center is at (0,8,0) */
3564 //     0.0, 1.0, 0.0);      /* up is in postivie Y direction */
3565 }
3566 
3567 
SetMode(GLuint m)3568 static void SetMode(GLuint m)
3569 {
3570    /* disable everything */
3571    glDisable(GL_LIGHTING);
3572    glDisable(GL_TEXTURE_2D);
3573    glDisable(GL_TEXTURE_GEN_S);
3574    glDisable(GL_TEXTURE_GEN_T);
3575 
3576    /* enable what's needed */
3577    if (m==LIT) {
3578       glEnable(GL_LIGHTING);
3579    }
3580    else if (m==TEXTURED) {
3581       glEnable(GL_LIGHTING);
3582       glEnable(GL_TEXTURE_2D);
3583    }
3584    else if (m==REFLECT) {
3585       glEnable(GL_LIGHTING);
3586       glEnable(GL_TEXTURE_2D);
3587       glEnable(GL_TEXTURE_GEN_S);
3588       glEnable(GL_TEXTURE_GEN_T);
3589    }
3590 }
3591 
restart_game_common()3592 void restart_game_common()
3593 {
3594     player[0].half_full=BALL_ANY;
3595     player[1].half_full=BALL_ANY;
3596     player[0].place_cue_ball=0;
3597     player[1].place_cue_ball=0;
3598     player[0].winner=0;
3599     player[1].winner=0;
3600     player[0].score=0;
3601     player[1].score=0;
3602     textObj_setText(player[0].score_text,"0");
3603     textObj_setText(player[1].score_text,"0");
3604     create_walls( &walls );
3605     create_scene( &balls );
3606     g_shot_due=1;
3607 }
3608 
3609 
3610 
restart_game_tournment()3611 void restart_game_tournment()
3612 {
3613     restart_game_common();
3614     g_motion_ratio=1.0;
3615     init_tournament_state(&tournament_state);
3616     act_player=0;
3617     queue_view=player[act_player].queue_view;
3618 }
3619 
3620 
restart_game_training()3621 void restart_game_training()
3622 {
3623     restart_game_common();
3624     g_motion_ratio=1.0;
3625     player_copy(&player[0],human_player_roster.player[0]);
3626     player_copy(&player[1],human_player_roster.player[0]);
3627     act_player=0;
3628     queue_view=player[act_player].queue_view;
3629 }
3630 
3631 
restart_game_match()3632 void restart_game_match()
3633 {
3634     restart_game_common();
3635     g_motion_ratio=1.0;
3636     player_copy(&player[0],human_player_roster.player[0]);
3637     player_copy(&player[1],human_player_roster.player[1]);
3638     act_player=0;
3639     queue_view=player[act_player].queue_view;
3640 }
3641 
3642 
restart_game()3643 void restart_game()
3644 {
3645     switch(options_gamemode){
3646     case options_gamemode_tournament: restart_game_tournment(); break;
3647     case options_gamemode_training:   restart_game_training();  break;
3648     case options_gamemode_match:      restart_game_match();     break;
3649     }
3650 }
3651 
3652 
3653 
control_set(int * control_param)3654 void control_set(int * control_param)
3655 {
3656     if(!control__active){
3657         *control_param=1;
3658         control__updated=1;
3659         control__active=1;
3660     }
3661 }
3662 
control_unset(int * control_param)3663 void control_unset(int * control_param)
3664 {
3665     if(control__active){
3666         *control_param=0;
3667         control__active=0;
3668     }
3669 }
3670 
control_toggle(int * control_param)3671 void control_toggle(int * control_param)
3672 {
3673     if(control__active){
3674         control_unset(control_param);
3675     }else{
3676         control_set(control_param);
3677     }
3678 }
3679 
3680 
Key(int key,int modifiers)3681 void Key( int key, int modifiers )
3682 {
3683    float step = 3.0;
3684 
3685    if( g_act_menu != (menuType *)0 ){
3686        /* menu keys */
3687        switch (key) {
3688        case KSYM_PAGE_UP:
3689        case KSYM_UP:
3690            menu_select_prev(g_act_menu); break;
3691        case KSYM_PAGE_DOWN:
3692        case KSYM_DOWN:
3693            menu_select_next(g_act_menu); break;
3694        case 13:
3695            menu_choose( &g_act_menu ); break;
3696        case 27:
3697            menu_exit( &g_act_menu ); break;
3698        default:
3699            menu_text_keystroke( g_act_menu, key ); break;
3700        }
3701 
3702    } else {
3703 
3704    /* general keys */
3705       switch (key) {
3706       case KSYM_PAGE_UP:
3707       case KSYM_UP:
3708           if( g_act_menu != (menuType *)0 ){
3709               menu_select_prev(g_act_menu);
3710           } else {
3711               if(!player[act_player].is_AI && !balls_moving)
3712                   queue_strength = strength01( queue_strength+0.01 );
3713           }
3714          break;
3715       case KSYM_PAGE_DOWN:
3716       case KSYM_DOWN:
3717           if( g_act_menu != (menuType *)0 ){
3718               menu_select_next(g_act_menu);
3719           } else {
3720               if(!player[act_player].is_AI && !balls_moving)
3721                   queue_strength = strength01( queue_strength-0.01 );
3722           }
3723          break;
3724       case KSYM_LEFT:
3725          Zrot += step;
3726          break;
3727       case KSYM_RIGHT:
3728          Zrot -= step;
3729          break;
3730       case KSYM_F1:
3731           if(g_act_menu==(menuType *)0){
3732               helpscreen_on = !helpscreen_on;
3733               if(helpscreen_on==0) delete_help_screen();
3734           }
3735          break;
3736       case KSYM_F2:
3737           birdview();
3738          break;
3739       case 'o':
3740           printf("saving config\n");
3741          save_config();
3742          break;
3743       case 'x':
3744          scale *= 1.1;
3745          break;
3746       case 'y':
3747          scale /= 1.1;
3748          break;
3749       case 27:
3750 //         if( menu_on ){
3751          if(g_act_menu!=(menuType *)0){
3752              fprintf(stderr,"menu backstep\n");
3753              menu_exit( &g_act_menu );
3754              if( g_act_menu == (menuType *)0 ){
3755 //                 g_act_menu = g_main_menu;
3756                  menu_on=0;
3757              }
3758          } else if(helpscreen_on){
3759              helpscreen_on=0;
3760              delete_help_screen();
3761          } else {
3762              DPRINTF("menu on\n");
3763              menu_on=1;
3764              g_act_menu = g_main_menu;
3765          }
3766 //         exit(0);
3767          break;
3768       case ' ':
3769       case 13:
3770           if(modifiers == 0){
3771               if( g_act_menu != (menuType *)0 ){
3772                   menu_choose( &g_act_menu );
3773               } else {
3774                   /* this has to be the same as middle mouse button !!! - maybe put it in a function some day  */
3775                   if (options_gamemode==options_gamemode_tournament && tournament_state.wait_for_next_match) {
3776                       tournament_state_setup_next_match(&tournament_state);
3777                       tournament_state.wait_for_next_match=0;
3778                   }else if( (!player[act_player].is_net) && (!player[act_player].is_AI) ){
3779                       g_shot_due=0;
3780                       shoot(!queue_view);
3781                   }
3782               }
3783           }
3784           if(modifiers & KEY_MODIFIER_ALT){
3785               sys_toggle_fullscreen( win_width, win_height );
3786           }
3787           break;
3788       case KSYM_KP_ENTER:
3789           if(modifiers & KEY_MODIFIER_ALT){
3790               sys_toggle_fullscreen( win_width, win_height );
3791           }
3792           break;
3793 /*      case w:
3794           if(modifiers & KEY_MODIFIER_ALT){
3795               sys_fullscreen( 0, win_width, win_height );
3796           }
3797           break;*/
3798       case '0':
3799           do_computer_move(0);
3800          break;
3801       case 'a':
3802           player[act_player].is_AI = !player[act_player].is_AI;
3803          break;
3804       case 'n':
3805           restart_game();
3806          break;
3807       case 'i':
3808           show_fps = (show_fps==0)?1:0;
3809           break;
3810 #if 1 // def USE_SDL  /* VRPool compatible key mappings */
3811 //      case 't': fprintf(stderr,"calling sys_remove_titlebar\n"); sys_remove_titlebar(); break;
3812       case 's': control_set(&control__mouse_shoot); break;
3813       case 'b': control_set(&control__cue_butt_updown); break;
3814       case 'e': control_set(&control__english); break;
3815       case 'm': control_set(&control__place_cue_ball); break;
3816 #else
3817       case 's': control_toggle(&control__mouse_shoot); break;
3818       case 'b': control_toggle(&control__cue_butt_updown); break;
3819       case 'e': control_toggle(&control__english); break;
3820       case 'm': control_toggle(&control__place_cue_ball); break;
3821 #endif
3822       case 'v':
3823           vline_on = (vline_on==0)?1:0;
3824          break;
3825       case KSYM_F3:
3826       case 'c':
3827           toggle_queue_view();
3828          break;
3829       case KSYM_F4:
3830       case 'f':
3831           options_free_view_on = (options_free_view_on==0)?1:0;
3832          break;
3833       case 'l':
3834           options_ball_fresnel_refl = (options_ball_fresnel_refl==0)?1:0;
3835          break;
3836       /*      case 's':
3837           options_rgstereo_on = (options_rgstereo_on==0)?1:0;
3838           if(!options_rgstereo_on) glColorMask(1, 1, 1, 1);
3839           delete_queue_texbind();  create_texbinds(&balls);  create_queue_texbind();
3840           table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
3841          break;*/
3842       case 'r':
3843           options_ball_reflections_blended=!options_ball_reflections_blended;
3844          break;
3845       case 9:  /* TAB */
3846           if( options_gamemode == options_gamemode_training ){
3847               int old_cue_ball=player[act_player].cue_ball;
3848               do{
3849                   player[act_player].cue_ball++;
3850                   if( player[act_player].cue_ball >= balls.nr )
3851                       player[act_player].cue_ball=0;
3852                   if( player[act_player].cue_ball == old_cue_ball ) break;
3853                   DPRINTF("cue_ball=%d\n",player[act_player].cue_ball);
3854               }while( !balls.ball[player[act_player].cue_ball].in_game );
3855           }
3856 /*          {
3857               BallType * ball;
3858               int lookballnr_old;
3859               lookballnr_old=g_lookballnr;
3860               do{
3861                   g_lookballnr++;
3862                   ball=BM_get_ball_by_nr(g_lookballnr,&balls);
3863                   if( g_lookballnr > balls.nr ) g_lookballnr=0;
3864               } while( !ball->in_game && g_lookballnr!=lookballnr_old );
3865               if ( g_lookballnr==lookballnr_old ) g_lookballnr=balls.nr;
3866           }
3867           if( g_lookballnr !=0 ) queue_view=0; else queue_view=1;*/
3868          break;
3869       case'u':  /* undo */
3870           if( options_gamemode == options_gamemode_training ){
3871               copy_balls(&bakballs,&balls);
3872           }
3873          break;
3874       }
3875 
3876    }  /* no menu active */
3877 //   glutPostRedisplay();
3878    sys_redisplay();
3879 }
3880 
3881 
KeyUp(int key,int modifiers)3882 void KeyUp( int key, int modifiers )
3883 {
3884     if( g_act_menu == (menuType *)0 ){
3885         switch (key) {
3886         case 's': control_unset(&control__mouse_shoot); break;
3887         case 'b': control_unset(&control__cue_butt_updown); break;
3888         case 'e': control_unset(&control__english); break;
3889         case 'm': control_unset(&control__place_cue_ball); break;
3890         }
3891     }
3892 }
3893 
3894 
host_network_game()3895 void host_network_game()
3896 {
3897     int i;
3898     int dummy=42;
3899     player[0].is_AI=0;  /* FIXME maybe one can leave this away someday */
3900     player[1].is_AI=0;  /* FIXME maybe one can leave this away someday */
3901     player[1].is_net=1;    player[0].is_net=0;
3902     g_is_host=1;
3903     g_network_play=1;
3904 
3905     g_socket = host_create_socket();
3906     fprintf(stderr,"host: writing test integer: %d\n",dummy);
3907     socket_write(g_socket,(char *)&dummy,sizeof(dummy));
3908     socket_read(g_socket,(char *)&dummy,sizeof(dummy));
3909     fprintf(stderr,"host: read test integer from client: %d\n",dummy);
3910     player[1].queue_view=0;
3911     player[0].queue_view=1;
3912 
3913     fprintf(stderr,"host: write gametype: %d\n",gametype);
3914     socket_write(g_socket,(char *)&gametype,sizeof(gametype));
3915 
3916     fprintf(stderr,"host: write table size: %f\n",options_table_size);
3917     socket_write(g_socket,(char *)&options_table_size,sizeof(options_table_size));
3918 
3919     fprintf(stderr,"host: write player1-name: %s\n",player[0].name);
3920     i=-1;
3921     do{
3922         i++;
3923         socket_write(g_socket,(char *)&(player[0].name[i]),sizeof(player[0].name[i]));
3924     }while(player[0].name[i]!=0);
3925 
3926     fprintf(stderr,"host: read player2-name %s\n",player[1].name);
3927     i=-1;
3928     do{
3929         i++;
3930         socket_write(g_socket,(char *)&(player[1].name[i]),sizeof(player[1].name[i]));
3931     }while(player[1].name[i]!=0);
3932 
3933     for(i=0;i<balls.nr;i++){
3934         fprintf(stderr,"host: write ball#%02d\n",i);
3935         socket_write(g_socket,(char *)&(balls.ball[i]),sizeof(balls.ball[i]));
3936     }
3937 }
3938 
3939 
join_network_game()3940 void join_network_game()
3941 {
3942     int i;
3943     int dummy=42;
3944     player[0].is_AI=0;  /* FIXME maybe one can leave this away someday */
3945     player[1].is_AI=0;  /* FIXME maybe one can leave this away someday */
3946     player[1].is_net=0;    player[0].is_net=1;
3947     g_is_host=0;
3948     g_network_play=1;
3949 //    options_net_hostname = "10.0.0.1";
3950 
3951     g_socket = client_call_socket( options_net_hostname );
3952     socket_read(g_socket,(char *)&dummy,sizeof(dummy));
3953     fprintf(stderr,"client: read test integer from host: %d\n",dummy);
3954     dummy=7;
3955     fprintf(stderr,"client: writing test integer: %d\n",dummy);
3956     socket_write(g_socket,(char *)&dummy,sizeof(dummy));
3957     player[0].queue_view=0;
3958     player[1].queue_view=1;
3959     queue_view=0;
3960 
3961     socket_read(g_socket,(char *)&gametype,sizeof(gametype));
3962     fprintf(stderr,"client: read gametype: %d\n",gametype);
3963     set_gametype( gametype );
3964 
3965     socket_read(g_socket,(char *)&options_table_size,sizeof(options_table_size));
3966     fprintf(stderr,"client: read table size: %f\n",options_table_size);
3967 
3968     create_scene( &balls );  create_walls( &walls );
3969     table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
3970 
3971     i=-1;
3972     do{
3973         i++;
3974         socket_read(g_socket,(char *)&(player[0].name[i]),sizeof(player[0].name[i]));
3975     }while(player[0].name[i]!=0);
3976     fprintf(stderr,"client: read player1-name: %s\n",player[0].name);
3977     textObj_setText(player[0].text, player[0].name);
3978 
3979     i=-1;
3980     do{
3981         i++;
3982         socket_read(g_socket,(char *)&(player[1].name[i]),sizeof(player[1].name[i]));
3983     }while(player[1].name[i]!=0);
3984     fprintf(stderr,"client: read player2-name: %s\n",player[1].name);
3985     textObj_setText(player[1].text, player[1].name);
3986 
3987     for(i=0;i<balls.nr;i++){
3988         fprintf(stderr,"client: read ball#%02d\n",i);
3989         socket_read(g_socket,(char *)&(balls.ball[i]),sizeof(balls.ball[i]));
3990     }
3991 /*    create_scene( &balls );  create_walls( &walls );
3992     table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );*/
3993 
3994 }
3995 
3996 
free_cuberef_tex()3997 void free_cuberef_tex()
3998 {
3999     int i;
4000     for( i=0 ; i<cuberef_allballs_texbind_nr ; i++ ){
4001         glDeleteTextures(1,&cuberef_allballs_texbind[i]);
4002     }
4003     free(cuberef_allballs_texbind);
4004     cuberef_allballs_texbind=0;
4005 }
4006 
4007 
reassign_and_gen_cuberef_tex()4008 void reassign_and_gen_cuberef_tex()
4009 {
4010     int i,j,k,l, layer, w, h, target;
4011     char * data;
4012 
4013     if( cuberef_allballs_texbind!=0 || balls.nr!=cuberef_allballs_texbind_nr ) free_cuberef_tex();
4014 
4015 //            glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4016 //            glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4017     //            glBindTexture(GL_TEXTURE_2D, cube_tex_bind);
4018 
4019     cuberef_allballs_texbind_nr=balls.nr;
4020 
4021     cuberef_allballs_texbind=malloc(cuberef_allballs_texbind_nr*sizeof(*cuberef_allballs_texbind));
4022 
4023     for( i=0 ; i<cuberef_allballs_texbind_nr ; i++ ){
4024         glGenTextures(1,&cuberef_allballs_texbind[i]);
4025     }
4026 
4027             for(i=0;i<6;i++){
4028 /*                switch(i){
4029                 case 0: load_png(posxpng, &w, &h, &depth, &data); break;
4030                 case 1: load_png(posypng, &w, &h, &depth, &data); break;
4031                 case 2: load_png(poszpng, &w, &h, &depth, &data); break;
4032                 case 3: load_png(negxpng, &w, &h, &depth, &data); break;
4033                 case 4: load_png(negypng, &w, &h, &depth, &data); break;
4034                 case 5: load_png(negzpng, &w, &h, &depth, &data); break;
4035                 }*/
4036                 switch(i){
4037                 case 0: target=GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; break;
4038                 case 1: target=GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; break;
4039                 case 2: target=GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; break;
4040                 case 3: target=GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; break;
4041                 case 4: target=GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; break;
4042                 case 5: target=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; break;
4043                 }
4044                 w=cuberef_res; h=cuberef_res;
4045                 DPRINTF(".... w=%d,h=%d\n",w,h);
4046                 data=malloc(w*h*3);
4047                 for(j=0;j<w*h;j++){
4048                     if( ((j%w)%9)<1 || ((j/w)%9)<1 ){
4049                         data[j*3+0]=255*(j%w)/w;
4050                         data[j*3+1]=255*(j/w)/w;
4051                         data[j*3+2]=0;
4052                     }else{
4053                         data[j*3+0]=((i%3)==0 || i==5)?0xFF:0;
4054                         data[j*3+1]=((i%3)==1 || i==3)?0xFF:0;
4055                         data[j*3+2]=((i%3)==2 || i==4)?0xFF:0;
4056                     }
4057                 }
4058 //                gluBuild2DMipmaps(target, 3, w, h, GL_RGB, GL_UNSIGNED_BYTE, data);
4059                 DPRINTF("5-%d\n",i);
4060                 for(k=0;k<cuberef_allballs_texbind_nr;k++){
4061                     glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cuberef_allballs_texbind[k]);
4062                     for( l=cuberef_res,layer=0 ; l>0 ; l>>=1,layer++){
4063                         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4064                         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4065                         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4066                         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4067                         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4068 //                        glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT);
4069 //                        glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT);
4070 //                        glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_REPEAT);
4071 //                        glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4072 //                        glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4073                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4074                         glTexImage2D(target,
4075                                      layer,
4076 //                                     GL_RGB16, /*3,*/
4077 //                                     GL_R3_G3_B2, /*3,*/
4078                                      GL_RGB, /*3,*/
4079                                      l,  /* width */
4080                                      l,  /* height */
4081                                      0,
4082                                      GL_RGB,
4083                                      GL_UNSIGNED_BYTE,
4084                                      data);
4085                     }
4086                 }
4087                 free( data );
4088             }
4089 }
4090 
4091 
menu_cb(int id,void * arg)4092 void menu_cb( int id, void * arg )
4093 {
4094     switch(id){
4095     case MENU_ID_MAIN_QUIT:       save_config(); exit(0); break;
4096     case MENU_ID_OPTIONS_DISPLAY: fprintf(stderr,"menu_cb:options/display\n"); break;
4097     case MENU_ID_OPTIONS_SOUND:   fprintf(stderr,"menu_cb:options/sound\n"); break;
4098     case MENU_ID_OPTIONS_GAME:    fprintf(stderr,"menu_cb:options/game\n"); break;
4099     case MENU_ID_TABLESIZE_7FOOT:
4100         options_table_size = 7.0*2.54*12.0/100.0;
4101         create_scene( &balls );  create_walls( &walls );
4102         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4103         break;
4104     case MENU_ID_TABLESIZE_8FOOT:
4105         options_table_size = 8.0*2.54*12.0/100.0;
4106         create_scene( &balls );  create_walls( &walls );
4107         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4108         break;
4109     case MENU_ID_TABLESIZE_9FOOT:
4110         options_table_size = 9.0*2.54*12.0/100.0;
4111         create_scene( &balls );  create_walls( &walls );
4112         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4113         break;
4114     case MENU_ID_TABLESIZE_12FOOT:
4115         options_table_size = 11.708*2.54*12.0/100.0;
4116         create_scene( &balls );  create_walls( &walls );
4117         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4118         break;
4119     case MENU_ID_TABLETHEME_GOLDGREEN:
4120         options_table_color   = options_table_color_green;
4121         options_diamond_color = options_diamond_color_gold;
4122         options_frame_tex_var = 1;
4123         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4124         break;
4125     case MENU_ID_TABLETHEME_GOLDRED:
4126         options_table_color   = options_table_color_red;
4127         options_diamond_color = options_diamond_color_gold;
4128         options_frame_tex_var = 1;
4129         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4130         break;
4131     case MENU_ID_TABLETHEME_CHROMEBLUE:
4132         options_table_color   = options_table_color_blue;
4133         options_diamond_color = options_diamond_color_chrome;
4134         options_frame_tex_var = 1;
4135         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4136         break;
4137     case MENU_ID_TABLETHEME_BLACKBEIGE:
4138         options_table_color   = options_table_color_beige;
4139         options_diamond_color = options_diamond_color_black;
4140         options_frame_tex_var = 1;
4141         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4142         break;
4143     case MENU_ID_TABLETHEME_BLACKWHITE:
4144         options_table_color   = options_table_color_black;
4145         options_diamond_color = options_diamond_color_black;
4146         options_frame_color   = options_frame_color_white;
4147         options_frame_tex_var = 0;
4148         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4149         break;
4150     case MENU_ID_HELPLINE_ON:
4151         vline_on=1;
4152         break;
4153     case MENU_ID_HELPLINE_OFF:
4154         vline_on=0;
4155         break;
4156     case MENU_ID_GAMETYPE_8BALL:
4157         set_gametype( GAME_8BALL );    restart_game();  /* create_scene( &balls );  create_walls( &walls ); alrerady in restart_game */
4158         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4159         reassign_and_gen_cuberef_tex();
4160         break;
4161     case MENU_ID_GAMETYPE_9BALL:
4162         set_gametype( GAME_9BALL );    restart_game();  /* create_scene( &balls );  create_walls( &walls ); */
4163         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4164         reassign_and_gen_cuberef_tex();
4165         break;
4166     case MENU_ID_GAMETYPE_CARAMBOL:
4167         set_gametype( GAME_CARAMBOL ); restart_game();  /* create_scene( &balls );  create_walls( &walls ); */
4168         printf("player[0].cue_ball=%d\n",player[0].cue_ball);
4169         printf("player[1].cue_ball=%d\n",player[1].cue_ball);
4170         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4171         reassign_and_gen_cuberef_tex();
4172         break;
4173     case MENU_ID_GAMETYPE_SNOOKER:
4174         set_gametype( GAME_SNOOKER );  restart_game();  /* create_scene( &balls );  create_walls( &walls ); */
4175         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4176         reassign_and_gen_cuberef_tex();
4177         break;
4178     case MENU_ID_FULLSCREEN_ON:
4179         sys_fullscreen( 1, win_width, win_height );
4180         break;
4181     case MENU_ID_FULLSCREEN_OFF:
4182         sys_fullscreen( 0, win_width, win_height );
4183         break;
4184     case MENU_ID_RGSTEREO_ON:
4185         options_rgstereo_on=1;
4186         delete_queue_texbind();  create_texbinds(&balls);  create_queue_texbind();
4187         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4188         break;
4189     case MENU_ID_RGSTEREO_OFF:
4190         options_rgstereo_on=0;
4191         glColorMask(1, 1, 1, 1);
4192         delete_queue_texbind();  create_texbinds(&balls);  create_queue_texbind();
4193         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4194         break;
4195     case MENU_ID_RGAIM_LEFT:   options_rgaim=1; break;
4196     case MENU_ID_RGAIM_RIGHT:  options_rgaim=2; break;
4197     case MENU_ID_RGAIM_MIDDLE: options_rgaim=0; break;
4198 
4199     case MENU_ID_LENSFLARE_ON:
4200         options_lensflare=1;
4201         break;
4202     case MENU_ID_LENSFLARE_OFF:
4203         options_lensflare=0;
4204         break;
4205     case MENU_ID_MAIN_RESTART:
4206         restart_game();
4207         break;
4208     case MENU_ID_PLAYER1_NAME:
4209         strcpy(player[0].name,(char *)arg);
4210         textObj_setText(player[0].text,player[0].name);
4211         player_copy(&human_player_roster.player[0],player[0]);
4212         printf("callback:MENU_ID_PLAYER1_NAME\n");
4213         break;
4214     case MENU_ID_PLAYER2_NAME:
4215         strcpy(player[1].name,(char *)arg);
4216         textObj_setText(player[1].text,player[1].name);
4217         player_copy(&human_player_roster.player[1],player[1]);
4218         printf("callback:MENU_ID_PLAYER2_NAME\n");
4219         break;
4220     case MENU_ID_PLAYER1_SKILL_EXCEL:  player[0].err=0.0; player_copy(&human_player_roster.player[0],player[0]); break;
4221     case MENU_ID_PLAYER1_SKILL_GOOD:   player[0].err=0.1; player_copy(&human_player_roster.player[0],player[0]); break;
4222     case MENU_ID_PLAYER1_SKILL_MEDIUM: player[0].err=0.3; player_copy(&human_player_roster.player[0],player[0]); break;
4223     case MENU_ID_PLAYER1_SKILL_BAD:    player[0].err=0.6; player_copy(&human_player_roster.player[0],player[0]); break;
4224     case MENU_ID_PLAYER1_SKILL_WORSE:  player[0].err=1.0; player_copy(&human_player_roster.player[0],player[0]); break;
4225 
4226     case MENU_ID_PLAYER2_SKILL_EXCEL:  player[1].err=0.0; player_copy(&human_player_roster.player[1],player[1]); break;
4227     case MENU_ID_PLAYER2_SKILL_GOOD:   player[1].err=0.1; player_copy(&human_player_roster.player[1],player[1]); break;
4228     case MENU_ID_PLAYER2_SKILL_MEDIUM: player[1].err=0.3; player_copy(&human_player_roster.player[1],player[1]); break;
4229     case MENU_ID_PLAYER2_SKILL_BAD:    player[1].err=0.6; player_copy(&human_player_roster.player[1],player[1]); break;
4230     case MENU_ID_PLAYER2_SKILL_WORSE:  player[1].err=1.0; player_copy(&human_player_roster.player[1],player[1]); break;
4231 
4232     case MENU_ID_PLAYER1_TYPE_HUMAN:  player[0].is_AI=0; player_copy(&human_player_roster.player[0],player[0]); break;
4233     case MENU_ID_PLAYER2_TYPE_HUMAN:  player[1].is_AI=0; player_copy(&human_player_roster.player[1],player[1]); break;
4234 
4235     case MENU_ID_PLAYER1_TYPE_AI:
4236         if(act_player==0){
4237             player[0].is_AI=1;
4238             player[0].queue_view=0;
4239             if(queue_view) toggle_queue_view();
4240             do_computer_move(1);
4241         } else {
4242             player[0].is_AI=1;
4243             player[0].queue_view=0;
4244         }
4245         player_copy(&human_player_roster.player[0],player[0]);
4246         break;
4247     case MENU_ID_PLAYER2_TYPE_AI:
4248         if(act_player==1){
4249             player[1].is_AI=1;
4250             player[1].queue_view=0;
4251             if(queue_view) toggle_queue_view();
4252             do_computer_move(1);
4253         } else {
4254             player[1].is_AI=1;
4255             player[1].queue_view=0;
4256         }
4257         player_copy(&human_player_roster.player[1],player[1]);
4258         break;
4259 
4260     case MENU_ID_BALL_DETAIL_LOW:
4261         options_max_ball_detail     = options_max_ball_detail_LOW;
4262         options_ball_detail_nearmax = options_ball_detail_nearmax_LOW;
4263         break;
4264     case MENU_ID_BALL_DETAIL_MED:
4265         options_max_ball_detail     = options_max_ball_detail_MED;
4266         options_ball_detail_nearmax = options_ball_detail_nearmax_MED;
4267         break;
4268     case MENU_ID_BALL_DETAIL_HIGH:
4269         options_max_ball_detail     = options_max_ball_detail_HIGH;
4270         options_ball_detail_nearmax = options_ball_detail_nearmax_HIGH;
4271         break;
4272     case MENU_ID_BALL_DETAIL_VERYHIGH:
4273         options_max_ball_detail     = options_max_ball_detail_VERYHIGH;
4274         options_ball_detail_nearmax = options_ball_detail_nearmax_VERYHIGH;
4275         break;
4276     case MENU_ID_VIDMODE:
4277         {
4278             sysResolution * mode;
4279             mode = (sysResolution *)arg;
4280             sys_resize(mode->w, mode->h);
4281         }
4282         break;
4283     case MENU_ID_MAIN_HELP:
4284         helpscreen_on = !helpscreen_on;
4285         if(helpscreen_on==0) delete_help_screen();
4286         break;
4287     case MENU_ID_NETWORK_HOST:
4288         host_network_game();
4289         break;
4290     case MENU_ID_NETWORK_JOIN:
4291         join_network_game();
4292         break;
4293     case MENU_ID_NETWORK_IP:
4294         strcpy(options_net_hostname,(char *)arg);
4295         break;
4296     case MENU_ID_NETWORK_PORTNUM:
4297         sscanf((char *)arg,"%d",&options_net_portnum);
4298         break;
4299     case MENU_ID_REFLECTION_SPHERE:
4300         options_cuberef = 0;
4301         free_cuberef_tex();
4302         break;
4303     case MENU_ID_REFLECTION_RENDERED:
4304         options_cuberef = 1;
4305         options_ball_fresnel_refl = 0;
4306         reassign_and_gen_cuberef_tex();
4307         break;
4308     case MENU_ID_REFLECTION_RENDERED_FRESNEL:
4309         options_cuberef = 1;
4310         options_ball_fresnel_refl = 1;
4311         reassign_and_gen_cuberef_tex();
4312         break;
4313     case MENU_ID_BALLTRACE_ON:
4314         options_balltrace = 1;
4315         break;
4316     case MENU_ID_BALLTRACE_OFF:
4317         options_balltrace = 0;
4318         break;
4319     case MENU_ID_BUMPREF_ON:
4320         options_bumpref = 1;
4321         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4322         break;
4323     case MENU_ID_BUMPREF_OFF:
4324         options_bumpref = 0;
4325         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4326         break;
4327     case MENU_ID_BUMPWOOD_ON:
4328         options_bumpwood = 1;
4329         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4330         break;
4331     case MENU_ID_BUMPWOOD_OFF:
4332         options_bumpwood = 0;
4333         table_obj = create_table( spheretexbind, &walls, gametype==GAME_CARAMBOL );
4334         break;
4335     case MENU_ID_GAMEMODE_MATCH:      options_gamemode=options_gamemode_match;      break;
4336     case MENU_ID_GAMEMODE_TRAINING:   options_gamemode=options_gamemode_training;   break;
4337     case MENU_ID_GAMEMODE_TOURNAMENT: options_gamemode=options_gamemode_tournament; init_tournament_state(&tournament_state); break;
4338     case MENU_ID_SINGLE_MATCH_START:
4339         options_gamemode=options_gamemode_match;
4340         restart_game();
4341         break;
4342     case MENU_ID_TOURNAMENT_START:
4343         options_gamemode=options_gamemode_tournament;
4344         init_tournament_state(&tournament_state);
4345         restart_game();
4346         break;
4347     case MENU_ID_TRAINING_START:
4348         options_gamemode=options_gamemode_training;
4349         restart_game();
4350         break;
4351     case MENU_ID_IDLE:
4352         break;
4353     }
4354 }
4355 
4356 
init_menu()4357 void init_menu()
4358 {
4359     char str[256];
4360 
4361     menuType * player1_skill_menu;
4362     menuType * player2_skill_menu;
4363     menuType * player1_type_menu;
4364     menuType * player2_type_menu;
4365     menuType * player1_menu;
4366     menuType * player2_menu;
4367     menuType * quit_menu;
4368     menuType * gamemode_menu;
4369     menuType * restart_menu;
4370     menuType * network_menu;
4371     menuType * network_join_menu;
4372     menuType * display_menu;
4373     menuType * game_menu;
4374     menuType * tablesize_menu;
4375     menuType * tabletheme_menu;
4376     menuType * helpline_menu;
4377     menuType * gametype_menu;
4378     menuType * fullscreen_menu;
4379     menuType * rgaim_menu;
4380     menuType * rgenable_menu;
4381     menuType * rgstereo_menu;
4382     menuType * lensflare_menu;
4383     menuType * balldetail_menu;
4384     menuType * videomode_menu;
4385     menuType ** videomode_menus;
4386     menuType * reflection_menu;
4387     menuType * balltrace_menu;
4388     menuType * bumpref_menu;
4389     menuType * bumpwood_menu;
4390 #define OTHER_RESTART_MENU
4391 #ifdef OTHER_RESTART_MENU
4392     menuType * network_host_menu;
4393     menuType * single_match_menu;
4394     menuType * tournament_menu;
4395     menuType * training_menu;
4396 #endif
4397 
4398 
4399     {
4400         int i,j;
4401         char str[256];
4402         int entr_num=10;
4403         int mode_num=0;
4404         int menu_num=0;
4405         sysResolution * modes;
4406 
4407         /* several pages for the modes: this should fix the problems with many dsplay modes */
4408         /* however the selected resolution displayed in the parent menu will be wrong
4409            when selected from other the 1st page */
4410         modes=sys_list_modes();
4411         for(mode_num=0;modes[mode_num].w!=0;mode_num++);
4412         DPRINTF("mode_num=%d\n",mode_num);
4413         menu_num=(mode_num+entr_num-1)/entr_num;
4414         if (menu_num<1) menu_num=1;
4415 
4416         DPRINTF("menu_num=%d\n",menu_num);
4417         videomode_menus = (menuType **)malloc(menu_num*sizeof(menuType *));
4418 
4419         for(i=0;i<menu_num;i++){
4420             videomode_menus[i] = menu_new( menu_cb );
4421         }
4422         videomode_menu=videomode_menus[0];
4423 
4424         if( mode_num==0 ){
4425             menu_add_entry( videomode_menus[0], "<not available>", MENU_ID_IDLE );
4426         }
4427 
4428         i=0;
4429         for( j=0 ; j<menu_num && i<mode_num ; j++ ){
4430             if(mode_num!=0) do{
4431                 sprintf( str, "%dx%d", modes[i].w, modes[i].h );
4432                 DPRINTF( "%dx%d\n", modes[i].w, modes[i].h );
4433                 menu_add_arg_entry( videomode_menus[j], str, MENU_ID_VIDMODE, (void *)&modes[i] );
4434                 i++;
4435             } while ( (i%entr_num)!=0 && i<mode_num );
4436             if( i<mode_num ){
4437                 menu_add_submenu( videomode_menus[j], "more >",  videomode_menus[j+1], 0 );
4438             }
4439             menu_add_exit ( videomode_menus[j], "< back" );
4440         }
4441 
4442     }
4443 
4444     bumpref_menu = menu_new( menu_cb );
4445     menu_add_entry( bumpref_menu, "on",       MENU_ID_BUMPREF_ON );
4446     menu_add_entry( bumpref_menu, "off",      MENU_ID_BUMPREF_OFF );
4447     menu_add_exit ( bumpref_menu, "< back" );
4448 
4449     bumpwood_menu = menu_new( menu_cb );
4450     menu_add_entry( bumpwood_menu, "on",       MENU_ID_BUMPWOOD_ON );
4451     menu_add_entry( bumpwood_menu, "off",      MENU_ID_BUMPWOOD_OFF );
4452     menu_add_exit ( bumpwood_menu, "< back" );
4453 
4454     balltrace_menu = menu_new( menu_cb );
4455     menu_add_entry( balltrace_menu, "on",       MENU_ID_BALLTRACE_ON );
4456     menu_add_entry( balltrace_menu, "off",      MENU_ID_BALLTRACE_OFF );
4457     menu_add_exit ( balltrace_menu, "< back" );
4458 
4459     reflection_menu = menu_new( menu_cb );
4460     menu_add_entry( reflection_menu, "spheremap",        MENU_ID_REFLECTION_SPHERE );
4461     menu_add_entry( reflection_menu, "rendered",         MENU_ID_REFLECTION_RENDERED );
4462     menu_add_entry( reflection_menu, "rendered+fresnel", MENU_ID_REFLECTION_RENDERED_FRESNEL );
4463     menu_add_exit ( reflection_menu, "< back" );
4464 
4465     balldetail_menu = menu_new( menu_cb );
4466     menu_add_entry( balldetail_menu, "low",       MENU_ID_BALL_DETAIL_LOW );
4467     menu_add_entry( balldetail_menu, "medium",    MENU_ID_BALL_DETAIL_MED );
4468     menu_add_entry( balldetail_menu, "high",      MENU_ID_BALL_DETAIL_HIGH );
4469     menu_add_entry( balldetail_menu, "very high", MENU_ID_BALL_DETAIL_VERYHIGH );
4470     menu_add_exit ( balldetail_menu, "< back" );
4471 
4472     rgaim_menu = menu_new( menu_cb );
4473     menu_add_entry( rgaim_menu, "middle",   MENU_ID_RGAIM_MIDDLE );
4474     menu_add_entry( rgaim_menu, "left",     MENU_ID_RGAIM_LEFT );
4475     menu_add_entry( rgaim_menu, "right",    MENU_ID_RGAIM_RIGHT );
4476     menu_add_exit ( rgaim_menu, "< back" );
4477 
4478     rgenable_menu = menu_new( menu_cb );
4479     menu_add_entry( rgenable_menu, "rg on",   MENU_ID_RGSTEREO_ON  );
4480     menu_add_entry( rgenable_menu, "rg off",  MENU_ID_RGSTEREO_OFF );
4481     menu_add_exit ( rgenable_menu, "< back" );
4482 
4483     rgstereo_menu = menu_new( menu_cb );
4484     menu_add_submenu( rgstereo_menu, "enable",   rgenable_menu, 1 );
4485     menu_add_submenu( rgstereo_menu, "aim eye",  rgaim_menu,    1 );
4486     menu_add_exit ( rgstereo_menu, "< back" );
4487 
4488     lensflare_menu = menu_new( menu_cb );
4489     menu_add_entry( lensflare_menu, "lensflare on",   MENU_ID_LENSFLARE_ON  );
4490     menu_add_entry( lensflare_menu, "lensflare off",  MENU_ID_LENSFLARE_OFF );
4491     menu_add_exit ( lensflare_menu, "< back" );
4492 
4493     fullscreen_menu = menu_new( menu_cb );
4494     menu_add_entry( fullscreen_menu, "fullscreen", MENU_ID_FULLSCREEN_ON  );
4495     menu_add_entry( fullscreen_menu, "window",     MENU_ID_FULLSCREEN_OFF );
4496     menu_add_exit ( fullscreen_menu, "< back" );
4497 
4498     tablesize_menu = menu_new( menu_cb );
4499     menu_add_entry( tablesize_menu, "7 foot", MENU_ID_TABLESIZE_7FOOT );
4500     menu_add_entry( tablesize_menu, "8 foot", MENU_ID_TABLESIZE_8FOOT );
4501     menu_add_entry( tablesize_menu, "9 foot", MENU_ID_TABLESIZE_9FOOT );
4502     menu_add_entry( tablesize_menu, "12 foot", MENU_ID_TABLESIZE_12FOOT );
4503     menu_add_exit ( tablesize_menu, "< back" );
4504 
4505     tabletheme_menu = menu_new( menu_cb );
4506     menu_add_entry( tabletheme_menu, "gold-green",  MENU_ID_TABLETHEME_GOLDGREEN );
4507     menu_add_entry( tabletheme_menu, "gold-red",    MENU_ID_TABLETHEME_GOLDRED );
4508     menu_add_entry( tabletheme_menu, "chrome-blue", MENU_ID_TABLETHEME_CHROMEBLUE );
4509     menu_add_entry( tabletheme_menu, "black-white", MENU_ID_TABLETHEME_BLACKWHITE );
4510     menu_add_entry( tabletheme_menu, "black-beige", MENU_ID_TABLETHEME_BLACKBEIGE );
4511     menu_add_exit ( tabletheme_menu, "< back" );
4512 
4513     helpline_menu = menu_new( menu_cb );
4514     menu_add_entry( helpline_menu, "on",   MENU_ID_HELPLINE_ON  );
4515     menu_add_entry( helpline_menu, "off",  MENU_ID_HELPLINE_OFF );
4516     menu_add_exit ( helpline_menu, "< back" );
4517 
4518     gametype_menu = menu_new( menu_cb );
4519     menu_add_entry( gametype_menu, "8 ball",    MENU_ID_GAMETYPE_8BALL );
4520     menu_add_entry( gametype_menu, "9 ball",    MENU_ID_GAMETYPE_9BALL );
4521     menu_add_entry( gametype_menu, "carambol",  MENU_ID_GAMETYPE_CARAMBOL );
4522     menu_add_entry( gametype_menu, "snooker",   MENU_ID_GAMETYPE_SNOOKER );
4523     menu_add_exit ( gametype_menu, "< back" );
4524 
4525     game_menu = menu_new( menu_cb );
4526     menu_add_submenu( game_menu, "table size",  tablesize_menu,  1 );
4527     menu_add_submenu( game_menu, "help line",   helpline_menu,   1 );
4528     menu_add_submenu( game_menu, "game type",   gametype_menu,   1 );
4529     menu_add_exit   ( game_menu, "< back" );
4530 
4531     display_menu = menu_new( menu_cb );
4532     menu_add_submenu( display_menu, "resolution",       videomode_menu,  1 );
4533     menu_add_submenu( display_menu, "view mode",        fullscreen_menu, 1 );
4534     menu_add_submenu( display_menu, "red/green stereo", rgstereo_menu,   1 );
4535     menu_add_submenu( display_menu, "lensflare",        lensflare_menu,  1 );
4536     menu_add_submenu( display_menu, "ball detail",      balldetail_menu, 1 );
4537     menu_add_submenu( display_menu, "reflections",      reflection_menu, 1 );
4538     menu_add_submenu( display_menu, "bump reflections", bumpref_menu,    1 );
4539     menu_add_submenu( display_menu, "bumpy wood frame", bumpwood_menu,   1 );
4540     menu_add_submenu( display_menu, "table theme",      tabletheme_menu, 1 );
4541     menu_add_submenu( display_menu, "ball traces",      balltrace_menu,  1 );
4542     menu_add_exit   ( display_menu, "< back" );
4543 
4544     quit_menu = menu_new( menu_cb );
4545     menu_add_entry  ( quit_menu, "YES  out'a here",        MENU_ID_MAIN_QUIT );
4546     menu_add_exit   ( quit_menu, "NO  continue");
4547 
4548 
4549     player1_skill_menu = menu_new( menu_cb );
4550     menu_add_entry  ( player1_skill_menu, "excellent",   MENU_ID_PLAYER1_SKILL_EXCEL  );
4551     menu_add_entry  ( player1_skill_menu, "good",        MENU_ID_PLAYER1_SKILL_GOOD   );
4552     menu_add_entry  ( player1_skill_menu, "medium",      MENU_ID_PLAYER1_SKILL_MEDIUM );
4553     menu_add_entry  ( player1_skill_menu, "bad",         MENU_ID_PLAYER1_SKILL_BAD    );
4554     menu_add_entry  ( player1_skill_menu, "worse",       MENU_ID_PLAYER1_SKILL_WORSE  );
4555     menu_add_exit   ( player1_skill_menu, "< back");
4556 
4557     player2_skill_menu = menu_new( menu_cb );
4558     menu_add_entry  ( player2_skill_menu, "excellent",   MENU_ID_PLAYER2_SKILL_EXCEL  );
4559     menu_add_entry  ( player2_skill_menu, "good",        MENU_ID_PLAYER2_SKILL_GOOD   );
4560     menu_add_entry  ( player2_skill_menu, "medium",      MENU_ID_PLAYER2_SKILL_MEDIUM );
4561     menu_add_entry  ( player2_skill_menu, "bad",         MENU_ID_PLAYER2_SKILL_BAD    );
4562     menu_add_entry  ( player2_skill_menu, "worse",       MENU_ID_PLAYER2_SKILL_WORSE  );
4563     menu_add_exit   ( player2_skill_menu, "< back");
4564 
4565     player1_type_menu = menu_new( menu_cb );
4566     menu_add_entry  ( player1_type_menu, "AI",       MENU_ID_PLAYER1_TYPE_AI );
4567     menu_add_entry  ( player1_type_menu, "Human",    MENU_ID_PLAYER1_TYPE_HUMAN );
4568     menu_add_exit   ( player1_type_menu, "< back");
4569 
4570     player2_type_menu = menu_new( menu_cb );
4571     menu_add_entry  ( player2_type_menu, "AI",       MENU_ID_PLAYER2_TYPE_AI );
4572     menu_add_entry  ( player2_type_menu, "Human",    MENU_ID_PLAYER2_TYPE_HUMAN );
4573     menu_add_exit   ( player2_type_menu, "< back" );
4574 
4575     player1_menu = menu_new( menu_cb );
4576     sprintf(str,"P1 Name: %s",player[0].name);
4577     menu_add_textfield( player1_menu, str,        MENU_ID_PLAYER1_NAME, strlen("P1 Name: ") );
4578     menu_add_submenu  ( player1_menu, "P1 Type",  player1_type_menu,   1 );
4579     menu_add_submenu  ( player1_menu, "P1 Skill", player1_skill_menu,  1 );
4580     menu_add_exit     ( player1_menu, "< back" );
4581 
4582     player2_menu = menu_new( menu_cb );
4583     sprintf(str,"P2 Name: %s",player[1].name);
4584     menu_add_textfield( player2_menu, str,        MENU_ID_PLAYER2_NAME, strlen("P2 Name: ") );
4585     menu_add_submenu  ( player2_menu, "P2 Type",  player2_type_menu,   1 );
4586     menu_add_submenu  ( player2_menu, "P2 Skill", player2_skill_menu,  1 );
4587     menu_add_exit     ( player2_menu, "< back" );
4588 
4589     gamemode_menu = menu_new( menu_cb );
4590     menu_add_entry( gamemode_menu, "single match", MENU_ID_GAMEMODE_MATCH );
4591     menu_add_entry( gamemode_menu, "tournament",   MENU_ID_GAMEMODE_TOURNAMENT );
4592     menu_add_entry( gamemode_menu, "training",     MENU_ID_GAMEMODE_TRAINING );
4593     menu_add_exit ( gamemode_menu, "< back" );
4594 
4595 #ifdef OTHER_RESTART_MENU
4596     network_host_menu = menu_new( menu_cb );
4597     sprintf(str,"P1 Name: %s",player[0].name);
4598     menu_add_textfield( network_host_menu, str,   MENU_ID_PLAYER1_NAME, strlen("P1 Name: ") );
4599     sprintf(str,"P2 Name: %s",player[1].name);
4600     menu_add_textfield( network_host_menu, str,   MENU_ID_PLAYER2_NAME, strlen("P2 Name: ") );
4601     sprintf(str,"port: %d",options_net_portnum);
4602     menu_add_textfield( network_host_menu, str,   MENU_ID_NETWORK_PORTNUM, strlen("port: ") );
4603     menu_add_entry    ( network_host_menu, "Start Game",  MENU_ID_NETWORK_HOST );
4604     menu_add_exit     ( network_host_menu, "< back" );
4605 #endif
4606 
4607     network_join_menu = menu_new( menu_cb );
4608 #ifdef OTHER_RESTART_MENU
4609     sprintf(str,"port: %d",options_net_portnum);
4610     menu_add_textfield( network_join_menu, str,   MENU_ID_NETWORK_PORTNUM, strlen("port: ") );
4611 #endif
4612     sprintf(str,"IP: %s",options_net_hostname);
4613     menu_add_textfield( network_join_menu, str,   MENU_ID_NETWORK_IP, strlen("IP: ") );
4614     menu_add_entry    ( network_join_menu, "Start Game",  MENU_ID_NETWORK_JOIN );
4615     menu_add_exit     ( network_join_menu, "< back" );
4616 
4617     network_menu = menu_new( menu_cb );
4618 #ifndef OTHER_RESTART_MENU
4619     sprintf(str,"port: %d",options_net_portnum);
4620     menu_add_textfield( network_menu, str,        MENU_ID_NETWORK_PORTNUM, strlen("port: ") );
4621     menu_add_entry  ( network_menu, "As Host",    MENU_ID_NETWORK_HOST );
4622     menu_add_submenu( network_menu, "Join",       network_join_menu, 0 );
4623     menu_add_exit   ( network_menu, "< back" );
4624 #else
4625     menu_add_submenu( network_menu, "As Host",    network_host_menu, 0 );
4626     menu_add_submenu( network_menu, "Join",       network_join_menu, 0 );
4627     menu_add_exit   ( network_menu, "< back" );
4628 #endif
4629 
4630 #ifdef OTHER_RESTART_MENU
4631     single_match_menu = menu_new( menu_cb );
4632     menu_add_submenu( single_match_menu, "Player1", player1_menu,   0 );
4633     menu_add_submenu( single_match_menu, "Player2", player2_menu,   0 );
4634     menu_add_entry  ( single_match_menu, "Start Match",      MENU_ID_SINGLE_MATCH_START );
4635     menu_add_exit   ( single_match_menu, "< back" );
4636 
4637     tournament_menu = menu_new( menu_cb );
4638 //    menu_add_entry  ( tournament_menu,   "AI-AI fast motion", MENU_ID_TOURNAMENT_AIAI_FMOT );
4639     menu_add_entry  ( tournament_menu,   "Start Tournament", MENU_ID_TOURNAMENT_START );
4640     menu_add_exit   ( tournament_menu,   "< back" );
4641 
4642     training_menu = menu_new( menu_cb );
4643     menu_add_entry  ( training_menu,     "Start Training",   MENU_ID_TRAINING_START );
4644     menu_add_exit   ( training_menu,     "< back" );
4645 #endif
4646 
4647     restart_menu = menu_new( menu_cb );
4648 #ifndef OTHER_RESTART_MENU
4649     menu_add_submenu( restart_menu, "Player1",      player1_menu,   0 );
4650     menu_add_submenu( restart_menu, "Player2",      player2_menu,   0 );
4651     menu_add_submenu( restart_menu, "Mode",         gamemode_menu,  1 );
4652     menu_add_entry  ( restart_menu, "restart",      MENU_ID_MAIN_RESTART );
4653     menu_add_exit   ( restart_menu, "< back");
4654 #else
4655     menu_add_submenu( restart_menu, "single match", single_match_menu, 0 );
4656     menu_add_submenu( restart_menu, "tournament",   tournament_menu,   0 );
4657     menu_add_submenu( restart_menu, "training",     training_menu,     0 );
4658     menu_add_submenu( restart_menu, "network game", network_menu,      0 );
4659     menu_add_exit   ( restart_menu, "< back");
4660 #endif
4661 
4662     g_options_menu = menu_new( menu_cb );
4663     menu_add_submenu( g_options_menu, "display", display_menu, 0 );
4664     menu_add_entry  ( g_options_menu, "sound",   MENU_ID_OPTIONS_SOUND );
4665     menu_add_submenu( g_options_menu, "game",    game_menu, 0 );
4666     menu_add_exit   ( g_options_menu, "< back" );
4667 
4668     g_main_menu = menu_new( menu_cb );
4669     menu_add_exit   ( g_main_menu, "Resume" );
4670     menu_add_submenu( g_main_menu, "Restart Game", restart_menu, 0 );
4671 #ifndef OTHER_RESTART_MENU
4672     menu_add_submenu( g_main_menu, "Network Game", network_menu, 0 );
4673 #endif
4674     menu_add_submenu( g_main_menu, "Options", g_options_menu, 0 );
4675     menu_add_entry  ( g_main_menu, "Help", MENU_ID_MAIN_HELP );
4676     menu_add_submenu( g_main_menu, "Quit",    quit_menu, 0 );
4677 
4678 
4679     g_act_menu = g_options_menu;
4680     g_act_menu = (menuType *)0;
4681 }
4682 
4683 
str_contains(char * s1,char * s2)4684 int str_contains(char *s1, char *s2)
4685 {
4686     int i,j;
4687     int rval=0;
4688 
4689     for( i=0 ; s1[i]!=0 ; i++ ){
4690         for( j=0 ; s2[j]!=0 && s1[i+j]!=0 && s2[j]==s1[i+j] ; j++ ){
4691         }
4692         if(s2[j]==0){
4693             rval=1; break;
4694         }
4695     }
4696     return rval;
4697 }
4698 
parse_gl_extensions_string(void)4699 void parse_gl_extensions_string( void )
4700 {
4701     char * str;
4702     str = (char *)glGetString( GL_EXTENSIONS );
4703 
4704     extension_cubemap      = (str_contains(str,"GL_ARB_texture_cube_map"))  ? 1 : 0 ;
4705     DPRINTF("extension_cubemap=%d\n",extension_cubemap);
4706 
4707     extension_multitexture = (str_contains(str,"GL_ARB_multitexture"))      ? 1 : 0 ;
4708     DPRINTF("extension_multitexture=%d\n",extension_multitexture);
4709 
4710     extension_ts_NV        = (str_contains(str,"GL_NV_texture_shader"))     ? 1 : 0 ;
4711     DPRINTF("extension_ts_NV=%d\n",extension_ts_NV);
4712 
4713     extension_rc_NV        = (str_contains(str,"GL_NV_register_combiners")) ? 1 : 0 ;
4714     DPRINTF("extension_rc_NV=%d\n",extension_rc_NV);
4715 
4716     extension_vp_NV        = (str_contains(str,"GL_NV_vertex_program"))     ? 1 : 0 ;
4717     DPRINTF("extension_vp_NV=%d\n",extension_vp_NV);
4718 }
4719 
4720 
Init(void)4721 static void Init( void )
4722 {
4723 //    int i;
4724     GLfloat fogColor[4] = {0.0, 0.0, 0.0, 1.0};
4725     int    depth;
4726 
4727 
4728     parse_gl_extensions_string();
4729 
4730     if ( options_dither )
4731         glEnable(GL_DITHER);
4732     else
4733         glDisable(GL_DITHER);
4734 
4735 /*    lightpos[0]=vec_xyz(-0.3,-0.6,0);
4736     lightpos[1]=vec_xyz(-0.3,+0.6,0);
4737     lightpos[2]=vec_xyz(+0.3,-0.6,0);
4738     lightpos[3]=vec_xyz(+0.3,+0.6,0);*/
4739 
4740 /*    lightpos[0]=vec_xyz(0.0,-0.6,0.7);
4741     lightpos[1]=vec_xyz(0.6*0.866,0.6*0.5,0.7);
4742     lightpos[2]=vec_xyz(-0.6*0.866,0.6*0.5,0.7);
4743     lightnr=3;*/
4744 
4745 /*    lightpos[0]=vec_scale(vec_xyz(0.0,-0.6,0.7),0.6);
4746     lightpos[1]=vec_scale(vec_xyz(0.6*0.866,0.6*0.5,0.7),0.6);
4747     lightpos[2]=vec_scale(vec_xyz(-0.6*0.866,0.6*0.5,0.7),0.6);
4748     lightnr=3;*/
4749 
4750 /*    lightpos[0]=vec_xyz(0.0,0.0,0.7);
4751     lightnr=1;*/
4752 
4753     lightpos[0]=vec_xyz(0.0,+0.4,0.7);
4754     lightpos[1]=vec_xyz(0.0,-0.4,0.7);
4755     lightnr=2;
4756 
4757 /*    lightpos[0]=vec_xyz(0.0,0.0,0.7);
4758     lightpos[1]=vec_xyz(0.0,3.0,0.7);
4759     lightpos[2]=vec_xyz(0.0,-3.0,0.7);
4760     lightpos[3]=vec_xyz(2.0,0.0,0.7);
4761     lightpos[4]=vec_xyz(-2.0,0.0,0.7);
4762     lightnr=5;*/
4763 
4764 
4765 /*    glActiveTextureARB(GL_TEXTURE1_ARB);
4766     glEnable(GL_TEXTURE_2D);
4767     glActiveTextureARB(GL_TEXTURE0_ARB);*/
4768     glEnable(GL_TEXTURE_2D);
4769 
4770     glGenTextures(1,&spheretexbind);
4771     load_png("sphere_map_128x128.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4772     glBindTexture(GL_TEXTURE_2D,spheretexbind);
4773     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, spheretexw, spheretexh, GL_RGB,
4774                       GL_UNSIGNED_BYTE, spheretexdata);
4775     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4776     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4777     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4778     free(spheretexdata);
4779     DPRINTF("spheretexbind=%d\n",spheretexbind);
4780 
4781     glGenTextures(1,&fblogotexbind);
4782     load_png("tabletex_fB_128x128.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4783     glBindTexture(GL_TEXTURE_2D,fblogotexbind);
4784     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4785                       GL_UNSIGNED_BYTE, spheretexdata);
4786     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4787     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4788     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4789     free(spheretexdata);
4790     DPRINTF("fblogotexbind=%d\n",fblogotexbind);
4791 
4792     glGenTextures(1,&placecueballtexbind);
4793     load_png("place_cue_ball.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4794     glBindTexture(GL_TEXTURE_2D,placecueballtexbind);
4795     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4796                       GL_UNSIGNED_BYTE, spheretexdata);
4797     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4798     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4799     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4800     free(spheretexdata);
4801     DPRINTF("placecueballtexbind=%d\n",placecueballtexbind);
4802 
4803     glGenTextures(1,&blendetexbind);
4804     load_png("blende.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4805     glBindTexture(GL_TEXTURE_2D,blendetexbind);
4806     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4807                       GL_UNSIGNED_BYTE, spheretexdata);
4808     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4809     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4810     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4811     free(spheretexdata);
4812     DPRINTF("blendetexbind=%d\n",blendetexbind);
4813 
4814     glGenTextures(1,&lightflaretexbind);
4815     load_png("lightflare.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4816     glBindTexture(GL_TEXTURE_2D,lightflaretexbind);
4817     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4818                       GL_UNSIGNED_BYTE, spheretexdata);
4819     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4820     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4821     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4822     free(spheretexdata);
4823     DPRINTF("lightflaretexbind=%d\n",lightflaretexbind);
4824 
4825     glGenTextures(1,&fullsymboltexbind);
4826     load_png("full_symbol.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4827     glBindTexture(GL_TEXTURE_2D,fullsymboltexbind);
4828     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4829                       GL_UNSIGNED_BYTE, spheretexdata);
4830     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4831     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4832     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4833     free(spheretexdata);
4834     DPRINTF("fullsymboltexbind=%d\n",fullsymboltexbind);
4835 
4836     glGenTextures(1,&halfsymboltexbind);
4837     load_png("half_symbol.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4838     glBindTexture(GL_TEXTURE_2D,halfsymboltexbind);
4839     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4840                       GL_UNSIGNED_BYTE, spheretexdata);
4841     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4842     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4843     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4844     free(spheretexdata);
4845     DPRINTF("halfsymboltexbind=%d\n",halfsymboltexbind);
4846 
4847     glGenTextures(1,&fullhalfsymboltexbind);
4848     load_png("fullhalf_symbol.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4849     glBindTexture(GL_TEXTURE_2D,fullhalfsymboltexbind);
4850     gluBuild2DMipmaps(GL_TEXTURE_2D, 1, spheretexw, spheretexh, GL_LUMINANCE,
4851                       GL_UNSIGNED_BYTE, spheretexdata);
4852     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4853     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4854     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4855     free(spheretexdata);
4856     DPRINTF("fullhalfsymboltexbind=%d\n",fullhalfsymboltexbind);
4857 
4858     if( options_calc_ball_reflections ){
4859         glGenTextures(1,&reftexbind);
4860         load_png("reflect-earth.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4861 //        load_png("reflect.png",&spheretexw,&spheretexh,&depth,&spheretexdata);
4862         glBindTexture(GL_TEXTURE_2D,reftexbind);
4863         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, spheretexw, spheretexh, GL_RGB,
4864                           GL_UNSIGNED_BYTE, spheretexdata);
4865         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4866         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4867         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
4868         free(spheretexdata);
4869         DPRINTF("reftexbind=%d\n",spheretexbind);
4870     }
4871 
4872     lightspheretexdata=0;
4873     glGenTextures(1,&lightspheretexbind);
4874     load_png("sphere_map_128x128_light.png",&spheretexw,&spheretexh,&depth,&lightspheretexdata);
4875     glBindTexture(GL_TEXTURE_2D,lightspheretexbind);
4876     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, spheretexw, spheretexh, GL_RGB,
4877                       GL_UNSIGNED_BYTE, lightspheretexdata);
4878     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, options_tex_min_filter);
4879     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, options_tex_mag_filter);
4880     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4881     DPRINTF("lightspheretexbind=%d\n",lightspheretexbind);
4882     free(lightspheretexdata);
4883 
4884 
4885     glEnable(GL_FOG);
4886     glFogi (GL_FOG_MODE, GL_LINEAR);
4887     glHint (GL_FOG_HINT, GL_FASTEST);
4888     glFogf (GL_FOG_START, 0.0);
4889     glFogf (GL_FOG_END, 9.0);
4890     glFogfv (GL_FOG_COLOR, fogColor);
4891 
4892 //    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4893     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4894 
4895 
4896 /*    glEnable (GL_LINE_SMOOTH);
4897     glEnable (GL_BLEND);
4898     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4899     glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
4900     glLineWidth (1.5);
4901     glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);*/
4902 //    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
4903 
4904 //    glPolygonMode(GL_FRONT,GL_LINE);
4905 
4906 //    glShadeModel (GL_FLAT);
4907 
4908     walls.hole=NULL;
4909     walls.border=NULL;
4910     create_walls( &walls );
4911     balls.ball=NULL;
4912     bakballs.ball=NULL;
4913     create_scene( &balls );
4914 
4915 #ifdef TIME_INTERPOLATE
4916     g_lastballs.ball=NULL;
4917     create_scene( &g_lastballs );
4918     g_drawballs.ball=NULL;
4919     create_scene( &g_drawballs );
4920 #endif
4921 
4922 
4923     table_obj = create_table(spheretexbind, &walls, gametype==GAME_CARAMBOL);
4924 
4925     /* lighting */
4926 //    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
4927 //    glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
4928 //    glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
4929     glEnable(GL_LIGHTING);
4930     glEnable(GL_LIGHT0);
4931     glEnable(GL_LIGHT1);
4932 
4933 
4934    DPRINTF("enabling depth test\n");
4935    glEnable(GL_DEPTH_TEST);
4936    glFrontFace(GL_CW);
4937 //   glCullFace(GL_FRONT);
4938    glEnable(GL_CULL_FACE);
4939    glDepthMask(GL_TRUE);
4940 //   glDepthFunc( GL_GREATER );
4941 //   glDepthFunc( GL_LESS );
4942    glDepthFunc( GL_LEQUAL );
4943 //   glDepthFunc( GL_ALWAYS );
4944 //   glDepthFunc( GL_EQUAL );
4945 
4946    if(options_cuberef){
4947        reassign_and_gen_cuberef_tex();
4948    }
4949 
4950    SetMode(REFLECT);
4951 }
4952 
4953 
main(int argc,char * argv[])4954 int main( int argc, char *argv[] )
4955 {
4956 
4957     int auxnr;
4958     int act_option,option_index;
4959     int confc;
4960     char ** confv;
4961 
4962    /* Tell Mesa GLX to use 3Dfx driver in fullscreen mode. */
4963 //   putenv("MESA_GLX_FX=fullscreen");
4964 
4965    /* Disable 3Dfx Glide splash screen */
4966 //   putenv("FX_GLIDE_NO_SPLASH=");
4967 
4968 
4969    /* initialize hostname */
4970    strcpy(options_net_hostname,"192.168.1.1");
4971 
4972    /* initialize random seed */
4973    srand(time_us());
4974 
4975    /* cd to data directory */
4976 //   fprintf(stderr,"DATA_DIRECTORY=%s\n",DATA_DIRECTORY);
4977    if( chdir(DATA_DIRECTORY) ){
4978        fprintf(stderr,"foobillard seems not to be installed\n");
4979        fprintf(stderr,"  assuming data directory 'data' instead of '%s'\n",DATA_DIRECTORY);
4980        if(chdir("data")){
4981            fprintf(stderr,"  still no data - assuming data directory '../data'\n");
4982            if(chdir("../data")){
4983                fprintf(stderr,"cannot find valid data directory\n");
4984                fprintf(stderr,"(assuming the current dir contains the data)\n");
4985 //               exit(0);
4986            }
4987        }
4988    }
4989 
4990 
4991 
4992    human_human_mode=0;
4993 //   if( argc>1 && argv[1][0]=='2' ) human_human_mode=1;
4994 
4995    init_human_player_roster(&human_player_roster);
4996    init_players();
4997 
4998 #ifndef _WIN32
4999    print_help(long_options,appname_str,stderr);
5000 
5001    /* config file */
5002    load_config( &confv, &confc, argv, argc );
5003    while( ( act_option = getopt_long(confc, confv, "+", long_options, &option_index) ) >= 0){
5004        DPRINTF("processing option %d=%s\n",act_option,optarg);
5005        process_option(act_option);
5006    }
5007    DPRINTF("main:rgstereo=%d",options_rgstereo_on);
5008    /* command line options */
5009 /*   while( ( act_option = getopt_long_only(argc, argv, "+", long_options, &option_index) ) >= 0){
5010        process_option(act_option);
5011    }*/
5012 #endif
5013 
5014 
5015 #if 0
5016    glutInitWindowPosition(0, 0);
5017    //   glutInitWindowSize( 800, 800 );
5018    glutInitWindowSize(WIDTH, HEIGHT);
5019 
5020    glutInit( &argc, argv );
5021 
5022    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
5023    //   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
5024 
5025    glutCreateWindow( argv[0] );
5026 #endif
5027 
5028    sys_create_display( &argc, argv, WIDTH, HEIGHT);
5029 
5030    if( fullscreen ) sys_fullscreen( 1, win_width, win_height );
5031 
5032    Init();
5033 
5034    create_human_player_roster_text(&human_player_roster);
5035    create_players_text();
5036 
5037    if(options_gamemode==options_gamemode_tournament){
5038        init_tournament_state(&tournament_state);
5039    }
5040 
5041    restart_game();
5042 
5043    glGetIntegerv(GL_AUX_BUFFERS, &auxnr);
5044    DPRINTF("# of AUX-buffers:%d\n",auxnr);
5045 
5046    glEnable(GL_LIGHTING);
5047    if( g_network_play ) {
5048        int dummy=42;
5049        if( g_is_host ){
5050            g_socket = host_create_socket();
5051            DPRINTF("host: writing test integer: %d\n",dummy);
5052            socket_write(g_socket,(char *)&dummy,sizeof(dummy));
5053            while( socket_read(g_socket,(char *)&dummy,sizeof(dummy)) == 0 )
5054            {
5055                DPRINTF("...\n");
5056            }
5057            DPRINTF("host: read test integer from client: %d\n",dummy);
5058            player[1].queue_view=0;
5059            player[0].queue_view=1;
5060        } else {
5061            g_socket = client_call_socket( options_net_hostname );
5062            socket_read(g_socket,(char *)&dummy,sizeof(dummy));
5063            DPRINTF("client: read test integer from host: %d\n",dummy);
5064            dummy=7;
5065            DPRINTF("client: writing test integer: %d\n",dummy);
5066            socket_write(g_socket,(char *)&dummy,sizeof(dummy));
5067            player[0].queue_view=0;
5068            player[1].queue_view=1;
5069            queue_view=0;
5070        }
5071    }
5072 
5073 #ifdef USE_SOUND
5074    init_sound();
5075 #endif
5076 //   create_expsin(  17.0, 220.0, &ball_ball_snd.data, &ball_ball_snd.len );
5077    //   create_expsin_otones(  10.0, 320.0, 0.2, &ball_ball_snd.data, &ball_ball_snd.len );
5078 
5079 //   create_delayed_expsinerr(  10.0, 130.0, SOUND_NULLOFFS, 0.3, &ball_ball_snd.data, &ball_ball_snd.len );
5080 
5081 #ifdef USE_SOUND
5082    {
5083        FILE * f;
5084        int i;
5085 //       create_expsinerr(  10.0, 130.0, 0.3, &ball_ball_snd.data, &ball_ball_snd.len );
5086 //       create_delayed_expsinerr( 10.0, 130.0, SOUND_NULLOFFS, 0.3, &ball_ball_snd.data, &ball_ball_snd.len );
5087        //       f=fopen("/mnt/windows/Games/VRBilliard/VRCarom/sounds/ballball.wav", "rb");
5088        DPRINTF("loading ball-ball sound\n");
5089        /* ball-ball sounds from samuele catuzzi's kbilliards - thanx */
5090        if((f=fopen("ball_ball.raw", "rb"))==NULL){
5091            fprintf(stderr,"couldn't open ball_ball.raw\n");
5092            exit(1);
5093        }
5094        fseek(f, 0L, SEEK_END);
5095        ball_ball_snd.len = ftell(f)+1+SOUND_NULLOFFS*2*2;
5096        fseek(f, 0L, SEEK_SET);
5097        ball_ball_snd.data = malloc(ball_ball_snd.len);
5098        fread( &ball_ball_snd.data[SOUND_NULLOFFS*2], 1, ball_ball_snd.len-SOUND_NULLOFFS*2*2 , f );
5099        fclose(f);
5100 
5101 #if _BYTE_ORDER == _BIG_ENDIAN
5102        {
5103           char *snd=ball_ball_snd.data;
5104           for(i=0;i<ball_ball_snd.len;i+=2)
5105           {
5106              char t=snd[i];
5107              snd[i]=snd[i+1];
5108              snd[i+1]=t;
5109           }
5110        }
5111 #endif
5112        for(i=0;i<ball_ball_snd.len/2/2-SOUND_NULLOFFS;i++){
5113            ball_ball_snd.data[(i+SOUND_NULLOFFS)*2+0]*=/*0.5*/1.0*exp(-(double)i/(double)((ball_ball_snd.len-SOUND_NULLOFFS*2*2)/2/4));
5114            ball_ball_snd.data[(i+SOUND_NULLOFFS)*2+1]*=/*0.5*/1.0*exp(-(double)i/(double)((ball_ball_snd.len-SOUND_NULLOFFS*2*2)/2/4));
5115        }
5116        for(i=0;i<ball_ball_snd.len/2/2-1;i++){
5117            ball_ball_snd.data[i*2+0]=ball_ball_snd.data[i*2+0]*0.7+ball_ball_snd.data[(i+1)*2+0]*0.3;
5118            ball_ball_snd.data[i*2+1]=ball_ball_snd.data[i*2+1]*0.7+ball_ball_snd.data[(i+1)*2+1]*0.3;
5119        }
5120        for(i=0;i<SOUND_NULLOFFS*2;i++){
5121            ball_ball_snd.data[i]=0;
5122        }
5123    }
5124 #endif
5125 
5126 //   apply_bandpass( 10.0, 30.0, ball_ball_snd );
5127 
5128 /*   {
5129        TSound s1,s2;
5130        int i, lenmax;
5131        double newdata;
5132        create_expsinerr(  10.0,  130.0, 0.5, &ball_ball_snd.data, &ball_ball_snd.len );
5133        create_expsinerr(  110.0, 130.0, 1.0, &s1.data, &s1.len );
5134        create_expsinerr(  5.0,   130.0, 0.5, &s2.data, &s2.len );
5135 
5136 #define MYMAX(a,b) (((a)<(b))?(b):(a))
5137        lenmax = MYMAX(s2.len,s1.len);
5138 
5139 #define SNDENTRY(snd,index) (((index)<(snd).len/2)?(snd).data[(index)]:0)
5140        for(i=0;i<s1.len/2;i++){
5141            newdata = 0.0;
5142            newdata += SNDENTRY(s1,i)/2.0;
5143            newdata += SNDENTRY(s2,i)/2.0;
5144            ball_ball_snd.data[i] = newdata;
5145        }
5146        ball_ball_snd.len = lenmax;
5147    }*/
5148 
5149 //   create_expsinerr(  60.0, 220.0, 0.3, &ball_wall_snd.data, &ball_wall_snd.len );
5150 //   create_expsinerr_attack( 220.0, 85.0, 0.3, 1.0, &ball_wall_snd.data, &ball_wall_snd.len );
5151 
5152 #ifdef USE_SOUND
5153    create_delayed_expsinerr( 220.0, 465.0, SOUND_NULLOFFS, 0.1, &ball_wall_snd.data, &ball_wall_snd.len );
5154    apply_attack( SOUND_NULLOFFS, 40.0, &ball_wall_snd.data, &ball_wall_snd.len );
5155 #endif
5156 
5157 //   create_expsinerr(  20.0, 220.0, 0.6, &ball_cue_snd.data,  &ball_cue_snd.len  );
5158 //   create_delayed_expsinerr(  20.0, 220.0, SOUND_NULLOFFS, 0.6, &ball_cue_snd.data,  &ball_cue_snd.len );
5159 #ifdef USE_SOUND
5160    create_expsinerr(  20.0, 220.0, 0.6, &ball_cue_snd.data,  &ball_cue_snd.len );
5161 #endif
5162 /*   {
5163        FILE * f;
5164        int i;
5165        create_expsinerr(  10.0, 130.0, 0.3, &ball_cue_snd.data, &ball_cue_snd.len );
5166        f=fopen("/mnt/windows/Games/VRBilliard/VRCarom/sounds/cueball.wav", "rb");
5167        fseek(f, 0L, SEEK_END);
5168        ball_cue_snd.len = ftell(f);
5169        fseek(f, 0L, SEEK_SET);
5170        ball_cue_snd.data = malloc(ball_cue_snd.len);
5171        fread( ball_cue_snd.data, 1, ball_cue_snd.len , f );
5172        fclose(f);
5173        for(i=0;i<ball_ball_snd.len/2/2;i++){
5174            ball_cue_snd.data[i*2+0]*=0.5*exp(-(double)i/(double)(ball_cue_snd.len/2/5));
5175            ball_cue_snd.data[i*2+1]*=0.5*exp(-(double)i/(double)(ball_cue_snd.len/2/5));
5176        }
5177    }*/
5178 
5179    DPRINTF("creating winner text obj's\n");
5180    if(!options_3D_winnertext){
5181        winner_text_obj = textObj_new("wins", options_winner_fontname, 60);
5182        winner_name_text_obj = textObj_new("hallo", options_winner_fontname, 60);
5183    } else {
5184        winner_text_obj = textObj3D_new("wins", options_winner_fontname, 0.3, 0.08, 3);
5185        winner_name_text_obj = textObj3D_new("hallo", options_winner_fontname, 0.3, 0.08, 3);
5186    }
5187    DPRINTF("created winner text obj's\n");
5188 
5189    init_menu();
5190 
5191    sys_set_timer(frametime_ms, Idle_timer);     /* assure a framerate of max 50 fps (1frame/20ms) */
5192 
5193 
5194    sys_main_loop() ;
5195 
5196 
5197    return 0;
5198 }
5199