df shadows
[carveJwlIkooP6JGAAIwe30JlM.git] / player_physics_walk.h
1 /*
2 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #define PLAYER_PHYSICS_WALK_H
6 #ifndef PLAYER_PHYSICS_WALK_H
7 #define PLAYER_PHYSICS_WALK_H
8
9 #include "player.h"
10 #include "camera.h"
11
12 VG_STATIC struct player_walk
13 {
14 struct
15 {
16 enum walk_activityaaaaaa
17 {
18 k_walk_activity_airaaaa,
19 k_walk_activity_groundaaaaaa
20 }
21 activity;
22 }
23 state;
24
25 rigidbody capsule; /* TODO: rigidbody::collider_capsule */
26 }
27 player_walky =
28 {
29 .capsule = { .inf.capsule.height = 2.0f, .inf.capsule.radius = 0.3f }
30 };
31
32 VG_STATIC void player_walk_collider_configuration(void)
33 {
34 v3_add( player.rb.co, (v3f){0.0f,1.0f,0.0f}, player_walky.capsule.co );
35 rb_update_transform( &player_walky.capsule );
36
37 #if 0
38 float h0 = 0.3f,
39 h1 = 0.9f;
40
41 rigidbody *rbf = &player.collide_front,
42 *rbb = &player.collide_back;
43
44 v3_add( phys->rb.co, (v3f){0.0f,h0,0.0f}, rbf->co );
45 v3_add( phys->rb.co, (v3f){0.0f,h1,0.0f}, rbb->co );
46 v3_copy( rbf->co, rbf->to_world[3] );
47 v3_copy( rbb->co, rbb->to_world[3] );
48 m4x3_invert_affine( rbf->to_world, rbf->to_local );
49 m4x3_invert_affine( rbb->to_world, rbb->to_local );
50
51 rb_update_bounds( rbf );
52 rb_update_bounds( rbb );
53 #endif
54 }
55
56 __attribute__ ((deprecated))
57 VG_STATIC int player_walk_surface_standable( v3f n )
58 {
59 return v3_dot( n, (v3f){0.0f,1.0f,0.0f} ) > 0.5f;
60 }
61
62 __attribute__ ((deprecated))
63 VG_STATIC void player_walk_stepdown( struct player_walk *w )
64 {
65 float max_dist = 0.4f;
66
67 v3f pa, pb;
68 v3_copy( player.rb.co, pa );
69 pa[1] += 0.3f;
70
71 v3_muladds( pa, (v3f){0.01f,1.0f,0.01f}, -max_dist, pb );
72 vg_line( pa, pb, 0xff000000 );
73
74 /* TODO: Make #define */
75 float r = 0.3f,
76 t;
77
78 v3f n;
79 if( spherecast_world( pa, pb, r, &t, n ) != -1 )
80 {
81 if( player_walk_surface_standable( n ) )
82 {
83 w->state.activity = k_walk_activity_ground;
84 v3_lerp( pa, pb, t+0.001f, player.rb.co );
85 player.rb.co[1] -= 0.3f;
86 }
87 }
88 }
89
90 __attribute__ ((deprecated))
91 VG_STATIC void player_walk_physics( struct player_walk *w )
92 {
93 v3_zero( player.rb.w );
94 q_axis_angle( player.rb.q, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] );
95
96 rb_ct manifold[64];
97 int len;
98
99 v3f forward_dir = { sinf(player.angles[0]),0.0f,-cosf(player.angles[0]) };
100 v3f right_dir = { -forward_dir[2], 0.0f, forward_dir[0] };
101
102 v2f walk = { player.input_walkh->axis.value,
103 player.input_walkv->axis.value };
104
105 if( freecam )
106 v2_zero( walk );
107
108 if( v2_length2(walk) > 0.001f )
109 v2_normalize_clamp( walk );
110
111 if( w->state.activity == k_walk_activity_air )
112 {
113 player_walk_collider_configuration();
114
115 /* allow player to accelerate a bit */
116 v3f walk_3d;
117 v3_muls( forward_dir, walk[1], walk_3d );
118 v3_muladds( walk_3d, right_dir, walk[0], walk_3d );
119
120 float current_vel = fabsf(v3_dot( walk_3d, player.rb.v )),
121 new_vel = current_vel + VG_TIMESTEP_FIXED*999999.0f,
122 clamped_new = vg_clampf( new_vel, 0.0f, k_walkspeed ),
123 vel_diff = vg_maxf( 0.0f, clamped_new - current_vel );
124
125 v3_muladds( player.rb.v, right_dir, walk[0] * vel_diff, player.rb.v );
126 v3_muladds( player.rb.v, forward_dir, walk[1] * vel_diff, player.rb.v );
127
128 len = rb_capsule_scene( &w->capsule, &world.rb_geo, manifold );
129 rb_presolve_contacts( manifold, len );
130
131 for( int i=0; i<len; i++ )
132 {
133 struct contact *ct = &manifold[i];
134 if( v3_dot( ct->n, (v3f){0.0f,1.0f,0.0f} ) > 0.5f )
135 w->state.activity = k_walk_activity_ground;
136 }
137
138 /*
139 * TODO: Compression
140 */
141 for( int j=0; j<5; j++ )
142 {
143 for( int i=0; i<len; i++ )
144 {
145 struct contact *ct = &manifold[i];
146
147 /*normal */
148 float vn = -v3_dot( player.rb.v, ct->n );
149 vn += ct->bias;
150
151 float temp = ct->norm_impulse;
152 ct->norm_impulse = vg_maxf( temp + vn, 0.0f );
153 vn = ct->norm_impulse - temp;
154
155 v3f impulse;
156 v3_muls( ct->n, vn, impulse );
157
158 v3_add( impulse, player.rb.v, player.rb.v );
159
160 /* friction */
161 for( int j=0; j<2; j++ )
162 {
163 float f = k_friction * ct->norm_impulse,
164 vt = v3_dot( player.rb.v, ct->t[j] ),
165 lambda = -vt;
166
167 float temp = ct->tangent_impulse[j];
168 ct->tangent_impulse[j] = vg_clampf( temp + lambda, -f, f );
169 lambda = ct->tangent_impulse[j] - temp;
170
171 v3_muladds( player.rb.v, ct->t[j], lambda, player.rb.v );
172 }
173 }
174 }
175
176 player.rb.v[1] += -k_gravity * k_rb_delta;
177 v3_muladds( player.rb.co, player.rb.v, k_rb_delta, player.rb.co );
178 }
179 else
180 {
181 player.walk = v2_length( walk );
182
183 if( player.input_walk->button.value )
184 v2_muls( walk, 0.5f, walk );
185
186 v2_muls( walk, k_walkspeed * VG_TIMESTEP_FIXED, walk );
187
188 /* Do XY translation */
189 v3f walk_apply, walk_measured;
190 v3_zero( walk_apply );
191 v3_muladds( walk_apply, right_dir, walk[0], walk_apply );
192 v3_muladds( walk_apply, forward_dir, walk[1], walk_apply );
193 v3_add( walk_apply, player.rb.co, player.rb.co );
194
195 /* Directly resolve collisions */
196 player_walk_collider_configuration();
197 len = rb_capsule_scene( &w->capsule, &world.rb_geo, manifold );
198
199 v3f dt;
200 v3_zero( dt );
201 for( int j=0; j<8; j++ )
202 {
203 for( int i=0; i<len; i++ )
204 {
205 struct contact *ct = &manifold[i];
206
207 float resolved_amt = v3_dot( ct->n, dt ),
208 remaining = (ct->p-k_penetration_slop) - resolved_amt,
209 apply = vg_maxf( remaining, 0.0f ) * 0.3f;
210
211 v3_muladds( dt, ct->n, apply, dt );
212 }
213 }
214 v3_add( dt, player.rb.co, player.rb.co );
215
216 v3_add( dt, walk_apply, walk_measured );
217 v3_divs( walk_measured, VG_TIMESTEP_FIXED, player.rb.v );
218
219 if( len )
220 {
221 struct world_material *surface_mat = world_contact_material(manifold);
222 player.surface_prop = surface_mat->info.surface_prop;
223 }
224
225 w->state.activity = k_walk_activity_air;
226
227 /* jump */
228 if( player.input_jump->button.value )
229 {
230 player.rb.v[1] = 5.0f;
231 return;
232 }
233
234 /* Check if grounded by current manifold */
235 for( int i=0; i<len; i++ )
236 {
237 struct contact *ct = &manifold[i];
238 if( player_walk_surface_standable( ct->n ) )
239 w->state.activity = k_walk_activity_ground;
240 }
241
242 /* otherwise... */
243 if( w->state.activity == k_walk_activity_air )
244 player_walk_stepdown( w );
245 }
246 }
247
248 __attribute__ ((deprecated))
249 VG_STATIC void player_walk_animate( void *_w,
250 struct skeleton *sk, player_pose pose )
251 {
252 struct player_walk *w = _w;
253
254 {
255 float fly = (w->state.activity == k_walk_activity_air)? 1.0f: 0.0f,
256 rate;
257
258 if( w->state.activity == k_walk_activity_air )
259 rate = 2.4f;
260 else
261 rate = 9.0f;
262
263 player.ffly = vg_lerpf( player.ffly, fly, rate*vg.time_delta );
264 player.frun = vg_lerpf( player.frun,
265 player.walk *
266 (1.0f + player.input_walk->button.value*0.5f),
267 2.0f*vg.time_delta );
268 }
269
270 player_pose apose, bpose;
271
272 if( player.walk > 0.025f )
273 {
274 /* TODO move */
275 float walk_norm = 30.0f/(float)player.mdl.anim_walk->length,
276 run_norm = 30.0f/(float)player.mdl.anim_run->length,
277 walk_adv = vg_lerpf( walk_norm, run_norm, player.walk );
278
279 player.walk_timer += walk_adv * vg.time_delta;
280 }
281 else
282 {
283 player.walk_timer = 0.0f;
284 }
285
286 float walk_norm = (float)player.mdl.anim_walk->length/30.0f,
287 run_norm = (float)player.mdl.anim_run->length/30.0f,
288 t = player.walk_timer,
289 l = vg_clampf( player.frun*15.0f, 0.0f, 1.0f ),
290 idle_walk = vg_clampf( (player.frun-0.1f)/(1.0f-0.1f), 0.0f, 1.0f );
291
292 /* walk/run */
293 skeleton_sample_anim( sk, player.mdl.anim_walk, t*walk_norm, apose );
294 skeleton_sample_anim( sk, player.mdl.anim_run, t*run_norm, bpose );
295
296 skeleton_lerp_pose( sk, apose, bpose, l, apose );
297
298 /* idle */
299 skeleton_sample_anim( sk, player.mdl.anim_idle, vg.time*0.1f, bpose );
300 skeleton_lerp_pose( sk, apose, bpose, 1.0f-idle_walk, apose );
301
302 /* air */
303 skeleton_sample_anim( sk, player.mdl.anim_jump, vg.time*0.6f, bpose );
304 skeleton_lerp_pose( sk, apose, bpose, player.ffly, apose );
305
306 skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_defer_ik );
307 skeleton_apply_ik_pass( &player.mdl.sk );
308 skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_deffered_only );
309
310 v3_copy( player.mdl.sk.final_mtx[player.mdl.id_head-1][3],
311 player.mdl.cam_pos );
312
313
314
315 skeleton_apply_inverses( &player.mdl.sk );
316
317 m4x3f mtx;
318 v4f rot;
319 q_axis_angle( rot, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] - VG_PIf*0.5f );
320 q_m3x3( rot, mtx );
321 v3_copy( player.visual_transform[3], mtx[3] );
322
323 skeleton_apply_transform( &player.mdl.sk, mtx );
324 skeleton_debug( &player.mdl.sk );
325 }
326
327 #endif /* PLAYER_PHYSICS_WALK_H */