e4711634a218e6f3e79c60a105c4165ed070777c
[carveJwlIkooP6JGAAIwe30JlM.git] / player_ragdoll.h
1 #ifndef PLAYER_RAGDOLL_H
2 #define PLAYER_RAGDOLL_H
3
4 #define VG_GAME
5 #include "vg/vg.h"
6 #include "skeleton.h"
7 #include "rigidbody.h"
8 #include "player_model.h"
9 #include "world.h"
10 #include "audio.h"
11
12 struct player_ragdoll
13 {
14 struct ragdoll_part
15 {
16 u32 bone_id;
17
18 /* Collider transform relative to bone */
19 m4x3f collider_mtx,
20 inv_collider_mtx;
21
22 u32 use_limits;
23 v3f limits[2];
24
25 rigidbody rb;
26 u32 parent;
27 u32 colour;
28 }
29 parts[32];
30 u32 part_count;
31
32 rb_constr_pos position_constraints[32];
33 u32 position_constraints_count;
34
35 rb_constr_swingtwist cone_constraints[32];
36 u32 cone_constraints_count;
37
38 int shoes[2];
39 };
40
41 VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
42 struct ragdoll_part *rp )
43 {
44 m4x3_identity( rp->collider_mtx );
45
46 if( bone->collider == k_bone_collider_box ){
47 v3f delta;
48 v3_sub( bone->hitbox[1], bone->hitbox[0], delta );
49 v3_muls( delta, 0.5f, delta );
50 v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] );
51
52 v3_copy( delta, rp->rb.bbx[1] );
53 v3_muls( delta, -1.0f, rp->rb.bbx[0] );
54
55 q_identity( rp->rb.q );
56 rp->rb.type = k_rb_shape_box;
57 rp->colour = 0xffcccccc;
58 }
59 else if( bone->collider == k_bone_collider_capsule ){
60 v3f v0, v1, tx, ty;
61 v3_sub( bone->hitbox[1], bone->hitbox[0], v0 );
62
63 int major_axis = 0;
64 float largest = -1.0f;
65
66 for( int i=0; i<3; i ++ ){
67 if( fabsf( v0[i] ) > largest ){
68 largest = fabsf( v0[i] );
69 major_axis = i;
70 }
71 }
72
73 v3_zero( v1 );
74 v1[ major_axis ] = 1.0f;
75 rb_tangent_basis( v1, tx, ty );
76
77 float r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f,
78 l = fabsf(v0[ major_axis ]);
79
80 /* orientation */
81 v3_muls( tx, -1.0f, rp->collider_mtx[0] );
82 v3_muls( v1, -1.0f, rp->collider_mtx[1] );
83 v3_muls( ty, -1.0f, rp->collider_mtx[2] );
84 v3_add( bone->hitbox[0], bone->hitbox[1], rp->collider_mtx[3] );
85 v3_muls( rp->collider_mtx[3], 0.5f, rp->collider_mtx[3] );
86
87 rp->rb.type = k_rb_shape_capsule;
88 rp->rb.inf.capsule.height = l;
89 rp->rb.inf.capsule.radius = r;
90
91 rp->colour = 0xff000000 | (0xff << (major_axis*8));
92 }
93 else{
94 vg_warn( "type: %u\n", bone->collider );
95 vg_fatal_exit_loop( "Invalid bone collider type" );
96 }
97
98 m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx );
99
100 /* Position collider into rest */
101 m3x3_q( rp->collider_mtx, rp->rb.q );
102 v3_add( rp->collider_mtx[3], bone->co, rp->rb.co );
103 rp->rb.is_world = 0;
104 rb_init( &rp->rb );
105 }
106
107 /*
108 * Get parent index in the ragdoll
109 */
110 VG_STATIC u32 ragdoll_bone_parent( struct player_ragdoll *rd,
111 struct player_avatar *av, u32 bone_id )
112 {
113 for( u32 j=0; j<rd->part_count; j++ )
114 if( rd->parts[ j ].bone_id == bone_id )
115 return j;
116
117 vg_fatal_exit_loop( "Referenced parent bone does not have a rigidbody" );
118 return 0;
119 }
120
121 /*
122 * Setup ragdoll colliders
123 */
124 VG_STATIC void player_setup_ragdoll_from_avatar( struct player_ragdoll *rd,
125 struct player_avatar *av )
126 {
127 rd->part_count = 0;
128
129 if( !av->sk.collider_count )
130 return;
131
132 rd->position_constraints_count = 0;
133 rd->cone_constraints_count = 0;
134
135 for( u32 i=1; i<av->sk.bone_count; i ++ ){
136 struct skeleton_bone *bone = &av->sk.bones[i];
137
138 /*
139 * Bones with colliders
140 */
141 if( !(bone->collider) )
142 continue;
143
144 if( rd->part_count > vg_list_size(rd->parts) )
145 vg_fatal_exit_loop( "Playermodel has too many colliders" );
146
147 struct ragdoll_part *rp = &rd->parts[ rd->part_count ++ ];
148 rp->bone_id = i;
149 rp->parent = 0xffffffff;
150
151 player_init_ragdoll_bone_collider( bone, rp );
152
153 /*
154 * Bones with collider and parent
155 */
156 if( !bone->parent )
157 continue;
158
159 rp->parent = ragdoll_bone_parent( rd, av, bone->parent );
160
161
162 if( bone->orig_bone->flags & k_bone_flag_cone_constraint ){
163 struct rb_constr_pos *c =
164 &rd->position_constraints[ rd->position_constraints_count ++ ];
165
166 struct skeleton_bone *bj = &av->sk.bones[rp->bone_id];
167 struct ragdoll_part *pp = &rd->parts[rp->parent];
168 struct skeleton_bone *bp = &av->sk.bones[pp->bone_id];
169
170 /* Convention: rba -- parent, rbb -- child */
171 c->rba = &pp->rb;
172 c->rbb = &rp->rb;
173
174 v3f delta;
175 v3_sub( bj->co, bp->co, delta );
176 m4x3_mulv( rp->inv_collider_mtx, (v3f){0.0f,0.0f,0.0f}, c->lcb );
177 m4x3_mulv( pp->inv_collider_mtx, delta, c->lca );
178
179
180 mdl_bone *inf = bone->orig_bone;
181
182 struct rb_constr_swingtwist *a =
183 &rd->cone_constraints[ rd->cone_constraints_count ++ ];
184
185 a->rba = &pp->rb;
186 a->rbb = &rp->rb;
187 a->conet = cosf( inf->conet )-0.0001f;
188
189 /* Store constraint in local space vectors */
190 m3x3_mulv( c->rba->to_local, inf->conevx, a->conevx );
191 m3x3_mulv( c->rba->to_local, inf->conevy, a->conevy );
192 m3x3_mulv( c->rbb->to_local, inf->coneva, a->coneva );
193 v3_copy( c->lca, a->view_offset );
194
195 v3_cross( inf->coneva, inf->conevy, a->conevxb );
196 m3x3_mulv( c->rbb->to_local, a->conevxb, a->conevxb );
197
198 v3_normalize( a->conevxb );
199 v3_normalize( a->conevx );
200 v3_normalize( a->conevy );
201 v3_normalize( a->coneva );
202
203 a->conevx[3] = v3_length( inf->conevx );
204 a->conevy[3] = v3_length( inf->conevy );
205
206 rp->use_limits = 1;
207 }
208 }
209 }
210
211 /*
212 * Make avatar copy the ragdoll
213 */
214 VG_STATIC void copy_ragdoll_pose_to_avatar( struct player_ragdoll *rd,
215 struct player_avatar *av )
216 {
217 for( int i=0; i<rd->part_count; i++ ){
218 struct ragdoll_part *part = &rd->parts[i];
219 m4x3f offset;
220 m3x3_identity(offset);
221 m4x3_mul( part->rb.to_world, part->inv_collider_mtx,
222 av->sk.final_mtx[part->bone_id] );
223 }
224
225 for( u32 i=1; i<av->sk.bone_count; i++ ){
226 struct skeleton_bone *sb = &av->sk.bones[i];
227
228 if( sb->parent && !sb->collider ){
229 v3f delta;
230 v3_sub( av->sk.bones[i].co, av->sk.bones[sb->parent].co, delta );
231
232 m4x3f posemtx;
233 m3x3_identity( posemtx );
234 v3_copy( delta, posemtx[3] );
235
236 /* final matrix */
237 m4x3_mul( av->sk.final_mtx[sb->parent], posemtx, av->sk.final_mtx[i] );
238 }
239 }
240
241 skeleton_apply_inverses( &av->sk );
242 }
243
244 /*
245 * Make the ragdoll copy the player model
246 */
247 VG_STATIC void copy_avatar_pose_to_ragdoll( struct player_avatar *av,
248 struct player_ragdoll *rd,
249 v3f velocity )
250 {
251 for( int i=0; i<rd->part_count; i++ ){
252 struct ragdoll_part *part = &rd->parts[i];
253
254 v3f pos, offset;
255 u32 bone = part->bone_id;
256
257 m4x3_mulv( av->sk.final_mtx[bone], av->sk.bones[bone].co, pos );
258 m3x3_mulv( av->sk.final_mtx[bone], part->collider_mtx[3], offset );
259 v3_add( pos, offset, part->rb.co );
260
261 m3x3f r;
262 m3x3_mul( av->sk.final_mtx[bone], part->collider_mtx, r );
263 m3x3_q( r, part->rb.q );
264
265 v3_copy( velocity, part->rb.v );
266 v3_zero( part->rb.w );
267
268 rb_update_transform( &part->rb );
269 }
270 }
271
272 /*
273 * Draw rigidbody colliders for ragdoll
274 */
275 VG_STATIC void player_debug_ragdoll(void)
276 {
277 }
278
279 /*
280 * Ragdoll physics step
281 */
282 VG_STATIC void player_ragdoll_iter( struct player_ragdoll *rd )
283 {
284 world_instance *world = get_active_world();
285
286 int run_sim = 0;
287 ragdoll_frame ++;
288
289 if( ragdoll_frame >= k_ragdoll_div ){
290 ragdoll_frame = 0;
291 run_sim = 1;
292 }
293
294 rb_solver_reset();
295
296 float contact_velocities[256];
297
298 for( int i=0; i<rd->part_count; i ++ ){
299 if( rb_global_has_space() ){
300 rb_ct *buf = rb_global_buffer();
301
302 int l;
303
304 if( rd->parts[i].rb.type == k_rb_shape_capsule ){
305 l = rb_capsule__scene( rd->parts[i].rb.to_world,
306 &rd->parts[i].rb.inf.capsule,
307 NULL, &world->rb_geo.inf.scene, buf );
308 }
309 else if( rd->parts[i].rb.type == k_rb_shape_box ){
310 l = rb_box__scene( rd->parts[i].rb.to_world,
311 rd->parts[i].rb.bbx,
312 NULL, &world->rb_geo.inf.scene, buf );
313 }
314 else continue;
315
316 for( int j=0; j<l; j++ ){
317 buf[j].rba = &rd->parts[i].rb;
318 buf[j].rbb = &world->rb_geo;
319 }
320
321 rb_contact_count += l;
322 }
323 }
324
325 /*
326 * self-collision
327 */
328 for( int i=0; i<rd->part_count-1; i ++ ){
329 for( int j=i+1; j<rd->part_count; j ++ ){
330 if( rd->parts[j].parent != i ){
331 if( !rb_global_has_space() )
332 break;
333
334 if( rd->parts[j].rb.type != k_rb_shape_capsule )
335 continue;
336
337 if( rd->parts[i].rb.type != k_rb_shape_capsule )
338 continue;
339
340 rb_ct *buf = rb_global_buffer();
341
342 int l = rb_capsule__capsule( rd->parts[i].rb.to_world,
343 &rd->parts[i].rb.inf.capsule,
344 rd->parts[j].rb.to_world,
345 &rd->parts[j].rb.inf.capsule,
346 buf );
347
348 for( int k=0; k<l; k++ ){
349 buf[k].rba = &rd->parts[i].rb;
350 buf[k].rbb = &rd->parts[j].rb;
351 }
352
353 rb_contact_count += l;
354 }
355 }
356 }
357
358 for( int j=0; j<rd->part_count; j++ ){
359 struct ragdoll_part *pj = &rd->parts[j];
360
361 if( run_sim ){
362 v4f plane = {0.0f,1.0f,0.0f,0.0f};
363 rb_effect_simple_bouyency( &pj->rb, plane, k_ragdoll_floatyiness,
364 k_ragdoll_floatydrag );
365 }
366 }
367
368 /*
369 * PRESOLVE
370 */
371 for( u32 i=0; i<rb_contact_count; i++ ){
372 rb_ct *ct = &rb_contact_buffer[i];
373
374 v3f rv, ra, rb;
375 v3_sub( ct->co, ct->rba->co, ra );
376 v3_sub( ct->co, ct->rbb->co, rb );
377 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
378 float vn = v3_dot( rv, ct->n );
379
380 contact_velocities[i] = vn;
381 }
382
383 rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
384 rb_presolve_swingtwist_constraints( rd->cone_constraints,
385 rd->cone_constraints_count );
386
387 /*
388 * DEBUG
389 */
390 if( k_ragdoll_debug_collider ){
391 for( u32 i=0; i<rd->part_count; i ++ )
392 rb_debug( &rd->parts[i].rb, rd->parts[i].colour );
393 }
394
395 if( k_ragdoll_debug_constraints ){
396 rb_debug_position_constraints( rd->position_constraints,
397 rd->position_constraints_count );
398
399 rb_debug_swingtwist_constraints( rd->cone_constraints,
400 rd->cone_constraints_count );
401 }
402
403 /*
404 * SOLVE CONSTRAINTS
405 */
406 if( run_sim ){
407 for( int i=0; i<16; i++ ){
408 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
409 rb_solve_swingtwist_constraints( rd->cone_constraints,
410 rd->cone_constraints_count );
411 rb_solve_position_constraints( rd->position_constraints,
412 rd->position_constraints_count );
413 }
414
415 for( int i=0; i<rd->part_count; i++ )
416 rb_iter( &rd->parts[i].rb );
417
418 for( int i=0; i<rd->part_count; i++ )
419 rb_update_transform( &rd->parts[i].rb );
420
421 rb_correct_swingtwist_constraints( rd->cone_constraints,
422 rd->cone_constraints_count, 0.25f );
423
424 rb_correct_position_constraints( rd->position_constraints,
425 rd->position_constraints_count, 0.5f );
426 }
427
428 rb_ct *stress = NULL;
429 float max_stress = 1.0f;
430
431 for( u32 i=0; i<rb_contact_count; i++ ){
432 rb_ct *ct = &rb_contact_buffer[i];
433
434 v3f rv, ra, rb;
435 v3_sub( ct->co, ct->rba->co, ra );
436 v3_sub( ct->co, ct->rbb->co, rb );
437 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
438 float vn = v3_dot( rv, ct->n );
439
440 float s = fabsf(vn - contact_velocities[i]);
441 if( s > max_stress ){
442 stress = ct;
443 max_stress = s;
444 }
445 }
446
447 static u32 temp_filter = 0;
448
449 if( temp_filter ){
450 temp_filter --;
451 return;
452 }
453
454 if( stress ){
455 temp_filter = 20;
456 audio_lock();
457 audio_oneshot_3d( &audio_hits[rand()%5], stress->co, 20.0f, 1.0f );
458 audio_unlock();
459 }
460 }
461
462 #endif /* PLAYER_RAGDOLL_H */