5 vg_tex2d tex_norwey
= { .path
= "textures/norway_foliage.qoi" };
6 vg_tex2d tex_grid
= { .path
= "textures/grid.qoi" };
7 vg_tex2d tex_road
= { .path
= "textures/road.qoi" };
8 vg_tex2d tex_gradients
= { .path
= "textures/gradients.qoi",
9 .flags
= VG_TEXTURE_CLAMP
};
10 vg_tex2d
*texture_list
[] =
19 static int freecam
= 0;
20 static int debugview
= 0;
21 static int debugsdf
= 0;
22 static int debugroad
= 0;
28 int main( int argc
, char *argv
[] )
30 vg_init( argc
, argv
, "Voyager Game Engine" );
37 v3f player
.view
; /* Relative to pos */
38 v3f player
.v
= { 0.0f
, 0.0f
, -0.2f
};
50 v2f look_dir
; /* TEMP */
52 m4x3f to_world
, to_local
;
60 u32 world_terrain_count
,
63 static void player_transform_update(void)
65 q_m3x3( player
.rot
, player
.to_world
);
66 v3_copy( player
.co
, player
.to_world
[3] );
69 q_inv( player
.rot
, inv
);
70 q_m3x3( inv
, player
.to_local
);
71 v3_negate( player
.co
, player
.to_local
[3] );
74 static int reset_player( int argc
, char const *argv
[] )
77 v3_copy( (v3f
){ 0.0f
, 0.0f
, -0.2f
}, player
.v
);
78 q_identity( player
.rot
);
80 player_transform_update();
84 void vg_register(void)
91 vg_tex2d_init( texture_list
, vg_list_size( texture_list
) );
93 road_patch_init( &road_main
);
94 road_generate( &road_main
);
96 vg_convar_push( (struct vg_convar
){
99 .data_type
= k_convar_dtype_i32
,
100 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
104 vg_convar_push( (struct vg_convar
){
107 .data_type
= k_convar_dtype_i32
,
108 .opt_i32
= { .min
=0, .max
=1, .clamp
=0 },
112 vg_convar_push( (struct vg_convar
){
115 .data_type
= k_convar_dtype_i32
,
116 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
120 vg_convar_push( (struct vg_convar
){
123 .data_type
= k_convar_dtype_i32
,
124 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
128 vg_function_push( (struct vg_cmd
){
130 .function
= reset_player
133 v3f lightDir
= { 0.1f
, 0.8f
, 0.2f
};
134 v3_normalize( lightDir
);
136 scene_init( &world_scene
);
137 scene_init( &test_scene
);
138 scene_init( &player_scene
);
139 model
*world
= vg_asset_read( "models/free_dev.mdl" );
140 model
*test
= vg_asset_read( "models/test.mdl" );
141 model
*char_dev
= vg_asset_read( "models/char_dev.mdl" );
142 scene_add_model( &player_scene
, char_dev
,
143 submodel_get( char_dev
, "joint" ),
144 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
147 scene_add_model( &world_scene
, world
,
148 submodel_get( world
, "terrain" ),
149 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
151 int id_tree
= submodel_get( test
, "tree" ),
154 submodel_get( test
, "bush" ),
155 submodel_get( test
, "grass" ),
156 submodel_get( test
, "blubber" ),
157 submodel_get( test
, "blubber" ),
158 submodel_get( test
, "blubber" ),
159 submodel_get( test
, "grassthin" )
162 /* Sprinkle some trees in the terrain areas */
164 v3_sub( world_scene
.bbx
[1], world_scene
.bbx
[0], range
);
166 for( int i
=0; i
<8000; i
++ )
173 v3_muladd( world_scene
.bbx
[0], pos
, range
, pos
);
175 if( sample_scene_height( &world_scene
, pos
) )
177 scene_add_model( &test_scene
, test
,
179 pos
, vg_randf() * VG_TAUf
, vg_randf() * 0.5f
+ 0.5f
);
183 world_terrain_count
= world_scene
.indice_count
;
185 scene_add_model( &world_scene
, world
,
186 submodel_get( world
, "road" ),
187 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
188 world_road_count
= world_scene
.indice_count
-world_terrain_count
;
194 scene_compute_occlusion( &test_scene
);
195 scene_shadow_gradient( &test_scene
, 1, 0.0f
, 1.0f
);
196 scene_shadow_sphere( &test_scene
, (v3f
){ 0.0f
,4.0f
,0.0f
},
197 (v4f
){1.0f
, 2.0f
, 0.0f
, 0.0f
}, lightDir
);
200 scene_upload( &player_scene
);
201 scene_upload( &world_scene
);
202 scene_upload( &test_scene
);
204 reset_player( 0, NULL
);
205 player_transform_update();
212 float timestep
= 1.0f
/60.0f
;
217 m4x3_identity( cam_rot
);
218 m4x3_rotate_y( cam_rot
, -player
.look_dir
[0] );
219 m4x3_rotate_x( cam_rot
, -player
.look_dir
[1] );
221 v3f lookdir
= { 0.0f
, 0.0f
, -1.0f
},
222 sidedir
= { 1.0f
, 0.0f
, 0.0f
};
224 m4x3_mulv( cam_rot
, lookdir
, lookdir
);
225 m4x3_mulv( cam_rot
, sidedir
, sidedir
);
227 float movespeed
= 5.0f
;
228 static v2f mouse_last
,
229 view_vel
= { 0.0f
, 0.0f
};
230 static v3f move_vel
= { 0.0f
, 0.0f
, 0.0f
};
232 if( vg_get_button_down( "primary" ) )
234 v2_copy( vg_mouse
, mouse_last
);
236 else if( vg_get_button( "primary" ) )
239 v2_sub( vg_mouse
, mouse_last
, delta
);
240 v2_copy( vg_mouse
, mouse_last
);
242 v2_muladds( view_vel
, delta
, 0.005f
, view_vel
);
245 v2_muls( view_vel
, 0.75f
, view_vel
);
246 v2_add( view_vel
, player
.look_dir
, player
.look_dir
);
248 vg_clampf( player
.look_dir
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
250 if( vg_get_button( "forward" ) )
251 v3_muladds( move_vel
, lookdir
, timestep
* movespeed
, move_vel
);
252 if( vg_get_button( "back" ) )
253 v3_muladds( move_vel
, lookdir
, timestep
*-movespeed
, move_vel
);
254 if( vg_get_button( "left" ) )
255 v3_muladds( move_vel
, sidedir
, timestep
*-movespeed
, move_vel
);
256 if( vg_get_button( "right" ) )
257 v3_muladds( move_vel
, sidedir
, timestep
* movespeed
, move_vel
);
259 v3_muls( move_vel
, 0.75f
, move_vel
);
260 v3_add( move_vel
, player
.view
, player
.view
);
265 if( vg_get_button( "forward" ) )
267 v3f dir
= { 0.0f
, 0.0f
, -1.0f
};
269 m3x3_mulv( player
.to_world
, dir
, dir
);
270 v3_muladds( player
.v
, dir
, 5.0f
* timestep
, player
.v
);
273 /* Get front and back contact points */
274 v3f contact_front
, contact_back
, fwd
, fwd1
, contact_norm
, vup
;
276 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, fwd
);
277 m3x3_mulv( player
.to_world
, (v3f
){0.03f
,0.0f
,-1.0f
}, fwd1
);
278 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, vup
);
280 v3_muladds( player
.co
, fwd
, 1.0f
, contact_front
);
281 v3_muladds( player
.co
, fwd
,-1.0f
, contact_back
);
282 v3_muladds( player
.co
, fwd1
, 1.0f
, contact_norm
);
284 sample_scene_height( &world_scene
, contact_front
);
285 sample_scene_height( &world_scene
, contact_back
);
286 sample_scene_height( &world_scene
, contact_norm
);
290 v3_sub( contact_back
, contact_norm
, v0
);
291 v3_sub( contact_front
, contact_norm
, v1
);
292 v3_cross( v1
, v0
, norm
);
293 v3_normalize( norm
);
295 v3f gravity
= { 0.0f
, -9.6f
, 0.0f
};
296 v3_muladds( player
.v
, gravity
, timestep
, player
.v
);
299 v3_copy( player
.co
, ground_pos
);
300 sample_scene_height( &world_scene
, ground_pos
);
302 static int in_air
= 1;
306 if( ground_pos
[1] > player
.co
[1] )
312 float resistance
= v3_dot( norm
, player
.v
);
314 if( resistance
>= 0.0f
)
318 v3_muladds( player
.v
, norm
, -resistance
, player
.v
);
322 /* vg_info( "%.3f | %.3f\n", player.v[1], resistance ); */
323 v3_muladds( player
.co
, player
.v
, timestep
, player
.co
);
330 player
.co
[1] = (contact_front
[1]+contact_back
[1])*0.5f
;
332 vg_line( player
.co
, contact_front
, 0xff00ffff );
333 vg_line( player
.co
, contact_back
, 0xff00ffa0 );
335 /* Create the 'travel' vector */
337 v3_sub( contact_front
, contact_back
, travel
);
338 v3_normalize( travel
);
342 float gravity_conversion
= -v3_dot( travel
, gravity
);
343 vel
[2] += gravity_conversion
* substep
;
346 /* Get localized (rotated) rigidbody forces
355 m3x3_mulv( player
.to_local
, player
.v
, vel
);
357 /* Calculate local forces */
358 slip
= -vel
[0] / vel
[2];
359 float substep
= timestep
* 0.2f
;
361 if( fabsf( slip
) > 1.2f
)
363 slip
= vg_signf( slip
) * 1.2f
;
366 for( int i
=0; i
<5; i
++ )
368 if( fabsf(vel
[2]) >= 0.02f
*substep
)
369 vel
[2] += vg_signf( vel
[2] ) * -0.02f
* substep
;
370 if( fabsf(vel
[0]) >= 6.0f
*substep
)
371 vel
[0] += vg_signf( vel
[0] ) * -6.0f
* substep
;
374 m3x3_mulv( player
.to_world
, vel
, player
.v
);
376 if( vg_get_button( "yawl" ) )
377 yawamt
= 1.6f
* timestep
;
378 if( vg_get_button( "yawr" ) )
379 yawamt
= -1.6f
* timestep
;
381 yawamt
-= vg_get_axis( "horizontal" ) * 1.6f
* timestep
;
386 yawamt
-= vg_get_axis( "horizontal" ) * 3.6f
* timestep
;
390 q_axis_angle( rotate
, vup
, yawamt
);
391 q_mul( rotate
, player
.rot
, player
.rot
);
393 player
.look_dir
[0] = atan2f( player
.v
[0], -player
.v
[2] );
395 /* Creating a skeleton of the player dynamically */
396 float kheight
= 1.8f
,
401 static v3f last_vel
= { 0.0f
, 0.0f
, 0.0f
};
402 static v3f bob
, bob1
;
404 v3_sub( player
.v
, last_vel
, player
.a
);
405 v3_copy( player
.v
, last_vel
);
406 v3_add( bob
, player
.a
, bob
);
408 bob
[0] = vg_clampf( bob
[0], -0.4f
, 1.0f
);
409 bob
[1] = vg_clampf( bob
[1], -0.4f
, 1.3f
);
410 bob
[2] = vg_clampf( bob
[2], -0.4f
, 1.0f
);
412 v3_lerp( bob
, (v3f
){ 0.0f
, 0.0f
, 0.0f
}, 0.1f
, bob
);
413 v3_lerp( bob1
, bob
, 0.1f
, bob1
);
416 head
[0] = (-sinf(slip
)*0.9f
* kheight
+ bob1
[0]*0.6f
) * 0.54f
;
417 head
[1] = cosf(slip
)*0.9f
* kheight
+-bob1
[1]*1.4f
;
420 m4x3_mulv( player
.to_world
, head
, head
);
421 v3_copy( head
, player
.view
);
423 player_transform_update();
426 static void debug_grid( v3f at
)
429 v3_floor( at
, base
);
431 for( int y
=0; y
<16; y
++ )
433 vg_line( (v3f
){ base
[0] - 8, base
[1], base
[2]+y
-8 },
434 (v3f
){ base
[0] + 8, base
[1], base
[2]+y
-8 },
437 for( int x
=0; x
<16; x
++ )
439 vg_line( (v3f
){ base
[0]+x
-8, base
[1], base
[2]-8 },
440 (v3f
){ base
[0]+x
-8, base
[1], base
[2]+8 },
447 glViewport( 0,0, vg_window_x
, vg_window_y
);
449 glDisable( GL_DEPTH_TEST
);
450 glClearColor( 0.1f
, 0.0f
, 0.2f
, 1.0f
);
451 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
454 v3_negate( player
.view
, pos_inv
);
456 float speed
= v3_length( player
.v
);
457 v3f shake
= { vg_randf()-0.5f
, vg_randf()-0.5f
, vg_randf()-0.5f
};
458 v3_muls( shake
, speed
*0.01f
, shake
);
460 m4x3_identity( world_matrix
);
461 m4x3_rotate_x( world_matrix
,
462 freecam
? player
.look_dir
[1]: 0.3f
+shake
[1]*0.04f
);
463 m4x3_rotate_y( world_matrix
, player
.look_dir
[0]+shake
[0]*0.02f
);
464 m4x3_translate( world_matrix
, pos_inv
);
467 m4x3_expand( world_matrix
, world_4x4
);
469 m4x4_projection( vg_pv
,
470 freecam
? 90.0f
: 130.0f
,
471 (float)vg_window_x
/ (float)vg_window_y
,
473 m4x4_mul( vg_pv
, world_4x4
, vg_pv
);
476 draw_road_patch_dev( &road_main
);
478 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 1.0f
, 0.0f
, 0.0f
}, 0xffff0000 );
479 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 1.0f
, 0.0f
}, 0xff00ff00 );
480 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 0.0f
, 1.0f
}, 0xff0000ff );
482 v3f board_fwd
= { 0.0f
, 0.0f
, -1.0f
};
483 v3f board_side
= { 1.0f
, 0.0f
, 0.0f
};
485 m3x3_mulv( player
.to_world
, board_fwd
, board_fwd
);
486 m3x3_mulv( player
.to_world
, board_side
, board_side
);
488 v3f bnw
, bne
, bse
, bsw
;
490 v3_muladds( player
.co
, board_fwd
, 0.75f
, bnw
);
491 v3_muladds( player
.co
, board_fwd
, -0.75f
, bsw
);
492 v3_muladds( bnw
, board_side
, 0.1f
, bne
);
493 v3_muladds( bnw
, board_side
, -0.1f
, bnw
);
494 v3_muladds( bsw
, board_side
, 0.1f
, bse
);
495 v3_muladds( bsw
, board_side
, -0.1f
, bsw
);
497 vg_line( bnw
, bne
, 0xff00ff00 );
498 vg_line( bne
, bse
, 0xff00ff00 );
499 vg_line( bse
, bsw
, 0xff00ff00 );
500 vg_line( bsw
, bnw
, 0xff00ff00 );
502 glEnable( GL_DEPTH_TEST
);
504 SHADER_USE( shader_debug_vcol
);
508 vg_tex2d_bind( &tex_grid
, 0 );
509 scene_tree_sway
= 0.0f
;
511 m4x3_identity( temp
);
512 m4x3_expand( temp
, temp1
);
513 glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol
, "uMdl" ),
514 1, GL_FALSE
, (float *)temp1
);
515 scene_draw( &player_scene
, -1, 0 );
517 m4x3_identity( temp
);
518 m4x3_expand( temp
, temp1
);
519 glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol
, "uMdl" ),
520 1, GL_FALSE
, (float *)temp1
);
522 vg_tex2d_bind( &tex_norwey
, 0 );
523 scene_tree_sway
= 0.1f
;
524 scene_draw( &test_scene
, -1, 0 );
526 vg_tex2d_bind( &tex_grid
, 0 );
527 scene_tree_sway
= 0.0f
;
528 scene_draw( &world_scene
, world_terrain_count
, 0 );
530 vg_tex2d_bind( &tex_road
, 0 );
531 scene_draw( &world_scene
, world_road_count
, world_terrain_count
);
533 glDisable( GL_DEPTH_TEST
);
540 snprintf( buf
, 20, "%.2fm/s", v3_length( player
.v
) );
541 gui_text( (ui_px
[2]){ 0, 0 }, buf
, 1, k_text_align_left
);
543 snprintf( buf
, 20, "%.2f %.2f %.2f m/s",
544 player
.a
[0], player
.a
[1], player
.a
[2] );
546 gui_text( (ui_px
[2]){ 0, 20 }, buf
, 1, k_text_align_left
);
548 if( vg_gamepad_ready
)
550 for( int i
=0; i
<6; i
++ )
552 snprintf( buf
, 20, "%.2f", vg_gamepad
.axes
[i
] );
553 gui_text( (ui_px
[2]){ 0, (i
+2)*20 }, buf
, 1, k_text_align_left
);
558 gui_text( (ui_px
[2]){ 0, 40 },
559 "Gamepad not ready", 1, k_text_align_left
);