c3e75104403cf7c8609a76f8eb5342982246e646
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;
26 static int sv_phys
= 0;
27 static int thirdperson
= 0;
34 int main( int argc
, char *argv
[] )
36 vg_init( argc
, argv
, "Voyager Game Engine" );
46 float vswitch
, slip
, slip_last
;
48 float iY
; /* Yaw inertia */
55 v2f look_dir
; /* TEMP */
60 m4x3f to_world
, to_local
;
72 leg_r0
, leg_r1
, foot_r
,
73 leg_l0
, leg_l1
, foot_l
,
74 arm_r0
, arm_r1
, hand_r
,
75 arm_l0
, arm_l1
, hand_l
,
79 m4x3f mleg_l
, mknee_l
, mleg_r
, mknee_r
, mboard
;
80 m4x3f marm_l
, melbow_l
, marm_r
, melbow_r
, mbutt
,
83 v3f handl_target
, handr_target
,
93 scene foliage
, /* Tree shader */
94 geo
, /* Std shader, collisions */
95 detail
; /* Std shader, no collisions */
103 static void player_transform_update(void)
105 q_m3x3( player
.rot
, player
.to_world
);
106 v3_copy( player
.co
, player
.to_world
[3] );
108 m4x3_invert_affine( player
.to_world
, player
.to_local
);
111 static int reset_player( int argc
, char const *argv
[] )
113 v3_zero( player
.co
);
114 v3_copy( (v3f
){ 0.0f
, 0.0f
, -0.2f
}, player
.v
);
115 q_identity( player
.rot
);
116 player
.vswitch
= 1.0f
;
117 player
.slip_last
= 0.0f
;
119 player_transform_update();
123 void vg_register(void)
130 vg_tex2d_init( texture_list
, vg_list_size( texture_list
) );
132 vg_convar_push( (struct vg_convar
){
135 .data_type
= k_convar_dtype_i32
,
136 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
140 vg_convar_push( (struct vg_convar
){
142 .data
= &sv_debugcam
,
143 .data_type
= k_convar_dtype_i32
,
144 .opt_i32
= { .min
=0, .max
=1, .clamp
=0 },
148 vg_convar_push( (struct vg_convar
){
151 .data_type
= k_convar_dtype_i32
,
152 .opt_i32
= { .min
=0, .max
=1, .clamp
=0 },
156 vg_convar_push( (struct vg_convar
){
159 .data_type
= k_convar_dtype_i32
,
160 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
164 vg_convar_push( (struct vg_convar
){
167 .data_type
= k_convar_dtype_i32
,
168 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
172 vg_convar_push( (struct vg_convar
){
173 .name
= "thirdperson",
174 .data
= &thirdperson
,
175 .data_type
= k_convar_dtype_i32
,
176 .opt_i32
= { .min
=0, .max
=1, .clamp
=1 },
180 vg_function_push( (struct vg_cmd
){
182 .function
= reset_player
185 v3f lightDir
= { 0.1f
, 0.8f
, 0.2f
};
186 v3_normalize( lightDir
);
189 model
*char_dev
= vg_asset_read( "models/char_dev.mdl" );
190 model_unpack( char_dev
, &player
.mesh
);
191 player
.legl
= *submodel_get( char_dev
, "legl" );
192 player
.legu
= *submodel_get( char_dev
, "legu" );
193 player
.board
= *submodel_get( char_dev
, "skateboard" );
194 player
.torso
= *submodel_get( char_dev
, "torso" );
195 player
.wheels
= *submodel_get( char_dev
, "wheels" );
196 player
.foot
= *submodel_get( char_dev
, "foot" );
199 player
.leg_r0
= *submodel_get( char_dev
, "leg_r0" );
200 player
.leg_r1
= *submodel_get( char_dev
, "leg_r1" );
201 player
.foot_r
= *submodel_get( char_dev
, "foot_r" );
202 player
.leg_l0
= *submodel_get( char_dev
, "leg_l0" );
203 player
.leg_l1
= *submodel_get( char_dev
, "leg_l1" );
204 player
.foot_l
= *submodel_get( char_dev
, "foot_l" );
205 player
.arm_r0
= *submodel_get( char_dev
, "arm_r0" );
206 player
.arm_r1
= *submodel_get( char_dev
, "arm_r1" );
207 player
.hand_r
= *submodel_get( char_dev
, "hand_r" );
208 player
.arm_l0
= *submodel_get( char_dev
, "arm_l0" );
209 player
.arm_l1
= *submodel_get( char_dev
, "arm_l1" );
210 player
.hand_l
= *submodel_get( char_dev
, "hand_l" );
211 player
.body
= *submodel_get( char_dev
, "body" );
212 player
.head
= *submodel_get( char_dev
, "head" );
216 model
*cement_model
= vg_asset_read("models/cement_r1.mdl" );
217 model_unpack( cement_model
, &world
.cement
);
218 free( cement_model
);
221 scene_init( &world
.geo
);
222 scene_init( &world
.detail
);
223 scene_init( &world
.foliage
);
225 model
*mworld
= vg_asset_read( "models/free_dev.mdl" );
226 model
*mtest
= vg_asset_read( "models/test.mdl" );
228 model
*msky
= vg_asset_read( "models/skydome.mdl" );
229 model_unpack( msky
, &world
.skydome
);
232 scene_add_model( &world
.geo
, mworld
, submodel_get( mworld
, "terrain" ),
233 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
234 scene_copy_slice( &world
.geo
, &world
.terrain
);
236 scene_add_model( &world
.geo
, mworld
, submodel_get( mworld
, "terrain_rocks" ),
237 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
238 scene_copy_slice( &world
.geo
, &world
.terrain_rocks
);
240 submodel
*ptree
= submodel_get( mtest
, "tree" ),
243 submodel_get( mtest
, "bush" ),
244 submodel_get( mtest
, "bush" ),
245 submodel_get( mtest
, "blubber" ),
248 /* Sprinkle some trees in the terrain areas */
250 v3_sub( world
.geo
.bbx
[1], world
.geo
.bbx
[0], range
);
253 int const ktree_count
= 8000,
254 kfoliage_count
= 200000;
256 int const ktree_count
= 200,
260 for( int i
=0; i
<ktree_count
; i
++ )
262 v3f pos
= { vg_randf(), 0.0f
, vg_randf() },
265 v3_muladd( world
.geo
.bbx
[0], pos
, range
, pos
);
267 if( sample_scene_height( &world
.geo
, pos
, norm
) )
269 if( v3_dot( norm
, (v3f
){ 0.0f
, 1.0f
, 0.0f
} ) > 0.9f
)
271 scene_add_model( &world
.foliage
, mtest
, ptree
,
272 pos
, vg_randf() * VG_TAUf
, vg_randf() * 0.5f
+ 0.5f
);
277 for( int i
=0; i
<kfoliage_count
; i
++ )
279 v3f pos
= { vg_randf(), 0.0f
, vg_randf() },
282 v3_muladd( world
.geo
.bbx
[0], pos
, range
, pos
);
284 if( sample_scene_height( &world
.geo
, pos
, norm
) )
286 if( v3_dot( norm
, (v3f
){ 0.0f
, 1.0f
, 0.0f
} ) > 0.7f
)
288 scene_add_model( &world
.foliage
, mtest
,
289 pt_groundcover
[rand()%vg_list_size(pt_groundcover
)],
290 pos
, vg_randf() * VG_TAUf
, vg_randf() * 0.5f
+ 0.5f
);
295 scene_add_model( &world
.geo
, mworld
, submodel_get( mworld
, "road" ),
296 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
297 scene_copy_slice( &world
.geo
, &world
.terrain_road
);
299 scene_add_model( &world
.detail
, mworld
, submodel_get( mworld
, "art" ),
300 (v3f
){0.0f
,0.0f
,0.0f
}, 0.0f
, 1.0f
);
305 scene_compute_occlusion( &world
.foliage
);
307 scene_upload( &world
.foliage
);
308 scene_upload( &world
.geo
);
309 scene_upload( &world
.detail
);
311 reset_player( 0, NULL
);
312 player_transform_update();
315 static float ktimestep
= 1.0f
/60.0f
;
317 static void player_freecam(void)
320 m4x3_identity( cam_rot
);
321 m4x3_rotate_y( cam_rot
, -player
.look_dir
[0] );
322 m4x3_rotate_x( cam_rot
, -player
.look_dir
[1] );
324 v3f lookdir
= { 0.0f
, 0.0f
, -1.0f
},
325 sidedir
= { 1.0f
, 0.0f
, 0.0f
};
327 m4x3_mulv( cam_rot
, lookdir
, lookdir
);
328 m4x3_mulv( cam_rot
, sidedir
, sidedir
);
330 float movespeed
= 5.0f
;
331 static v2f mouse_last
,
332 view_vel
= { 0.0f
, 0.0f
};
334 static v3f move_vel
= { 0.0f
, 0.0f
, 0.0f
};
336 if( vg_get_button_down( "primary" ) )
337 v2_copy( vg_mouse
, mouse_last
);
338 else if( vg_get_button( "primary" ) )
341 v2_sub( vg_mouse
, mouse_last
, delta
);
342 v2_copy( vg_mouse
, mouse_last
);
344 v2_muladds( view_vel
, delta
, 0.005f
, view_vel
);
347 v2_muls( view_vel
, 0.75f
, view_vel
);
348 v2_add( view_vel
, player
.look_dir
, player
.look_dir
);
350 vg_clampf( player
.look_dir
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
352 if( vg_get_button( "forward" ) )
353 v3_muladds( move_vel
, lookdir
, ktimestep
* movespeed
, move_vel
);
354 if( vg_get_button( "back" ) )
355 v3_muladds( move_vel
, lookdir
, ktimestep
*-movespeed
, move_vel
);
356 if( vg_get_button( "left" ) )
357 v3_muladds( move_vel
, sidedir
, ktimestep
*-movespeed
, move_vel
);
358 if( vg_get_button( "right" ) )
359 v3_muladds( move_vel
, sidedir
, ktimestep
* movespeed
, move_vel
);
361 v3_muls( move_vel
, 0.75f
, move_vel
);
362 v3_add( move_vel
, player
.view
, player
.view
);
366 static void apply_gravity( v3f vel
, float const timestep
)
368 v3f gravity
= { 0.0f
, -9.6f
, 0.0f
};
369 v3_muladds( vel
, gravity
, timestep
, vel
);
372 static void player_physics_ground(void)
375 * Getting surface collision points,
376 * the contact manifold is a triangle for simplicity.
378 v3f contact_front
, contact_back
, fwd
, fwd1
, contact_norm
, vup
, vside
,
381 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,0.0f
,-1.0f
}, fwd
);
382 m4x3_mulv( player
.to_world
, (v3f
){ 0.15f
,0.0f
,-1.0f
}, contact_norm
);
383 m4x3_mulv( player
.to_world
, (v3f
){-0.15f
,0.0f
,-1.0f
}, contact_front
);
384 m4x3_mulv( player
.to_world
, (v3f
){ 0.00f
,0.0f
, 1.0f
}, contact_back
);
385 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, vup
);
386 m3x3_mulv( player
.to_world
, (v3f
){1.0f
,0.0f
,0.0f
}, vside
);
389 sample_scene_height( &world
.geo
, contact_front
, NULL
) &&
390 sample_scene_height( &world
.geo
, contact_back
, NULL
) &&
391 sample_scene_height( &world
.geo
, contact_norm
, NULL
);
393 if( !all_contacting
)
401 v3_sub( contact_norm
, contact_front
, v0
);
402 v3_sub( contact_back
, contact_front
, v1
);
403 v3_cross( v1
, v0
, norm
);
404 v3_normalize( norm
);
406 vg_line( contact_norm
, contact_front
, 0xff00ff00 );
407 vg_line( contact_back
, contact_front
, 0xff0000ff );
409 /* Surface alignment */
410 float angle
= v3_dot( vup
, norm
);
411 v3_cross( vup
, norm
, axis
);
416 q_axis_angle( correction
, axis
, acosf(angle
) );
417 q_mul( correction
, player
.rot
, player
.rot
);
420 float resistance
= v3_dot( norm
, player
.v
);
422 if( resistance
>= 0.0f
)
429 v3_muladds( player
.v
, norm
, -resistance
, player
.v
);
432 /* This is where velocity integration used to be */
436 player
.co
[1] = (contact_front
[1]+contact_back
[1])*0.5f
;
439 m3x3_mulv( player
.to_local
, player
.v
, vel
);
441 /* Calculate local forces */
443 slip
= (-vel
[0] / vel
[2]) * player
.vswitch
;
444 if( fabsf( slip
) > 1.2f
)
445 slip
= vg_signf( slip
) * 1.2f
;
449 if( player
.slip_last
*slip
< 0.0f
&& fabsf(slip
) > 0.7f
)
451 vg_warn( "SWITCH\n" );
452 player
.vswitch
= -player
.vswitch
;
456 player
.slip_last
= slip
;
459 float substep
= ktimestep
* 0.2f
;
461 for( int i
=0; i
<5; i
++ )
463 if( fabsf(vel
[2]) >= 0.02f
*substep
)
464 vel
[2] += vg_signf( vel
[2] ) * -0.02f
* substep
;
465 if( fabsf(vel
[0]) >= 7.0f
*substep
)
466 vel
[0] += vg_signf( vel
[0] ) * -7.0f
* substep
;
469 m3x3_mulv( player
.to_world
, vel
, player
.v
);
471 if( vg_get_button( "yawl" ) )
472 player
.iY
+= 3.6f
* ktimestep
;
473 if( vg_get_button( "yawr" ) )
474 player
.iY
-= 3.6f
* ktimestep
;
476 float steer
= vg_get_axis( "horizontal" );
477 player
.iY
-= vg_signf(steer
)*powf(steer
,2.0f
) * 1.5f
* ktimestep
;
480 static void player_physics_air(void)
482 v3f ground_pos
, ground_norm
;
483 v3_copy( player
.co
, ground_pos
);
485 if( sample_scene_height( &world
.geo
, ground_pos
, ground_norm
) )
487 if( ground_pos
[1] > player
.co
[1] )
496 * TODO: Find best landing surface and guide player towords it
498 float pstep
= ktimestep
*10.0f
;
501 v3_copy( player
.co
, pco
);
502 v3_copy( player
.v
, pv
);
505 for( int i
=0; i
<50; i
++ )
507 v3_copy( pco
, pco1
);
508 apply_gravity( pv
, pstep
);
509 v3_muladds( pco
, pv
, pstep
, pco
);
511 vg_line( pco
, pco1
, i
&0x1?0xff000000:0xffffffff );
515 int hit
= sample_scene_height( &world
.geo
, sh
, targetn
);
517 if( sh
[1] >= pco
[1] && hit
)
520 m3x3_mulv( player
.to_world
, (v3f
){0.0f
,1.0f
,0.0f
}, localup
);
522 float angle
= v3_dot( localup
, targetn
);
524 v3_cross( localup
, targetn
, axis
);
529 q_axis_angle( correction
, axis
, acosf(angle
)*0.01f
);
530 q_mul( correction
, player
.rot
, player
.rot
);
537 player
.iY
-= vg_get_axis( "horizontal" ) * 3.6f
* ktimestep
;
540 static void player_animate(void);
541 static void player_update(void)
550 if( vg_get_axis("grabl")>0.0f
)
551 reset_player(0,NULL
);
552 if( vg_get_button( "forward" ) )
554 v3f dir
= { 0.0f
, 0.0f
, -1.0f
};
556 m3x3_mulv( player
.to_world
, dir
, dir
);
557 v3_muladds( player
.v
, dir
, 5.0f
* ktimestep
, player
.v
);
560 float horizontal
= vg_get_axis("horizontal"),
561 vertical
= vg_get_axis("vertical");
563 player
.joy_l
[0] = vg_signf(horizontal
) * powf( horizontal
, 2.0f
);
564 player
.joy_l
[1] = vg_signf(vertical
) * powf( vertical
, 2.0f
);
566 /* Integrate velocity */
569 apply_gravity( player
.v
, ktimestep
);
570 v3_muladds( player
.co
, player
.v
, ktimestep
, player
.co
);
573 /* Integrate inertia */
574 v4f rotate
; v3f vup
= {0.0f
,1.0f
,0.0f
};
575 m3x3_mulv( player
.to_world
, vup
, vup
);
577 q_axis_angle( rotate
, vup
, player
.iY
);
578 q_mul( rotate
, player
.rot
, player
.rot
);
580 player
.look_dir
[0] = atan2f( player
.v
[0], -player
.v
[2] );
581 player
.look_dir
[1] = atan2f( -player
.v
[1], sqrtf(player
.v
[0]*player
.v
[0]+
582 player
.v
[2]*player
.v
[2]) ) * 0.3f
;
584 player
.iY
= 0.0f
; /* temp */
587 player_physics_air();
590 player_physics_ground();
592 /* Camera and character */
594 player_transform_update();
595 q_normalize(player
.rot
);
603 /* Creating a skeleton of the player dynamically */
607 player
.handl_target
[0] = head
[0] + 0.2f
;
608 player
.handl_target
[1] = head
[1] - 0.8f
*(1.0f
-fabsf(slip
));
609 player
.handl_target
[2] = head
[2] + 0.2f
+ 0.7f
*fabsf(slip
);
611 player
.handr_target
[0] = head
[0] + 0.2f
;
612 player
.handr_target
[1] = head
[1] - 0.8f
*(1.0f
-fabsf(slip
));
613 player
.handr_target
[2] = head
[2] - (0.2f
+ 0.7f
*fabsf(slip
));
615 if( vg_maxf(lslip
,grab
) > 0.5f
)
617 if( player
.slip
< 0.0f
&& player
.in_air
)
619 player
.handl_target
[0] = 0.15f
;
620 player
.handl_target
[1] = 0.1f
;
621 player
.handl_target
[2] = 0.4f
;
625 player
.handr_target
[0] = 0.15f
;
626 player
.handr_target
[1] = 0.1f
;
627 player
.handr_target
[2] = -0.4f
;
632 player
.handr_target
[0] = -0.15f
;
633 player
.handr_target
[1] = 0.1f
;
634 player
.handr_target
[2] = 0.4f
;
641 static void player_animate(void)
643 /* Camera position */
644 static v3f last_vel
= { 0.0f
, 0.0f
, 0.0f
};
645 static v3f momentum
, bob
;
647 v3_sub( player
.v
, last_vel
, player
.a
);
648 v3_copy( player
.v
, last_vel
);
650 v3_add( momentum
, player
.a
, momentum
);
651 v3_lerp( momentum
, (v3f
){0.0f
,0.0f
,0.0f
}, 0.1f
, momentum
);
654 momentum
[0] = vg_clampf( momentum
[0], -2.0f
, 2.0f
);
655 momentum
[1] = vg_clampf( momentum
[1], -0.2f
, 5.0f
);
656 momentum
[2] = vg_clampf( momentum
[2], -2.0f
, 2.0f
);
657 v3_copy( momentum
, target
);
658 v3_lerp( bob
, target
, 0.2f
, bob
);
661 float lslip
= fabsf(player
.slip
); //vg_minf( 0.4f, slip );
663 float grabt
= vg_get_axis( "grabr" )*0.5f
+0.5f
;
664 player
.grab
= vg_lerpf( player
.grab
, grabt
, 0.04f
);
666 float kheight
= 1.8f
,
671 head
[1] = (0.3f
+cosf(lslip
)*0.5f
*(1.0f
-player
.grab
*0.7f
)) * kheight
;
675 m3x3_mulv( player
.to_local
, bob
, offset
);
677 offset
[0] *= 0.3333f
;
680 v3_muladds( head
, offset
, 0.7f
, head
);
681 head
[1] = vg_clampf( head
[1], 0.3f
, kheight
);
683 m4x3_mulv( player
.to_world
, head
, head
);
685 v3_copy( head
, player
.view
);
687 /* New board transformation */
688 v4f board_rotation
; v3f board_location
;
690 /* TODO: Move this out of animate into update */
691 v2_lerp( player
.board_xy
, (v2f
){ vg_get_axis("h1"), vg_get_axis("v1") },
692 ktimestep
*3.0f
, player
.board_xy
);
695 q_axis_angle( rz
, (v3f
){ 0.0f
, 0.0f
, 1.0f
}, player
.board_xy
[0] );
696 q_axis_angle( rx
, (v3f
){ 1.0f
, 0.0f
, 0.0f
}, player
.board_xy
[1] );
697 q_mul( rx
, rz
, board_rotation
);
699 q_m3x3( board_rotation
, player
.mboard
);
700 m3x3_mulv( player
.mboard
, (v3f
){ 0.0f
, -0.5f
, 0.0f
}, board_location
);
701 v3_add( (v3f
){0.0f
,0.5f
,0.0f
}, board_location
, board_location
);
703 m3x3_mul( player
.to_world
, player
.mboard
, player
.mboard
);
704 m4x3_mulv( player
.to_world
, board_location
, player
.mboard
[3] );
707 /* In the air, the dude should grab with the side thats highest,
708 * while also sliding the same foot downwards a bit */
713 player
.handl_target
[0] = 0.0f
;
714 player
.handl_target
[1] = 0.0f
;
715 player
.handl_target
[2] = 0.6f
;
717 player
.handr_target
[0] = 0.0f
;
718 player
.handr_target
[1] = 0.0f
;
719 player
.handr_target
[2] = -0.6f
;
720 if( 1||player
.in_air
)
722 float tuck
= player
.board_xy
[1],
723 tuck_amt
= fabsf( tuck
) * (1.0f
-fabsf(player
.board_xy
[0]));
727 foot_l
*= 1.0f
-tuck_amt
*1.5f
;
729 if( player
.grab
> 0.1f
)
731 m4x3_mulv( player
.mboard
, (v3f
){0.1f
,0.14f
,0.6f
},
732 player
.handl_target
);
733 m4x3_mulv( player
.to_local
,
734 player
.handl_target
, player
.handl_target
);
739 foot_r
*= 1.0f
-tuck_amt
*1.4f
;
741 if( player
.grab
> 0.1f
)
743 m4x3_mulv( player
.mboard
, (v3f
){0.1f
,0.14f
,-0.6f
},
744 player
.handr_target
);
745 m4x3_mulv( player
.to_local
,
746 player
.handr_target
, player
.handr_target
);
754 m3x3_copy( player
.mboard
, player
.mfoot_l
);
755 m4x3_mulv( player
.mboard
, (v3f
){ 0.0f
,0.16f
,foot_l
}, player
.mfoot_l
[3] );
757 m3x3_copy( player
.mboard
, player
.mfoot_r
);
758 m4x3_mulv( player
.mboard
, (v3f
){ 0.0f
,0.16f
,foot_r
}, player
.mfoot_r
[3] );
760 float const kleg_upper
= 0.53f
,
763 karm_upper
= kleg_upper
*karm_ratio
,
764 karm_lower
= kleg_lower
*karm_ratio
;
766 /* Create IK targets */
767 struct ik_basic ik_leg_l
= { .l1
= kleg_upper
, .l2
= kleg_lower
},
768 ik_leg_r
= { .l1
= kleg_upper
, .l2
= kleg_lower
},
769 ik_arm_l
= { .l1
= karm_upper
, .l2
= karm_lower
},
770 ik_arm_r
= { .l1
= karm_upper
, .l2
= karm_lower
};
775 /* create hip rotation */
776 q_axis_angle( hip_rotation
, (v3f
){0.0f
,1.0f
,0.0f
}, sinf(vg_time
) );
777 q_m3x3( hip_rotation
, player
.mbutt
);
778 m3x3_mul( player
.to_world
, player
.mbutt
, player
.mbutt
);
781 m3x3_mulv( player
.to_world
, (v3f
){ 0.2f
,-0.55f
,0.0f
}, butt
);
782 v3_add( butt
, player
.view
, butt
);
783 v3_copy( butt
, player
.mbutt
[3] );
785 m4x3_mulv( player
.mbutt
, (v3f
){0.0f
,0.0f
,-0.1f
}, ik_leg_r
.base
);
786 m4x3_mulv( player
.mbutt
, (v3f
){0.0f
,0.0f
, 0.1f
}, ik_leg_l
.base
);
788 m4x3_mulv( player
.mboard
, (v3f
){ 0.0f
,0.16f
, foot_r
}, ik_leg_r
.end
);
789 m4x3_mulv( player
.mboard
, (v3f
){ 0.0f
,0.16f
, foot_l
}, ik_leg_l
.end
);
790 m4x3_mulv( player
.mboard
, (v3f
){ -0.6f
,0.50f
,-0.40f
}, ik_leg_r
.pole
);
791 m4x3_mulv( player
.mboard
, (v3f
){ -0.6f
,0.50f
, 0.35f
}, ik_leg_l
.pole
);
794 ik_basic( &ik_leg_r
, player
.mleg_r
, player
.mknee_r
);
795 ik_basic( &ik_leg_l
, player
.mleg_l
, player
.mknee_l
);
798 v3f hl
, hr
, neckl
= {0.0f
, 0.5f
, 0.2f
},
799 neckr
= {0.0f
, 0.5f
,-0.2f
};
801 m4x3_mulv( player
.mbutt
, neckl
, ik_arm_l
.base
);
802 m4x3_mulv( player
.mbutt
, neckr
, ik_arm_r
.base
);
804 v3_lerp( player
.handl
, player
.handl_target
, 0.1f
, player
.handl
);
805 v3_lerp( player
.handr
, player
.handr_target
, 0.1f
, player
.handr
);
807 m4x3_mulv( player
.to_world
, player
.handl
, ik_arm_l
.end
);
808 m4x3_mulv( player
.to_world
, player
.handr
, ik_arm_r
.end
);
809 m4x3_mulv( player
.to_world
, (v3f
){ 0.6f
,0.7f
, 0.4f
}, ik_arm_l
.pole
);
810 m4x3_mulv( player
.to_world
, (v3f
){ 0.6f
,0.7f
,-0.35f
}, ik_arm_r
.pole
);
812 ik_basic( &ik_arm_l
, player
.marm_l
, player
.melbow_l
);
813 ik_basic( &ik_arm_r
, player
.marm_r
, player
.melbow_r
);
818 v3_copy( player
.v
, nv
);
820 v3_muladds( player
.view
, nv
, -3.0f
, player
.view
);
824 static void draw_player(void)
826 mesh_bind( &player
.mesh
);
829 vg_tex2d_bind( &tex_grid
, 0 );
830 scene_tree_sway
= 0.0f
;
832 mesh_bind( &player
.mesh
);
835 SHADER_USE(shader_standard_lit
);
837 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit
, "uPv" ),
838 1, GL_FALSE
, (float *)vg_pv
);
839 glUniform1i( SHADER_UNIFORM( shader_standard_lit
, "uTexMain" ), 0 );
840 vg_tex2d_bind( &tex_grid
, 0 );
842 GLint kuMdl
= SHADER_UNIFORM( shader_standard_lit
, "uMdl" );
845 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
846 0.35f
*kscale
,0.35f
*kscale
,0.35f
*kscale
,1.0f
);
848 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mboard
);
849 submodel_draw( &player
.board
);
851 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
852 0.7f
*kscale
,0.7f
*kscale
,0.7f
*kscale
,1.0f
);
853 submodel_draw( &player
.wheels
);
856 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
857 glBlendEquation(GL_FUNC_ADD
);
858 glDisable( GL_DEPTH_TEST
);
859 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
860 0.2f
*kscale
,0.8f
*kscale
,0.4f
*kscale
,0.14f
);
862 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mfoot_l
);
863 submodel_draw( &player
.foot_l
);
864 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mfoot_r
);
865 submodel_draw( &player
.foot_r
);
867 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mleg_l
);
868 submodel_draw( &player
.leg_l0
);
870 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mknee_l
);
871 submodel_draw( &player
.leg_l1
);
873 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mleg_r
);
874 submodel_draw( &player
.leg_r0
);
876 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mknee_r
);
877 submodel_draw( &player
.leg_r1
);
880 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.marm_l
);
881 submodel_draw( &player
.arm_l0
);
883 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.melbow_l
);
884 submodel_draw( &player
.arm_l1
);
886 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.marm_r
);
887 submodel_draw( &player
.arm_r0
);
889 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.melbow_r
);
890 submodel_draw( &player
.arm_r1
);
893 glUniformMatrix4x3fv( kuMdl
, 1, GL_FALSE
, (float *)player
.mbutt
);
894 submodel_draw( &player
.body
);
896 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
897 0.2f
*kscale
,0.2f
*kscale
,0.2f
*kscale
,0.14f
);
898 submodel_draw( &player
.head
);
901 glEnable( GL_DEPTH_TEST
);
906 glViewport( 0,0, vg_window_x
, vg_window_y
);
908 glDisable( GL_DEPTH_TEST
);
909 glClearColor( 0.1f
, 0.0f
, 0.2f
, 1.0f
);
910 glClearColor(141.0f
/255.0f
, 176.0f
/255.0f
, 215.0f
/255.0f
,1.0f
);
911 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
914 v3_negate( player
.view
, pos_inv
);
916 float speed
= v3_length( player
.v
);
917 v3f shake
= { vg_randf()-0.5f
, vg_randf()-0.5f
, vg_randf()-0.5f
};
918 v3_muls( shake
, speed
*0.01f
, shake
);
920 static v2f look_lerped
= {0.0f
,0.0f
};
921 v2_lerp( look_lerped
, player
.look_dir
, 0.03f
, look_lerped
);
923 m4x3_identity( world_matrix
);
924 m4x3_rotate_x( world_matrix
,
925 freecam
? look_lerped
[1]: 0.6f
+shake
[1]*0.04f
+look_lerped
[1] );
927 m4x3_rotate_y( world_matrix
, look_lerped
[0]+shake
[0]*0.02f
);
928 m4x3_translate( world_matrix
, pos_inv
);
931 m4x3_expand( world_matrix
, world_4x4
);
932 m4x4_projection( vg_pv
,
933 freecam
? 90.0f
: 130.0f
,
934 (float)vg_window_x
/ (float)vg_window_y
,
936 m4x4_mul( vg_pv
, world_4x4
, vg_pv
);
938 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 1.0f
, 0.0f
, 0.0f
}, 0xffff0000 );
939 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 1.0f
, 0.0f
}, 0xff00ff00 );
940 vg_line( (v3f
){ 0.0f
, 0.0f
, 0.0f
}, (v3f
){ 0.0f
, 0.0f
, 1.0f
}, 0xff0000ff );
942 glEnable( GL_DEPTH_TEST
);
944 scene_foliage_shader_use();
946 m4x3_identity( temp1
);
947 glUniformMatrix4x3fv( SHADER_UNIFORM( shader_debug_vcol
, "uMdl" ),
948 1, GL_FALSE
, (float *)temp1
);
950 vg_tex2d_bind( &tex_norwey
, 0 );
951 scene_tree_sway
= 0.1f
;
953 scene_bind( &world
.foliage
);
954 scene_draw( &world
.foliage
);
956 scene_debugsdf( &world
.foliage
);
958 SHADER_USE(shader_unlit
);
960 m4x3_identity(temp2
);
961 //m4x4_translate( temp2, player.co );
962 glUniformMatrix4x3fv( SHADER_UNIFORM( shader_unlit
, "uMdl" ),
963 1, GL_FALSE
, (float *)temp2
);
964 glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit
, "uPv" ),
965 1, GL_FALSE
, (float *)vg_pv
);
967 glUniform1i( SHADER_UNIFORM( shader_unlit
, "uTexMain" ), 0 );
968 vg_tex2d_bind( &tex_sky
, 0 );
970 mesh_bind( &world
.skydome
);
971 mesh_draw( &world
.skydome
);
974 vg_tex2d_bind( &tex_cement
, 0 );
975 mesh_bind( &world
.cement
);
976 mesh_draw( &world
.cement
);
979 SHADER_USE(shader_standard_lit
);
981 glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit
, "uPv" ),
982 1, GL_FALSE
, (float *)vg_pv
);
983 glUniform1i( SHADER_UNIFORM( shader_standard_lit
, "uTexMain" ), 0 );
984 glUniformMatrix4x3fv( SHADER_UNIFORM( shader_standard_lit
, "uMdl" ),
985 1, GL_FALSE
, (float *)temp1
);
987 vg_tex2d_bind( &tex_grid
, 0 );
989 scene_bind( &world
.geo
);
991 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
992 0.2f
,0.36f
,0.25f
,1.0f
);
993 submodel_draw( &world
.terrain
);
995 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
996 0.2f
,0.2f
,0.21f
,1.0f
);
997 submodel_draw( &world
.terrain_rocks
);
998 glUniform4f( SHADER_UNIFORM(shader_standard_lit
,"uColour"),
999 0.4f
,0.4f
,0.4f
,1.0f
);
1000 submodel_draw( &world
.terrain_road
);
1003 scene_bind( &world
.detail
);
1004 scene_draw( &world
.detail
);
1008 glDisable( GL_DEPTH_TEST
);
1009 vg_lines_drawall( (float *)vg_pv
);
1011 /* Debugger camera */
1012 glViewport( 0,0, 800, 800 );
1013 glClearColor( 0.1f
, 0.0f
, 0.2f
, 1.0f
);
1014 glClear( GL_DEPTH_BUFFER_BIT
);
1016 m4x3_identity( world_matrix
);
1019 v3_negate( player
.co
, debugcam
);
1020 debugcam
[2] -= 2.0f
;
1021 debugcam
[1] -= 0.7f
;
1023 m4x3_translate( world_matrix
, debugcam
);
1024 m4x3_expand( world_matrix
, world_4x4
);
1026 m4x4_projection( vg_pv
,
1028 (float)128.0f
/ (float)128.0f
,
1030 m4x4_mul( vg_pv
, world_4x4
, vg_pv
);
1034 glEnable( GL_DEPTH_TEST
);
1039 glDisable( GL_DEPTH_TEST
);
1040 vg_lines_drawall( (float *)vg_pv
);
1042 glViewport( 0,0, vg_window_x
, vg_window_y
);
1049 snprintf( buf
, 20, "%.2fm/s", v3_length( player
.v
) );
1050 gui_text( (ui_px
[2]){ 0, 0 }, buf
, 1, k_text_align_left
);
1052 snprintf( buf
, 20, "%.2f %.2f %.2f m/s",
1053 player
.a
[0], player
.a
[1], player
.a
[2] );
1055 gui_text( (ui_px
[2]){ 0, 20 }, buf
, 1, k_text_align_left
);
1057 if( vg_gamepad_ready
)
1059 for( int i
=0; i
<6; i
++ )
1061 snprintf( buf
, 20, "%.2f", vg_gamepad
.axes
[i
] );
1062 gui_text( (ui_px
[2]){ 0, (i
+2)*20 }, buf
, 1, k_text_align_left
);
1067 gui_text( (ui_px
[2]){ 0, 40 },
1068 "Gamepad not ready", 1, k_text_align_left
);
1072 void vg_free(void){}