basic animation
[carveJwlIkooP6JGAAIwe30JlM.git] / skeleton.h
1 #ifndef SKELETON_H
2 #define SKELETON_H
3
4 #include "model.h"
5
6 struct skeleton
7 {
8 struct skeleton_bone
9 {
10 v3f co, end;
11 u32 children; /* maybe remove */
12 u32 parent;
13
14 mdl_keyframe kf;
15 }
16 *bones;
17 m4x3f *final_transforms;
18
19 struct skeleton_anim
20 {
21 float rate;
22 u32 length;
23 struct mdl_keyframe *anim_data;
24 char name[32];
25 }
26 *anims;
27
28 u32 bone_count,
29 anim_count;
30 };
31
32 static void skeleton_apply_frame( m4x3f transform,
33 struct skeleton *skele,
34 struct skeleton_anim *anim,
35 float time )
36 {
37 u32 frame = time*anim->rate;
38 frame = frame % anim->length;
39
40 mdl_keyframe *base = anim->anim_data + (skele->bone_count-1)*frame;
41 m4x3_copy( transform, skele->final_transforms[0] );
42
43 for( int i=1; i<skele->bone_count; i++ )
44 {
45 struct skeleton_bone *sb = &skele->bones[i];
46
47 /* process pose */
48 m4x3f posemtx;
49
50 v3f temp_delta;
51 v3_sub( skele->bones[i].co, skele->bones[sb->parent].co, temp_delta );
52
53
54 /* pose matrix */
55 mdl_keyframe *kf = base+i-1;
56
57 q_m3x3( kf->q, posemtx );
58 v3_copy( kf->co, posemtx[3] );
59 v3_add( temp_delta, posemtx[3], posemtx[3] );
60
61 /* final matrix */
62 m4x3_mul( skele->final_transforms[ sb->parent ], posemtx,
63 skele->final_transforms[i] );
64 }
65
66 /* armature space -> bone space matrix ( for verts ) */
67 for( int i=1; i<skele->bone_count; i++ )
68 {
69 m4x3f abmtx;
70 m3x3_identity( abmtx );
71 v3_negate( skele->bones[i].co, abmtx[3] );
72 m4x3_mul( skele->final_transforms[i], abmtx,
73 skele->final_transforms[i] );
74 }
75 }
76
77 static struct skeleton_anim *skeleton_get_anim( struct skeleton *skele,
78 const char *name )
79 {
80 for( int i=0; i<skele->anim_count; i++ )
81 {
82 struct skeleton_anim *anim = &skele->anims[i];
83
84 if( !strcmp( anim->name, name ) )
85 return anim;
86 }
87
88 return NULL;
89 }
90
91 /* Setup an animated skeleton from model */
92 static int skeleton_setup( struct skeleton *skele, mdl_header *mdl )
93 {
94 u32 bone_count = 1, skeleton_root = 0;
95 skele->bone_count = 0;
96 skele->bones = NULL;
97 skele->final_transforms = NULL;
98 skele->anims = NULL;
99
100 struct classtype_skeleton *inf = NULL;
101
102 for( u32 i=0; i<mdl->node_count; i++ )
103 {
104 mdl_node *pnode = mdl_node_from_id( mdl, i );
105
106 if( pnode->classtype == k_classtype_skeleton )
107 {
108 inf = mdl_get_entdata( mdl, pnode );
109 if( skele->bone_count )
110 {
111 vg_error( "Multiple skeletons in model file\n" );
112 free( skele->bones );
113 return 0;
114 }
115
116 skele->bone_count = inf->channels;
117 skele->bones = malloc(sizeof(struct skeleton_bone)*skele->bone_count);
118 skeleton_root = i;
119 }
120 else if( skele->bone_count )
121 {
122 if( pnode->classtype == k_classtype_bone )
123 {
124 struct skeleton_bone *sb = &skele->bones[bone_count ++];
125 v3_copy( pnode->co, sb->co );
126 v3_copy( pnode->s, sb->end );
127 sb->parent = pnode->parent-skeleton_root;
128 }
129 else
130 {
131 break;
132 }
133 }
134 }
135
136 if( !inf )
137 {
138 vg_error( "No skeleton in model\n" );
139 return 0;
140 }
141
142 if( bone_count != skele->bone_count )
143 {
144 vg_error( "Loaded %u bones out of %u\n", bone_count, skele->bone_count );
145 return 0;
146 }
147
148 /* fill in implicit root bone */
149 v3_zero( skele->bones[0].co );
150 v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end );
151 skele->bones[0].parent = 0xffffffff;
152
153 skele->final_transforms = malloc( sizeof(m4x3f) * skele->bone_count );
154 skele->anim_count = inf->anim_count;
155 skele->anims = malloc( sizeof(struct skeleton_anim) * inf->anim_count);
156
157 for( int i=0; i<inf->anim_count; i++ )
158 {
159 mdl_animation *anim =
160 mdl_animation_from_id( mdl, inf->anim_start+i );
161
162 skele->anims[i].rate = anim->rate;
163 skele->anims[i].length = anim->length;
164 strncpy( skele->anims[i].name, mdl_pstr(mdl, anim->pstr_name), 32 );
165
166 u32 total_keyframes = (skele->bone_count-1)*anim->length;
167 size_t block_size = sizeof(mdl_keyframe) * total_keyframes;
168 mdl_keyframe *dst = malloc( block_size );
169
170 skele->anims[i].anim_data = dst;
171 memcpy( dst, mdl_get_animdata( mdl, anim ), block_size );
172 }
173
174 vg_success( "Loaded skeleton with %u bones\n", skele->bone_count );
175 return 1;
176 }
177
178 static void skeleton_debug( struct skeleton *skele )
179 {
180 for( int i=0; i<skele->bone_count; i ++ )
181 {
182 struct skeleton_bone *sb = &skele->bones[i];
183
184 v3f p0, p1;
185 v3_copy( sb->co, p0 );
186 v3_add( p0, sb->end, p1 );
187 vg_line( p0, p1, 0xffffffff );
188
189 m4x3_mulv( skele->final_transforms[i], p0, p0 );
190 m4x3_mulv( skele->final_transforms[i], p1, p1 );
191 vg_line( p0, p1, 0xff0000ff );
192 }
193 }
194
195 #endif /* SKELETON_H */