?
[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 #include "common.h"
16 #include "conf.h"
17 #include "steam.h"
18 #include "render.h"
19 #include "audio.h"
20 #include "world.h"
21 #include "player.h"
22 #include "network.h"
23 #include "menu.h"
24 #include "vehicle.h"
25
26 static int cl_ui = 1,
27 cl_view_id = 0,
28 cl_light_edit = 0;
29
30 int main( int argc, char *argv[] )
31 {
32 vg_mem.use_libc_malloc = 0;
33 vg_set_mem_quota( 128*1024*1024 );
34 vg_enter( argc, argv, "Voyager Game Engine" );
35
36 return 0;
37 }
38
39 VG_STATIC void highscores_save_at_exit(void)
40 {
41 highscores_serialize_all();
42 }
43
44 VG_STATIC void vg_launch_opt(void)
45 {
46
47 }
48
49 VG_STATIC void vg_preload(void)
50 {
51 g_conf_init();
52
53 vg_var_push( (struct vg_var){
54 .name = "cl_ui",
55 .data = &cl_ui,
56 .data_type = k_var_dtype_i32,
57 .opt_i32 = { .min=0, .max=1, .clamp=1 },
58 .persistent = 0
59 });
60
61 vg_var_push( (struct vg_var){
62 .name = "cl_view_id",
63 .data = &cl_view_id,
64 .data_type = k_var_dtype_i32,
65 .opt_i32 = { .min=0, .max=1, .clamp=1 },
66 .persistent = 0
67 });
68
69 vg_var_push( (struct vg_var){
70 .name = "ledit",
71 .data = &cl_light_edit,
72 .data_type = k_var_dtype_i32,
73 .opt_i32 = { .min=0, .max=1, .clamp=1 },
74 .persistent = 0
75 });
76
77 vg_info(" Copyright . . . -----, ,----- ,---. .---. \n" );
78 vg_info(" 2021-2022 |\\ /| | / | | | | /| \n" );
79 vg_info(" | \\ / | +-- / +----- +---' | / | \n" );
80 vg_info(" | \\ / | | / | | \\ | / | \n" );
81 vg_info(" | \\/ | | / | | \\ | / | \n" );
82 vg_info(" ' ' '--' [] '----- '----- ' ' '---' "
83 "SOFTWARE\n" );
84
85 highscores_init( 2000, 50 );
86 if( !highscores_read() )
87 highscores_create_db();
88
89 vg_loader_step( NULL, highscores_save_at_exit );
90
91 steam_init();
92 vg_loader_step( NULL, steam_end );
93 vg_loader_step( network_init, network_end );
94 }
95
96 VG_STATIC void vg_load(void)
97 {
98 vg_loader_step( render_init, NULL );
99 vg_loader_step( menu_init, NULL );
100 vg_loader_step( world_init, NULL );
101 vg_loader_step( player_init, NULL );
102 vg_loader_step( vehicle_init, NULL );
103
104 vg_bake_shaders();
105 vg_loader_step( audio_init, audio_free );
106 world_audio_init();
107
108 /* 'systems' are completely loaded now */
109 strcpy( world.world_name, "maps/mp_mtzero.mdl" );
110 strcpy( world.world_name, "maps/mp_gridmap.mdl" );
111 world_load();
112 vg_console_load_autos();
113 }
114
115 VG_STATIC void vg_start(void)
116 {
117 reset_player( 1, (const char *[]){ "start" } );
118 }
119
120 VG_STATIC void draw_origin_axis(void)
121 {
122 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
123 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
124 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
125 }
126
127 VG_STATIC void vg_update(void)
128 {
129 steam_update();
130
131 if( vg.is_loaded )
132 {
133 draw_origin_axis();
134 network_update();
135
136 player_update_pre();
137 world_update( player.phys.rb.co );
138 }
139 }
140
141 VG_STATIC void vg_update_fixed(void)
142 {
143 if( vg.is_loaded )
144 {
145 player_update_fixed();
146 vehicle_update_fixed();
147 }
148 }
149
150 VG_STATIC void vg_update_post(void)
151 {
152 if( vg.is_loaded )
153 {
154 player_update_post();
155 menu_update();
156 vehicle_update_post();
157 }
158 }
159
160 VG_STATIC void vg_framebuffer_resize( int w, int h )
161 {
162 render_fb_resize();
163 }
164
165 VG_STATIC void present_view_with_post_processing(void)
166 {
167 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
168
169 glEnable(GL_BLEND);
170 glDisable(GL_DEPTH_TEST);
171 glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
172 glBlendEquation(GL_FUNC_ADD);
173
174 if( cl_blur )
175 {
176 shader_blitblur_use();
177 shader_blitblur_uTexMain( 0 );
178 shader_blitblur_uTexMotion( 1 );
179 shader_blitblur_uBlurStrength(cl_blur_strength / (vg.frame_delta*60.0f));
180
181 v2f menu_blurring;
182 v2_muls( (v2f){ 0.04f, 0.001f }, menu_opacity, menu_blurring );
183 shader_blitblur_uOverrideDir( menu_blurring );
184
185 if( cl_view_id == 0 )
186 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
187 else if( cl_view_id == 1 )
188 render_fb_bind_texture( gpipeline.fb_main, 1, 0 );
189 else
190 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
191
192 render_fb_bind_texture( gpipeline.fb_main, 1, 1 );
193 }
194 else
195 {
196 shader_blit_use();
197 shader_blit_uTexMain( 0 );
198 render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
199 }
200
201 render_fsquad();
202 }
203
204 VG_STATIC void render_player_transparent(void)
205 {
206 static camera small_cam; /* DOES NOT NEED TO BE STATIC BUT MINGW
207 SAIS OTHERWISE */
208
209 m4x3_copy( main_camera.transform, small_cam.transform );
210
211 small_cam.fov = main_camera.fov;
212 small_cam.nearz = 0.05f;
213 small_cam.farz = 60.0f;
214
215 camera_update_view( &small_cam );
216 camera_update_projection( &small_cam );
217 camera_finalize( &small_cam );
218
219 /* Draw player to window buffer and blend background ontop */
220
221 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
222 draw_player( &small_cam );
223 }
224
225 VG_STATIC void render_scene(void)
226 {
227 render_fb_bind( gpipeline.fb_main );
228 glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
229 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
230
231 /* Draw world */
232 glEnable( GL_DEPTH_TEST );
233
234 render_world( &main_camera );
235
236 int player_transparent = !(player.is_dead || freecam),
237 player_draw = !cl_menu;
238
239 if( !player_transparent && player_draw )
240 draw_player( &main_camera );
241
242 render_water_texture( &main_camera );
243 render_fb_bind( gpipeline.fb_main );
244 render_water_surface( &main_camera );
245 render_world_gates( &main_camera );
246
247 if( player_transparent && player_draw )
248 render_player_transparent();
249 }
250
251 VG_STATIC void render_menu(void)
252 {
253 glClear( GL_DEPTH_BUFFER_BIT );
254 menu_render( &main_camera );
255 }
256
257 VG_STATIC void render_main_game(void)
258 {
259 static float fov = 60.0f;
260 float fov_target = vg_lerpf( 90.0f, 110.0f, cl_fov );
261 if( player.phys.on_board )
262 fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov );
263 if( cl_menu )
264 fov_target = menu_fov_target;
265 fov = vg_lerpf( fov, fov_target, vg.frame_delta * 2.0f );
266 fov = freecam? 60.0f: fov;
267
268 main_camera.fov = fov;
269 main_camera.nearz = 0.1f;
270 main_camera.farz = 2100.0f;
271
272 camera_update_view( &main_camera );
273 camera_update_projection( &main_camera );
274 camera_finalize( &main_camera );
275
276 /* ========== Begin Frame ========== */
277
278 render_scene();
279 present_view_with_post_processing();
280
281 if( cl_menu )
282 {
283 render_menu();
284 render_player_transparent();
285 }
286
287 /* =========== End Frame =========== */
288 }
289
290 VG_STATIC void vg_render(void)
291 {
292 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
293
294 glViewport( 0,0, vg.window_x, vg.window_y );
295 glDisable( GL_DEPTH_TEST );
296
297 glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
298 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
299
300 render_main_game();
301
302 /* Other shite */
303 glDisable(GL_BLEND);
304 glDisable( GL_DEPTH_TEST );
305 vg_lines_drawall( (float *)main_camera.mtx.pv );
306 glViewport( 0,0, vg.window_x, vg.window_y );
307 }
308
309 VG_STATIC void run_light_widget( struct light_widget *lw );
310 VG_STATIC void vg_ui(void)
311 {
312 menu_crap_ui();
313
314 if( cl_light_edit )
315 {
316 vg_uictx.cursor[0] = 10;
317 vg_uictx.cursor[1] = 10;
318 vg_uictx.cursor[2] = 200;
319 vg_uictx.cursor[3] = 20;
320
321 struct ub_world_lighting *wl = &gpipeline.ub_world_lighting;
322 struct ui_slider_vector
323 s5 = { .min=0.0f, .max=2.0f, .len=3, .data=wl->g_ambient_colour };
324
325 struct ui_slider
326 s8 = { .min=0.0f, .max=2.0f, .data = &gpipeline.shadow_spread },
327 s9 = { .min=0.0f, .max=25.0f, .data = &gpipeline.shadow_length };
328
329 for( int i=0; i<3; i++ )
330 run_light_widget( &gpipeline.widgets[i] );
331
332 ui_text( vg_uictx.cursor, "Ambient", 1, 0 );
333 vg_uictx.cursor[1] += 16;
334 ui_slider_vector( &s5 );
335
336 ui_text( vg_uictx.cursor, "Shadows", 1, 0 );
337 vg_uictx.cursor[1] += 16;
338 ui_slider( &s8 );
339 ui_slider( &s9 );
340
341 ui_text( vg_uictx.cursor, "Misc", 1, 0 );
342 vg_uictx.cursor[1] += 16;
343 struct ui_checkbox c1 = {.data = &wl->g_light_preview};
344 ui_checkbox( &c1 );
345
346 render_update_lighting_ub();
347 }
348
349 //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
350 if( cl_ui )
351 {
352 render_world_routes_ui();
353 }
354 //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
355
356 audio_debug_soundscapes();
357 render_view_framebuffer_ui();
358 player_physics_gui();
359 }
360
361 VG_STATIC void run_light_widget( struct light_widget *lw )
362 {
363 struct ui_checkbox c1 = { .data=&lw->enabled };
364
365 ui_checkbox( &c1 );
366
367 if( lw->enabled )
368 {
369 struct ui_slider_vector
370 colour = { .min=0.0f, .max=2.0f, .len=3, .data=lw->colour },
371 dir = { .min=-VG_PIf, .max=VG_PIf, .len=2, .data=lw->dir };
372
373 ui_slider_vector( &colour );
374 vg_uictx.cursor[1] += 4;
375 ui_slider_vector( &dir );
376 }
377 }
378
379 VG_STATIC void run_debug_info(void)
380 {
381 char buf[40];
382
383 snprintf( buf, 40, "%.2fm/s", v3_length( player.phys.rb.v ) );
384 ui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left );
385
386 snprintf( buf, 40, "%.2f %.2f %.2f m/s",
387 player.phys.a[0], player.phys.a[1], player.phys.a[2] );
388 ui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left );
389
390 snprintf( buf, 40, "pos %.2f %.2f %.2f",
391 player.phys.rb.co[0], player.phys.rb.co[1], player.phys.rb.co[2] );
392 ui_text( (ui_px [2]){ 0, 40 }, buf, 1, k_text_align_left );
393
394 if( vg_input.controller_handle )
395 {
396 for( int i=0; i<vg_list_size(vg_input.controller_axises); i++ )
397 {
398 snprintf( buf, 40, "%.2f", vg_input.controller_axises[i] );
399 ui_text( (ui_px [2]){ 0, (i+3)*20 }, buf, 1, k_text_align_left );
400 }
401 }
402 else
403 {
404 ui_text( (ui_px [2]){ 0, 60 },
405 "Gamepad not ready", 1, k_text_align_left );
406 }
407 }