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 tex_cement
= { .path
= "textures/cement512.qoi" };
12 vg_tex2d
*texture_list
[] =
22 static int freecam
= 0;
23 static int debugview
= 0;
24 static int debugsdf
= 0;
25 static int sv_debugcam
= 0;
32 int main( int argc
, char *argv
[] )
34 vg_init( argc
, argv
, "Voyager Game Engine" );
44 float vswitch
, slip_last
;
46 float iY
; /* Yaw inertia */
53 v2f look_dir
; /* TEMP */
56 m4x3f to_world
, to_local
;
58 v3f handl_target
, handr_target
,
76 scene foliage
, /* Tree shader */
77 geo
, /* Std shader, collisions */
78 detail
; /* Std shader, no collisions */
86 static void player_transform_update(void)
88 q_m3x3( player
.rot
, player
.to_world
);
89 v3_copy( player
.co
, player
.to_world
[3] );
92 q_inv( player
.rot
, inv
);
93 q_m3x3( inv
, player
.to_local
);
94 v3_negate( player
.co
, player
.to_local
[3] );
97 static int reset_player( int argc
, char const *argv
[] )
100 v3_copy( (v3f
){ 0.0f
, 0.0f
, -0.2f
}, player
.v
);
101 q_identity( player
.rot
);
102 player
.vswitch
= 1.0f
;
103 player
.slip_last
= 0.0f
;
105 player_transform_update();
109 void vg_register(void)
116 vg_tex2d_init( texture_list
, vg_list_size( texture_list
) );
118 vg_convar_push( (struct vg_convar
){
121 .data_type
= k_convar_dtype_i32
,
122 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
126 vg_convar_push( (struct vg_convar
){
128 .data
= &sv_debugcam
,
129 .data_type
= k_convar_dtype_i32
,
130 .opt_i32
= { .min
=0, .max
=1, .clamp
=0 },
134 vg_convar_push( (struct vg_convar
){
137 .data_type
= k_convar_dtype_i32
,
138 .opt_i32
= { .min
=0, .max
=1, .clamp
=0 },
142 vg_convar_push( (struct vg_convar
){
145 .data_type
= k_convar_dtype_i32
,
146 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
150 vg_function_push( (struct vg_cmd
){
152 .function
= reset_player
155 v3f lightDir
= { 0.1f
, 0.8f
, 0.2f
};
156 v3_normalize( lightDir
);
159 model
*char_dev
= vg_asset_read( "models/char_dev.mdl" );
160 model_unpack( char_dev
, &player
.mesh
);
161 player
.legl
= *submodel_get( char_dev
, "legl" );
162 player
.legu
= *submodel_get( char_dev
, "legu" );
163 player
.board
= *submodel_get( char_dev
, "skateboard" );
164 player
.torso
= *submodel_get( char_dev
, "torso" );
165 player
.wheels
= *submodel_get( char_dev
, "wheels" );
166 player
.feet
= *submodel_get( char_dev
, "feet" );
170 model
*cement_model
= vg_asset_read("models/cement_r1.mdl" );
171 model_unpack( cement_model
, &world
.cement
);
172 free( cement_model
);
175 scene_init( &world
.geo
);
176 scene_init( &world
.detail
);
177 scene_init( &world
.foliage
);
179 model
*mworld
= vg_asset_read( "models/free_dev.mdl" );
180 model
*mtest
= vg_asset_read( "models/test.mdl" );
182 model
*msky
= vg_asset_read( "models/skydome.mdl" );
183 model_unpack( msky
, &world
.skydome
);
186 scene_add_model( &world
.geo
, mworld
, submodel_get( mworld
, "terrain" ),
187 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
188 scene_copy_slice( &world
.geo
, &world
.terrain
);
190 scene_add_model( &world
.geo
, mworld
, submodel_get( mworld
, "terrain_rocks" ),
191 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
192 scene_copy_slice( &world
.geo
, &world
.terrain_rocks
);
194 submodel
*ptree
= submodel_get( mtest
, "tree" ),
197 submodel_get( mtest
, "bush" ),
198 submodel_get( mtest
, "bush" ),
199 submodel_get( mtest
, "blubber" ),
202 /* Sprinkle some trees in the terrain areas */
204 v3_sub( world
.geo
.bbx
[1], world
.geo
.bbx
[0], range
);
207 int const ktree_count
= 8000,
208 kfoliage_count
= 200000;
210 int const ktree_count
= 200,
214 for( int i
=0; i
<ktree_count
; i
++ )
216 v3f pos
= { vg_randf(), 0.0f
, vg_randf() },
219 v3_muladd( world
.geo
.bbx
[0], pos
, range
, pos
);
221 if( sample_scene_height( &world
.geo
, pos
, norm
) )
223 if( v3_dot( norm
, (v3f
){ 0.0f
, 1.0f
, 0.0f
} ) > 0.9f
)
225 scene_add_model( &world
.foliage
, mtest
, ptree
,
226 pos
, vg_randf() * VG_TAUf
, vg_randf() * 0.5f
+ 0.5f
);
231 for( int i
=0; i
<kfoliage_count
; i
++ )
233 v3f pos
= { vg_randf(), 0.0f
, vg_randf() },
236 v3_muladd( world
.geo
.bbx
[0], pos
, range
, pos
);
238 if( sample_scene_height( &world
.geo
, pos
, norm
) )
240 if( v3_dot( norm
, (v3f
){ 0.0f
, 1.0f
, 0.0f
} ) > 0.7f
)
242 scene_add_model( &world
.foliage
, mtest
,
243 pt_groundcover
[rand()%vg_list_size(pt_groundcover
)],
244 pos
, vg_randf() * VG_TAUf
, vg_randf() * 0.5f
+ 0.5f
);
249 scene_add_model( &world
.geo
, mworld
, submodel_get( mworld
, "road" ),
250 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
251 scene_copy_slice( &world
.geo
, &world
.terrain_road
);
253 scene_add_model( &world
.detail
, mworld
, submodel_get( mworld
, "art" ),
254 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
259 scene_compute_occlusion( &world
.foliage
);
261 scene_upload( &world
.foliage
);
262 scene_upload( &world
.geo
);
263 scene_upload( &world
.detail
);
265 reset_player( 0, NULL
);
266 player_transform_update();
269 static float ktimestep
= 1.0f
/60.0f
;
271 static void player_freecam(void)
274 m4x3_identity( cam_rot
);
275 m4x3_rotate_y( cam_rot
, -player
.look_dir
[0] );
276 m4x3_rotate_x( cam_rot
, -player
.look_dir
[1] );
278 v3f lookdir
= { 0.0f
, 0.0f
, -1.0f
},
279 sidedir
= { 1.0f
, 0.0f
, 0.0f
};
281 m4x3_mulv( cam_rot
, lookdir
, lookdir
);
282 m4x3_mulv( cam_rot
, sidedir
, sidedir
);
284 float movespeed
= 5.0f
;
285 static v2f mouse_last
,
286 view_vel
= { 0.0f
, 0.0f
};
288 static v3f move_vel
= { 0.0f
, 0.0f
, 0.0f
};
290 if( vg_get_button_down( "primary" ) )
291 v2_copy( vg_mouse
, mouse_last
);
292 else if( vg_get_button( "primary" ) )
295 v2_sub( vg_mouse
, mouse_last
, delta
);
296 v2_copy( vg_mouse
, mouse_last
);
298 v2_muladds( view_vel
, delta
, 0.005f
, view_vel
);
301 v2_muls( view_vel
, 0.75f
, view_vel
);
302 v2_add( view_vel
, player
.look_dir
, player
.look_dir
);
304 vg_clampf( player
.look_dir
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
306 if( vg_get_button( "forward" ) )
307 v3_muladds( move_vel
, lookdir
, ktimestep
* movespeed
, move_vel
);
308 if( vg_get_button( "back" ) )
309 v3_muladds( move_vel
, lookdir
, ktimestep
*-movespeed
, move_vel
);
310 if( vg_get_button( "left" ) )
311 v3_muladds( move_vel
, sidedir
, ktimestep
*-movespeed
, move_vel
);
312 if( vg_get_button( "right" ) )
313 v3_muladds( move_vel
, sidedir
, ktimestep
* movespeed
, move_vel
);
315 v3_muls( move_vel
, 0.75f
, move_vel
);
316 v3_add( move_vel
, player
.view
, player
.view
);
319 static void apply_gravity( v3f vel
, float const timestep
)
321 v3f gravity
= { 0.0f
, -9.6f
, 0.0f
};
322 v3_muladds( vel
, gravity
, timestep
, vel
);
325 static void player_physics_ground(void)
328 * Getting surface collision points,
329 * the contact manifold is a triangle for simplicity.
331 v3f contact_front
, contact_back
, fwd
, fwd1
, contact_norm
, vup
, vside
,
334 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, fwd
);
335 m4x3_mulv( player
.to_world
, (v3f
){ 0.15f
,0.0f
,-1.0f
}, contact_norm
);
336 m4x3_mulv( player
.to_world
, (v3f
){-0.15f
,0.0f
,-1.0f
}, contact_front
);
337 m4x3_mulv( player
.to_world
, (v3f
){ 0.00f
,0.0f
, 1.0f
}, contact_back
);
338 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, vup
);
339 m3x3_mulv( player
.to_world
, (v3f
){1.0f
,0.0f
,0.0f
}, vside
);
342 sample_scene_height( &world
.geo
, contact_front
, NULL
) &&
343 sample_scene_height( &world
.geo
, contact_back
, NULL
) &&
344 sample_scene_height( &world
.geo
, contact_norm
, NULL
);
346 if( !all_contacting
)
354 v3_sub( contact_norm
, contact_front
, v0
);
355 v3_sub( contact_back
, contact_front
, v1
);
356 v3_cross( v1
, v0
, norm
);
357 v3_normalize( norm
);
359 vg_line( contact_norm
, contact_front
, 0xff00ff00 );
360 vg_line( contact_back
, contact_front
, 0xff0000ff );
362 /* Surface alignment */
363 float angle
= v3_dot( vup
, norm
);
364 v3_cross( vup
, norm
, axis
);
369 q_axis_angle( correction
, axis
, acosf(angle
) );
370 q_mul( correction
, player
.rot
, player
.rot
);
373 float resistance
= v3_dot( norm
, player
.v
);
375 if( resistance
>= 0.0f
)
382 v3_muladds( player
.v
, norm
, -resistance
, player
.v
);
385 /* This is where velocity integration used to be */
389 player
.co
[1] = (contact_front
[1]+contact_back
[1])*0.5f
;
392 m3x3_mulv( player
.to_local
, player
.v
, vel
);
394 /* Calculate local forces */
396 slip
= (-vel
[0] / vel
[2]) * player
.vswitch
;
397 if( fabsf( slip
) > 1.2f
)
398 slip
= vg_signf( slip
) * 1.2f
;
401 if( player
.slip_last
*slip
< 0.0f
&& fabsf(slip
) > 0.7f
)
403 vg_warn( "SWITCH\n" );
404 player
.vswitch
= -player
.vswitch
;
408 player
.slip_last
= slip
;
410 float substep
= ktimestep
* 0.2f
;
412 for( int i
=0; i
<5; i
++ )
414 if( fabsf(vel
[2]) >= 0.02f
*substep
)
415 vel
[2] += vg_signf( vel
[2] ) * -0.02f
* substep
;
416 if( fabsf(vel
[0]) >= 7.0f
*substep
)
417 vel
[0] += vg_signf( vel
[0] ) * -7.0f
* substep
;
420 m3x3_mulv( player
.to_world
, vel
, player
.v
);
422 if( vg_get_button( "yawl" ) )
423 player
.iY
+= 3.6f
* ktimestep
;
424 if( vg_get_button( "yawr" ) )
425 player
.iY
-= 3.6f
* ktimestep
;
427 float steer
= vg_get_axis( "horizontal" );
428 player
.iY
-= vg_signf(steer
)*powf(steer
,2.0f
) * 3.5f
* ktimestep
;
431 static void player_physics_air(void)
433 v3f ground_pos
, ground_norm
;
434 v3_copy( player
.co
, ground_pos
);
436 if( sample_scene_height( &world
.geo
, ground_pos
, ground_norm
) )
438 if( ground_pos
[1] > player
.co
[1] )
447 * TODO: Find best landing surface and guide player towords it
449 float pstep
= ktimestep
*10.0f
;
452 v3_copy( player
.co
, pco
);
453 v3_copy( player
.v
, pv
);
456 for( int i
=0; i
<50; i
++ )
458 v3_copy( pco
, pco1
);
459 apply_gravity( pv
, pstep
);
460 v3_muladds( pco
, pv
, pstep
, pco
);
462 vg_line( pco
, pco1
, i
&0x1?0xff000000:0xffffffff );
466 int hit
= sample_scene_height( &world
.geo
, sh
, targetn
);
468 if( sh
[1] >= pco
[1] && hit
)
471 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, localup
);
473 float angle
= v3_dot( localup
, targetn
);
475 v3_cross( localup
, targetn
, axis
);
480 q_axis_angle( correction
, axis
, acosf(angle
)*0.01f
);
481 q_mul( correction
, player
.rot
, player
.rot
);
488 player
.iY
-= vg_get_axis( "horizontal" ) * 3.6f
* ktimestep
;
491 static void player_update(void)
494 if( vg_get_axis("grabl")>0.0f
)
495 reset_player(0,NULL
);
496 if( vg_get_button( "forward" ) )
498 v3f dir
= { 0.0f
, 0.0f
, -1.0f
};
500 m3x3_mulv( player
.to_world
, dir
, dir
);
501 v3_muladds( player
.v
, dir
, 5.0f
* ktimestep
, player
.v
);
505 float horizontal
= vg_get_axis("horizontal"),
506 vertical
= vg_get_axis("vertical");
508 player
.joy_l
[0] = vg_signf(horizontal
) * powf( horizontal
, 2.0f
);
509 player
.joy_l
[1] = vg_signf(vertical
) * powf( vertical
, 2.0f
);
517 /* Integrate velocity */
518 apply_gravity( player
.v
, ktimestep
);
519 v3_muladds( player
.co
, player
.v
, ktimestep
, player
.co
);
521 /* Integrate inertia */
522 v4f rotate
; v3f vup
= {0.0f
,1.0f
,0.0f
};
523 m3x3_mulv( player
.to_world
, vup
, vup
);
525 q_axis_angle( rotate
, vup
, player
.iY
);
526 q_mul( rotate
, player
.rot
, player
.rot
);
528 player
.look_dir
[0] = atan2f( player
.v
[0], -player
.v
[2] );
529 player
.look_dir
[1] = atan2f( -player
.v
[1], sqrtf(player
.v
[0]*player
.v
[0]+
530 player
.v
[2]*player
.v
[2]) ) * 0.3f
;
532 player
.iY
= 0.0f
; /* temp */
535 player_physics_air();
538 player_physics_ground();
540 /* Camera and character */
541 float kheight
= 1.8f
,
549 m4x3_mulv( player
.to_world
, head
, head
);
550 v3_copy( head
, player
.view
);
552 player_transform_update();
553 q_normalize(player
.rot
);
560 /* Creating a skeleton of the player dynamically */
564 static v3f last_vel
= { 0.0f
, 0.0f
, 0.0f
};
565 static v3f momentum
, bob
;
567 v3_sub( player
.v
, last_vel
, player
.a
);
568 v3_copy( player
.v
, last_vel
);
570 v3_add( momentum
, player
.a
, momentum
);
572 v3_lerp( momentum
, (v3f
){0.0f
,0.0f
,0.0f
}, 0.1f
, momentum
);
575 momentum
[0] = vg_clampf( momentum
[0], -2.0f
, 2.0f
);
576 momentum
[1] = vg_clampf( momentum
[1], -0.2f
, 5.0f
);
577 momentum
[2] = vg_clampf( momentum
[2], -2.0f
, 2.0f
);
578 v3_copy( momentum
, target
);
580 v3_lerp( bob
, target
, 0.2f
, bob
);
584 float lslip
= fabsf(slip
); //vg_minf( 0.4f, slip );
586 static float grab
= 0.0f
;
587 float grabt
= vg_get_axis( "grabr" )*0.5f
+0.5f
;
588 grab
= vg_lerpf( grab
, grabt
, 0.04f
);
591 head
[0] = 0.0f
;//(-sinf(lslip)*0.9f * kheight) * 0.44f;
592 head
[1] = (0.3f
+ cosf(lslip
)*0.5f
) * kheight
- grab
*0.7f
;
596 m3x3_mulv( player
.to_local
, bob
, offset
);
600 v3_muladds( head
, offset
, 0.7f
, head
);
602 head
[1] = vg_clampf( head
[1], 0.3f
, 20.0f
);
604 player
.handl_target
[0] = head
[0] + 0.2f
;
605 player
.handl_target
[1] = head
[1] - 0.8f
*(1.0f
-fabsf(slip
));
606 player
.handl_target
[2] = head
[2] + 0.2f
+ 0.7f
*fabsf(slip
);
608 player
.handr_target
[0] = head
[0] + 0.2f
;
609 player
.handr_target
[1] = head
[1] - 0.8f
*(1.0f
-fabsf(slip
));
610 player
.handr_target
[2] = head
[2] - (0.2f
+ 0.7f
*fabsf(slip
));
612 if( vg_maxf(lslip
,grab
) > 0.5f
)
614 if( slip
< 0.0f
&& in_air
)
616 player
.handl_target
[0] = 0.15f
;
617 player
.handl_target
[1] = 0.1f
;
618 player
.handl_target
[2] = 0.4f
;
622 player
.handr_target
[0] = 0.15f
;
623 player
.handr_target
[1] = 0.1f
;
624 player
.handr_target
[2] = -0.4f
;
629 player
.handr_target
[0] = -0.15f
;
630 player
.handr_target
[1] = 0.1f
;
631 player
.handr_target
[2] = 0.4f
;
638 static void debug_grid( v3f at
)
641 v3_floor( at
, base
);
643 for( int y
=0; y
<16; y
++ )
645 vg_line( (v3f
){ base
[0] - 8, base
[1], base
[2]+y
-8 },
646 (v3f
){ base
[0] + 8, base
[1], base
[2]+y
-8 },
649 for( int x
=0; x
<16; x
++ )
651 vg_line( (v3f
){ base
[0]+x
-8, base
[1], base
[2]-8 },
652 (v3f
){ base
[0]+x
-8, base
[1], base
[2]+8 },
657 static void draw_player(void)
659 mesh_bind( &player
.mesh
);
660 float const kleg_upper
= 0.53f
,
663 karm_upper
= kleg_upper
*karm_ratio
,
664 karm_lower
= kleg_lower
*karm_ratio
;
666 /* Create IK targets */
667 struct ik_basic ik_leg_l
= { .l1
= kleg_upper
, .l2
= kleg_lower
},
668 ik_leg_r
= { .l1
= kleg_upper
, .l2
= kleg_lower
},
669 ik_arm_l
= { .l1
= karm_upper
, .l2
= karm_lower
},
670 ik_arm_r
= { .l1
= karm_upper
, .l2
= karm_lower
};
674 m4x3_mulv( player
.to_world
, (v3f
){ 0.0f
,0.16f
,-0.4f
}, ik_leg_r
.end
);
675 m4x3_mulv( player
.to_world
, (v3f
){ 0.0f
,0.16f
, 0.3f
}, ik_leg_l
.end
);
676 m4x3_mulv( player
.to_world
, (v3f
){ -0.6f
,0.5f
,-0.4f
}, ik_leg_r
.pole
);
677 m4x3_mulv( player
.to_world
, (v3f
){ -0.6f
,0.5f
,0.35f
}, ik_leg_l
.pole
);
679 m3x3_mulv( player
.to_world
, (v3f
){ 0.2f
,-0.55f
,0.0f
}, butt
);
680 v3_add( butt
, player
.view
, butt
);
682 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, fwd
);
683 v3_muladds( butt
, fwd
, 0.1f
, ik_leg_r
.base
);
684 v3_muladds( butt
, fwd
,-0.1f
, ik_leg_l
.base
);
687 m4x3f mleg_l
, mknee_l
, mleg_r
, mknee_r
, mboard
;
689 ik_basic( &ik_leg_r
, mleg_r
, mknee_r
);
690 ik_basic( &ik_leg_l
, mleg_l
, mknee_l
);
693 v3f hl
, hr
, neckl
= {0.2f
,-0.1f
, 0.2f
},
694 neckr
= {0.2f
,-0.1f
,-0.2f
};
696 v3_lerp( player
.handl
, player
.handl_target
, 0.04f
, player
.handl
);
697 v3_lerp( player
.handr
, player
.handr_target
, 0.04f
, player
.handr
);
699 m3x3_mulv( player
.to_world
, neckl
, neckl
);
700 m3x3_mulv( player
.to_world
, neckr
, neckr
);
702 v3_add( player
.view
, neckl
, ik_arm_l
.base
);
703 v3_add( player
.view
, neckr
, ik_arm_r
.base
);
704 m4x3_mulv( player
.to_world
, player
.handl
, ik_arm_l
.end
);
705 m4x3_mulv( player
.to_world
, player
.handr
, ik_arm_r
.end
);
706 m4x3_mulv( player
.to_world
, (v3f
){ 0.6f
,0.7f
, 0.4f
}, ik_arm_l
.pole
);
707 m4x3_mulv( player
.to_world
, (v3f
){ 0.6f
,0.7f
,-0.35f
}, ik_arm_r
.pole
);
709 m4x3f marm_l
, melbow_l
, marm_r
, melbow_r
;
710 ik_basic( &ik_arm_l
, marm_l
, melbow_l
);
711 ik_basic( &ik_arm_r
, marm_r
, melbow_r
);
712 m4x3_scale( marm_l
, karm_ratio
);
713 m4x3_scale( marm_r
, karm_ratio
);
714 m4x3_scale( melbow_l
, karm_ratio
);
715 m4x3_scale( melbow_r
, karm_ratio
);
718 vg_tex2d_bind( &tex_grid
, 0 );
719 scene_tree_sway
= 0.0f
;
721 mesh_bind( &player
.mesh
);
724 SHADER_USE(shader_standard_lit
);
726 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit
, "uPv" ),
727 1, GL_FALSE
, (float *)vg_pv
);
728 glUniform1i( SHADER_UNIFORM( shader_standard_lit
, "uTexMain" ), 0 );
729 vg_tex2d_bind( &tex_grid
, 0 );
731 GLint kuMdl
= SHADER_UNIFORM( shader_standard_lit
, "uMdl" );
734 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
735 0.35f
*kscale
,0.35f
*kscale
,0.35f
*kscale
,1.0f
);
737 m4x3_expand( player
.to_world
, mat
);
738 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
739 submodel_draw( &player
.board
);
741 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
742 0.7f
*kscale
,0.7f
*kscale
,0.7f
*kscale
,1.0f
);
743 submodel_draw( &player
.wheels
);
746 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
747 glBlendEquation(GL_FUNC_ADD
);
748 glDisable( GL_DEPTH_TEST
);
749 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
750 0.2f
*kscale
,0.8f
*kscale
,0.4f
*kscale
,0.14f
);
752 submodel_draw( &player
.feet
);
754 m4x3_expand( mleg_l
, mat
);
755 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
756 submodel_draw( &player
.legu
);
758 m4x3_expand( mknee_l
, mat
);
759 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
760 submodel_draw( &player
.legl
);
762 m4x3_expand( mleg_r
, mat
);
763 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
764 submodel_draw( &player
.legu
);
766 m4x3_expand( mknee_r
, mat
);
767 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
768 submodel_draw( &player
.legl
);
771 m4x3_expand( marm_l
, mat
);
772 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
773 submodel_draw( &player
.legu
);
775 m4x3_expand( melbow_l
, mat
);
776 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
777 submodel_draw( &player
.legl
);
779 m4x3_expand( marm_r
, mat
);
780 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
781 submodel_draw( &player
.legu
);
783 m4x3_expand( melbow_r
, mat
);
784 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
785 submodel_draw( &player
.legl
);
789 m3x3_copy( player
.to_world
, mbutt
);
790 v3_copy( butt
, mbutt
[3] );
792 m4x3_expand( mbutt
, mat
);
793 glUniformMatrix4fv( kuMdl
, 1, GL_FALSE
, (float *)mat
);
794 submodel_draw( &player
.torso
);
797 glEnable( GL_DEPTH_TEST
);
802 glViewport( 0,0, vg_window_x
, vg_window_y
);
804 glDisable( GL_DEPTH_TEST
);
805 glClearColor( 0.1f
, 0.0f
, 0.2f
, 1.0f
);
806 glClearColor(141.0f
/255.0f
, 176.0f
/255.0f
, 215.0f
/255.0f
,1.0f
);
807 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
810 v3_negate( player
.view
, pos_inv
);
812 float speed
= v3_length( player
.v
);
813 v3f shake
= { vg_randf()-0.5f
, vg_randf()-0.5f
, vg_randf()-0.5f
};
814 v3_muls( shake
, speed
*0.01f
, shake
);
816 static v2f look_lerped
= {0.0f
,0.0f
};
817 v2_lerp( look_lerped
, player
.look_dir
, 0.03f
, look_lerped
);
819 m4x3_identity( world_matrix
);
820 m4x3_rotate_x( world_matrix
,
821 freecam
? look_lerped
[1]: 0.6f
+shake
[1]*0.04f
+look_lerped
[1] );
823 m4x3_rotate_y( world_matrix
, look_lerped
[0]+shake
[0]*0.02f
);
824 m4x3_translate( world_matrix
, pos_inv
);
827 m4x3_expand( world_matrix
, world_4x4
);
829 m4x4_projection( vg_pv
,
830 freecam
? 90.0f
: 130.0f
,
831 (float)vg_window_x
/ (float)vg_window_y
,
833 m4x4_mul( vg_pv
, world_4x4
, vg_pv
);
835 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 1.0f
, 0.0f
, 0.0f
}, 0xffff0000 );
836 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 1.0f
, 0.0f
}, 0xff00ff00 );
837 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 0.0f
, 1.0f
}, 0xff0000ff );
839 glEnable( GL_DEPTH_TEST
);
841 scene_foliage_shader_use();
843 m4x4_identity( temp1
);
844 glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol
, "uMdl" ),
845 1, GL_FALSE
, (float *)temp1
);
847 vg_tex2d_bind( &tex_norwey
, 0 );
848 scene_tree_sway
= 0.1f
;
850 scene_bind( &world
.foliage
);
851 scene_draw( &world
.foliage
);
853 scene_debugsdf( &world
.foliage
);
855 SHADER_USE(shader_unlit
);
857 m4x4_identity(temp2
);
858 //m4x4_translate( temp2, player.co );
859 glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit
, "uMdl" ),
860 1, GL_FALSE
, (float *)temp2
);
861 glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit
, "uPv" ),
862 1, GL_FALSE
, (float *)vg_pv
);
864 glUniform1i( SHADER_UNIFORM( shader_unlit
, "uTexMain" ), 0 );
865 vg_tex2d_bind( &tex_sky
, 0 );
867 mesh_bind( &world
.skydome
);
868 mesh_draw( &world
.skydome
);
870 vg_tex2d_bind( &tex_cement
, 0 );
871 mesh_bind( &world
.cement
);
872 mesh_draw( &world
.cement
);
874 SHADER_USE(shader_standard_lit
);
876 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit
, "uPv" ),
877 1, GL_FALSE
, (float *)vg_pv
);
878 glUniform1i( SHADER_UNIFORM( shader_standard_lit
, "uTexMain" ), 0 );
880 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit
, "uMdl" ),
881 1, GL_FALSE
, (float *)temp1
);
883 vg_tex2d_bind( &tex_grid
, 0 );
885 scene_bind( &world
.geo
);
887 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
888 0.2f
,0.36f
,0.25f
,1.0f
);
889 submodel_draw( &world
.terrain
);
891 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
892 0.2f
,0.2f
,0.21f
,1.0f
);
893 submodel_draw( &world
.terrain_rocks
);
894 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
895 0.4f
,0.4f
,0.4f
,1.0f
);
896 submodel_draw( &world
.terrain_road
);
899 scene_bind( &world
.detail
);
900 scene_draw( &world
.detail
);
904 glDisable( GL_DEPTH_TEST
);
905 vg_lines_drawall( (float *)vg_pv
);
907 /* Debugger camera */
908 glViewport( 0,0, 512, 512 );
909 glClearColor( 0.1f
, 0.0f
, 0.2f
, 1.0f
);
910 glClear( GL_DEPTH_BUFFER_BIT
);
912 m4x3_identity( world_matrix
);
915 v3_negate( player
.co
, debugcam
);
919 m4x3_translate( world_matrix
, debugcam
);
920 m4x3_expand( world_matrix
, world_4x4
);
922 m4x4_projection( vg_pv
,
924 (float)128.0f
/ (float)128.0f
,
926 m4x4_mul( vg_pv
, world_4x4
, vg_pv
);
930 glEnable( GL_DEPTH_TEST
);
934 glDisable( GL_DEPTH_TEST
);
935 vg_lines_drawall( (float *)vg_pv
);
937 glViewport( 0,0, vg_window_x
, vg_window_y
);
944 snprintf( buf
, 20, "%.2fm/s", v3_length( player
.v
) );
945 gui_text( (ui_px
[2]){ 0, 0 }, buf
, 1, k_text_align_left
);
947 snprintf( buf
, 20, "%.2f %.2f %.2f m/s",
948 player
.a
[0], player
.a
[1], player
.a
[2] );
950 gui_text( (ui_px
[2]){ 0, 20 }, buf
, 1, k_text_align_left
);
952 if( vg_gamepad_ready
)
954 for( int i
=0; i
<6; i
++ )
956 snprintf( buf
, 20, "%.2f", vg_gamepad
.axes
[i
] );
957 gui_text( (ui_px
[2]){ 0, (i
+2)*20 }, buf
, 1, k_text_align_left
);
962 gui_text( (ui_px
[2]){ 0, 40 },
963 "Gamepad not ready", 1, k_text_align_left
);