]> icculus.org git repositories - divverent/darkplaces.git/blob - matrixlib.c
cleaned up almost all direct indexing of matrix4x4_t structures to go through proper...
[divverent/darkplaces.git] / matrixlib.c
1
2 #include <math.h>
3 #include "matrixlib.h"
4
5 const matrix4x4_t identitymatrix =
6 {
7         {
8                 {1, 0, 0, 0},
9                 {0, 1, 0, 0},
10                 {0, 0, 1, 0},
11                 {0, 0, 0, 1}
12         }
13 };
14
15 void Matrix4x4_Copy (matrix4x4_t *out, const matrix4x4_t *in)
16 {
17         *out = *in;
18 }
19
20 void Matrix4x4_CopyRotateOnly (matrix4x4_t *out, const matrix4x4_t *in)
21 {
22         out->m[0][0] = in->m[0][0];
23         out->m[0][1] = in->m[0][1];
24         out->m[0][2] = in->m[0][2];
25         out->m[0][3] = 0.0f;
26         out->m[1][0] = in->m[1][0];
27         out->m[1][1] = in->m[1][1];
28         out->m[1][2] = in->m[1][2];
29         out->m[1][3] = 0.0f;
30         out->m[2][0] = in->m[2][0];
31         out->m[2][1] = in->m[2][1];
32         out->m[2][2] = in->m[2][2];
33         out->m[2][3] = 0.0f;
34         out->m[3][0] = 0.0f;
35         out->m[3][1] = 0.0f;
36         out->m[3][2] = 0.0f;
37         out->m[3][3] = 1.0f;
38 }
39
40 void Matrix4x4_CopyTranslateOnly (matrix4x4_t *out, const matrix4x4_t *in)
41 {
42         out->m[0][0] = 1.0f;
43         out->m[0][1] = 0.0f;
44         out->m[0][2] = 0.0f;
45         out->m[0][3] = in->m[0][3];
46         out->m[1][0] = 0.0f;
47         out->m[1][1] = 1.0f;
48         out->m[1][2] = 0.0f;
49         out->m[1][3] = in->m[1][3];
50         out->m[2][0] = 0.0f;
51         out->m[2][1] = 0.0f;
52         out->m[2][2] = 1.0f;
53         out->m[2][3] = in->m[2][3];
54         out->m[3][0] = 0.0f;
55         out->m[3][1] = 0.0f;
56         out->m[3][2] = 0.0f;
57         out->m[3][3] = 1.0f;
58 }
59
60 void Matrix4x4_Concat (matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
61 {
62         out->m[0][0] = in1->m[0][0] * in2->m[0][0] + in1->m[0][1] * in2->m[1][0] + in1->m[0][2] * in2->m[2][0] + in1->m[0][3] * in2->m[3][0];
63         out->m[0][1] = in1->m[0][0] * in2->m[0][1] + in1->m[0][1] * in2->m[1][1] + in1->m[0][2] * in2->m[2][1] + in1->m[0][3] * in2->m[3][1];
64         out->m[0][2] = in1->m[0][0] * in2->m[0][2] + in1->m[0][1] * in2->m[1][2] + in1->m[0][2] * in2->m[2][2] + in1->m[0][3] * in2->m[3][2];
65         out->m[0][3] = in1->m[0][0] * in2->m[0][3] + in1->m[0][1] * in2->m[1][3] + in1->m[0][2] * in2->m[2][3] + in1->m[0][3] * in2->m[3][3];
66         out->m[1][0] = in1->m[1][0] * in2->m[0][0] + in1->m[1][1] * in2->m[1][0] + in1->m[1][2] * in2->m[2][0] + in1->m[1][3] * in2->m[3][0];
67         out->m[1][1] = in1->m[1][0] * in2->m[0][1] + in1->m[1][1] * in2->m[1][1] + in1->m[1][2] * in2->m[2][1] + in1->m[1][3] * in2->m[3][1];
68         out->m[1][2] = in1->m[1][0] * in2->m[0][2] + in1->m[1][1] * in2->m[1][2] + in1->m[1][2] * in2->m[2][2] + in1->m[1][3] * in2->m[3][2];
69         out->m[1][3] = in1->m[1][0] * in2->m[0][3] + in1->m[1][1] * in2->m[1][3] + in1->m[1][2] * in2->m[2][3] + in1->m[1][3] * in2->m[3][3];
70         out->m[2][0] = in1->m[2][0] * in2->m[0][0] + in1->m[2][1] * in2->m[1][0] + in1->m[2][2] * in2->m[2][0] + in1->m[2][3] * in2->m[3][0];
71         out->m[2][1] = in1->m[2][0] * in2->m[0][1] + in1->m[2][1] * in2->m[1][1] + in1->m[2][2] * in2->m[2][1] + in1->m[2][3] * in2->m[3][1];
72         out->m[2][2] = in1->m[2][0] * in2->m[0][2] + in1->m[2][1] * in2->m[1][2] + in1->m[2][2] * in2->m[2][2] + in1->m[2][3] * in2->m[3][2];
73         out->m[2][3] = in1->m[2][0] * in2->m[0][3] + in1->m[2][1] * in2->m[1][3] + in1->m[2][2] * in2->m[2][3] + in1->m[2][3] * in2->m[3][3];
74         out->m[3][0] = in1->m[3][0] * in2->m[0][0] + in1->m[3][1] * in2->m[1][0] + in1->m[3][2] * in2->m[2][0] + in1->m[3][3] * in2->m[3][0];
75         out->m[3][1] = in1->m[3][0] * in2->m[0][1] + in1->m[3][1] * in2->m[1][1] + in1->m[3][2] * in2->m[2][1] + in1->m[3][3] * in2->m[3][1];
76         out->m[3][2] = in1->m[3][0] * in2->m[0][2] + in1->m[3][1] * in2->m[1][2] + in1->m[3][2] * in2->m[2][2] + in1->m[3][3] * in2->m[3][2];
77         out->m[3][3] = in1->m[3][0] * in2->m[0][3] + in1->m[3][1] * in2->m[1][3] + in1->m[3][2] * in2->m[2][3] + in1->m[3][3] * in2->m[3][3];
78 }
79
80 void Matrix4x4_Transpose (matrix4x4_t *out, const matrix4x4_t *in1)
81 {
82         out->m[0][0] = in1->m[0][0];
83         out->m[0][1] = in1->m[1][0];
84         out->m[0][2] = in1->m[2][0];
85         out->m[0][3] = in1->m[3][0];
86         out->m[1][0] = in1->m[0][1];
87         out->m[1][1] = in1->m[1][1];
88         out->m[1][2] = in1->m[2][1];
89         out->m[1][3] = in1->m[3][1];
90         out->m[2][0] = in1->m[0][2];
91         out->m[2][1] = in1->m[1][2];
92         out->m[2][2] = in1->m[2][2];
93         out->m[2][3] = in1->m[3][2];
94         out->m[3][0] = in1->m[0][3];
95         out->m[3][1] = in1->m[1][3];
96         out->m[3][2] = in1->m[2][3];
97         out->m[3][3] = in1->m[3][3];
98 }
99
100 void Matrix4x4_Transpose3x3 (matrix4x4_t *out, const matrix4x4_t *in1)
101 {
102         out->m[0][0] = in1->m[0][0];
103         out->m[0][1] = in1->m[1][0];
104         out->m[0][2] = in1->m[2][0];
105         out->m[1][0] = in1->m[0][1];
106         out->m[1][1] = in1->m[1][1];
107         out->m[1][2] = in1->m[2][1];
108         out->m[2][0] = in1->m[0][2];
109         out->m[2][1] = in1->m[1][2];
110         out->m[2][2] = in1->m[2][2];
111
112         out->m[0][3] = in1->m[0][3];
113         out->m[1][3] = in1->m[1][3];
114         out->m[2][3] = in1->m[2][3];
115         out->m[3][0] = in1->m[0][3];
116         out->m[3][1] = in1->m[1][3];
117         out->m[3][2] = in1->m[2][3];
118         out->m[3][3] = in1->m[3][3];
119 }
120
121 void Matrix4x4_Invert_Simple (matrix4x4_t *out, const matrix4x4_t *in1)
122 {
123         // we only support uniform scaling, so assume the first row is enough
124         // (note the lack of sqrt here, because we're trying to undo the scaling,
125         // this means multiplying by the inverse scale twice - squaring it, which
126         // makes the sqrt a waste of time)
127 #if 1
128         double scale = 1.0 / (in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2]);
129 #else
130         double scale = 3.0 / sqrt
131                  (in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2]
132                 + in1->m[1][0] * in1->m[1][0] + in1->m[1][1] * in1->m[1][1] + in1->m[1][2] * in1->m[1][2]
133                 + in1->m[2][0] * in1->m[2][0] + in1->m[2][1] * in1->m[2][1] + in1->m[2][2] * in1->m[2][2]);
134         scale *= scale;
135 #endif
136
137         // invert the rotation by transposing and multiplying by the squared
138         // recipricol of the input matrix scale as described above
139         out->m[0][0] = (float)(in1->m[0][0] * scale);
140         out->m[0][1] = (float)(in1->m[1][0] * scale);
141         out->m[0][2] = (float)(in1->m[2][0] * scale);
142         out->m[1][0] = (float)(in1->m[0][1] * scale);
143         out->m[1][1] = (float)(in1->m[1][1] * scale);
144         out->m[1][2] = (float)(in1->m[2][1] * scale);
145         out->m[2][0] = (float)(in1->m[0][2] * scale);
146         out->m[2][1] = (float)(in1->m[1][2] * scale);
147         out->m[2][2] = (float)(in1->m[2][2] * scale);
148
149         // invert the translate
150         out->m[0][3] = -(in1->m[0][3] * out->m[0][0] + in1->m[1][3] * out->m[0][1] + in1->m[2][3] * out->m[0][2]);
151         out->m[1][3] = -(in1->m[0][3] * out->m[1][0] + in1->m[1][3] * out->m[1][1] + in1->m[2][3] * out->m[1][2]);
152         out->m[2][3] = -(in1->m[0][3] * out->m[2][0] + in1->m[1][3] * out->m[2][1] + in1->m[2][3] * out->m[2][2]);
153
154         // don't know if there's anything worth doing here
155         out->m[3][0] = 0;
156         out->m[3][1] = 0;
157         out->m[3][2] = 0;
158         out->m[3][3] = 1;
159 }
160
161 void Matrix4x4_Normalize (matrix4x4_t *out, matrix4x4_t *in1)
162 {
163         // scale rotation matrix vectors to a length of 1
164         // note: this is only designed to undo uniform scaling
165         double scale = 1.0 / sqrt(in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2]);
166         out->m[0][0] = (float)(in1->m[0][0] * scale);
167         out->m[0][1] = (float)(in1->m[0][1] * scale);
168         out->m[0][2] = (float)(in1->m[0][2] * scale);
169         out->m[0][3] = (float)(in1->m[0][3]);
170         out->m[1][0] = (float)(in1->m[1][0] * scale);
171         out->m[1][1] = (float)(in1->m[1][1] * scale);
172         out->m[1][2] = (float)(in1->m[1][2] * scale);
173         out->m[1][3] = (float)(in1->m[1][3]);
174         out->m[2][0] = (float)(in1->m[2][0] * scale);
175         out->m[2][1] = (float)(in1->m[2][1] * scale);
176         out->m[2][2] = (float)(in1->m[2][2] * scale);
177         out->m[2][3] = (float)(in1->m[2][3]);
178         out->m[3][0] = 0;
179         out->m[3][1] = 0;
180         out->m[3][2] = 0;
181         out->m[3][3] = 1;
182 }
183
184 void Matrix4x4_CreateIdentity (matrix4x4_t *out)
185 {
186         out->m[0][0]=1.0f;
187         out->m[0][1]=0.0f;
188         out->m[0][2]=0.0f;
189         out->m[0][3]=0.0f;
190         out->m[1][0]=0.0f;
191         out->m[1][1]=1.0f;
192         out->m[1][2]=0.0f;
193         out->m[1][3]=0.0f;
194         out->m[2][0]=0.0f;
195         out->m[2][1]=0.0f;
196         out->m[2][2]=1.0f;
197         out->m[2][3]=0.0f;
198         out->m[3][0]=0.0f;
199         out->m[3][1]=0.0f;
200         out->m[3][2]=0.0f;
201         out->m[3][3]=1.0f;
202 }
203
204 void Matrix4x4_CreateTranslate (matrix4x4_t *out, double x, double y, double z)
205 {
206         out->m[0][0]=1.0f;
207         out->m[0][1]=0.0f;
208         out->m[0][2]=0.0f;
209         out->m[0][3]=x;
210         out->m[1][0]=0.0f;
211         out->m[1][1]=1.0f;
212         out->m[1][2]=0.0f;
213         out->m[1][3]=y;
214         out->m[2][0]=0.0f;
215         out->m[2][1]=0.0f;
216         out->m[2][2]=1.0f;
217         out->m[2][3]=z;
218         out->m[3][0]=0.0f;
219         out->m[3][1]=0.0f;
220         out->m[3][2]=0.0f;
221         out->m[3][3]=1.0f;
222 }
223
224 void Matrix4x4_CreateRotate (matrix4x4_t *out, double angle, double x, double y, double z)
225 {
226         double len, c, s;
227
228         len = x*x+y*y+z*z;
229         if (len != 0.0f)
230                 len = 1.0f / (float)sqrt(len);
231         x *= len;
232         y *= len;
233         z *= len;
234
235         angle *= (float)(-M_PI / 180.0);
236         c = (float)cos(angle);
237         s = (float)sin(angle);
238
239         out->m[0][0]=x * x + c * (1 - x * x);
240         out->m[0][1]=x * y * (1 - c) + z * s;
241         out->m[0][2]=z * x * (1 - c) - y * s;
242         out->m[0][3]=0.0f;
243         out->m[1][0]=x * y * (1 - c) - z * s;
244         out->m[1][1]=y * y + c * (1 - y * y);
245         out->m[1][2]=y * z * (1 - c) + x * s;
246         out->m[1][3]=0.0f;
247         out->m[2][0]=z * x * (1 - c) + y * s;
248         out->m[2][1]=y * z * (1 - c) - x * s;
249         out->m[2][2]=z * z + c * (1 - z * z);
250         out->m[2][3]=0.0f;
251         out->m[3][0]=0.0f;
252         out->m[3][1]=0.0f;
253         out->m[3][2]=0.0f;
254         out->m[3][3]=1.0f;
255 }
256
257 void Matrix4x4_CreateScale (matrix4x4_t *out, double x)
258 {
259         out->m[0][0]=x;
260         out->m[0][1]=0.0f;
261         out->m[0][2]=0.0f;
262         out->m[0][3]=0.0f;
263         out->m[1][0]=0.0f;
264         out->m[1][1]=x;
265         out->m[1][2]=0.0f;
266         out->m[1][3]=0.0f;
267         out->m[2][0]=0.0f;
268         out->m[2][1]=0.0f;
269         out->m[2][2]=x;
270         out->m[2][3]=0.0f;
271         out->m[3][0]=0.0f;
272         out->m[3][1]=0.0f;
273         out->m[3][2]=0.0f;
274         out->m[3][3]=1.0f;
275 }
276
277 void Matrix4x4_CreateScale3 (matrix4x4_t *out, double x, double y, double z)
278 {
279         out->m[0][0]=x;
280         out->m[0][1]=0.0f;
281         out->m[0][2]=0.0f;
282         out->m[0][3]=0.0f;
283         out->m[1][0]=0.0f;
284         out->m[1][1]=y;
285         out->m[1][2]=0.0f;
286         out->m[1][3]=0.0f;
287         out->m[2][0]=0.0f;
288         out->m[2][1]=0.0f;
289         out->m[2][2]=z;
290         out->m[2][3]=0.0f;
291         out->m[3][0]=0.0f;
292         out->m[3][1]=0.0f;
293         out->m[3][2]=0.0f;
294         out->m[3][3]=1.0f;
295 }
296
297 void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale)
298 {
299         double angle, sr, sp, sy, cr, cp, cy;
300
301         if (roll)
302         {
303                 angle = yaw * (M_PI*2 / 360);
304                 sy = sin(angle);
305                 cy = cos(angle);
306                 angle = pitch * (M_PI*2 / 360);
307                 sp = sin(angle);
308                 cp = cos(angle);
309                 angle = roll * (M_PI*2 / 360);
310                 sr = sin(angle);
311                 cr = cos(angle);
312                 out->m[0][0] = (float)((cp*cy) * scale);
313                 out->m[0][1] = (float)((sr*sp*cy+cr*-sy) * scale);
314                 out->m[0][2] = (float)((cr*sp*cy+-sr*-sy) * scale);
315                 out->m[0][3] = x;
316                 out->m[1][0] = (float)((cp*sy) * scale);
317                 out->m[1][1] = (float)((sr*sp*sy+cr*cy) * scale);
318                 out->m[1][2] = (float)((cr*sp*sy+-sr*cy) * scale);
319                 out->m[1][3] = y;
320                 out->m[2][0] = (float)((-sp) * scale);
321                 out->m[2][1] = (float)((sr*cp) * scale);
322                 out->m[2][2] = (float)((cr*cp) * scale);
323                 out->m[2][3] = z;
324                 out->m[3][0] = 0;
325                 out->m[3][1] = 0;
326                 out->m[3][2] = 0;
327                 out->m[3][3] = 1;
328         }
329         else if (pitch)
330         {
331                 angle = yaw * (M_PI*2 / 360);
332                 sy = sin(angle);
333                 cy = cos(angle);
334                 angle = pitch * (M_PI*2 / 360);
335                 sp = sin(angle);
336                 cp = cos(angle);
337                 out->m[0][0] = (float)((cp*cy) * scale);
338                 out->m[0][1] = (float)((-sy) * scale);
339                 out->m[0][2] = (float)((sp*cy) * scale);
340                 out->m[0][3] = x;
341                 out->m[1][0] = (float)((cp*sy) * scale);
342                 out->m[1][1] = (float)((cy) * scale);
343                 out->m[1][2] = (float)((sp*sy) * scale);
344                 out->m[1][3] = y;
345                 out->m[2][0] = (float)((-sp) * scale);
346                 out->m[2][1] = 0;
347                 out->m[2][2] = (float)((cp) * scale);
348                 out->m[2][3] = z;
349                 out->m[3][0] = 0;
350                 out->m[3][1] = 0;
351                 out->m[3][2] = 0;
352                 out->m[3][3] = 1;
353         }
354         else if (yaw)
355         {
356                 angle = yaw * (M_PI*2 / 360);
357                 sy = sin(angle);
358                 cy = cos(angle);
359                 out->m[0][0] = (float)((cy) * scale);
360                 out->m[0][1] = (float)((-sy) * scale);
361                 out->m[0][2] = 0;
362                 out->m[0][3] = x;
363                 out->m[1][0] = (float)((sy) * scale);
364                 out->m[1][1] = (float)((cy) * scale);
365                 out->m[1][2] = 0;
366                 out->m[1][3] = y;
367                 out->m[2][0] = 0;
368                 out->m[2][1] = 0;
369                 out->m[2][2] = scale;
370                 out->m[2][3] = z;
371                 out->m[3][0] = 0;
372                 out->m[3][1] = 0;
373                 out->m[3][2] = 0;
374                 out->m[3][3] = 1;
375         }
376         else
377         {
378                 out->m[0][0] = scale;
379                 out->m[0][1] = 0;
380                 out->m[0][2] = 0;
381                 out->m[0][3] = x;
382                 out->m[1][0] = 0;
383                 out->m[1][1] = scale;
384                 out->m[1][2] = 0;
385                 out->m[1][3] = y;
386                 out->m[2][0] = 0;
387                 out->m[2][1] = 0;
388                 out->m[2][2] = scale;
389                 out->m[2][3] = z;
390                 out->m[3][0] = 0;
391                 out->m[3][1] = 0;
392                 out->m[3][2] = 0;
393                 out->m[3][3] = 1;
394         }
395 }
396
397 void Matrix4x4_ToVectors(const matrix4x4_t *in, float vx[3], float vy[3], float vz[3], float t[3])
398 {
399         vx[0] = in->m[0][0];
400         vx[1] = in->m[1][0];
401         vx[2] = in->m[2][0];
402         vy[0] = in->m[0][1];
403         vy[1] = in->m[1][1];
404         vy[2] = in->m[2][1];
405         vz[0] = in->m[0][2];
406         vz[1] = in->m[1][2];
407         vz[2] = in->m[2][2];
408         t[0] = in->m[0][3];
409         t[1] = in->m[1][3];
410         t[2] = in->m[2][3];
411 }
412
413 void Matrix4x4_FromVectors(matrix4x4_t *out, const float vx[3], const float vy[3], const float vz[3], const float t[3])
414 {
415         out->m[0][0] = vx[0];
416         out->m[0][1] = vy[0];
417         out->m[0][2] = vz[0];
418         out->m[0][3] = t[0];
419         out->m[1][0] = vx[1];
420         out->m[1][1] = vy[1];
421         out->m[1][2] = vz[1];
422         out->m[1][3] = t[1];
423         out->m[2][0] = vx[2];
424         out->m[2][1] = vy[2];
425         out->m[2][2] = vz[2];
426         out->m[2][3] = t[2];
427         out->m[3][0] = 0.0f;
428         out->m[3][1] = 0.0f;
429         out->m[3][2] = 0.0f;
430         out->m[3][3] = 1.0f;
431 }
432
433 void Matrix4x4_FromArrayDoubleGL (matrix4x4_t *out, const double in[16])
434 {
435         out->m[0][0] = in[0];
436         out->m[1][0] = in[1];
437         out->m[2][0] = in[2];
438         out->m[3][0] = in[3];
439         out->m[0][1] = in[4];
440         out->m[1][1] = in[5];
441         out->m[2][1] = in[6];
442         out->m[3][1] = in[7];
443         out->m[0][2] = in[8];
444         out->m[1][2] = in[9];
445         out->m[2][2] = in[10];
446         out->m[3][2] = in[11];
447         out->m[0][3] = in[12];
448         out->m[1][3] = in[13];
449         out->m[2][3] = in[14];
450         out->m[3][3] = in[15];
451 }
452
453 void Matrix4x4_FromArrayDoubleD3D (matrix4x4_t *out, const double in[16])
454 {
455         out->m[0][0] = in[0];
456         out->m[0][1] = in[1];
457         out->m[0][2] = in[2];
458         out->m[0][3] = in[3];
459         out->m[1][0] = in[4];
460         out->m[1][1] = in[5];
461         out->m[1][2] = in[6];
462         out->m[1][3] = in[7];
463         out->m[2][0] = in[8];
464         out->m[2][1] = in[9];
465         out->m[2][2] = in[10];
466         out->m[2][3] = in[11];
467         out->m[3][0] = in[12];
468         out->m[3][1] = in[13];
469         out->m[3][2] = in[14];
470         out->m[3][3] = in[15];
471 }
472
473 void Matrix4x4_ToArray12FloatGL(const matrix4x4_t *in, float out[12])
474 {
475         out[ 0] = in->m[0][0];
476         out[ 1] = in->m[1][0];
477         out[ 2] = in->m[2][0];
478         out[ 3] = in->m[0][1];
479         out[ 4] = in->m[1][1];
480         out[ 5] = in->m[2][1];
481         out[ 6] = in->m[0][2];
482         out[ 7] = in->m[1][2];
483         out[ 8] = in->m[2][2];
484         out[ 9] = in->m[0][3];
485         out[10] = in->m[1][3];
486         out[11] = in->m[2][3];
487 }
488
489 void Matrix4x4_FromArray12FloatGL(matrix4x4_t *out, const float in[12])
490 {
491         out->m[0][0] = in[0];
492         out->m[1][0] = in[1];
493         out->m[2][0] = in[2];
494         out->m[3][0] = 0;
495         out->m[0][1] = in[3];
496         out->m[1][1] = in[4];
497         out->m[2][1] = in[5];
498         out->m[3][1] = 0;
499         out->m[0][2] = in[6];
500         out->m[1][2] = in[7];
501         out->m[2][2] = in[8];
502         out->m[3][2] = 0;
503         out->m[0][3] = in[9];
504         out->m[1][3] = in[10];
505         out->m[2][3] = in[11];
506         out->m[3][3] = 1;
507 }
508
509 void Matrix4x4_ToArray12FloatD3D(const matrix4x4_t *in, float out[12])
510 {
511         out[ 0] = in->m[0][0];
512         out[ 1] = in->m[0][1];
513         out[ 2] = in->m[0][2];
514         out[ 3] = in->m[0][3];
515         out[ 4] = in->m[1][0];
516         out[ 5] = in->m[1][1];
517         out[ 6] = in->m[1][2];
518         out[ 7] = in->m[1][3];
519         out[ 8] = in->m[2][0];
520         out[ 9] = in->m[2][1];
521         out[10] = in->m[2][2];
522         out[11] = in->m[2][3];
523 }
524
525 void Matrix4x4_FromArray12FloatD3D(matrix4x4_t *out, const float in[12])
526 {
527         out->m[0][0] = in[0];
528         out->m[0][1] = in[1];
529         out->m[0][2] = in[2];
530         out->m[0][3] = in[3];
531         out->m[1][0] = in[4];
532         out->m[1][1] = in[5];
533         out->m[1][2] = in[6];
534         out->m[1][3] = in[7];
535         out->m[2][0] = in[8];
536         out->m[2][1] = in[9];
537         out->m[2][2] = in[10];
538         out->m[2][3] = in[11];
539         out->m[3][0] = 0;
540         out->m[3][1] = 0;
541         out->m[3][2] = 0;
542         out->m[3][3] = 1;
543 }
544
545 void Matrix4x4_FromOriginQuat(matrix4x4_t *m, double ox, double oy, double oz, double x, double y, double z, double w)
546 {
547         m->m[0][0]=1-2*(y*y+z*z);m->m[0][1]=  2*(x*y-z*w);m->m[0][2]=  2*(x*z+y*w);m->m[0][3]=ox;
548         m->m[1][0]=  2*(x*y+z*w);m->m[1][1]=1-2*(x*x+z*z);m->m[1][2]=  2*(y*z-x*w);m->m[1][3]=oy;
549         m->m[2][0]=  2*(x*z-y*w);m->m[2][1]=  2*(y*z+x*w);m->m[2][2]=1-2*(x*x+y*y);m->m[2][3]=oz;
550         m->m[3][0]=  0          ;m->m[3][1]=  0          ;m->m[3][2]=  0          ;m->m[3][3]=1;
551 }
552
553 // LordHavoc: I got this code from:
554 //http://www.doom3world.org/phpbb2/viewtopic.php?t=2884
555 void Matrix4x4_FromDoom3Joint(matrix4x4_t *m, double ox, double oy, double oz, double x, double y, double z)
556 {
557         double w = 1.0 - (x*x+y*y+z*z);
558         w = w > 0.0 ? -sqrt(w) : 0.0;
559         m->m[0][0]=1-2*(y*y+z*z);m->m[0][1]=  2*(x*y-z*w);m->m[0][2]=  2*(x*z+y*w);m->m[0][3]=ox;
560         m->m[1][0]=  2*(x*y+z*w);m->m[1][1]=1-2*(x*x+z*z);m->m[1][2]=  2*(y*z-x*w);m->m[1][3]=oy;
561         m->m[2][0]=  2*(x*z-y*w);m->m[2][1]=  2*(y*z+x*w);m->m[2][2]=1-2*(x*x+y*y);m->m[2][3]=oz;
562         m->m[3][0]=  0          ;m->m[3][1]=  0          ;m->m[3][2]=  0          ;m->m[3][3]=1;
563 }
564
565 void Matrix4x4_Blend (matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2, double blend)
566 {
567         double iblend = 1 - blend;
568         out->m[0][0] = in1->m[0][0] * iblend + in2->m[0][0] * blend;
569         out->m[0][1] = in1->m[0][1] * iblend + in2->m[0][1] * blend;
570         out->m[0][2] = in1->m[0][2] * iblend + in2->m[0][2] * blend;
571         out->m[0][3] = in1->m[0][3] * iblend + in2->m[0][3] * blend;
572         out->m[1][0] = in1->m[1][0] * iblend + in2->m[1][0] * blend;
573         out->m[1][1] = in1->m[1][1] * iblend + in2->m[1][1] * blend;
574         out->m[1][2] = in1->m[1][2] * iblend + in2->m[1][2] * blend;
575         out->m[1][3] = in1->m[1][3] * iblend + in2->m[1][3] * blend;
576         out->m[2][0] = in1->m[2][0] * iblend + in2->m[2][0] * blend;
577         out->m[2][1] = in1->m[2][1] * iblend + in2->m[2][1] * blend;
578         out->m[2][2] = in1->m[2][2] * iblend + in2->m[2][2] * blend;
579         out->m[2][3] = in1->m[2][3] * iblend + in2->m[2][3] * blend;
580         out->m[3][0] = in1->m[3][0] * iblend + in2->m[3][0] * blend;
581         out->m[3][1] = in1->m[3][1] * iblend + in2->m[3][1] * blend;
582         out->m[3][2] = in1->m[3][2] * iblend + in2->m[3][2] * blend;
583         out->m[3][3] = in1->m[3][3] * iblend + in2->m[3][3] * blend;
584 }
585
586
587 void Matrix4x4_Transform (const matrix4x4_t *in, const float v[3], float out[3])
588 {
589         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2] + in->m[0][3];
590         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2] + in->m[1][3];
591         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2] + in->m[2][3];
592 }
593
594 void Matrix4x4_Transform4 (const matrix4x4_t *in, const float v[4], float out[4])
595 {
596         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2] + v[3] * in->m[0][3];
597         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2] + v[3] * in->m[1][3];
598         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2] + v[3] * in->m[2][3];
599         out[3] = v[0] * in->m[3][0] + v[1] * in->m[3][1] + v[2] * in->m[3][2] + v[3] * in->m[3][3];
600 }
601
602 void Matrix4x4_Transform3x3 (const matrix4x4_t *in, const float v[3], float out[3])
603 {
604         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2];
605         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2];
606         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2];
607 }
608
609 /*
610 void Matrix4x4_SimpleUntransform (const matrix4x4_t *in, const float v[3], float out[3])
611 {
612         double t[3];
613         t[0] = v[0] - in->m[0][3];
614         t[1] = v[1] - in->m[1][3];
615         t[2] = v[2] - in->m[2][3];
616         out[0] = t[0] * in->m[0][0] + t[1] * in->m[1][0] + t[2] * in->m[2][0];
617         out[1] = t[0] * in->m[0][1] + t[1] * in->m[1][1] + t[2] * in->m[2][1];
618         out[2] = t[0] * in->m[0][2] + t[1] * in->m[1][2] + t[2] * in->m[2][2];
619 }
620 */
621
622 // FIXME: optimize
623 void Matrix4x4_ConcatTranslate (matrix4x4_t *out, double x, double y, double z)
624 {
625         matrix4x4_t base, temp;
626         base = *out;
627         Matrix4x4_CreateTranslate(&temp, x, y, z);
628         Matrix4x4_Concat(out, &base, &temp);
629 }
630
631 // FIXME: optimize
632 void Matrix4x4_ConcatRotate (matrix4x4_t *out, double angle, double x, double y, double z)
633 {
634         matrix4x4_t base, temp;
635         base = *out;
636         Matrix4x4_CreateRotate(&temp, angle, x, y, z);
637         Matrix4x4_Concat(out, &base, &temp);
638 }
639
640 // FIXME: optimize
641 void Matrix4x4_ConcatScale (matrix4x4_t *out, double x)
642 {
643         matrix4x4_t base, temp;
644         base = *out;
645         Matrix4x4_CreateScale(&temp, x);
646         Matrix4x4_Concat(out, &base, &temp);
647 }
648
649 // FIXME: optimize
650 void Matrix4x4_ConcatScale3 (matrix4x4_t *out, double x, double y, double z)
651 {
652         matrix4x4_t base, temp;
653         base = *out;
654         Matrix4x4_CreateScale3(&temp, x, y, z);
655         Matrix4x4_Concat(out, &base, &temp);
656 }
657
658 void Matrix4x4_OriginFromMatrix (const matrix4x4_t *in, float *out)
659 {
660         out[0] = in->m[0][3];
661         out[1] = in->m[1][3];
662         out[2] = in->m[2][3];
663 }
664
665 double Matrix4x4_ScaleFromMatrix (const matrix4x4_t *in)
666 {
667         // we only support uniform scaling, so assume the first row is enough
668         return (float)sqrt(in->m[0][0] * in->m[0][0] + in->m[0][1] * in->m[0][1] + in->m[0][2] * in->m[0][2]);
669 }
670
671 void Matrix4x4_SetOrigin (matrix4x4_t *out, double x, double y, double z)
672 {
673         out->m[0][3] = x;
674         out->m[1][3] = y;
675         out->m[2][3] = z;
676 }
677
678 void Matrix4x4_AdjustOrigin (matrix4x4_t *out, double x, double y, double z)
679 {
680         out->m[0][3] += x;
681         out->m[1][3] += y;
682         out->m[2][3] += z;
683 }
684