]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - mod_skeletal_animatevertices_generic.c
8c5f7d0f762f7934810e79ce34bd5d097fb57d0f
[xonotic/darkplaces.git] / mod_skeletal_animatevertices_generic.c
1 #include "mod_skeletal_animatevertices_generic.h"
2
3 typedef struct
4 {
5         float f[12];
6 }
7 float12_t;
8
9 void Mod_Skeletal_AnimateVertices_Generic(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
10 {
11         // vertex weighted skeletal
12         int i, k;
13         int blends;
14         float12_t *bonepose;
15         float12_t *boneposerelative;
16         float m[12];
17         const blendweights_t * RESTRICT weights;
18
19         //unsigned long long ts = rdtsc();
20         bonepose = (float12_t *) Mod_Skeletal_AnimateVertices_AllocBuffers(sizeof(float12_t) * (model->num_bones*2 + model->surfmesh.num_blends));
21         boneposerelative = bonepose + model->num_bones;
22
23         if (skeleton && !skeleton->relativetransforms)
24                 skeleton = NULL;
25
26         // interpolate matrices
27         if (skeleton)
28         {
29                 for (i = 0;i < model->num_bones;i++)
30                 {
31                         Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
32                         if (model->data_bones[i].parent >= 0)
33                                 R_ConcatTransforms(bonepose[model->data_bones[i].parent].f, m, bonepose[i].f);
34                         else
35                                 memcpy(bonepose[i].f, m, sizeof(m));
36
37                         // create a relative deformation matrix to describe displacement
38                         // from the base mesh, which is used by the actual weighting
39                         R_ConcatTransforms(bonepose[i].f, model->data_baseboneposeinverse + i * 12, boneposerelative[i].f);
40                 }
41         }
42         else
43         {
44                 float originscale = -model->num_posescale;
45                 for (i = 0;i < model->num_bones;i++)
46                 {
47                     const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
48                         float lerp = frameblend[0].lerp,
49                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
50                                 rx = pose7s[3] * lerp,
51                                 ry = pose7s[4] * lerp,
52                                 rz = pose7s[5] * lerp,
53                                 rw = pose7s[6] * lerp,
54                                 dx = tx*rw + ty*rz - tz*ry,
55                                 dy = -tx*rz + ty*rw + tz*rx,
56                                 dz = tx*ry - ty*rx + tz*rw,
57                                 dw = -tx*rx - ty*ry - tz*rz,
58                                 scale;
59                         for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
60                         {
61                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
62                                 float lerp = frameblend[blends].lerp,
63                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
64                                         qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
65                                 if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
66                                 qx *= lerp;
67                                 qy *= lerp;
68                                 qz *= lerp;
69                                 qw *= lerp;
70                                 rx += qx;
71                                 ry += qy;
72                                 rz += qz;
73                                 rw += qw;
74                                 dx += tx*qw + ty*qz - tz*qy;
75                                 dy += -tx*qz + ty*qw + tz*qx;
76                                 dz += tx*qy - ty*qx + tz*qw;
77                                 dw += -tx*qx - ty*qy - tz*qz;
78                         }
79                         scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
80                         m[0] = scale*(rw*rw + rx*rx - ry*ry - rz*rz);
81                         m[1] = 2*scale*(rx*ry - rw*rz);
82                         m[2] = 2*scale*(rx*rz + rw*ry);
83                         m[3] = originscale*scale*(dw*rx - dx*rw + dy*rz - dz*ry);
84                         m[4] = 2*scale*(rx*ry + rw*rz);
85                         m[5] = scale*(rw*rw + ry*ry - rx*rx - rz*rz);
86                         m[6] = 2*scale*(ry*rz - rw*rx);
87                         m[7] = originscale*scale*(dw*ry - dx*rz - dy*rw + dz*rx);
88                         m[8] = 2*scale*(rx*rz - rw*ry);
89                         m[9] = 2*scale*(ry*rz + rw*rx);
90                         m[10] = scale*(rw*rw + rz*rz - rx*rx - ry*ry);
91                         m[11] = originscale*scale*(dw*rz + dx*ry - dy*rx - dz*rw);
92                         if (i == r_skeletal_debugbone.integer)
93                                 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
94                         m[3] *= r_skeletal_debugtranslatex.value;
95                         m[7] *= r_skeletal_debugtranslatey.value;
96                         m[11] *= r_skeletal_debugtranslatez.value;
97                         if (model->data_bones[i].parent >= 0)
98                                 R_ConcatTransforms(bonepose[model->data_bones[i].parent].f, m, bonepose[i].f);
99                         else
100                                 memcpy(bonepose[i].f, m, sizeof(m));
101                         // create a relative deformation matrix to describe displacement
102                         // from the base mesh, which is used by the actual weighting
103                         R_ConcatTransforms(bonepose[i].f, model->data_baseboneposeinverse + i * 12, boneposerelative[i].f);
104                 }
105         }
106
107         // generate matrices for all blend combinations
108         weights = model->surfmesh.data_blendweights;
109         for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
110         {
111                 float * RESTRICT b = boneposerelative[model->num_bones + i].f;
112                 const float * RESTRICT m = boneposerelative[weights->index[0]].f;
113                 float f = weights->influence[0] * (1.0f / 255.0f);
114                 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
115                 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
116                 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
117                 for (k = 1;k < 4 && weights->influence[k];k++)
118                 {
119                         m = boneposerelative[weights->index[k]].f;
120                         f = weights->influence[k] * (1.0f / 255.0f);
121                         b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
122                         b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
123                         b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
124                 }
125         }
126
127 #define LOAD_MATRIX_SCALAR() const float * RESTRICT m = boneposerelative[*b].f
128
129 #define LOAD_MATRIX3() \
130         LOAD_MATRIX_SCALAR()
131 #define LOAD_MATRIX4() \
132         LOAD_MATRIX_SCALAR()
133
134 #define TRANSFORM_POSITION_SCALAR(in, out) \
135         (out)[0] = ((in)[0] * m[0] + (in)[1] * m[1] + (in)[2] * m[ 2] + m[3]); \
136         (out)[1] = ((in)[0] * m[4] + (in)[1] * m[5] + (in)[2] * m[ 6] + m[7]); \
137         (out)[2] = ((in)[0] * m[8] + (in)[1] * m[9] + (in)[2] * m[10] + m[11]);
138 #define TRANSFORM_VECTOR_SCALAR(in, out) \
139         (out)[0] = ((in)[0] * m[0] + (in)[1] * m[1] + (in)[2] * m[ 2]); \
140         (out)[1] = ((in)[0] * m[4] + (in)[1] * m[5] + (in)[2] * m[ 6]); \
141         (out)[2] = ((in)[0] * m[8] + (in)[1] * m[9] + (in)[2] * m[10]);
142
143 #define TRANSFORM_POSITION(in, out) \
144         TRANSFORM_POSITION_SCALAR(in, out)
145 #define TRANSFORM_VECTOR(in, out) \
146         TRANSFORM_VECTOR_SCALAR(in, out)
147
148         // transform vertex attributes by blended matrices
149         if (vertex3f)
150         {
151                 const float * RESTRICT v = model->surfmesh.data_vertex3f;
152                 const unsigned short * RESTRICT b = model->surfmesh.blends;
153                 // special case common combinations of attributes to avoid repeated loading of matrices
154                 if (normal3f)
155                 {
156                         const float * RESTRICT n = model->surfmesh.data_normal3f;
157                         if (svector3f && tvector3f)
158                         {
159                                 const float * RESTRICT sv = model->surfmesh.data_svector3f;
160                                 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
161
162                                 // Note that for SSE each iteration stores one element past end, so we break one vertex short
163                                 // and handle that with scalars in that case
164                                 for (i = 0; i < model->surfmesh.num_vertices; i++, v += 3, n += 3, sv += 3, tv += 3, b++,
165                                                 vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3)
166                                 {
167                                         LOAD_MATRIX4();
168                                         TRANSFORM_POSITION(v, vertex3f);
169                                         TRANSFORM_VECTOR(n, normal3f);
170                                         TRANSFORM_VECTOR(sv, svector3f);
171                                         TRANSFORM_VECTOR(tv, tvector3f);
172                                 }
173
174                                 return;
175                         }
176
177                         for (i = 0;i < model->surfmesh.num_vertices; i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
178                         {
179                                 LOAD_MATRIX4();
180                                 TRANSFORM_POSITION(v, vertex3f);
181                                 TRANSFORM_VECTOR(n, normal3f);
182                         }
183                 }
184                 else
185                 {
186                         for (i = 0;i < model->surfmesh.num_vertices; i++, v += 3, b++, vertex3f += 3)
187                         {
188                                 LOAD_MATRIX4();
189                                 TRANSFORM_POSITION(v, vertex3f);
190                         }
191                 }
192         }
193
194         else if (normal3f)
195         {
196                 const float * RESTRICT n = model->surfmesh.data_normal3f;
197                 const unsigned short * RESTRICT b = model->surfmesh.blends;
198                 for (i = 0; i < model->surfmesh.num_vertices; i++, n += 3, b++, normal3f += 3)
199                 {
200                         LOAD_MATRIX3();
201                         TRANSFORM_VECTOR(n, normal3f);
202                 }
203         }
204
205         if (svector3f)
206         {
207                 const float * RESTRICT sv = model->surfmesh.data_svector3f;
208                 const unsigned short * RESTRICT b = model->surfmesh.blends;
209                 for (i = 0; i < model->surfmesh.num_vertices; i++, sv += 3, b++, svector3f += 3)
210                 {
211                         LOAD_MATRIX3();
212                         TRANSFORM_VECTOR(sv, svector3f);
213                 }
214         }
215
216         if (tvector3f)
217         {
218                 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
219                 const unsigned short * RESTRICT b = model->surfmesh.blends;
220                 for (i = 0; i < model->surfmesh.num_vertices; i++, tv += 3, b++, tvector3f += 3)
221                 {
222                         LOAD_MATRIX3();
223                         TRANSFORM_VECTOR(tv, tvector3f);
224                 }
225         }
226 }