2 * =============================================================================
4 * Copyright . . . -----, ,----- ,---. .---.
5 * 2021-2023 |\ /| | / | | | | /|
6 * | \ / | +-- / +----- +---' | / |
7 * | \ / | | / | | \ | / |
8 * | \/ | | / | | \ | / |
9 * ' ' '--' [] '----- '----- ' ' '---' SOFTWARE
11 * =============================================================================
25 static player_instance localplayer
;
26 VG_STATIC
struct player_avatar localplayer_avatar
;
27 VG_STATIC glmesh localplayer_meshes
[3];
28 vg_tex2d localplayer_texture
= { .path
= "textures/ch_gradient.qoi" };
30 player_instance
*tmp_localplayer(void)
42 int main( int argc
, char *argv
[] )
44 vg_mem
.use_libc_malloc
= 0;
45 vg_set_mem_quota( 160*1024*1024 );
46 vg_enter( argc
, argv
, "Voyager Game Engine" );
51 VG_STATIC
void highscores_save_at_exit(void)
53 highscores_serialize_all();
56 VG_STATIC
void vg_launch_opt(void)
61 VG_STATIC
int __kill( int argc
, const char *argv
[] )
64 player_use_device( &localplayer
, &player_device_dead
, &localplayer_dead
);
69 VG_STATIC
int __respawn( int argc
, const char *argv
[] )
71 ent_spawn
*rp
= NULL
, *r
;
72 world_instance
*world
= get_active_world();
75 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_spawn
); i
++ ){
76 r
= mdl_arritm( &world
->ent_spawn
, i
);
77 if( !strcmp( mdl_pstr(&world
->meta
, r
->pstr_name
),argv
[0] ) ){
84 vg_warn( "No spawn named '%s'\n", argv
[0] );
88 float min_dist
= INFINITY
;
90 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_spawn
); i
++ ){
91 r
= mdl_arritm( &world
->ent_spawn
, i
);
92 float d
= v3_dist2( r
->transform
.co
, localplayer
.rb
.co
);
102 vg_error( "No spawn found\n" );
104 if( !mdl_arrcount(&world
->ent_spawn
) )
107 rp
= mdl_arritm( &world
->ent_spawn
, 0 );
110 player__spawn( &localplayer
, rp
);
114 VG_STATIC
void vg_preload(void)
120 vg_var_push( (struct vg_var
){
123 .data_type
= k_var_dtype_i32
,
124 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
128 vg_var_push( (struct vg_var
){
130 .data
= &cl_light_edit
,
131 .data_type
= k_var_dtype_i32
,
132 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
136 vg_function_push( (struct vg_cmd
) {
138 .function
= __respawn
,
139 //.poll_suggest = reset_player_poll
142 vg_function_push( (struct vg_cmd
) {
145 //.poll_suggest = reset_player_poll
148 vg_info(" Copyright . . . -----, ,----- ,---. .---. \n" );
149 vg_info(" 2021-2022 |\\ /| | / | | | | /| \n" );
150 vg_info(" | \\ / | +-- / +----- +---' | / | \n" );
151 vg_info(" | \\ / | | / | | \\ | / | \n" );
152 vg_info(" | \\/ | | / | | \\ | / | \n" );
153 vg_info(" ' ' '--' [] '----- '----- ' ' '---' "
156 highscores_init( 2000, 50 );
157 if( !highscores_read() )
158 highscores_create_db();
160 vg_loader_step( NULL
, highscores_save_at_exit
);
163 vg_loader_step( NULL
, steam_end
);
164 vg_loader_step( network_init
, network_end
);
167 VG_STATIC
void load_playermodels(void)
169 vg_linear_clear( vg_mem
.scratch
);
172 * load in other player models. This may need to be more sophisticated in
173 * the futre if we have more of these guys
175 mdl_context ctx_default
,
179 mdl_open( &ctx_default
, "models/ch_new.mdl", vg_mem
.scratch
);
180 mdl_load_metadata_block( &ctx_default
, vg_mem
.scratch
);
181 mdl_load_mesh_block( &ctx_default
, vg_mem
.scratch
);
182 mdl_close( &ctx_default
);
184 mdl_open( &ctx_outlaw
, "models/ch_outlaw.mdl", vg_mem
.scratch
);
185 mdl_load_metadata_block( &ctx_outlaw
, vg_mem
.scratch
);
186 mdl_load_mesh_block( &ctx_outlaw
, vg_mem
.scratch
);
187 mdl_close( &ctx_outlaw
);
189 mdl_open( &ctx_jordan
, "models/ch_jordan.mdl", vg_mem
.scratch
);
190 mdl_load_metadata_block( &ctx_jordan
, vg_mem
.scratch
);
191 mdl_load_mesh_block( &ctx_jordan
, vg_mem
.scratch
);
192 mdl_close( &ctx_jordan
);
194 vg_acquire_thread_sync();
196 mdl_unpack_glmesh( &ctx_default
, &localplayer_meshes
[0] );
197 mdl_unpack_glmesh( &ctx_outlaw
, &localplayer_meshes
[1] );
198 mdl_unpack_glmesh( &ctx_jordan
, &localplayer_meshes
[2] );
200 vg_release_thread_sync();
203 shader_model_character_view_register();
204 vg_acquire_thread_sync();
206 vg_tex2d_init( (vg_tex2d
*[]){ &localplayer_texture
}, 1 );
208 vg_release_thread_sync();
211 void temp_update_playermodel(void){
212 player__use_mesh( &localplayer
, &localplayer_meshes
[cl_playermdl_id
] );
215 VG_STATIC
void vg_load(void)
217 vg_loader_step( render_init
, NULL
);
218 vg_loader_step( menu_init
, NULL
);
219 vg_loader_step( world_init
, NULL
);
220 //vg_loader_step( player_init, NULL );
221 //vg_loader_step( vehicle_init, NULL );
223 //vg_loader_step( player_model_init, NULL );
225 /* ----------------- */
226 vg_loader_step( load_playermodels
, NULL
);
229 player__create( &localplayer
);
230 player_avatar_load( &localplayer_avatar
, "models/ch_new.mdl" );
231 player__use_avatar( &localplayer
, &localplayer_avatar
);
232 player__use_mesh( &localplayer
, &localplayer_meshes
[cl_playermdl_id
] );
233 player__use_texture( &localplayer
, &localplayer_texture
);
234 player__bind( &localplayer
);
236 /* --------------------- */
239 vg_loader_step( audio_init
, audio_free
);
241 /* 'systems' are completely loaded now */
243 /* load home world */
244 //world_load( &world_global.worlds[0], "maps/mp_gridmap.mdl" );
245 world_load( &world_global
.worlds
[0], "maps/mp_mtzero.mdl" );
248 world_load( &world_global
.worlds
[1], "maps/mp_gridmap.mdl" );
249 world_link_nonlocal_gates( 0, 1 );
250 world_load( &world_global
.worlds
[2], "maps/mp_mtzero.mdl" );
251 world_link_nonlocal_gates( 0, 2 );
254 vg_console_load_autos();
257 VG_STATIC
void vg_start(void)
259 __respawn( 1, (const char *[]){ "start" } );
262 VG_STATIC
void draw_origin_axis(void)
264 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 1.0f
, 0.0f
, 0.0f
}, 0xffff0000 );
265 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 1.0f
, 0.0f
}, 0xff00ff00 );
266 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 0.0f
, 1.0f
}, 0xff0000ff );
269 VG_STATIC
void vg_update(void)
279 if( !gzoomer
.inside
)
283 player__pre_update( &localplayer
);
284 world_update( get_active_world(), localplayer
.rb
.co
);
290 VG_STATIC
void vg_update_fixed(void)
295 if( !gzoomer
.inside
)
296 player_update_fixed();
298 vehicle_update_fixed();
301 player__update( &localplayer
);
305 VG_STATIC
void vg_update_post(void)
316 player_update_post();
320 player__post_update( &localplayer
);
323 float inr3
= 0.57735027,
324 inr2
= 0.70710678118;
326 v3f sample_directions
[] = {
327 { -1.0f
, 0.0f
, 0.0f
},
328 { 1.0f
, 0.0f
, 0.0f
},
329 { 0.0f
, 0.0f
, 1.0f
},
330 { 0.0f
, 0.0f
, -1.0f
},
331 { 0.0f
, 1.0f
, 0.0f
},
332 { 0.0f
, -1.0f
, 0.0f
},
333 { -inr3
, inr3
, inr3
},
334 { inr3
, inr3
, inr3
},
335 { -inr3
, inr3
, -inr3
},
336 { inr3
, inr3
, -inr3
},
337 { -inr2
, 0.0f
, inr2
},
338 { inr2
, 0.0f
, inr2
},
339 { -inr2
, 0.0f
, -inr2
},
340 { inr2
, 0.0f
, -inr2
},
344 static float distances
[16];
350 v3_copy( sample_directions
[ si
], rd
);
351 v3_add( localplayer
.rb
.co
, (v3f
){0.0f
,1.5f
,0.0f
}, ro
);
356 for( int i
=0; i
<10; i
++ ){
357 if( ray_world( get_active_world(), rc
, rd
, &ray
) ){
358 dist
= (float)i
*5.0f
+ ray
.dist
;
362 v3_muladds( rc
, rd
, ray
.dist
, rc
);
366 distances
[si
] = dist
;
369 for( int i
=0; i
<14; i
++ ){
370 if( distances
[i
] != 200.0f
){
371 u32 colours
[] = { VG__RED
, VG__BLUE
, VG__GREEN
,
372 VG__CYAN
, VG__YELOW
, VG__PINK
,
375 u32 colour
= colours
[i
%7];
378 v3_muladds( ro
, sample_directions
[i
], distances
[i
], p1
);
379 vg_line( ro
, p1
, colour
);
380 vg_line_pt3( p1
, 0.1f
, colour
);
391 vg_dsp
.echo_distances
[si
] = dist
;
393 v3f ears
= { 1.0f
,0.0f
,0.0f
};
394 m3x3_mulv( main_camera
.transform
, ears
, ears
);
395 v3_copy( ears
, vg_audio
.external_listener_ears
);
396 v3_copy( main_camera
.transform
[3], vg_audio
.external_listener_pos
);
398 /* TODO: this is transformed back and fourth twice. */
399 if( localplayer
.gate_waiting
){
400 m4x3_mulv( localplayer
.gate_waiting
->transport
,
401 vg_audio
.external_listener_pos
,
402 vg_audio
.external_listener_pos
);
405 v3_copy( localplayer
.rb
.v
, vg_audio
.external_lister_velocity
);
410 vehicle_update_post();
415 VG_STATIC
void vg_framebuffer_resize( int w
, int h
)
420 VG_STATIC
void present_view_with_post_processing(void)
422 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
423 glViewport( 0,0, vg
.window_x
, vg
.window_y
);
426 glDisable(GL_DEPTH_TEST
);
427 glBlendFunc(GL_ONE_MINUS_DST_ALPHA
, GL_DST_ALPHA
);
428 glBlendEquation(GL_FUNC_ADD
);
431 render_fb_inverse_ratio( gpipeline
.fb_main
, inverse
);
434 shader_blitblur_use();
435 shader_blitblur_uTexMain( 0 );
436 shader_blitblur_uTexMotion( 1 );
437 shader_blitblur_uBlurStrength(cl_blur_strength
/ (vg
.frame_delta
*60.0f
));
438 shader_blitblur_uInverseRatio( inverse
);
441 v2_muls( (v2f
){ 0.04f
, 0.001f
}, menu_opacity
, menu_blurring
);
442 shader_blitblur_uOverrideDir( menu_blurring
);
444 render_fb_bind_texture( gpipeline
.fb_main
, 0, 0 );
445 render_fb_bind_texture( gpipeline
.fb_main
, 1, 1 );
449 shader_blit_uTexMain( 0 );
450 shader_blit_uInverseRatio( inverse
);
451 render_fb_bind_texture( gpipeline
.fb_main
, 0, 0 );
457 VG_STATIC
void render_player_transparent(void)
459 static camera small_cam
; /* DOES NOT NEED TO BE STATIC BUT MINGW
462 m4x3_copy( main_camera
.transform
, small_cam
.transform
);
464 small_cam
.fov
= main_camera
.fov
;
465 small_cam
.nearz
= 0.05f
;
466 small_cam
.farz
= 60.0f
;
468 camera_update_view( &small_cam
);
469 camera_update_projection( &small_cam
);
470 camera_finalize( &small_cam
);
472 /* Draw player to window buffer and blend background ontop */
473 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
474 glViewport( 0,0, vg
.window_x
, vg
.window_y
);
475 player__render( &small_cam
, &localplayer
);
478 VG_STATIC
void render_scene(void)
480 render_fb_bind( gpipeline
.fb_main
, 1 );
481 glClearColor( 0.0f
, 0.0f
, 0.0f
, 1.0f
);
482 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
|GL_STENCIL_BUFFER_BIT
);
485 glEnable( GL_DEPTH_TEST
);
487 world_instance
*view_world
= localplayer
.viewable_world
;
489 if( view_world
== NULL
){
490 glClearColor( 0.25f
, 0.25f
, 0.0f
, 1.0f
);
491 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
|GL_STENCIL_BUFFER_BIT
);
495 render_world( view_world
, &main_camera
, 0 );
497 render_water_texture( view_world
, &main_camera
, 0 );
498 render_fb_bind( gpipeline
.fb_main
, 1 );
499 render_water_surface( view_world
, &main_camera
);
502 if( localplayer
.gate_waiting
) depth
= 0;
503 render_world_gates( view_world
, &main_camera
, depth
);
506 render_player_transparent();
509 VG_STATIC
void render_main_game(void)
512 static float fov
= 60.0f
;
513 float fov_target
= vg_lerpf( 90.0f
, 110.0f
, cl_fov
);
515 if( player
.controller
== k_player_controller_skate
)
516 fov_target
= vg_lerpf( 97.0f
, 135.0f
, cl_fov
);
519 fov_target
= menu_fov_target
;
520 fov
= vg_lerpf( fov
, fov_target
, vg
.frame_delta
* 2.0f
);
521 fov
= freecam
? 60.0f
: fov
;
523 main_camera
.fov
= fov
;
526 player__pre_render( &localplayer
);
528 v3_lerp( localplayer
.cam
.pos
, menu_camera_pos
, menu_opacity
,
530 main_camera
.angles
[0] =
531 vg_alerpf( localplayer
.cam
.angles
[0], menu_camera_angles
[0],
533 main_camera
.angles
[1] =
534 vg_lerpf ( localplayer
.cam
.angles
[1], menu_camera_angles
[1],
537 main_camera
.fov
= vg_lerpf( localplayer
.cam
.fov
, menu_smooth_fov
,
539 main_camera
.nearz
= 0.1f
;
540 main_camera
.farz
= 2100.0f
;
542 camera_update_transform( &main_camera
);
544 if( localplayer
.gate_waiting
){
545 m3x3_mul( localplayer
.basis_gate
, main_camera
.transform
,
546 main_camera
.transform
);
549 m3x3_mul( localplayer
.basis
, main_camera
.transform
,
550 main_camera
.transform
);
553 camera_update_view( &main_camera
);
554 camera_update_projection( &main_camera
);
555 camera_finalize( &main_camera
);
557 /* ========== Begin Frame ========== */
562 glClear( GL_DEPTH_BUFFER_BIT
);
564 glEnable( GL_DEPTH_TEST
);
565 render_player_transparent();
568 present_view_with_post_processing();
571 menu_render_fg( &main_camera
);
573 /* =========== End Frame =========== */
576 VG_STATIC
void vg_render(void)
578 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
580 glViewport( 0,0, vg
.window_x
, vg
.window_y
);
581 glDisable( GL_DEPTH_TEST
);
583 glClearColor( 1.0f
, 0.0f
, 0.0f
, 0.0f
);
584 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
588 m4x4_copy( main_camera
.mtx
.pv
, vg
.pv
);
592 glDisable(GL_DEPTH_TEST
);
594 glViewport( 0,0, vg
.window_x
, vg
.window_y
);
597 VG_STATIC
void vg_ui(void)
600 player__im_gui( &localplayer
);
602 world_instance
*world
= get_active_world();
605 audio_debug_soundscapes();
606 render_view_framebuffer_ui();
609 player_physics_gui();
613 VG_STATIC
void run_debug_info(void)
618 snprintf( buf
, 40, "%.2fm/s", v3_length( player
.rb
.v
) );
619 ui_text( (ui_px
[2]){ 0, 0 }, buf
, 1, k_text_align_left
);
621 snprintf( buf
, 40, "%.2f %.2f %.2f m/s",
622 player
.phys
.a
[0], player
.phys
.a
[1], player
.phys
.a
[2] );
623 ui_text( (ui_px
[2]){ 0, 20 }, buf
, 1, k_text_align_left
);
625 snprintf( buf
, 40, "pos %.2f %.2f %.2f",
626 player
.phys
.rb
.co
[0], player
.phys
.rb
.co
[1], player
.phys
.rb
.co
[2] );
627 ui_text( (ui_px
[2]){ 0, 40 }, buf
, 1, k_text_align_left
);
629 if( vg_input
.controller_handle
)
631 for( int i
=0; i
<vg_list_size(vg_input
.controller_axises
); i
++ )
633 snprintf( buf
, 40, "%.2f", vg_input
.controller_axises
[i
] );
634 ui_text( (ui_px
[2]){ 0, (i
+3)*20 }, buf
, 1, k_text_align_left
);
639 ui_text( (ui_px
[2]){ 0, 60 },
640 "Gamepad not ready", 1, k_text_align_left
);