whoopsie
[carveJwlIkooP6JGAAIwe30JlM.git] / skeleton.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #ifndef SKELETON_H
6 #define SKELETON_H
7
8 #include "model.h"
9
10 struct skeleton
11 {
12 struct skeleton_bone
13 {
14 v3f co, end;
15 u32 parent;
16
17 u32 flags;
18 int defer;
19
20 mdl_keyframe kf;
21 mdl_bone *orig_bone;
22
23 u32 collider;
24 boxf hitbox;
25 const char *name;
26 }
27 *bones;
28 u32 bone_count;
29
30 struct skeleton_anim
31 {
32 const char *name;
33 u32 length;
34
35 float rate;
36 mdl_keyframe *anim_data;
37 }
38 *anims;
39 u32 anim_count;
40
41 m4x3f *final_mtx;
42
43 struct skeleton_ik
44 {
45 u32 lower, upper, target, pole;
46 m3x3f ia, ib;
47 }
48 *ik;
49 u32 ik_count;
50
51 u32
52 collider_count,
53 bindable_count;
54 };
55
56 VG_STATIC u32 skeleton_bone_id( struct skeleton *skele, const char *name )
57 {
58 for( u32 i=1; i<skele->bone_count; i++ ){
59 if( !strcmp( skele->bones[i].name, name ))
60 return i;
61 }
62
63 vg_error( "skeleton_bone_id( *, \"%s\" );\n", name );
64 vg_fatal_exit_loop( "Bone does not exist\n" );
65
66 return 0;
67 }
68
69 VG_STATIC void keyframe_copy_pose( mdl_keyframe *kfa, mdl_keyframe *kfb,
70 int num )
71 {
72 for( int i=0; i<num; i++ )
73 kfb[i] = kfa[i];
74 }
75
76
77 /* apply a rotation from the perspective of root */
78 VG_STATIC void keyframe_rotate_around( mdl_keyframe *kf,
79 v3f origin, v3f offset, v4f q )
80 {
81 v3f v0, co;
82 v3_add( kf->co, offset, co );
83 v3_sub( co, origin, v0 );
84 q_mulv( q, v0, v0 );
85 v3_add( v0, origin, co );
86 v3_sub( co, offset, kf->co );
87
88 q_mul( q, kf->q, kf->q );
89 q_normalize( kf->q );
90 }
91
92 /*
93 * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
94 */
95 VG_STATIC void keyframe_lerp_pose( mdl_keyframe *kfa, mdl_keyframe *kfb,
96 float t, mdl_keyframe *kfd, int count )
97 {
98 if( t <= 0.0001f ){
99 keyframe_copy_pose( kfa, kfd, count );
100 return;
101 }
102 else if( t >= 0.9999f ){
103 keyframe_copy_pose( kfb, kfd, count );
104 return;
105 }
106
107 for( int i=0; i<count; i++ ){
108 v3_lerp( kfa[i].co, kfb[i].co, t, kfd[i].co );
109 q_nlerp( kfa[i].q, kfb[i].q, t, kfd[i].q );
110 v3_lerp( kfa[i].s, kfb[i].s, t, kfd[i].s );
111 }
112 }
113
114 VG_STATIC
115 void skeleton_lerp_pose( struct skeleton *skele,
116 mdl_keyframe *kfa, mdl_keyframe *kfb, float t,
117 mdl_keyframe *kfd )
118 {
119 keyframe_lerp_pose( kfa, kfb, t, kfd, skele->bone_count-1 );
120 }
121
122 VG_STATIC void skeleton_copy_pose( struct skeleton *skele,
123 mdl_keyframe *kfa, mdl_keyframe *kfd )
124 {
125 keyframe_copy_pose( kfa, kfd, skele->bone_count-1 );
126 }
127
128 /*
129 * Sample animation between 2 closest frames using time value. Output is a
130 * keyframe buffer that is allocated with an appropriate size
131 */
132 VG_STATIC void skeleton_sample_anim( struct skeleton *skele,
133 struct skeleton_anim *anim,
134 float time,
135 mdl_keyframe *output )
136 {
137 float animtime = time*anim->rate;
138
139 u32 frame = ((u32)animtime) % anim->length,
140 next = (frame+1) % anim->length;
141
142 float t = vg_fractf( animtime );
143
144 mdl_keyframe *base = anim->anim_data + (skele->bone_count-1)*frame,
145 *nbase = anim->anim_data + (skele->bone_count-1)*next;
146
147 skeleton_lerp_pose( skele, base, nbase, t, output );
148 }
149
150 VG_STATIC int skeleton_sample_anim_clamped( struct skeleton *skele,
151 struct skeleton_anim *anim,
152 float time,
153 mdl_keyframe *output )
154 {
155 float end = (float)(anim->length-1) / anim->rate;
156 skeleton_sample_anim( skele, anim, vg_minf( end, time ), output );
157
158 if( time > end )
159 return 0;
160 else
161 return 1;
162 }
163
164 typedef enum anim_apply
165 {
166 k_anim_apply_always,
167 k_anim_apply_defer_ik,
168 k_anim_apply_deffered_only
169 }
170 anim_apply;
171
172 VG_STATIC
173 int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type )
174 {
175 struct skeleton_bone *sb = &skele->bones[ id ],
176 *sp = &skele->bones[ sb->parent ];
177
178 if( type == k_anim_apply_defer_ik ){
179 if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik))
180 || sp->defer )
181 {
182 sb->defer = 1;
183 return 0;
184 }
185 else{
186 sb->defer = 0;
187 return 1;
188 }
189 }
190 else if( type == k_anim_apply_deffered_only ){
191 if( sb->defer )
192 return 1;
193 else
194 return 0;
195 }
196
197 return 1;
198 }
199
200 /*
201 * Apply block of keyframes to skeletons final pose
202 */
203 VG_STATIC void skeleton_apply_pose( struct skeleton *skele, mdl_keyframe *pose,
204 anim_apply passtype )
205 {
206 m4x3_identity( skele->final_mtx[0] );
207 skele->bones[0].defer = 0;
208 skele->bones[0].flags &= ~k_bone_flag_ik;
209
210 for( u32 i=1; i<skele->bone_count; i++ ){
211 struct skeleton_bone *sb = &skele->bones[i],
212 *sp = &skele->bones[sb->parent];
213
214 if( !should_apply_bone( skele, i, passtype ) )
215 continue;
216
217 sb->defer = 0;
218
219 /* process pose */
220 m4x3f posemtx;
221
222 v3f temp_delta;
223 v3_sub( skele->bones[i].co, skele->bones[sb->parent].co, temp_delta );
224
225 /* pose matrix */
226 mdl_keyframe *kf = &pose[i-1];
227 q_m3x3( kf->q, posemtx );
228 v3_copy( kf->co, posemtx[3] );
229 v3_add( temp_delta, posemtx[3], posemtx[3] );
230
231 /* final matrix */
232 m4x3_mul( skele->final_mtx[ sb->parent ], posemtx, skele->final_mtx[i] );
233 }
234 }
235
236 /*
237 * creates the reference inverse matrix for an IK bone, as it has an initial
238 * intrisic rotation based on the direction that the IK is setup..
239 */
240 VG_STATIC void skeleton_inverse_for_ik( struct skeleton *skele,
241 v3f ivaxis,
242 u32 id, m3x3f inverse )
243 {
244 v3_copy( ivaxis, inverse[0] );
245 v3_copy( skele->bones[id].end, inverse[1] );
246 v3_normalize( inverse[1] );
247 v3_cross( inverse[0], inverse[1], inverse[2] );
248 m3x3_transpose( inverse, inverse );
249 }
250
251 /*
252 * Creates inverse rotation matrices which the IK system uses.
253 */
254 VG_STATIC void skeleton_create_inverses( struct skeleton *skele )
255 {
256 /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
257 for( u32 i=0; i<skele->ik_count; i++ ){
258 struct skeleton_ik *ik = &skele->ik[i];
259
260 m4x3f inverse;
261 v3f iv0, iv1, ivaxis;
262 v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 );
263 v3_sub( skele->bones[ik->pole].co, skele->bones[ik->lower].co, iv1 );
264 v3_cross( iv0, iv1, ivaxis );
265 v3_normalize( ivaxis );
266
267 skeleton_inverse_for_ik( skele, ivaxis, ik->lower, ik->ia );
268 skeleton_inverse_for_ik( skele, ivaxis, ik->upper, ik->ib );
269 }
270 }
271
272 /*
273 * Apply a model matrix to all bones, should be done last
274 */
275 VG_STATIC
276 void skeleton_apply_transform( struct skeleton *skele, m4x3f transform )
277 {
278 for( u32 i=0; i<skele->bone_count; i++ ){
279 struct skeleton_bone *sb = &skele->bones[i];
280 m4x3_mul( transform, skele->final_mtx[i], skele->final_mtx[i] );
281 }
282 }
283
284 /*
285 * Apply an inverse matrix to all bones which maps vertices from bind space into
286 * bone relative positions
287 */
288 VG_STATIC void skeleton_apply_inverses( struct skeleton *skele )
289 {
290 for( u32 i=0; i<skele->bone_count; i++ ){
291 struct skeleton_bone *sb = &skele->bones[i];
292 m4x3f inverse;
293 m3x3_identity( inverse );
294 v3_negate( sb->co, inverse[3] );
295
296 m4x3_mul( skele->final_mtx[i], inverse, skele->final_mtx[i] );
297 }
298 }
299
300 /*
301 * Apply all IK modifiers (2 bone ik reference from blender is supported)
302 */
303 VG_STATIC void skeleton_apply_ik_pass( struct skeleton *skele )
304 {
305 for( u32 i=0; i<skele->ik_count; i++ ){
306 struct skeleton_ik *ik = &skele->ik[i];
307
308 v3f v0, /* base -> target */
309 v1, /* base -> pole */
310 vaxis;
311
312 v3f co_base,
313 co_target,
314 co_pole;
315
316 v3_copy( skele->final_mtx[ik->lower][3], co_base );
317 v3_copy( skele->final_mtx[ik->target][3], co_target );
318 v3_copy( skele->final_mtx[ik->pole][3], co_pole );
319
320 v3_sub( co_target, co_base, v0 );
321 v3_sub( co_pole, co_base, v1 );
322 v3_cross( v0, v1, vaxis );
323 v3_normalize( vaxis );
324 v3_normalize( v0 );
325 v3_cross( vaxis, v0, v1 );
326
327 /* localize problem into [x:v0,y:v1] 2d plane */
328 v2f base = { v3_dot( v0, co_base ), v3_dot( v1, co_base ) },
329 end = { v3_dot( v0, co_target ), v3_dot( v1, co_target ) },
330 knee;
331
332 /* Compute angles (basic trig)*/
333 v2f delta;
334 v2_sub( end, base, delta );
335
336 float
337 l1 = v3_length( skele->bones[ik->lower].end ),
338 l2 = v3_length( skele->bones[ik->upper].end ),
339 d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
340 c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
341 rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
342
343 knee[0] = sinf(-rot) * l1;
344 knee[1] = cosf(-rot) * l1;
345
346 m4x3_identity( skele->final_mtx[ik->lower] );
347 m4x3_identity( skele->final_mtx[ik->upper] );
348
349 /* create rotation matrix */
350 v3f co_knee;
351 v3_muladds( co_base, v0, knee[0], co_knee );
352 v3_muladds( co_knee, v1, knee[1], co_knee );
353 vg_line( co_base, co_knee, 0xff00ff00 );
354
355 m4x3f transform;
356 v3_copy( vaxis, transform[0] );
357 v3_muls( v0, knee[0], transform[1] );
358 v3_muladds( transform[1], v1, knee[1], transform[1] );
359 v3_normalize( transform[1] );
360 v3_cross( transform[0], transform[1], transform[2] );
361 v3_copy( co_base, transform[3] );
362
363 m3x3_mul( transform, ik->ia, transform );
364 m4x3_copy( transform, skele->final_mtx[ik->lower] );
365
366 /* upper/knee bone */
367 v3_copy( vaxis, transform[0] );
368 v3_sub( co_target, co_knee, transform[1] );
369 v3_normalize( transform[1] );
370 v3_cross( transform[0], transform[1], transform[2] );
371 v3_copy( co_knee, transform[3] );
372
373 m3x3_mul( transform, ik->ib, transform );
374 m4x3_copy( transform, skele->final_mtx[ik->upper] );
375 }
376 }
377
378 /*
379 * Applies the typical operations that you want for an IK rig:
380 * Pose, IK, Pose(deferred), Inverses, Transform
381 */
382 VG_STATIC void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose,
383 m4x3f transform )
384 {
385 skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik );
386 skeleton_apply_ik_pass( skele );
387 skeleton_apply_pose( skele, pose, k_anim_apply_deffered_only );
388 skeleton_apply_inverses( skele );
389 skeleton_apply_transform( skele, transform );
390 }
391
392 /*
393 * Get an animation by name
394 */
395 VG_STATIC struct skeleton_anim *skeleton_get_anim( struct skeleton *skele,
396 const char *name )
397 {
398 for( u32 i=0; i<skele->anim_count; i++ ){
399 struct skeleton_anim *anim = &skele->anims[i];
400
401 if( !strcmp( anim->name, name ) )
402 return anim;
403 }
404
405 vg_error( "skeleton_get_anim( *, \"%s\" )\n", name );
406 vg_fatal_exit_loop( "Invalid animation name\n" );
407
408 return NULL;
409 }
410
411 VG_STATIC void skeleton_alloc_from( struct skeleton *skele,
412 void *lin_alloc,
413 mdl_context *mdl,
414 mdl_armature *armature )
415 {
416 skele->bone_count = armature->bone_count+1;
417 skele->anim_count = armature->anim_count;
418 skele->ik_count = 0;
419 skele->collider_count = 0;
420
421 for( u32 i=0; i<armature->bone_count; i++ ){
422 mdl_bone *bone = mdl_arritm( &mdl->bones, armature->bone_start+i );
423
424 if( bone->flags & k_bone_flag_ik )
425 skele->ik_count ++;
426
427 if( bone->collider )
428 skele->collider_count ++;
429 }
430
431 u32 bone_size = sizeof(struct skeleton_bone) * skele->bone_count,
432 ik_size = sizeof(struct skeleton_ik) * skele->ik_count,
433 mtx_size = sizeof(m4x3f) * skele->bone_count,
434 anim_size = sizeof(struct skeleton_anim) * skele->anim_count;
435
436 skele->bones = vg_linear_alloc( lin_alloc, bone_size );
437 skele->ik = vg_linear_alloc( lin_alloc, ik_size );
438 skele->final_mtx = vg_linear_alloc( lin_alloc, mtx_size );
439 skele->anims = vg_linear_alloc( lin_alloc, anim_size );
440 }
441
442 VG_STATIC void skeleton_fatal_err(void)
443 {
444 vg_fatal_exit_loop( "Skeleton setup failed" );
445 }
446
447 /* Setup an animated skeleton from model. mdl's metadata should stick around */
448 VG_STATIC void skeleton_setup( struct skeleton *skele,
449 void *lin_alloc, mdl_context *mdl )
450 {
451 u32 ik_count = 0, collider_count = 0;
452 skele->bone_count = 0;
453 skele->bones = NULL;
454 skele->final_mtx = NULL;
455 skele->anims = NULL;
456
457 if( !mdl->armatures.count ){
458 vg_error( "No skeleton in model\n" );
459 skeleton_fatal_err();
460 }
461
462 mdl_armature *armature = mdl_arritm( &mdl->armatures, 0 );
463 skeleton_alloc_from( skele, lin_alloc, mdl, armature );
464
465 for( u32 i=0; i<armature->bone_count; i++ ){
466 mdl_bone *bone = mdl_arritm( &mdl->bones, armature->bone_start+i );
467 struct skeleton_bone *sb = &skele->bones[i+1];
468
469 v3_copy( bone->co, sb->co );
470 v3_copy( bone->end, sb->end );
471
472 sb->parent = bone->parent;
473 sb->name = mdl_pstr( mdl, bone->pstr_name );
474 sb->flags = bone->flags;
475 sb->collider = bone->collider;
476 sb->orig_bone = bone;
477
478 vg_info( "orig: %u\n", bone->collider );
479
480 if( sb->flags & k_bone_flag_ik ){
481 skele->bones[ sb->parent ].flags |= k_bone_flag_ik;
482
483 if( ik_count == skele->ik_count ){
484 vg_error( "Too many ik bones, corrupt model file\n" );
485 skeleton_fatal_err();
486 }
487
488 struct skeleton_ik *ik = &skele->ik[ ik_count ++ ];
489 ik->upper = i+1;
490 ik->lower = bone->parent;
491 ik->target = bone->ik_target;
492 ik->pole = bone->ik_pole;
493 }
494
495 box_copy( bone->hitbox, sb->hitbox );
496
497 if( bone->collider ){
498 if( collider_count == skele->collider_count ){
499 vg_error( "Too many collider bones\n" );
500 skeleton_fatal_err();
501 }
502
503 collider_count ++;
504 }
505 }
506
507 /* fill in implicit root bone */
508 v3_zero( skele->bones[0].co );
509 v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end );
510 skele->bones[0].parent = 0xffffffff;
511 skele->bones[0].flags = 0;
512 skele->bones[0].name = "[root]";
513
514 /* process animation quick refs */
515 for( u32 i=0; i<skele->anim_count; i++ ){
516 mdl_animation *anim =
517 mdl_arritm( &mdl->animations, armature->anim_start+i );
518
519 skele->anims[i].rate = anim->rate;
520 skele->anims[i].length = anim->length;
521 skele->anims[i].name = mdl_pstr(mdl, anim->pstr_name);
522 skele->anims[i].anim_data =
523 mdl_arritm( &mdl->keyframes, anim->offset );
524
525 vg_info( "animation[ %f, %u ] '%s'\n", anim->rate,
526 anim->length,
527 skele->anims[i].name );
528 }
529
530 skeleton_create_inverses( skele );
531 vg_success( "Loaded skeleton with %u bones\n", skele->bone_count );
532 vg_success( " %u colliders\n", skele->collider_count );
533 }
534
535 VG_STATIC void skeleton_debug( struct skeleton *skele )
536 {
537 for( u32 i=1; i<skele->bone_count; i ++ ){
538 struct skeleton_bone *sb = &skele->bones[i];
539
540 v3f p0, p1;
541 v3_copy( sb->co, p0 );
542 v3_add( p0, sb->end, p1 );
543
544 m4x3_mulv( skele->final_mtx[i], p0, p0 );
545 m4x3_mulv( skele->final_mtx[i], p1, p1 );
546
547 if( sb->flags & k_bone_flag_deform ){
548 if( sb->flags & k_bone_flag_ik ){
549 vg_line( p0, p1, 0xff0000ff );
550 }
551 else{
552 vg_line( p0, p1, 0xffcccccc );
553 }
554 }
555 else
556 vg_line( p0, p1, 0xff00ffff );
557 }
558 }
559
560 #endif /* SKELETON_H */