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