wrong port
[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 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 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 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 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 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,
208 localplayer.final_mtx[part->bone_id] );
209 }
210
211 for( u32 i=1; i<av->sk.bone_count; i++ ){
212 struct skeleton_bone *sb = &av->sk.bones[i];
213
214 if( sb->parent && !sb->collider ){
215 v3f delta;
216 v3_sub( av->sk.bones[i].co, av->sk.bones[sb->parent].co, delta );
217
218 m4x3f posemtx;
219 m3x3_identity( posemtx );
220 v3_copy( delta, posemtx[3] );
221
222 /* final matrix */
223 m4x3_mul( localplayer.final_mtx[sb->parent], posemtx,
224 localplayer.final_mtx[i] );
225 }
226 }
227
228 skeleton_apply_inverses( &av->sk, localplayer.final_mtx );
229 }
230
231 /*
232 * Make the ragdoll copy the player model
233 */
234 static void copy_avatar_pose_to_ragdoll( struct player_avatar *av,
235 struct player_ragdoll *rd,
236 v3f velocity )
237 {
238 for( int i=0; i<rd->part_count; i++ ){
239 struct ragdoll_part *part = &rd->parts[i];
240
241 v3f pos, offset;
242 u32 bone = part->bone_id;
243
244 m4x3_mulv( localplayer.final_mtx[bone], av->sk.bones[bone].co, pos );
245 m3x3_mulv( localplayer.final_mtx[bone], part->collider_mtx[3], offset );
246 v3_add( pos, offset, part->obj.rb.co );
247
248 m3x3f r;
249 m3x3_mul( localplayer.final_mtx[bone], part->collider_mtx, r );
250 m3x3_q( r, part->obj.rb.q );
251
252 v3_copy( velocity, part->obj.rb.v );
253 v3_zero( part->obj.rb.w );
254
255 v3_copy( part->obj.rb.co, part->prev_co );
256 v4_copy( part->obj.rb.q, part->prev_q );
257
258 rb_update_transform( &part->obj.rb );
259 }
260 }
261
262 /*
263 * Draw rigidbody colliders for ragdoll
264 */
265 static void player_debug_ragdoll(void)
266 {
267 }
268
269 /*
270 * Ragdoll physics step
271 */
272 static void player_ragdoll_iter( struct player_ragdoll *rd ){
273 world_instance *world = world_current_instance();
274
275 int run_sim = 0;
276 ragdoll_frame ++;
277
278 if( ragdoll_frame >= k_ragdoll_div ){
279 ragdoll_frame = 0;
280 run_sim = 1;
281 }
282
283 rb_solver_reset();
284
285 float contact_velocities[256];
286
287 for( int i=0; i<rd->part_count; i ++ ){
288 v4_copy( rd->parts[i].obj.rb.q, rd->parts[i].prev_q );
289 v3_copy( rd->parts[i].obj.rb.co, rd->parts[i].prev_co );
290
291 if( rb_global_has_space() ){
292 rb_ct *buf = rb_global_buffer();
293
294 int l;
295
296 if( rd->parts[i].obj.type == k_rb_shape_capsule ){
297 l = rb_capsule__scene( rd->parts[i].obj.rb.to_world,
298 &rd->parts[i].obj.inf.capsule,
299 NULL, &world->rb_geo.inf.scene, buf,
300 k_material_flag_ghosts );
301 }
302 else if( rd->parts[i].obj.type == k_rb_shape_box ){
303 l = rb_box__scene( rd->parts[i].obj.rb.to_world,
304 rd->parts[i].obj.rb.bbx,
305 NULL, &world->rb_geo.inf.scene, buf,
306 k_material_flag_ghosts );
307 }
308 else continue;
309
310 for( int j=0; j<l; j++ ){
311 buf[j].rba = &rd->parts[i].obj.rb;
312 buf[j].rbb = &world->rb_geo.rb;
313 }
314
315 rb_contact_count += l;
316 }
317 }
318
319 /*
320 * self-collision
321 */
322 for( int i=0; i<rd->part_count-1; i ++ ){
323 for( int j=i+1; j<rd->part_count; j ++ ){
324 if( rd->parts[j].parent != i ){
325 if( !rb_global_has_space() )
326 break;
327
328 if( rd->parts[j].obj.type != k_rb_shape_capsule )
329 continue;
330
331 if( rd->parts[i].obj.type != k_rb_shape_capsule )
332 continue;
333
334 rb_ct *buf = rb_global_buffer();
335
336 int l = rb_capsule__capsule( rd->parts[i].obj.rb.to_world,
337 &rd->parts[i].obj.inf.capsule,
338 rd->parts[j].obj.rb.to_world,
339 &rd->parts[j].obj.inf.capsule,
340 buf );
341
342 for( int k=0; k<l; k++ ){
343 buf[k].rba = &rd->parts[i].obj.rb;
344 buf[k].rbb = &rd->parts[j].obj.rb;
345 }
346
347 rb_contact_count += l;
348 }
349 }
350 }
351
352 if( world->water.enabled ){
353 for( int j=0; j<rd->part_count; j++ ){
354 struct ragdoll_part *pj = &rd->parts[j];
355
356 if( run_sim ){
357 rb_effect_simple_bouyency( &pj->obj.rb, world->water.plane,
358 k_ragdoll_floatyiness,
359 k_ragdoll_floatydrag );
360 }
361 }
362 }
363
364 /*
365 * PRESOLVE
366 */
367 for( u32 i=0; i<rb_contact_count; i++ ){
368 rb_ct *ct = &rb_contact_buffer[i];
369
370 v3f rv, ra, rb;
371 v3_sub( ct->co, ct->rba->co, ra );
372 v3_sub( ct->co, ct->rbb->co, rb );
373 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
374 float vn = v3_dot( rv, ct->n );
375
376 contact_velocities[i] = vn;
377 }
378
379 rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
380 rb_presolve_swingtwist_constraints( rd->cone_constraints,
381 rd->cone_constraints_count );
382
383 /*
384 * DEBUG
385 */
386 if( k_ragdoll_debug_collider ){
387 for( u32 i=0; i<rd->part_count; i ++ )
388 rb_object_debug( &rd->parts[i].obj, rd->parts[i].colour );
389 }
390
391 if( k_ragdoll_debug_constraints ){
392 rb_debug_position_constraints( rd->position_constraints,
393 rd->position_constraints_count );
394
395 rb_debug_swingtwist_constraints( rd->cone_constraints,
396 rd->cone_constraints_count );
397 }
398
399 /*
400 * SOLVE CONSTRAINTS
401 */
402 if( run_sim ){
403 for( int i=0; i<16; i++ ){
404 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
405 rb_solve_swingtwist_constraints( rd->cone_constraints,
406 rd->cone_constraints_count );
407 rb_solve_position_constraints( rd->position_constraints,
408 rd->position_constraints_count );
409 }
410
411 for( int i=0; i<rd->part_count; i++ )
412 rb_iter( &rd->parts[i].obj.rb );
413
414 for( int i=0; i<rd->part_count; i++ )
415 rb_update_transform( &rd->parts[i].obj.rb );
416
417 rb_correct_swingtwist_constraints( rd->cone_constraints,
418 rd->cone_constraints_count, 0.25f );
419
420 rb_correct_position_constraints( rd->position_constraints,
421 rd->position_constraints_count, 0.5f );
422 }
423
424 rb_ct *stress = NULL;
425 float max_stress = 1.0f;
426
427 for( u32 i=0; i<rb_contact_count; i++ ){
428 rb_ct *ct = &rb_contact_buffer[i];
429
430 v3f rv, ra, rb;
431 v3_sub( ct->co, ct->rba->co, ra );
432 v3_sub( ct->co, ct->rbb->co, rb );
433 rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
434 float vn = v3_dot( rv, ct->n );
435
436 float s = fabsf(vn - contact_velocities[i]);
437 if( s > max_stress ){
438 stress = ct;
439 max_stress = s;
440 }
441 }
442
443 static u32 temp_filter = 0;
444
445 if( temp_filter ){
446 temp_filter --;
447 return;
448 }
449
450 if( stress ){
451 temp_filter = 20;
452 audio_lock();
453 audio_oneshot_3d( &audio_hits[vg_randu32()%5], stress->co, 20.0f, 1.0f );
454 audio_unlock();
455 }
456 }
457
458 #endif /* PLAYER_RAGDOLL_C */