latest
[carveJwlIkooP6JGAAIwe30JlM.git] / main.c
1 #define VG_3D
2 #include "vg/vg.h"
3
4 /* Resources */
5 vg_tex2d tex_norwey = { .path = "textures/norway_foliage.qoi" };
6 vg_tex2d tex_grid = { .path = "textures/grid.qoi" };
7 vg_tex2d tex_sky = { .path = "textures/sky.qoi" };
8 vg_tex2d tex_gradients = { .path = "textures/gradients.qoi",
9 .flags = VG_TEXTURE_CLAMP };
10 vg_tex2d *texture_list[] =
11 {
12 &tex_norwey,
13 &tex_gradients,
14 &tex_grid,
15 &tex_sky
16 };
17
18 /* Convars */
19 static int freecam = 0;
20 static int debugview = 0;
21 static int debugsdf = 0;
22 static int sv_debugcam = 0;
23
24 /* Components */
25 #include "road.h"
26 #include "scene.h"
27 #include "ik.h"
28
29 int main( int argc, char *argv[] )
30 {
31 vg_init( argc, argv, "Voyager Game Engine" );
32 }
33
34 m4x3f world_matrix;
35
36 static struct gplayer
37 {
38 v3f co, v, a;
39 v4f rot;
40 float vswitch, slip_last;
41
42 v3f view;
43 v2f look_dir; /* TEMP */
44
45 m4x3f to_world, to_local;
46
47 glmesh mesh;
48
49 submodel legl,
50 legu,
51 board,
52 torso,
53 wheels;
54 }
55 player;
56
57 static struct gworld
58 {
59 glmesh skydome;
60
61 scene foliage, /* Tree shader */
62 geo, /* Std shader, collisions */
63 detail; /* Std shader, no collisions */
64
65 submodel terrain,
66 terrain_rocks,
67 terrain_road;
68 }
69 world;
70
71 static void player_transform_update(void)
72 {
73 q_m3x3( player.rot, player.to_world );
74 v3_copy( player.co, player.to_world[3] );
75
76 v4f inv;
77 q_inv( player.rot, inv );
78 q_m3x3( inv, player.to_local );
79 v3_negate( player.co, player.to_local[3] );
80 }
81
82 static int reset_player( int argc, char const *argv[] )
83 {
84 v3_zero( player.co );
85 v3_copy( (v3f){ 0.0f, 0.0f, -0.2f }, player.v );
86 q_identity( player.rot );
87 player.vswitch = 1.0f;
88 player.slip_last = 0.0f;
89
90 player_transform_update();
91 return 0;
92 }
93
94 void vg_register(void)
95 {
96 scene_register();
97 }
98
99 void vg_start(void)
100 {
101 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
102
103 vg_convar_push( (struct vg_convar){
104 .name = "freecam",
105 .data = &freecam,
106 .data_type = k_convar_dtype_i32,
107 .opt_i32 = { .min=0, .max=1, .clamp=1 },
108 .persistent = 1
109 });
110
111 vg_convar_push( (struct vg_convar){
112 .name = "debugcam",
113 .data = &sv_debugcam,
114 .data_type = k_convar_dtype_i32,
115 .opt_i32 = { .min=0, .max=1, .clamp=0 },
116 .persistent = 1
117 });
118
119 vg_convar_push( (struct vg_convar){
120 .name = "debugview",
121 .data = &debugview,
122 .data_type = k_convar_dtype_i32,
123 .opt_i32 = { .min=0, .max=1, .clamp=0 },
124 .persistent = 1
125 });
126
127 vg_convar_push( (struct vg_convar){
128 .name = "debugsdf",
129 .data = &debugsdf,
130 .data_type = k_convar_dtype_i32,
131 .opt_i32 = { .min=0, .max=1, .clamp=1 },
132 .persistent = 1
133 });
134
135 vg_function_push( (struct vg_cmd){
136 .name = "reset",
137 .function = reset_player
138 });
139
140 v3f lightDir = { 0.1f, 0.8f, 0.2f };
141 v3_normalize( lightDir );
142
143 /* Unpack player */
144 model *char_dev = vg_asset_read( "models/char_dev.mdl" );
145 model_unpack( char_dev, &player.mesh );
146 player.legl = *submodel_get( char_dev, "legl" );
147 player.legu = *submodel_get( char_dev, "legu" );
148 player.board = *submodel_get( char_dev, "skateboard" );
149 player.torso = *submodel_get( char_dev, "torso" );
150 player.wheels = *submodel_get( char_dev, "wheels" );
151 free(char_dev);
152
153 /* Setup scene */
154 scene_init( &world.geo );
155 scene_init( &world.detail );
156 scene_init( &world.foliage );
157
158 model *mworld = vg_asset_read( "models/free_dev.mdl" );
159 model *mtest = vg_asset_read( "models/test.mdl" );
160
161 model *msky = vg_asset_read( "models/skydome.mdl" );
162 model_unpack( msky, &world.skydome );
163 free( msky );
164
165 scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain" ),
166 (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
167 scene_copy_slice( &world.geo, &world.terrain );
168
169 scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain_rocks" ),
170 (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
171 scene_copy_slice( &world.geo, &world.terrain_rocks );
172
173 submodel *ptree = submodel_get( mtest, "tree" ),
174 *pt_groundcover[] =
175 {
176 submodel_get( mtest, "bush" ),
177 submodel_get( mtest, "bush" ),
178 submodel_get( mtest, "blubber" ),
179 };
180
181 /* Sprinkle some trees in the terrain areas */
182 v3f range;
183 v3_sub( world.geo.bbx[1], world.geo.bbx[0], range );
184
185 #ifdef VG_RELEASE
186 int const ktree_count = 8000,
187 kfoliage_count = 200000;
188 #else
189 int const ktree_count = 200,
190 kfoliage_count = 0;
191 #endif
192
193 for( int i=0; i<ktree_count; i++ )
194 {
195 v3f pos = { vg_randf(), 0.0f, vg_randf() },
196 norm;
197
198 v3_muladd( world.geo.bbx[0], pos, range, pos );
199
200 if( sample_scene_height( &world.geo, pos, norm ) )
201 {
202 if( v3_dot( norm, (v3f){ 0.0f, 1.0f, 0.0f } ) > 0.9f )
203 {
204 scene_add_model( &world.foliage, mtest, ptree,
205 pos, vg_randf() * VG_TAUf, vg_randf() * 0.5f + 0.5f );
206 }
207 }
208 }
209
210 for( int i=0; i<kfoliage_count; i++ )
211 {
212 v3f pos = { vg_randf(), 0.0f, vg_randf() },
213 norm;
214
215 v3_muladd( world.geo.bbx[0], pos, range, pos );
216
217 if( sample_scene_height( &world.geo, pos, norm ) )
218 {
219 if( v3_dot( norm, (v3f){ 0.0f, 1.0f, 0.0f } ) > 0.7f )
220 {
221 scene_add_model( &world.foliage, mtest,
222 pt_groundcover[rand()%vg_list_size(pt_groundcover)],
223 pos, vg_randf() * VG_TAUf, vg_randf() * 0.5f + 0.5f );
224 }
225 }
226 }
227
228 scene_add_model( &world.geo, mworld, submodel_get( mworld, "road" ),
229 (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
230 scene_copy_slice( &world.geo, &world.terrain_road );
231
232 scene_add_model( &world.detail, mworld, submodel_get( mworld, "art" ),
233 (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
234
235 free( mtest );
236 free( mworld );
237
238 scene_compute_occlusion( &world.foliage );
239
240 scene_upload( &world.foliage );
241 scene_upload( &world.geo );
242 scene_upload( &world.detail );
243
244 reset_player( 0, NULL );
245 player_transform_update();
246 }
247
248 v3f head;
249
250 void vg_update(void)
251 {
252 float timestep = 1.0f/60.0f;
253
254 if( freecam )
255 {
256 m4x3f cam_rot;
257 m4x3_identity( cam_rot );
258 m4x3_rotate_y( cam_rot, -player.look_dir[0] );
259 m4x3_rotate_x( cam_rot, -player.look_dir[1] );
260
261 v3f lookdir = { 0.0f, 0.0f, -1.0f },
262 sidedir = { 1.0f, 0.0f, 0.0f };
263
264 m4x3_mulv( cam_rot, lookdir, lookdir );
265 m4x3_mulv( cam_rot, sidedir, sidedir );
266
267 float movespeed = 5.0f;
268 static v2f mouse_last,
269 view_vel = { 0.0f, 0.0f };
270 static v3f move_vel = { 0.0f, 0.0f, 0.0f };
271
272 if( vg_get_button_down( "primary" ) )
273 {
274 v2_copy( vg_mouse, mouse_last );
275 }
276 else if( vg_get_button( "primary" ) )
277 {
278 v2f delta;
279 v2_sub( vg_mouse, mouse_last, delta );
280 v2_copy( vg_mouse, mouse_last );
281
282 v2_muladds( view_vel, delta, 0.005f, view_vel );
283 }
284
285 v2_muls( view_vel, 0.75f, view_vel );
286 v2_add( view_vel, player.look_dir, player.look_dir );
287 player.look_dir[1] =
288 vg_clampf( player.look_dir[1], -VG_PIf*0.5f, VG_PIf*0.5f );
289
290 if( vg_get_button( "forward" ) )
291 v3_muladds( move_vel, lookdir, timestep * movespeed, move_vel );
292 if( vg_get_button( "back" ) )
293 v3_muladds( move_vel, lookdir, timestep *-movespeed, move_vel );
294 if( vg_get_button( "left" ) )
295 v3_muladds( move_vel, sidedir, timestep *-movespeed, move_vel );
296 if( vg_get_button( "right" ) )
297 v3_muladds( move_vel, sidedir, timestep * movespeed, move_vel );
298
299 v3_muls( move_vel, 0.75f, move_vel );
300 v3_add( move_vel, player.view, player.view );
301 }
302
303
304 static int in_air = 1;
305
306 v3f ground_pos, ground_norm;
307 v3_copy( player.co, ground_pos );
308
309 if( sample_scene_height( &world.geo, ground_pos, ground_norm ) )
310 {
311 #if 0
312 v3f localup;
313 m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, localup );
314 v3_normalize(localup);
315 v3_normalize(ground_norm);
316
317 float angle = v3_dot( localup, ground_norm );
318 v3f axis;
319 v3_cross( localup, ground_norm, axis );
320
321 if( angle < 0.999f && !in_air )
322 {
323 v4f correction;
324 q_axis_angle( correction, axis, acosf(angle) );
325 q_mul( correction, player.rot, player.rot );
326 }
327 #endif
328 }
329
330 if( freecam )
331 return;
332
333 if( in_air )
334 {
335 v3f pco, pco1, pv;
336
337 float pstep = timestep*10.0f;
338
339 v3f gravity = { 0.0f, -9.6f, 0.0f };
340 v3_copy( player.co, pco );
341 v3_copy( player.v, pv );
342
343 v3f targetn;
344
345 for( int i=0; i<20; i++ )
346 {
347 v3_copy( pco, pco1 );
348 v3_muladds( pv, gravity, pstep, pv );
349 v3_muladds( pco, pv, pstep, pco );
350
351 vg_line( pco, pco1, i&0x1?0xff000000:0xffffffff );
352
353 v3f sh;
354 v3_copy( pco, sh );
355 sample_scene_height( &world.geo, sh, targetn );
356
357 if( sh[1] >= pco[1] )
358 {
359 v3f localup;
360 m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, localup );
361
362 float angle = v3_dot( localup, targetn );
363 v3f axis;
364 v3_cross( localup, targetn, axis );
365
366 if( angle < 0.99f )
367 {
368 v4f correction;
369 q_axis_angle( correction, axis, acosf(angle)*0.1f );
370 q_mul( correction, player.rot, player.rot );
371 }
372
373 break;
374 }
375 }
376
377 if( ground_pos[1] > player.co[1] )
378 {
379 in_air = 0;
380 }
381 }
382
383 if( vg_get_button( "forward" ) )
384 {
385 v3f dir = { 0.0f, 0.0f, -1.0f };
386
387 m3x3_mulv( player.to_world, dir, dir );
388 v3_muladds( player.v, dir, 5.0f * timestep, player.v );
389 }
390
391 /* Get front and back contact points */
392
393 v3f contact_front, contact_back, fwd, fwd1, contact_norm, vup, vside;
394 v3f axis;
395
396 m3x3_mulv( player.to_world, (v3f){0.0f,0.0f,-1.0f}, fwd );
397 m4x3_mulv( player.to_world, (v3f){ 0.15f,0.0f,-1.0f}, contact_norm );
398 m4x3_mulv( player.to_world, (v3f){-0.15f,0.0f,-1.0f}, contact_front );
399 m4x3_mulv( player.to_world, (v3f){ 0.00f,0.0f, 1.0f}, contact_back );
400 m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, vup );
401 m3x3_mulv( player.to_world, (v3f){1.0f,0.0f,0.0f}, vside );
402
403 int all_contacting =
404 sample_scene_height( &world.geo, contact_front, NULL ) &&
405 sample_scene_height( &world.geo, contact_back, NULL ) &&
406 sample_scene_height( &world.geo, contact_norm, NULL );
407
408 v3f norm;
409 v3f v0, v1;
410 v3_sub( contact_norm, contact_front, v0 );
411 v3_sub( contact_back, contact_front, v1 );
412 v3_cross( v1, v0, norm );
413 v3_normalize( norm );
414
415 vg_line( contact_norm, contact_front, 0xff00ff00 );
416 vg_line( contact_back, contact_front, 0xff0000ff );
417
418 /* Surface alignment */
419 float angle = v3_dot( vup, norm );
420 v3_cross( vup, norm, axis );
421
422 if( angle < 0.999f && !in_air )
423 {
424 v4f correction;
425 q_axis_angle( correction, axis, acosf(angle) );
426 q_mul( correction, player.rot, player.rot );
427 }
428
429
430 v3f gravity = { 0.0f, -9.6f, 0.0f };
431 v3_muladds( player.v, gravity, timestep, player.v );
432
433 if( !in_air )
434 {
435 float resistance = v3_dot( norm, player.v );
436
437 if( resistance >= 0.0f )
438 in_air = 1;
439 else
440 {
441 v3_muladds( player.v, norm, -resistance, player.v );
442 }
443 }
444
445 /* vg_info( "%.3f | %.3f\n", player.v[1], resistance ); */
446 v3_muladds( player.co, player.v, timestep, player.co );
447
448 float slip = 0.0f;
449 float yawamt = 0.0f;
450
451 if( !in_air )
452 {
453 player.co[1] = (contact_front[1]+contact_back[1])*0.5f;
454
455 v3f vel;
456 m3x3_mulv( player.to_local, player.v, vel );
457
458 /* Calculate local forces */
459
460 slip = (-vel[0] / vel[2]) * player.vswitch;
461 if( fabsf( slip ) > 1.2f )
462 slip = vg_signf( slip ) * 1.2f;
463
464
465 if( player.slip_last*slip < 0.0f && fabsf(slip) > 0.7f )
466 {
467 vg_warn( "SWITCH\n" );
468 player.vswitch = -player.vswitch;
469 slip = -slip;
470 }
471
472 player.slip_last = slip;
473
474 float substep = timestep * 0.2f;
475
476 for( int i=0; i<5; i++ )
477 {
478 if( fabsf(vel[2]) >= 0.02f*substep )
479 vel[2] += vg_signf( vel[2] ) * -0.02f * substep;
480 if( fabsf(vel[0]) >= 6.0f*substep )
481 vel[0] += vg_signf( vel[0] ) * -6.0f * substep;
482 }
483
484 m3x3_mulv( player.to_world, vel, player.v );
485
486 if( vg_get_button( "yawl" ) )
487 yawamt = 1.6f * timestep;
488 if( vg_get_button( "yawr" ) )
489 yawamt = -1.6f * timestep;
490
491 yawamt -= vg_get_axis( "horizontal" ) * 1.6f * timestep;
492
493 }
494 else
495 {
496 yawamt -= vg_get_axis( "horizontal" ) * 3.6f * timestep;
497
498 v4f pitch;
499 q_axis_angle( pitch, vside, vg_get_axis( "vertical" ) * 3.6f *timestep );
500 q_mul( pitch, player.rot, player.rot );
501 }
502
503 v4f rotate;
504 q_axis_angle( rotate, vup, yawamt );
505 q_mul( rotate, player.rot, player.rot );
506
507 player.look_dir[0] = atan2f( player.v[0], -player.v[2] );
508
509 /* Creating a skeleton of the player dynamically */
510 float kheight = 1.8f,
511 kleg = 0.6f;
512
513 v2f ac;
514
515 static v3f last_vel = { 0.0f, 0.0f, 0.0f };
516 static v3f momentum, bob;
517
518 v3_sub( player.v, last_vel, player.a );
519 v3_copy( player.v, last_vel );
520
521 v3_add( momentum, player.a, momentum );
522
523 v3_lerp( momentum, (v3f){0.0f,0.0f,0.0f}, 0.1f, momentum );
524 v3f target;
525
526 momentum[0] = vg_clampf( momentum[0], -2.0f, 2.0f );
527 momentum[1] = vg_clampf( momentum[1], -0.2f, 5.0f );
528 momentum[2] = vg_clampf( momentum[2], -2.0f, 2.0f );
529 v3_copy( momentum, target );
530
531 v3_lerp( bob, target, 0.2f, bob );
532
533 /* Head */
534 float lslip = fabsf(slip); //vg_minf( 0.4f, slip );
535 head[0] = 0.0f;//(-sinf(lslip)*0.9f * kheight) * 0.44f;
536 head[1] = (0.3f + cosf(lslip)*0.5f) * kheight;
537 head[2] = 0.0f;
538
539 v3f offset;
540 m3x3_mulv( player.to_local, bob, offset );
541 offset[0] *= 0.25f;
542 offset[1] *= -0.25f;
543 offset[2] *= 0.7f;
544 v3_muladds( head, offset, 1.0f, head );
545
546 player_transform_update();
547
548 m4x3_mulv( player.to_world, head, head );
549 v3_copy( head, player.view );
550
551 q_normalize(player.rot);
552 }
553
554 static void debug_grid( v3f at )
555 {
556 v3f base;
557 v3_floor( at, base );
558
559 for( int y=0; y<16; y++ )
560 {
561 vg_line( (v3f){ base[0] - 8, base[1], base[2]+y-8 },
562 (v3f){ base[0] + 8, base[1], base[2]+y-8 },
563 0x40ffffff );
564 }
565 for( int x=0; x<16; x++ )
566 {
567 vg_line( (v3f){ base[0]+x-8, base[1], base[2]-8 },
568 (v3f){ base[0]+x-8, base[1], base[2]+8 },
569 0x40ffffff );
570 }
571 }
572
573 static void draw_player(void)
574 {
575 mesh_bind( &player.mesh );
576 float const kleg_upper = 0.53f,
577 kleg_lower = 0.5f;
578
579 /* Create IK targets */
580 struct ik_basic ik_leg_l = { .l1 = kleg_upper, .l2 = kleg_lower },
581 ik_leg_r = { .l1 = kleg_upper, .l2 = kleg_lower };
582
583 v3f butt, fwd;
584
585 m4x3_mulv( player.to_world, (v3f){ 0.0f,0.16f,-0.4f }, ik_leg_r.end );
586 m4x3_mulv( player.to_world, (v3f){ 0.0f,0.16f, 0.3f }, ik_leg_l.end );
587 m4x3_mulv( player.to_world, (v3f){ -0.6f,0.5f,-0.4f }, ik_leg_r.pole );
588 m4x3_mulv( player.to_world, (v3f){ -0.6f,0.5f,0.35f }, ik_leg_l.pole );
589
590 m3x3_mulv( player.to_world, (v3f){ 0.2f,-0.55f,0.0f}, butt );
591 v3_add( butt, player.view, butt );
592
593 m3x3_mulv( player.to_world, (v3f){0.0f,0.0f,-1.0f}, fwd );
594 v3_muladds( butt, fwd, 0.1f, ik_leg_r.base );
595 v3_muladds( butt, fwd,-0.1f, ik_leg_l.base );
596
597 /* Compute IK */
598 m4x3f mleg_l, mknee_l, mleg_r, mknee_r, mboard;
599
600 ik_basic( &ik_leg_r, mleg_r, mknee_r );
601 ik_basic( &ik_leg_l, mleg_l, mknee_l );
602
603 /* Draw */
604 vg_tex2d_bind( &tex_grid, 0 );
605 scene_tree_sway = 0.0f;
606
607 mesh_bind( &player.mesh );
608 m4x4f mat;
609
610 SHADER_USE(shader_standard_lit);
611
612 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ),
613 1, GL_FALSE, (float *)vg_pv );
614 glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 );
615 vg_tex2d_bind( &tex_grid, 0 );
616
617 GLint kuMdl = SHADER_UNIFORM( shader_standard_lit, "uMdl" );
618
619 float kscale = 0.7f;
620 glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"),
621 0.9f*kscale,0.6f*kscale,0.1f*kscale,1.0f );
622
623 m4x3_expand( player.to_world, mat );
624 glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
625 submodel_draw( &player.board );
626
627 glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"),
628 0.2f*kscale,0.3f*kscale,1.0f*kscale,1.0f );
629 submodel_draw( &player.wheels );
630
631 glEnable(GL_BLEND);
632 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
633 glBlendEquation(GL_FUNC_ADD);
634 glDisable( GL_DEPTH_TEST );
635 glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"),
636 0.2f*kscale,0.3f*kscale,1.0f*kscale,0.2f );
637
638 m4x3_expand( mleg_l, mat );
639 glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
640 submodel_draw( &player.legu );
641
642 m4x3_expand( mknee_l, mat );
643 glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
644 submodel_draw( &player.legl );
645
646 m4x3_expand( mleg_r, mat );
647 glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
648 submodel_draw( &player.legu );
649
650 m4x3_expand( mknee_r, mat );
651 glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
652 submodel_draw( &player.legl );
653
654 m4x3f mbutt;
655 m3x3_copy( player.to_world, mbutt );
656 v3_copy( butt, mbutt[3] );
657
658 m4x3_expand( mbutt, mat );
659 glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
660 submodel_draw( &player.torso );
661
662 glDisable(GL_BLEND);
663 glEnable( GL_DEPTH_TEST );
664 }
665
666 void vg_render(void)
667 {
668 glViewport( 0,0, vg_window_x, vg_window_y );
669
670 glDisable( GL_DEPTH_TEST );
671 glClearColor( 0.1f, 0.0f, 0.2f, 1.0f );
672 glClearColor(141.0f/255.0f, 176.0f/255.0f, 215.0f/255.0f,1.0f);
673 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
674
675 v3f pos_inv;
676 v3_negate( player.view, pos_inv );
677
678 float speed = v3_length( player.v );
679 v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f };
680 v3_muls( shake, speed*0.01f, shake );
681
682 m4x3_identity( world_matrix );
683 m4x3_rotate_x( world_matrix,
684 freecam? player.look_dir[1]: 0.5f+shake[1]*0.04f );
685 m4x3_rotate_y( world_matrix, player.look_dir[0]+shake[0]*0.02f );
686 m4x3_translate( world_matrix, pos_inv );
687
688 m4x4f world_4x4;
689 m4x3_expand( world_matrix, world_4x4 );
690
691 m4x4_projection( vg_pv,
692 freecam? 90.0f: 130.0f,
693 (float)vg_window_x / (float)vg_window_y,
694 0.01f, 1000.0f );
695 m4x4_mul( vg_pv, world_4x4, vg_pv );
696
697 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
698 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
699 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
700
701 glEnable( GL_DEPTH_TEST );
702
703 scene_foliage_shader_use();
704 m4x4f temp1;
705 m4x4_identity( temp1 );
706 glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol, "uMdl" ),
707 1, GL_FALSE, (float *)temp1 );
708
709 vg_tex2d_bind( &tex_norwey, 0 );
710 scene_tree_sway = 0.1f;
711
712 scene_bind( &world.foliage );
713 scene_draw( &world.foliage );
714 if( debugsdf )
715 scene_debugsdf( &world.foliage );
716
717 SHADER_USE(shader_unlit);
718 m4x4f temp2;
719 m4x4_identity(temp2);
720 //m4x4_translate( temp2, player.co );
721 glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit, "uMdl" ),
722 1, GL_FALSE, (float *)temp2 );
723 glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit, "uPv" ),
724 1, GL_FALSE, (float *)vg_pv );
725
726 glUniform1i( SHADER_UNIFORM( shader_unlit, "uTexMain" ), 0 );
727 vg_tex2d_bind( &tex_sky, 0 );
728
729 SHADER_USE(shader_standard_lit);
730
731 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ),
732 1, GL_FALSE, (float *)vg_pv );
733 glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 );
734
735 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uMdl" ),
736 1, GL_FALSE, (float *)temp1 );
737
738 vg_tex2d_bind( &tex_grid, 0 );
739
740 scene_bind( &world.geo );
741 glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"),
742 0.2f,0.36f,0.25f,1.0f );
743 submodel_draw( &world.terrain );
744
745 glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"),
746 0.2f,0.2f,0.21f,1.0f );
747 submodel_draw( &world.terrain_rocks );
748
749 glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"),
750 0.4f,0.4f,0.4f,1.0f );
751 submodel_draw( &world.terrain_road );
752
753 scene_bind( &world.detail );
754 scene_draw( &world.detail );
755
756 draw_player();
757
758 glDisable( GL_DEPTH_TEST );
759 vg_lines_drawall( (float *)vg_pv );
760
761 /* Debugger camera */
762 glViewport( 0,0, 512, 512 );
763 glClearColor( 0.1f, 0.0f, 0.2f, 1.0f );
764 glClear( GL_DEPTH_BUFFER_BIT );
765
766 m4x3_identity( world_matrix );
767
768 v3f debugcam;
769 v3_negate( player.co, debugcam );
770 debugcam[2] -= 2.0f;
771 debugcam[1] -= 0.7f;
772
773 m4x3_translate( world_matrix, debugcam );
774 m4x3_expand( world_matrix, world_4x4 );
775
776 m4x4_projection( vg_pv,
777 100.0f,
778 (float)128.0f / (float)128.0f,
779 0.01f, 1000.0f );
780 m4x4_mul( vg_pv, world_4x4, vg_pv );
781
782 if(sv_debugcam)
783 {
784 glEnable( GL_DEPTH_TEST );
785 draw_player();
786 }
787
788 glDisable( GL_DEPTH_TEST );
789 vg_lines_drawall( (float *)vg_pv );
790
791 glViewport( 0,0, vg_window_x, vg_window_y );
792 }
793
794 void vg_ui(void)
795 {
796 char buf[20];
797
798 snprintf( buf, 20, "%.2fm/s", v3_length( player.v ) );
799 gui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left );
800
801 snprintf( buf, 20, "%.2f %.2f %.2f m/s",
802 player.a[0], player.a[1], player.a[2] );
803
804 gui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left );
805
806 if( vg_gamepad_ready )
807 {
808 for( int i=0; i<6; i++ )
809 {
810 snprintf( buf, 20, "%.2f", vg_gamepad.axes[i] );
811 gui_text( (ui_px [2]){ 0, (i+2)*20 }, buf, 1, k_text_align_left );
812 }
813 }
814 else
815 {
816 gui_text( (ui_px [2]){ 0, 40 },
817 "Gamepad not ready", 1, k_text_align_left );
818 }
819 }
820
821 void vg_free(void){}