sat
[carveJwlIkooP6JGAAIwe30JlM.git] / skaterift.c
1 /*
2 * =============================================================================
3 *
4 * Copyright . . . -----, ,----- ,---. .---.
5 * 2021-2023 |\ /| | / | | | | /|
6 * | \ / | +-- / +----- +---' | / |
7 * | \ / | | / | | \ | / |
8 * | \/ | | / | | \ | / |
9 * ' ' '--' [] '----- '----- ' ' '---' SOFTWARE
10 *
11 * =============================================================================
12 */
13
14 #define SR_NETWORKED
15 #define VG_DEVWINDOW
16 #include "common.h"
17 #include "conf.h"
18 #include "steam.h"
19 #include "render.h"
20 #include "audio.h"
21 #include "world.h"
22 #include "font.h"
23
24
25 #include "player.h"
26 static player_instance localplayer;
27 VG_STATIC struct player_avatar localplayer_avatar;
28 VG_STATIC glmesh localplayer_meshes[3];
29 vg_tex2d localplayer_texture = { .path = "textures/ch_gradient.qoi" };
30
31 player_instance *tmp_localplayer(void)
32 {
33 return &localplayer;
34 }
35
36 #include "network.h"
37 #include "menu.h"
38 #include "vehicle.h"
39
40 static int cl_ui = 1,
41 cl_light_edit = 0;
42
43 #define DEV_AARON
44 #ifdef DEV_AARON
45 static rb_object aaron={
46 .type=k_rb_shape_box,
47 .rb.bbx = {{ -2.0f, -1.0f, -1.0f }, { 2.0f, 1.0f, 1.0f }}
48 };
49 #endif
50
51 int main( int argc, char *argv[] )
52 {
53 vg_mem.use_libc_malloc = 0;
54 vg_set_mem_quota( 160*1024*1024 );
55 vg_enter( argc, argv, "Voyager Game Engine" );
56 return 0;
57 }
58
59 VG_STATIC void highscores_save_at_exit(void)
60 {
61 highscores_serialize_all();
62 }
63
64 VG_STATIC void vg_launch_opt(void)
65 {
66
67 }
68
69 VG_STATIC int __kill( int argc, const char *argv[] )
70 {
71 #if 0
72 player_use_device( &localplayer, &player_device_dead, &localplayer_dead );
73 #endif
74 return 0;
75 }
76
77 VG_STATIC int __respawn( int argc, const char *argv[] )
78 {
79 ent_spawn *rp = NULL, *r;
80 world_instance *world = get_active_world();
81
82 if( argc == 1 ){
83 for( u32 i=0; i<mdl_arrcount(&world->ent_spawn); i++ ){
84 r = mdl_arritm( &world->ent_spawn, i );
85 if( !strcmp( mdl_pstr(&world->meta, r->pstr_name),argv[0] ) ){
86 rp = r;
87 break;
88 }
89 }
90
91 if( !rp )
92 vg_warn( "No spawn named '%s'\n", argv[0] );
93 }
94
95 if( !rp ){
96 float min_dist = INFINITY;
97
98 for( u32 i=0; i<mdl_arrcount(&world->ent_spawn); i++ ){
99 r = mdl_arritm( &world->ent_spawn, i );
100 float d = v3_dist2( r->transform.co, localplayer.rb.co );
101
102 if( d < min_dist ){
103 min_dist = d;
104 rp = r;
105 }
106 }
107 }
108
109 if( !rp ){
110 vg_error( "No spawn found\n" );
111
112 if( !mdl_arrcount(&world->ent_spawn) )
113 return 0;
114
115 rp = mdl_arritm( &world->ent_spawn, 0 );
116 }
117
118 player__spawn( &localplayer, rp );
119 return 1;
120 }
121
122 VG_STATIC void vg_preload(void)
123 {
124 g_conf_init();
125
126 common_var_temp();
127
128 vg_var_push( (struct vg_var){
129 .name = "cl_ui",
130 .data = &cl_ui,
131 .data_type = k_var_dtype_i32,
132 .opt_i32 = { .min=0, .max=1, .clamp=1 },
133 .persistent = 0
134 });
135
136 vg_var_push( (struct vg_var){
137 .name = "ledit",
138 .data = &cl_light_edit,
139 .data_type = k_var_dtype_i32,
140 .opt_i32 = { .min=0, .max=1, .clamp=1 },
141 .persistent = 0
142 });
143
144 vg_function_push( (struct vg_cmd) {
145 .name = "respawn",
146 .function = __respawn,
147 //.poll_suggest = reset_player_poll
148 });
149
150 vg_function_push( (struct vg_cmd) {
151 .name = "ded",
152 .function = __kill,
153 //.poll_suggest = reset_player_poll
154 });
155
156 vg_info(" Copyright . . . -----, ,----- ,---. .---. \n" );
157 vg_info(" 2021-2022 |\\ /| | / | | | | /| \n" );
158 vg_info(" | \\ / | +-- / +----- +---' | / | \n" );
159 vg_info(" | \\ / | | / | | \\ | / | \n" );
160 vg_info(" | \\/ | | / | | \\ | / | \n" );
161 vg_info(" ' ' '--' [] '----- '----- ' ' '---' "
162 "SOFTWARE\n" );
163
164 highscores_init( 2000, 50 );
165 if( !highscores_read() )
166 highscores_create_db();
167
168 vg_loader_step( NULL, highscores_save_at_exit );
169
170 steam_init();
171 vg_loader_step( NULL, steam_end );
172 vg_loader_step( network_init, network_end );
173
174 #ifdef DEV_AARON
175 q_identity( aaron.rb.q );
176 v3_zero( aaron.rb.w );
177 v3_zero( aaron.rb.co );
178 v3_zero( aaron.rb.v );
179 rb_init_object( &aaron );
180 #endif
181 }
182
183 VG_STATIC void load_playermodels(void)
184 {
185 vg_linear_clear( vg_mem.scratch );
186
187 /*
188 * load in other player models. This may need to be more sophisticated in
189 * the futre if we have more of these guys
190 */
191 mdl_context ctx_default,
192 ctx_outlaw,
193 ctx_jordan;
194
195 mdl_open( &ctx_default, "models/ch_new.mdl", vg_mem.scratch );
196 mdl_load_metadata_block( &ctx_default, vg_mem.scratch );
197 mdl_load_mesh_block( &ctx_default, vg_mem.scratch );
198 mdl_close( &ctx_default );
199
200 mdl_open( &ctx_outlaw, "models/ch_outlaw.mdl", vg_mem.scratch );
201 mdl_load_metadata_block( &ctx_outlaw, vg_mem.scratch );
202 mdl_load_mesh_block( &ctx_outlaw, vg_mem.scratch );
203 mdl_close( &ctx_outlaw );
204
205 mdl_open( &ctx_jordan, "models/ch_jordan.mdl", vg_mem.scratch );
206 mdl_load_metadata_block( &ctx_jordan, vg_mem.scratch );
207 mdl_load_mesh_block( &ctx_jordan, vg_mem.scratch );
208 mdl_close( &ctx_jordan );
209
210 vg_acquire_thread_sync();
211 {
212 mdl_unpack_glmesh( &ctx_default, &localplayer_meshes[0] );
213 mdl_unpack_glmesh( &ctx_outlaw, &localplayer_meshes[1] );
214 mdl_unpack_glmesh( &ctx_jordan, &localplayer_meshes[2] );
215 }
216 vg_release_thread_sync();
217
218 /* FIXME: hack */
219 shader_model_character_view_register();
220 vg_acquire_thread_sync();
221 {
222 vg_tex2d_init( (vg_tex2d *[]){ &localplayer_texture }, 1 );
223 }
224 vg_release_thread_sync();
225 }
226
227 void temp_update_playermodel(void){
228 player__use_mesh( &localplayer, &localplayer_meshes[cl_playermdl_id] );
229 }
230
231 VG_STATIC void vg_load(void)
232 {
233 vg_loader_step( render_init, NULL );
234 vg_loader_step( menu_init, NULL );
235 vg_loader_step( world_init, NULL );
236 vg_loader_step( font3d_init, NULL );
237
238 font3d_load( &world_global.font, "models/rs_font.mdl", vg_mem.rtmemory );
239
240 //vg_loader_step( player_init, NULL );
241 vg_loader_step( vehicle_init, NULL );
242 //
243 //vg_loader_step( player_model_init, NULL );
244
245 /* ----------------- */
246 vg_loader_step( load_playermodels, NULL );
247
248 /* player setup */
249 player__create( &localplayer );
250 player_avatar_load( &localplayer_avatar, "models/ch_new.mdl" );
251 player__use_avatar( &localplayer, &localplayer_avatar );
252 player__use_mesh( &localplayer, &localplayer_meshes[cl_playermdl_id] );
253 player__use_texture( &localplayer, &localplayer_texture );
254 player__bind( &localplayer );
255
256 /* --------------------- */
257
258 vg_bake_shaders();
259 vg_loader_step( audio_init, audio_free );
260
261 /* 'systems' are completely loaded now */
262
263 /* load home world */
264 world_load( &world_global.worlds[0], "maps/mp_gridmap.mdl" );
265 //world_load( &world_global.worlds[0], "maps/mp_mtzero.mdl" );
266
267 #if 0
268 world_load( &world_global.worlds[1], "maps/mp_gridmap.mdl" );
269 world_link_nonlocal_gates( 0, 1 );
270 world_load( &world_global.worlds[2], "maps/mp_mtzero.mdl" );
271 world_link_nonlocal_gates( 0, 2 );
272 #endif
273
274 vg_console_load_autos();
275 }
276
277 VG_STATIC void vg_start(void)
278 {
279 __respawn( 1, (const char *[]){ "start" } );
280 }
281
282 VG_STATIC void draw_origin_axis(void)
283 {
284 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
285 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
286 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
287 }
288
289 VG_STATIC void vg_update(void)
290 {
291 steam_update();
292
293 if( vg.is_loaded ){
294 draw_origin_axis();
295 network_update();
296
297 player__pre_update( &localplayer );
298
299 world_update( get_active_world(), localplayer.rb.co );
300 audio_ambient_sprites_update( get_active_world(), localplayer.rb.co );
301 }
302 }
303
304 VG_STATIC void vg_update_fixed(void)
305 {
306 if( vg.is_loaded ){
307 world_routes_fixedupdate( get_active_world() );
308
309 player__update( &localplayer );
310 vehicle_update_fixed();
311
312 #ifdef DEV_AARON
313 world_instance *world = get_active_world();
314 rb_solver_reset();
315 rb_ct *buf = rb_global_buffer();
316
317 int l = rb_box__scene( aaron.rb.to_world, aaron.rb.bbx,
318 NULL, &world->rb_geo.inf.scene, buf );
319 for( int j=0; j<l; j++ ){
320 buf[j].rba = &aaron.rb;
321 buf[j].rbb = &world->rb_geo.rb;
322 }
323 rb_contact_count += l;
324 rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
325
326 for( int j=0; j<8; j++ ){
327 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
328 }
329
330 rb_iter( &aaron.rb );
331 rb_update_transform( &aaron.rb );
332 #endif
333
334 }
335 }
336
337 VG_STATIC void vg_update_post(void)
338 {
339 if( vg.is_loaded ){
340 player__post_update( &localplayer );
341
342 float inr3 = 0.57735027,
343 inr2 = 0.70710678118;
344
345 v3f sample_directions[] = {
346 { -1.0f, 0.0f, 0.0f },
347 { 1.0f, 0.0f, 0.0f },
348 { 0.0f, 0.0f, 1.0f },
349 { 0.0f, 0.0f, -1.0f },
350 { 0.0f, 1.0f, 0.0f },
351 { 0.0f, -1.0f, 0.0f },
352 { -inr3, inr3, inr3 },
353 { inr3, inr3, inr3 },
354 { -inr3, inr3, -inr3 },
355 { inr3, inr3, -inr3 },
356 { -inr2, 0.0f, inr2 },
357 { inr2, 0.0f, inr2 },
358 { -inr2, 0.0f, -inr2 },
359 { inr2, 0.0f, -inr2 },
360 };
361
362 static int si = 0;
363 static float distances[16];
364
365 ray_hit ray;
366 ray.dist = 5.0f;
367
368 v3f rc, rd, ro;
369 v3_copy( sample_directions[ si ], rd );
370 v3_add( localplayer.rb.co, (v3f){0.0f,1.5f,0.0f}, ro );
371 v3_copy( ro, rc );
372
373 float dist = 200.0f;
374
375 for( int i=0; i<10; i++ ){
376 if( ray_world( get_active_world(), rc, rd, &ray ) ){
377 dist = (float)i*5.0f + ray.dist;
378 break;
379 }
380 else{
381 v3_muladds( rc, rd, ray.dist, rc );
382 }
383 }
384
385 distances[si] = dist;
386
387
388 for( int i=0; i<14; i++ ){
389 if( distances[i] != 200.0f ){
390 u32 colours[] = { VG__RED, VG__BLUE, VG__GREEN,
391 VG__CYAN, VG__YELOW, VG__PINK,
392 VG__WHITE };
393
394 u32 colour = colours[i%7];
395
396 v3f p1;
397 v3_muladds( ro, sample_directions[i], distances[i], p1 );
398 vg_line( ro, p1, colour );
399 vg_line_pt3( p1, 0.1f, colour );
400 }
401 }
402
403 si ++;
404 if( si >= 14 )
405 si = 0;
406
407 /* FIXME: TEMP */
408 audio_lock();
409 vg_dsp.echo_distances[si] = dist;
410
411 v3f ears = { 1.0f,0.0f,0.0f };
412 m3x3_mulv( main_camera.transform, ears, ears );
413 v3_copy( ears, vg_audio.external_listener_ears );
414 v3_copy( main_camera.transform[3], vg_audio.external_listener_pos );
415
416 /* TODO: this is transformed back and fourth twice. */
417 if( localplayer.gate_waiting ){
418 m4x3_mulv( localplayer.gate_waiting->transport,
419 vg_audio.external_listener_pos,
420 vg_audio.external_listener_pos );
421 }
422
423 v3_copy( localplayer.rb.v, vg_audio.external_lister_velocity );
424 audio_unlock();
425
426 menu_update();
427 vehicle_update_post();
428
429 #ifdef DEV_AARON
430 SDL_Scancode sc = SDL_GetScancodeFromKey( SDLK_q );
431 if( vg_input.sdl_keys[sc] ){
432 m4x3_mulv( main_camera.transform, (v3f){0.0f,0.0f,-3.0f},
433 aaron.rb.co );
434
435 v3_zero( aaron.rb.v );
436 v3_zero( aaron.rb.w );
437 rb_update_transform( &aaron.rb );
438 }
439
440 rb_object_debug( &aaron, VG__PINK );
441 #endif
442 }
443 }
444
445 VG_STATIC void vg_framebuffer_resize( int w, int h )
446 {
447 render_fb_resize();
448 }
449
450 VG_STATIC void present_view_with_post_processing(void)
451 {
452 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
453 glViewport( 0,0, vg.window_x, vg.window_y );
454
455 glEnable(GL_BLEND);
456 glDisable(GL_DEPTH_TEST);
457 glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
458 glBlendEquation(GL_FUNC_ADD);
459
460 v2f inverse;
461 render_fb_inverse_ratio( gpipeline.fb_main, inverse );
462
463 if( cl_blur ){
464 shader_blitblur_use();
465 shader_blitblur_uTexMain( 0 );
466 shader_blitblur_uTexMotion( 1 );
467 shader_blitblur_uBlurStrength(cl_blur_strength / (vg.frame_delta*60.0f));
468 shader_blitblur_uInverseRatio( inverse );
469
470 v2f menu_blurring;
471 v2_muls( (v2f){ 0.04f, 0.001f }, menu_opacity, menu_blurring );
472 shader_blitblur_uOverrideDir( menu_blurring );
473
474 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
475 render_fb_bind_texture( gpipeline.fb_main, 1, 1 );
476 }
477 else{
478 shader_blit_use();
479 shader_blit_uTexMain( 0 );
480 shader_blit_uInverseRatio( inverse );
481 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
482 }
483
484 render_fsquad();
485 }
486
487 VG_STATIC void render_player_transparent(void)
488 {
489 static camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
490 SAIS OTHERWISE */
491
492 m4x3_copy( main_camera.transform, small_cam.transform );
493
494 small_cam.fov = main_camera.fov;
495 small_cam.nearz = 0.05f;
496 small_cam.farz = 60.0f;
497
498 camera_update_view( &small_cam );
499 camera_update_projection( &small_cam );
500 camera_finalize( &small_cam );
501
502 /* Draw player to window buffer and blend background ontop */
503 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
504 glViewport( 0,0, vg.window_x, vg.window_y );
505 player__render( &small_cam, &localplayer );
506 }
507
508 VG_STATIC void render_scene(void)
509 {
510 render_fb_bind( gpipeline.fb_main, 1 );
511 glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
512 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
513
514 /* Draw world */
515 glEnable( GL_DEPTH_TEST );
516
517 world_instance *view_world = localplayer.viewable_world;
518
519 if( view_world == NULL ){
520 glClearColor( 0.25f, 0.25f, 0.0f, 1.0f );
521 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
522 return;
523 }
524
525 render_world( view_world, &main_camera, 0 );
526
527 render_water_texture( view_world, &main_camera, 0 );
528 render_fb_bind( gpipeline.fb_main, 1 );
529 render_water_surface( view_world, &main_camera );
530
531 int depth = 1;
532 if( localplayer.gate_waiting ) depth = 0;
533 render_world_gates( view_world, &main_camera, depth );
534
535 if( !cl_menu )
536 render_player_transparent();
537 }
538
539 VG_STATIC void render_main_game(void)
540 {
541 #if 0
542 static float fov = 60.0f;
543 float fov_target = vg_lerpf( 90.0f, 110.0f, cl_fov );
544
545 if( player.controller == k_player_controller_skate )
546 fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov );
547
548 if( cl_menu )
549 fov_target = menu_fov_target;
550 fov = vg_lerpf( fov, fov_target, vg.frame_delta * 2.0f );
551 fov = freecam? 60.0f: fov;
552
553 main_camera.fov = fov;
554 #endif
555
556 player__pre_render( &localplayer );
557
558 v3_lerp( localplayer.cam.pos, menu_camera_pos, menu_opacity,
559 main_camera.pos );
560 main_camera.angles[0] =
561 vg_alerpf( localplayer.cam.angles[0], menu_camera_angles[0],
562 menu_opacity );
563 main_camera.angles[1] =
564 vg_lerpf ( localplayer.cam.angles[1], menu_camera_angles[1],
565 menu_opacity );
566
567 main_camera.fov = vg_lerpf( localplayer.cam.fov, menu_smooth_fov,
568 menu_opacity );
569 main_camera.nearz = 0.1f;
570 main_camera.farz = 2100.0f;
571
572 camera_update_transform( &main_camera );
573
574 if( localplayer.gate_waiting ){
575 m3x3_mul( localplayer.basis_gate, main_camera.transform,
576 main_camera.transform );
577 }
578 else{
579 m3x3_mul( localplayer.basis, main_camera.transform,
580 main_camera.transform );
581 }
582
583 camera_update_view( &main_camera );
584 camera_update_projection( &main_camera );
585 camera_finalize( &main_camera );
586
587 /* ========== Begin Frame ========== */
588
589 render_scene();
590
591 if( cl_menu ) {
592 glClear( GL_DEPTH_BUFFER_BIT );
593 menu_render_bg();
594 glEnable( GL_DEPTH_TEST );
595 render_player_transparent();
596 }
597
598 present_view_with_post_processing();
599
600 if( cl_menu )
601 menu_render_fg( &main_camera );
602
603 /* =========== End Frame =========== */
604 }
605
606 VG_STATIC void vg_render(void)
607 {
608 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
609
610 glViewport( 0,0, vg.window_x, vg.window_y );
611 glDisable( GL_DEPTH_TEST );
612
613 glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
614 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
615
616 render_main_game();
617
618 m4x4_copy( main_camera.mtx.pv, vg.pv );
619
620 /* Other shite */
621 glDisable(GL_BLEND);
622 glDisable(GL_DEPTH_TEST);
623 vg_lines_drawall();
624 glViewport( 0,0, vg.window_x, vg.window_y );
625 }
626
627 VG_STATIC void vg_ui(void)
628 {
629 #if 0
630 player__im_gui( &localplayer );
631 #endif
632 world_instance *world = get_active_world();
633 menu_crap_ui();
634
635 render_view_framebuffer_ui();
636 }