well yeah i guess
[carveJwlIkooP6JGAAIwe30JlM.git] / player_ragdoll.h
1 #ifndef PLAYER_RAGDOLL_H
2 #define PLAYER_RAGDOLL_H
3
4 #include "player.h"
5
6 VG_STATIC float k_ragdoll_floatyiness = 20.0f,
7 k_ragdoll_floatydrag = 1.0f;
8
9 /*
10 * Setup ragdoll colliders
11 */
12 VG_STATIC void player_init_ragdoll(void)
13 {
14 struct player_model *mdl = &player.mdl;
15 mdl_context *src = &mdl->meta;
16
17 if( !mdl->sk.collider_count )
18 {
19 mdl->ragdoll_count = 0;
20 return;
21 }
22
23 mdl->ragdoll_count = 0;
24
25 for( u32 i=0; i<mdl->sk.bone_count; i ++ )
26 {
27 struct skeleton_bone *bone = &mdl->sk.bones[i];
28
29 if( bone->collider )
30 {
31 if( mdl->ragdoll_count > vg_list_size(player.mdl.ragdoll) )
32 vg_fatal_exit_loop( "Playermodel has too many colliders" );
33
34 struct ragdoll_part *rp = &mdl->ragdoll[ mdl->ragdoll_count ++ ];
35 rp->bone_id = i;
36
37 v3f delta;
38 v3_sub( bone->hitbox[1], bone->hitbox[0], delta );
39 v3_muls( delta, 0.5f, delta );
40
41 v3_add( bone->hitbox[0], delta, rp->offset );
42
43 v3_copy( delta, rp->rb.bbx[1] );
44 v3_muls( delta, -1.0f, rp->rb.bbx[0] );
45
46 q_identity( rp->rb.q );
47 v3_add( bone->co, rp->offset, rp->rb.co );
48 rp->rb.type = k_rb_shape_box;
49 rp->rb.is_world = 0;
50 rp->parent = 0xffffffff;
51
52 if( bone->parent )
53 {
54 for( u32 j=0; j<mdl->ragdoll_count; j++ )
55 {
56 if( mdl->ragdoll[ j ].bone_id == bone->parent )
57 {
58 rp->parent = j;
59 break;
60 }
61 }
62 }
63
64 struct mdl_node *pnode = mdl_node_from_id( src, bone->orig_node );
65 struct classtype_bone *bone_inf = mdl_get_entdata( src, pnode );
66
67 rp->use_limits = bone_inf->use_limits;
68 v3_copy( bone_inf->angle_limits[0], rp->limits[0] );
69 v3_copy( bone_inf->angle_limits[1], rp->limits[1] );
70
71 rb_init( &rp->rb );
72 }
73 }
74 }
75
76 /*
77 * Make the player model copy the ragdoll
78 */
79 VG_STATIC void player_model_copy_ragdoll(void)
80 {
81 struct player_model *mdl = &player.mdl;
82
83 for( int i=0; i<mdl->ragdoll_count; i++ )
84 {
85 struct ragdoll_part *part = &mdl->ragdoll[i];
86 m4x3f offset;
87 m3x3_identity(offset);
88 v3_negate( part->offset, offset[3] );
89 m4x3_mul( part->rb.to_world, offset, mdl->sk.final_mtx[part->bone_id] );
90 }
91
92 skeleton_apply_inverses( &mdl->sk );
93 }
94
95 /*
96 * Make the ragdoll copy the player model
97 */
98 VG_STATIC void player_ragdoll_copy_model( v3f v )
99 {
100 struct player_model *mdl = &player.mdl;
101
102 for( int i=0; i<mdl->ragdoll_count; i++ )
103 {
104 struct ragdoll_part *part = &mdl->ragdoll[i];
105
106 v3f pos, offset;
107 u32 bone = part->bone_id;
108
109 m4x3_mulv( mdl->sk.final_mtx[bone], mdl->sk.bones[bone].co, pos );
110 m3x3_mulv( mdl->sk.final_mtx[bone], part->offset, offset );
111 v3_add( pos, offset, part->rb.co );
112 m3x3_q( mdl->sk.final_mtx[bone], part->rb.q );
113 v3_copy( v, part->rb.v );
114 v3_zero( part->rb.w );
115
116 rb_update_transform( &part->rb );
117 }
118 }
119
120 /*
121 * Draw rigidbody colliders for ragdoll
122 */
123 VG_STATIC void player_debug_ragdoll(void)
124 {
125 struct player_model *mdl = &player.mdl;
126
127 for( u32 i=0; i<mdl->ragdoll_count; i ++ )
128 rb_debug( &mdl->ragdoll[i].rb, 0xff00ff00 );
129 }
130
131 /*
132 * Ragdoll physics step
133 */
134 VG_STATIC void player_ragdoll_iter(void)
135 {
136 struct player_model *mdl = &player.mdl;
137 rb_solver_reset();
138
139 for( int i=0; i<mdl->ragdoll_count; i ++ )
140 rb_collide( &mdl->ragdoll[i].rb, &world.rb_geo );
141
142 rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
143
144 v3f rv;
145
146 #if 0
147 float shoe_vel[2] = {0.0f,0.0f};
148 for( int i=0; i<2; i++ )
149 if( mdl->shoes[i] )
150 shoe_vel[i] = v3_length( mdl->ragdoll[i].rb.v );
151 #endif
152
153 for( int j=0; j<mdl->ragdoll_count; j++ )
154 {
155 struct ragdoll_part *pj = &mdl->ragdoll[j];
156 struct skeleton_bone *bj = &mdl->sk.bones[pj->bone_id];
157
158 if( pj->parent != 0xffffffff )
159 {
160 struct ragdoll_part *pp = &mdl->ragdoll[pj->parent];
161 struct skeleton_bone *bp = &mdl->sk.bones[pp->bone_id];
162
163 v3f lca, lcb;
164 v3_negate( pj->offset, lca );
165 v3_add( bp->co, pp->offset, lcb );
166 v3_sub( bj->co, lcb, lcb );
167
168 rb_debug_constraint_position( &pj->rb, lca, &pp->rb, lcb );
169
170 if( pj->use_limits )
171 {
172 rb_debug_constraint_limits( &pj->rb, &pp->rb, lca, pj->limits );
173 }
174 }
175
176 v4f plane = {0.0f,1.0f,0.0f,0.0f};
177 rb_effect_simple_bouyency( &pj->rb, plane, k_ragdoll_floatyiness,
178 k_ragdoll_floatydrag );
179 }
180
181 /* CONSTRAINTS */
182 for( int i=0; i<10; i++ )
183 {
184 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
185
186 for( int j=0; j<mdl->ragdoll_count; j++ )
187 {
188 struct ragdoll_part *pj = &mdl->ragdoll[j];
189 struct skeleton_bone *bj = &mdl->sk.bones[pj->bone_id];
190
191 if( (pj->parent != 0xffffffff) && pj->use_limits )
192 {
193 struct ragdoll_part *pp = &mdl->ragdoll[pj->parent];
194 struct skeleton_bone *bp = &mdl->sk.bones[pp->bone_id];
195
196 v3f lca, lcb;
197 v3_negate( pj->offset, lca );
198 v3_add( bp->co, pp->offset, lcb );
199 v3_sub( bj->co, lcb, lcb );
200
201 rb_constraint_position( &pj->rb, lca, &pp->rb, lcb );
202
203 rb_constraint_limits( &pj->rb, lca, &pp->rb, lcb, pj->limits );
204 }
205 }
206 }
207
208 /* INTEGRATION */
209 for( int i=0; i<mdl->ragdoll_count; i++ )
210 rb_iter( &mdl->ragdoll[i].rb );
211
212 /* SHOES */
213 for( int i=0; i<mdl->ragdoll_count; i++ )
214 rb_update_transform( &mdl->ragdoll[i].rb );
215 }
216
217 #endif /* PLAYER_RAGDOLL_H */