2 #ifndef PLAYER_INTERFACE_H
3 #define PLAYER_INTERFACE_H
8 #include "player_ragdoll.h"
9 #include "player_model.h"
12 typedef struct player_device player_device
;
13 typedef struct player_interface player_interface
;
14 typedef struct player_device_transition player_device_transition
;
15 typedef mdl_keyframe player_pose
[32];
17 #define PLAYER_DEVICE_API VG_STATIC
19 struct player_interface
24 player_device
*devices
[ 8 ];
30 * ---------------------------
34 k_camera_mode_firstperson
,
35 k_camera_mode_thirdperson
38 float camera_type_blend
;
40 teleport_gate
*gate_waiting
;
44 * --------------------------------
46 struct input_binding
*input_js1h
,
62 * --------------------------------------------------
65 struct player_avatar
*playeravatar
;
67 struct player_ragdoll ragdoll
;
70 enum player_device_event_type
72 k_player_device_event_bind
,
73 k_player_device_event_respawn
,
74 k_player_device_event_custom_transition
,
76 k_player_device_event_pre_update
,
77 k_player_device_event_update
,
78 k_player_device_event_post_update
,
79 k_player_device_event_animate
,
80 k_player_device_event_post_animate
,
81 k_player_device_event_debug_ui
,
82 k_player_device_event_restore_state
,
86 vg_tex2d tex_characters
= { .path
= "textures/ch_gradient.qoi" };
91 int (* event
) ( player_device
*dev
, player_interface
*player
,
92 enum player_device_event_type ev
, void *data
);
96 /* animation driven */
100 camera cam_1st
, cam_3rd
;
103 VG_STATIC
void player_interface_create_player( player_interface
*inst
)
105 static int only_once
= 0;
106 assert( only_once
== 0 );
109 inst
->input_js1h
= vg_create_named_input( "steer-h", k_input_type_axis
);
110 inst
->input_js1v
= vg_create_named_input( "steer-v", k_input_type_axis
);
111 inst
->input_grab
= vg_create_named_input( "grab", k_input_type_axis_norm
);
112 inst
->input_js2h
= vg_create_named_input( "grab-h", k_input_type_axis
);
113 inst
->input_js2v
= vg_create_named_input( "grab-v", k_input_type_axis
);
114 inst
->input_jump
= vg_create_named_input( "jump", k_input_type_button
);
115 inst
->input_push
= vg_create_named_input( "push", k_input_type_button
);
116 inst
->input_walk
= vg_create_named_input( "walk", k_input_type_button
);
117 inst
->input_walkh
= vg_create_named_input( "walk-h", k_input_type_axis
);
118 inst
->input_walkv
= vg_create_named_input( "walk-v", k_input_type_axis
);
119 inst
->input_use
= vg_create_named_input( "use", k_input_type_button
);
120 inst
->input_reset
= vg_create_named_input( "reset", k_input_type_button
);
121 inst
->input_camera
=vg_create_named_input( "camera", k_input_type_button
);
123 const char *default_cfg
[] =
125 "bind steer-h gp-ls-h",
129 "bind steer-v gp-ls-v",
135 "bind grab-h gp-rs-h",
136 "bind grab-v gp-rs-v",
147 "bind walk-h gp-ls-h",
148 "bind walk-v -gp-ls-v",
162 for( int i
=0; i
<vg_list_size(default_cfg
); i
++ )
163 vg_execute_console_input(default_cfg
[i
]);
165 v3_zero( inst
->rb
.co
);
166 v3_zero( inst
->rb
.w
);
167 v3_zero( inst
->rb
.v
);
168 q_identity( inst
->rb
.q
);
169 m4x3_identity( inst
->rb
.to_world
);
170 m4x3_identity( inst
->rb
.to_local
);
173 PLAYER_DEVICE_API u32
player_get_device( player_interface
*player
,
176 for( u32 i
=0; i
<player
->device_count
; i
++ )
178 player_device
*dev
= player
->devices
[i
];
179 if( !strcmp( name
, dev
->name
) )
183 vg_fatal_exit_loop( "Invalid device name\n" );
187 VG_STATIC
void player_use_avatar( player_interface
*player
,
188 struct player_avatar
*av
)
190 player
->playeravatar
= av
;
191 player_setup_ragdoll_from_avatar( &player
->ragdoll
, av
);
194 VG_STATIC
void player_use_mesh( player_interface
*player
, glmesh
*mesh
)
196 player
->playermesh
= mesh
;
199 /* FIXME: Seperate concepts for binding and equip.
201 VG_STATIC
void player_add_device( player_interface
*player
, player_device
*dev
)
203 if( player
->device_count
== vg_list_size( player
->devices
) )
204 vg_fatal_exit_loop( "Too many devices added\n" );
206 player
->devices
[ player
->device_count
++ ] = dev
;
208 assert( dev
->event
);
209 assert( dev
->storage
);
211 vg_success( "Added player device '%s'\n", dev
->name
);
214 VG_STATIC
void player_bind( player_interface
*player
)
216 for( int i
=0; i
<player
->device_count
; i
++ )
218 player_device
*dev
= player
->devices
[i
];
219 dev
->event( dev
, player
, k_player_device_event_bind
, NULL
);
223 PLAYER_DEVICE_API
void player_transition_to_device( player_interface
*player
,
226 assert( id
< player
->device_count
);
228 player
->active_device
= id
;
229 player_device
*dev
= player
->devices
[ player
->active_device
];
231 dev
->event( dev
, player
, k_player_device_event_custom_transition
, data
);
232 //dev->event( dev, player, k_player_device_event_pre_update, NULL );
235 VG_STATIC
void player_pre_update( player_interface
*player
)
237 if( vg_input_button_down( player
->input_camera
) )
239 if( player
->camera_mode
== k_camera_mode_firstperson
)
240 player
->camera_mode
= k_camera_mode_thirdperson
;
242 player
->camera_mode
= k_camera_mode_firstperson
;
246 if( vg_input_button_down( player
->input_use
) )
247 player
->active_device
^= 0x1;
251 v3_copy( player
->rb
.co
, player
->prev_position
);
254 player_device
*dev
= player
->devices
[ player
->active_device
];
255 dev
->event( dev
, player
, k_player_device_event_pre_update
, NULL
);
258 VG_STATIC
void player_update( player_interface
*player
)
260 player_device
*dev
= player
->devices
[ player
->active_device
];
261 dev
->event( dev
, player
, k_player_device_event_update
, NULL
);
264 VG_STATIC
void player_apply_transport_to_cam( m4x3f transport
)
266 /* FIXME: Applies to main_camera directly! */
268 /* Pre-emptively edit the camera matrices so that the motion vectors
272 m4x3_invert_affine( transport
, transport_i
);
273 m4x3_expand( transport_i
, transport_4
);
274 m4x4_mul( main_camera
.mtx
.pv
, transport_4
, main_camera
.mtx
.pv
);
275 m4x4_mul( main_camera
.mtx
.v
, transport_4
, main_camera
.mtx
.v
);
279 * Applies gate transport to a player_interface
282 void player_pass_gate( player_interface
*player
, teleport_gate
*gate
)
284 player
->gate_waiting
= gate
;
287 VG_STATIC
void player_post_update( player_interface
*player
)
289 player_device
*dev
= player
->devices
[ player
->active_device
];
290 dev
->event( dev
, player
, k_player_device_event_post_update
, NULL
);
293 VG_STATIC
void player_pre_render( player_interface
*player
)
295 player_device
*dev
= player
->devices
[ player
->active_device
];
296 dev
->event( dev
, player
, k_player_device_event_animate
, NULL
);
298 /* TODO: eventually, blending code goes here */
301 q_m3x3( dev
->pose_root_q
, transform
);
302 v3_copy( dev
->pose_root_co
, transform
[3] );
304 struct skeleton
*sk
= &player
->playeravatar
->sk
;
306 skeleton_apply_pose( sk
, dev
->pose
, k_anim_apply_defer_ik
);
307 skeleton_apply_ik_pass( sk
);
308 skeleton_apply_pose( sk
, dev
->pose
, k_anim_apply_deffered_only
);
309 skeleton_apply_inverses( sk
);
310 skeleton_apply_transform( sk
, transform
);
311 skeleton_debug( sk
);
314 if( player
->dev
.device
->pose
)
316 player
->dev
.device
->pose( player
, &player
->dev
, pose
, transform
);
318 struct skeleton
*sk
= &player
->playeravatar
->sk
;
320 skeleton_apply_pose( sk
, pose
, k_anim_apply_defer_ik
);
321 skeleton_apply_ik_pass( sk
);
322 skeleton_apply_pose( sk
, pose
, k_anim_apply_deffered_only
);
323 skeleton_apply_inverses( sk
);
324 skeleton_apply_transform( sk
, transform
);
325 skeleton_debug( sk
);
329 dev
->event( dev
, player
, k_player_device_event_post_animate
, NULL
);
331 /* TODO: eventually, blending code goes here */
333 float camera_blend_target
= 1.0f
;
334 if( player
->camera_mode
== k_camera_mode_firstperson
)
335 camera_blend_target
= 0.0f
;
337 player
->camera_type_blend
= vg_lerpf( player
->camera_type_blend
,
339 5.0f
* vg
.frame_delta
);
341 float t
= player
->camera_type_blend
;
342 camera_lerp( &dev
->cam_1st
, &dev
->cam_3rd
, t
, &player
->cam
);
343 player
->cam
.fov
= vg_lerpf( 118.0f
, 90.0f
, t
);
345 if( player
->gate_waiting
)
347 /* construct plane equation for reciever gate */
349 q_mulv( player
->gate_waiting
->q
[1], (v3f
){0.0f
,0.0f
,1.0f
}, plane
);
350 plane
[3] = v3_dot( plane
, player
->gate_waiting
->co
[1] );
352 /* check camera polarity */
353 if( v3_dot( player
->cam
.pos
, plane
) < plane
[3] )
355 vg_success( "Plane cleared\n" );
356 player_apply_transport_to_cam( player
->gate_waiting
->transport
);
357 player
->gate_waiting
= NULL
;
361 /* de-transform camera and player back */
363 m4x3_invert_affine( player
->gate_waiting
->transport
, inverse
);
364 m4x3_mulv( inverse
, player
->cam
.pos
, player
->cam
.pos
);
366 /* TODO: Find robust method for this */
367 v3f fwd_dir
= { cosf(player
->cam
.angles
[0]),
369 sinf(player
->cam
.angles
[0])};
370 m3x3_mulv( inverse
, fwd_dir
, fwd_dir
);
371 player
->cam
.angles
[0] = atan2f( fwd_dir
[2], fwd_dir
[0] );
373 skeleton_apply_transform( sk
, inverse
);
378 v3_copy( player
->dev
.cam_1st
.pos
, player
->cam
.pos
);
379 v3_copy( player
->dev
.cam_1st
.angles
, player
->cam
.angles
);
380 player
->cam
.fov
= player
->dev
.cam_1st
.fov
;
384 VG_STATIC
void player_render( camera
*cam
, player_interface
*player
)
386 shader_viewchar_use();
387 vg_tex2d_bind( &tex_characters
, 0 );
388 shader_viewchar_uTexMain( 0 );
389 shader_viewchar_uCamera( cam
->transform
[3] );
390 shader_viewchar_uPv( cam
->mtx
.pv
);
391 shader_link_standard_ub( _shader_viewchar
.id
, 2 );
392 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms
,
393 player
->playeravatar
->sk
.bone_count
,
395 (float *)player
->playeravatar
->sk
.final_mtx
);
397 mesh_bind( player
->playermesh
);
398 mesh_draw( player
->playermesh
);
401 VG_STATIC
void player_debugtext( int size
, const char *fmt
, ... )
406 va_start( args
, fmt
);
407 vsnprintf( buffer
, 1024, fmt
, args
);
410 ui_text( vg_uictx
.cursor
, buffer
, size
, k_text_align_right
);
411 vg_uictx
.cursor
[1] += 14*size
;
414 VG_STATIC
void player_ui( player_interface
*player
)
416 /* TODO: if debugger enabled */
417 player_device
*dev
= player
->devices
[ player
->active_device
];
419 vg_uictx
.cursor
[0] = vg
.window_x
- 200;
420 vg_uictx
.cursor
[1] = 0;
421 vg_uictx
.cursor
[2] = 200;
422 vg_uictx
.cursor
[3] = 200;
424 struct ui_vert
*b
= ui_fill_rect( vg_uictx
.cursor
, 0x70000000 );
426 vg_uictx
.cursor
[0] = vg
.window_x
;
427 dev
->event( dev
, player
, k_player_device_event_debug_ui
, NULL
);
429 b
[2].co
[1] = vg_uictx
.cursor
[1];
430 b
[3].co
[1] = vg_uictx
.cursor
[1];
433 VG_STATIC
void player_spawn( player_interface
*player
,
434 struct respawn_point
*rp
)
436 player_device
*dev
= player
->devices
[ player
->active_device
];
437 v3_copy( rp
->co
, player
->rb
.co
);
439 v3_copy( rp
->co
, player
->prev_position
);
441 v3_zero( player
->rb
.v
);
442 v3_zero( player
->rb
.w
);
443 q_identity( player
->rb
.q
);
444 rb_update_transform( &player
->rb
);
446 dev
->event( dev
, player
, k_player_device_event_respawn
, rp
);
450 VG_STATIC
void player_kill( player_interface
*player
)
456 * Apply per render-frame mouse look from player to angles
459 void player_look( player_interface
*player
, v3f angles
)
462 v2_muladds( angles
, vg
.mouse_delta
, 0.0025f
, angles
);
464 if( vg_input
.controller_should_use_trackpad_look
)
466 static v2f last_input
;
468 static v2f vel_smooth
;
470 v2f input
= { player
->input_js2h
->axis
.value
,
471 player
->input_js2v
->axis
.value
};
473 if( (v2_length2(last_input
) > 0.001f
) && (v2_length2(input
) > 0.001f
) )
475 v2_sub( input
, last_input
, vel
);
476 v2_muls( vel
, 1.0f
/vg
.time_delta
, vel
);
483 v2_lerp( vel_smooth
, vel
, vg
.time_delta
*8.0f
, vel_smooth
);
485 v2_muladds( angles
, vel_smooth
, vg
.time_delta
, angles
);
486 v2_copy( input
, last_input
);
490 angles
[0] += player
->input_js2h
->axis
.value
* vg
.time_delta
* 4.0f
;
491 angles
[1] += player
->input_js2v
->axis
.value
* vg
.time_delta
* 4.0f
;
494 angles
[1] = vg_clampf( angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
497 #endif /* PLAYER_INTERFACE_H */