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