]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/player_skeleton.qc
support up to 2 aim bones
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / player_skeleton.qc
1 .float skeleton_info_modelindex;
2 .float skeleton_info_skin;
3 #define BONETYPE_LOWER 0
4 #define BONETYPE_UPPER 1
5 #define MAX_BONES 128
6 .float skeleton_bonetype[MAX_BONES];
7 .float skeleton_numbones;
8
9 void skeleton_loadinfo(entity e)
10 {
11         if(e.skeleton_info_modelindex == e.modelindex && e.skeleton_info_skin == e.skin)
12                 return;
13         e.bone_upperbody = 0;
14         e.bone_weapon = gettagindex(e, "weapon");
15         if(!e.bone_weapon)
16                 e.bone_weapon = gettagindex(e, "tag_weapon");
17         if(!e.bone_weapon)
18                 e.bone_weapon = gettagindex(e, "bip01 r hand");
19         e.bone_aim1 = 0;
20         e.bone_aim2 = 0;
21         e.bone_aim1weight = 0;
22         e.bone_aim2weight = 0;
23         e.fixbone = 0;
24         if(get_model_parameters(e.model, e.skin))
25         {
26                 if(get_model_parameters_bone_upperbody)
27                         e.bone_upperbody = gettagindex(e, get_model_parameters_bone_upperbody);
28                 if(e.bone_upperbody)
29                         e.fixbone = get_model_parameters_fixbone;
30                 if(get_model_parameters_bone_weapon)
31                         e.bone_weapon = gettagindex(e, get_model_parameters_bone_weapon);
32                 if(get_model_parameters_bone_aim1)
33                         e.bone_aim1 = gettagindex(e, get_model_parameters_bone_aim1);
34                 if(e.bone_aim1)
35                         e.bone_aim1weight = get_model_parameters_bone_aim1weight;
36                 if(get_model_parameters_bone_aim2)
37                         e.bone_aim2 = gettagindex(e, get_model_parameters_bone_aim2);
38                 if(e.bone_aim2)
39                         e.bone_aim2weight = get_model_parameters_bone_aim2weight;
40         }
41         else
42                 dprint("No model parameters for ", e.model, "\n");
43         dprint(e.model, " uses ", ftos(e.bone_upperbody), " ", ftos(e.fixbone), "\n");
44         get_model_parameters(string_null, 0);
45         e.skeleton_info_modelindex = e.modelindex;
46         e.skeleton_info_skin = e.skin;
47         if(e.skeletonindex)
48         {
49                 skel_delete(e.skeletonindex);
50                 e.skeletonindex = 0;
51         }
52 }
53
54 void skeleton_markbones(entity e)
55 {
56         float s = e.skeletonindex;
57         float n = (e.skeleton_numbones = skel_get_numbones(s));
58         float i;
59         for(i = 1; i <= n; ++i)
60         {
61                 float t = BONETYPE_LOWER;
62                 float p = skel_get_boneparent(s, i);
63                 if(p > 0)
64                         t = e.(skeleton_bonetype[p-1]);
65                 if(i == e.bone_upperbody)
66                         t = BONETYPE_UPPER;
67                 e.(skeleton_bonetype[i-1]) = t;
68         }
69 }
70
71 void skel_set_boneabs(float s, float bone, vector absorg)
72 {
73         vector absang = fixedvectoangles2(v_forward, v_up);
74
75         vector parentorg = skel_get_boneabs(s, skel_get_boneparent(s, bone));
76         vector parentang = fixedvectoangles2(v_forward, v_up);
77
78         vector relang = AnglesTransform_LeftDivide(parentang, absang);
79         vector relorg = AnglesTransform_Apply(AnglesTransform_Invert(parentang), absorg - parentorg);
80
81         fixedmakevectors(relang);
82         skel_set_bone(s, bone, relorg);
83
84         /*
85         vector neworg = skel_get_boneabs(s, bone);
86         print(sprintf("ANG: want: %v, got: %v\n", absang, fixedvectoangles2(v_forward, v_up)));
87         print(sprintf("ORG: want: %v, got: %v\n", absorg, neworg));
88         */
89 }
90
91 void free_skeleton_from_frames(entity e)
92 {
93         if(e.skeletonindex)
94         {
95                 skel_delete(e.skeletonindex);
96                 e.skeletonindex = 0;
97         }
98 }
99
100 void skeleton_from_frames(entity e)
101 {
102         float m = e.modelindex;
103         if(!e.skeletonindex)
104         {
105                 e.skeletonindex = skel_create(m);
106                 skeleton_markbones(e);
107         }
108         float s = e.skeletonindex;
109         if(!s)
110                 return;
111         float bone;
112         float n = e.skeleton_numbones;
113         float savelerpfrac = e.lerpfrac;
114         float savelerpfrac3 = e.lerpfrac3;
115         float savelerpfrac4 = e.lerpfrac4;
116
117         vector fixbone_oldangles = '0 0 0';
118         if(e.fixbone)
119         {
120                 // make all bones BONETYPE_UPPER
121                 e.lerpfrac = 0;
122                 e.lerpfrac3 = savelerpfrac3 * 2;
123                 e.lerpfrac4 = 0;
124                 // build skeleton
125                 skel_build(s, e, m, 0, 1, n);
126                 // get hip bone
127                 skel_get_boneabs(s, e.bone_upperbody);
128                 fixbone_oldangles = fixedvectoangles2(v_forward, v_up);
129         }
130
131         for(bone = 0; bone < n; )
132         {
133                 float firstbone = bone;
134                 float bonetype = e.skeleton_bonetype[bone];
135                 for(++bone; (bone < n) && (e.skeleton_bonetype[bone] == bonetype); ++bone)
136                         ;
137                 if(bonetype == BONETYPE_UPPER)
138                 {
139                         // only show frames 1+3 (upper body)
140                         e.lerpfrac = 0;
141                         e.lerpfrac3 = savelerpfrac3 * 2;
142                         e.lerpfrac4 = 0;
143                 }
144                 else
145                 {
146                         // only show frames 2+4 (lower body)
147                         e.lerpfrac = savelerpfrac * 2;
148                         e.lerpfrac3 = 0;
149                         e.lerpfrac4 = savelerpfrac4 * 2;
150                 }
151                 //print(sprintf("Run: bone %d to %d, type %d\n", firstbone + 1, bone, bonetype));
152                 //print(sprintf("frame %d %d %d %d lerpfrac * %d %d %d\n", e.frame, e.frame2, e.frame3, e.frame4, e.lerpfrac, e.lerpfrac3, e.lerpfrac4));
153                 skel_build(s, e, m, 0, firstbone + 1, bone);
154         }
155         e.lerpfrac = savelerpfrac;
156         e.lerpfrac3 = savelerpfrac3;
157         e.lerpfrac4 = savelerpfrac4;
158
159         if(e.fixbone)
160         {
161                 // FIX IT
162                 vector org = skel_get_boneabs(s, e.bone_upperbody);
163                 fixedmakevectors(fixbone_oldangles);
164                 skel_set_boneabs(s, e.bone_upperbody, org);
165         }
166
167         if(e.bone_aim1)
168         {
169                 vector aim = '1 0 0' * bound(-90, self.v_angle_x, 90) * e.bone_aim1weight;
170                 vector org = skel_get_boneabs(s, e.bone_aim1);
171                 vector ang_cur = fixedvectoangles2(v_forward, v_up);
172                 vector ang = AnglesTransform_Multiply(aim, ang_cur);
173                 fixedmakevectors(ang);
174                 skel_set_boneabs(s, e.bone_aim1, org);
175         }
176
177         if(e.bone_aim2)
178         {
179                 vector aim = '1 0 0' * bound(-90, self.v_angle_x, 90) * e.bone_aim2weight;
180                 vector org = skel_get_boneabs(s, e.bone_aim2);
181                 vector ang_cur = fixedvectoangles2(v_forward, v_up);
182                 vector ang = AnglesTransform_Multiply(aim, ang_cur);
183                 fixedmakevectors(ang);
184                 skel_set_boneabs(s, e.bone_aim2, org);
185         }
186 }