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