4 #include "player_glide.h"
7 static f32 k_glide_steer
= 2.0f
,
10 k_glide_drag
= 0.0001f
,
11 k_glide_slip_yaw
= 0.1f
,
12 k_glide_lift_pitch
= 0.0f
,
13 k_glide_wing_orient
= -0.1f
,
14 k_glide_balance
= 1.0f
;
16 static i32 k_glide_pause
= 0;
18 static void player_glide_pre_update(void){
21 static void massless_accel( rigidbody
*rb
, v3f delta
, v3f impulse
){
23 v3_muladds( rb
->v
, impulse
, k_rb_delta
, rb
->v
);
25 /* Angular velocity */
27 v3_cross( delta
, impulse
, wa
);
28 v3_muladds( rb
->w
, wa
, k_rb_delta
, rb
->w
);
31 static void calculate_lift( v3f vl
, f32 aoa_bias
,
32 v3f axis
, v3f back
, f32 power
,
35 v3_cross( back
, axis
, up
);
38 v3_muladds( vl
, axis
, -v3_dot(axis
,vl
), wind
);
40 f32 windv2
= v3_length2(wind
),
41 aoa
= atan2f( v3_dot( up
, wind
), v3_dot( back
, wind
) ) + aoa_bias
,
42 cl
= aoa
/ VG_PIf
, /* TODO: make it a curve */
43 L
= windv2
* cl
* power
;
47 v3_cross( wind
, axis
, lift_dir
);
49 /* this is where induced drag (from the flappy things) would go */
51 v3_muls( lift_dir
, L
, out_force
);
54 static void calculate_drag( v3f vl
, f32 cd
, v3f out_force
){
55 f32 v2
= v3_length2( vl
);
59 v3_muls( vl
, -cd
*v2
, out_force
);
62 static void player_glide_update(void){
63 rigidbody
*rb
= &player_glide
.rb
;
66 joystick_state( k_srjoystick_steer
, steer
);
70 m3x3_mulv( rb
->to_local
, rb
->v
, vl
);
71 m3x3_mulv( rb
->to_local
, rb
->w
, wl
);
73 v3f F
, Flift
, Fslip
, Fdrag
, FslipW
, FliftW
;
75 calculate_lift( vl
, steer
[1]*k_glide_steer
,
77 (v3f
){0,sinf(k_glide_wing_orient
),cosf(k_glide_wing_orient
)},
79 v3_copy( Flift
, player_glide
.info_lift
);
80 v3_cross( (v3f
){0,0,0}, Flift
, FliftW
);
82 calculate_lift( vl
, 0.0f
,
83 (v3f
){0,1,0},(v3f
){0,0,1},
85 v3_copy( Fslip
, player_glide
.info_slip
);
86 v3_cross( (v3f
){0,k_glide_lift_pitch
,k_glide_slip_yaw
}, Fslip
, FslipW
);
88 calculate_drag( vl
, k_glide_drag
, Fdrag
);
89 v3_copy( Fdrag
, player_glide
.info_drag
);
91 v3f balance
= {0.0f
,-k_glide_balance
,0.0f
};
92 m3x3_mulv( rb
->to_local
, balance
, balance
);
95 steer
[1]*k_glide_steer
- balance
[2],
97 -steer
[0]*k_glide_steer
+ balance
[0],
100 if( player_glide
.ticker
){
101 player_glide
.ticker
--;
104 player_glide
.ticker
+= k_glide_pause
;
107 v3_add( Flift
, Fslip
, F
);
108 v3_add( F
, Fdrag
, F
);
110 m3x3_mulv( rb
->to_world
, F
, F
);
111 v3_muladds( rb
->v
, F
, k_rb_delta
, rb
->v
);
113 v3_add( Fw
, FslipW
, Fw
);
114 v3_add( Fw
, FliftW
, Fw
);
115 m3x3_mulv( rb
->to_world
, Fw
, Fw
);
116 v3_muladds( rb
->w
, Fw
, k_rb_delta
, rb
->w
);
119 * collisions & constraints
121 world_instance
*world
= world_current_instance();
124 rigidbody _null
= {0};
125 _null
.inv_mass
= 0.0f
;
126 m3x3_zero( _null
.iI
);
127 for( u32 i
=0; i
< vg_list_size(player_glide
.parts
); i
++ ){
129 m4x3_mul( rb
->to_world
, player_glide
.parts
[i
].mdl
, mmdl
);
131 if( player_glide
.parts
[i
].shape
== k_rb_shape_capsule
){
132 vg_line_capsule( mmdl
,
133 player_glide
.parts
[i
].inf
.r
,
134 player_glide
.parts
[i
].inf
.h
,
137 else if( player_glide
.parts
[i
].shape
== k_rb_shape_sphere
){
138 vg_line_sphere( mmdl
, player_glide
.parts
[i
].r
, 0 );
141 if( rb_global_has_space() ){
142 rb_ct
*buf
= rb_global_buffer();
146 if( player_glide
.parts
[i
].shape
== k_rb_shape_capsule
){
147 l
= rb_capsule__scene( mmdl
, &player_glide
.parts
[i
].inf
,
148 NULL
, world
->geo_bh
, buf
,
149 k_material_flag_ghosts
);
151 else if( player_glide
.parts
[i
].shape
== k_rb_shape_sphere
){
152 l
= rb_sphere__scene( mmdl
, player_glide
.parts
[i
].r
,
153 NULL
, world
->geo_bh
, buf
,
154 k_material_flag_ghosts
);
157 for( u32 j
=0; j
<l
; j
++ ){
162 rb_contact_count
+= l
;
166 rb_presolve_contacts( rb_contact_buffer
, rb_contact_count
);
167 for( u32 i
=0; i
<10; i
++ )
168 rb_solve_contacts( rb_contact_buffer
, rb_contact_count
);
171 rb_update_matrices( rb
);
174 static void player_glide_post_update(void){
175 v3_copy( player_glide
.rb
.co
, localplayer
.rb
.co
);
176 v4_copy( player_glide
.rb
.q
, localplayer
.rb
.q
);
177 v3_copy( player_glide
.rb
.v
, localplayer
.rb
.v
);
178 v3_copy( player_glide
.rb
.w
, localplayer
.rb
.w
);
179 rb_update_matrices( &localplayer
.rb
);
182 static void player_glide_animate(void){
183 struct player_glide
*g
= &player_glide
;
184 struct player_glide_animator
*animator
= &g
->animator
;
185 rb_extrapolate( &localplayer
.rb
, animator
->root_co
, animator
->root_q
);
188 static void player_glide_pose( void *_animator
, player_pose
*pose
){
189 struct skeleton
*sk
= &localplayer
.skeleton
;
190 struct player_glide_animator
*animator
= _animator
;
192 skeleton_sample_anim( sk
, player_glide
.anim_temp
, 0.0f
, pose
->keyframes
);
194 v3_copy( animator
->root_co
, pose
->root_co
);
195 v4_copy( animator
->root_q
, pose
->root_q
);
198 static void player_glide_post_animate(void){
199 if( localplayer
.cam_control
.camera_mode
== k_cam_firstperson
)
200 localplayer
.cam_velocity_influence
= 0.0f
;
202 localplayer
.cam_velocity_influence
= 0.0f
;
205 v3_muls( localplayer
.rb
.to_world
[2], -1.0f
, fwd
);
206 v3_angles( fwd
, localplayer
.angles
);
209 static void player_glide_im_gui(void){
210 player__debugtext( 1, "Nothing here" );
211 player__debugtext( 1, " lift: %.2f %.2f %.2f",
212 player_glide
.info_lift
[0],
213 player_glide
.info_lift
[1],
214 player_glide
.info_lift
[2] );
215 player__debugtext( 1, " slip: %.2f %.2f %.2f",
216 player_glide
.info_slip
[0],
217 player_glide
.info_slip
[1],
218 player_glide
.info_slip
[2] );
219 player__debugtext( 1, " drag: %.2f %.2f %.2f",
220 player_glide
.info_drag
[0],
221 player_glide
.info_drag
[1],
222 player_glide
.info_drag
[2] );
225 static void player_glide_bind(void){
226 struct skeleton
*sk
= &localplayer
.skeleton
;
227 player_glide
.anim_temp
= skeleton_get_anim( sk
, "idle_cycle+y" );
229 u32 mask
= VG_VAR_CHEAT
|VG_VAR_PERSISTENT
;
230 VG_VAR_F32( k_glide_steer
, flags
=mask
);
231 VG_VAR_F32( k_glide_cl
, flags
=mask
);
232 VG_VAR_F32( k_glide_cs
, flags
=mask
);
233 VG_VAR_F32( k_glide_drag
, flags
=mask
);
234 VG_VAR_F32( k_glide_slip_yaw
, flags
=mask
);
235 VG_VAR_F32( k_glide_lift_pitch
, flags
=mask
);
236 VG_VAR_I32( k_glide_pause
, flags
=mask
);
237 VG_VAR_F32( k_glide_balance
, flags
=mask
);
238 VG_VAR_F32( k_glide_wing_orient
, flags
=mask
);
242 k_inertia_scale
= 1.0f
;
246 for( u32 i
=0; i
<vg_list_size(player_glide
.parts
); i
++ ){
247 /* create part transform matrix */
249 q_axis_angle( qp
, (v3f
){1,0,0}, player_glide
.parts
[i
].euler
[0] );
250 q_axis_angle( qy
, (v3f
){0,1,0}, player_glide
.parts
[i
].euler
[1] );
251 q_axis_angle( qr
, (v3f
){0,0,1}, player_glide
.parts
[i
].euler
[2] );
256 q_m3x3( q
, player_glide
.parts
[i
].mdl
);
257 v3_copy( player_glide
.parts
[i
].co
, player_glide
.parts
[i
].mdl
[3] );
259 /* add it to inertia model */
261 if( player_glide
.parts
[i
].shape
== k_rb_shape_capsule
){
262 f32 r
= player_glide
.parts
[i
].inf
.r
,
263 h
= player_glide
.parts
[i
].inf
.h
,
264 pv
= vg_capsule_volume( r
, h
),
270 rb_capsule_inertia( r
, h
, pm
, pI
);
271 rb_rotate_inertia( pI
, player_glide
.parts
[i
].mdl
);
272 rb_translate_inertia( pI
, pm
, player_glide
.parts
[i
].co
);
273 m3x3_add( I
, pI
, I
);
275 else if( player_glide
.parts
[i
].shape
== k_rb_shape_sphere
){
276 f32 r
= player_glide
.parts
[i
].r
,
277 pv
= vg_sphere_volume( r
),
282 rb_sphere_inertia( r
, pm
, pI
);
283 rb_translate_inertia( pI
, pm
, player_glide
.parts
[i
].co
);
284 m3x3_add( I
, pI
, I
);
289 m3x3_inv( I
, player_glide
.rb
.iI
);
290 player_glide
.rb
.inv_mass
= 1.0f
/ mass
;
293 #endif /* PLAYER_GLIDE_C */