more cleaning of matrix4x4_t struct access
[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_ToArrayDoubleGL(const matrix4x4_t *in, double out[16])
434 {
435         out[ 0] = in->m[0][0];
436         out[ 1] = in->m[1][0];
437         out[ 2] = in->m[2][0];
438         out[ 3] = in->m[3][0];
439         out[ 4] = in->m[0][1];
440         out[ 5] = in->m[1][1];
441         out[ 6] = in->m[2][1];
442         out[ 7] = in->m[3][1];
443         out[ 8] = in->m[0][2];
444         out[ 9] = in->m[1][2];
445         out[10] = in->m[2][2];
446         out[11] = in->m[3][2];
447         out[12] = in->m[0][3];
448         out[13] = in->m[1][3];
449         out[14] = in->m[2][3];
450         out[15] = in->m[3][3];
451 }
452
453 void Matrix4x4_FromArrayDoubleGL (matrix4x4_t *out, const double in[16])
454 {
455         out->m[0][0] = in[0];
456         out->m[1][0] = in[1];
457         out->m[2][0] = in[2];
458         out->m[3][0] = in[3];
459         out->m[0][1] = in[4];
460         out->m[1][1] = in[5];
461         out->m[2][1] = in[6];
462         out->m[3][1] = in[7];
463         out->m[0][2] = in[8];
464         out->m[1][2] = in[9];
465         out->m[2][2] = in[10];
466         out->m[3][2] = in[11];
467         out->m[0][3] = in[12];
468         out->m[1][3] = in[13];
469         out->m[2][3] = in[14];
470         out->m[3][3] = in[15];
471 }
472
473 void Matrix4x4_ToArrayDoubleD3D(const matrix4x4_t *in, double out[16])
474 {
475         out[ 0] = in->m[0][0];
476         out[ 1] = in->m[0][1];
477         out[ 2] = in->m[0][2];
478         out[ 3] = in->m[0][3];
479         out[ 4] = in->m[1][0];
480         out[ 5] = in->m[1][1];
481         out[ 6] = in->m[1][2];
482         out[ 7] = in->m[1][3];
483         out[ 8] = in->m[2][0];
484         out[ 9] = in->m[2][1];
485         out[10] = in->m[2][2];
486         out[11] = in->m[2][3];
487         out[12] = in->m[3][0];
488         out[13] = in->m[3][1];
489         out[14] = in->m[3][2];
490         out[15] = in->m[3][3];
491 }
492
493 void Matrix4x4_FromArrayDoubleD3D (matrix4x4_t *out, const double in[16])
494 {
495         out->m[0][0] = in[0];
496         out->m[0][1] = in[1];
497         out->m[0][2] = in[2];
498         out->m[0][3] = in[3];
499         out->m[1][0] = in[4];
500         out->m[1][1] = in[5];
501         out->m[1][2] = in[6];
502         out->m[1][3] = in[7];
503         out->m[2][0] = in[8];
504         out->m[2][1] = in[9];
505         out->m[2][2] = in[10];
506         out->m[2][3] = in[11];
507         out->m[3][0] = in[12];
508         out->m[3][1] = in[13];
509         out->m[3][2] = in[14];
510         out->m[3][3] = in[15];
511 }
512
513 void Matrix4x4_ToArray12FloatGL(const matrix4x4_t *in, float out[12])
514 {
515         out[ 0] = in->m[0][0];
516         out[ 1] = in->m[1][0];
517         out[ 2] = in->m[2][0];
518         out[ 3] = in->m[0][1];
519         out[ 4] = in->m[1][1];
520         out[ 5] = in->m[2][1];
521         out[ 6] = in->m[0][2];
522         out[ 7] = in->m[1][2];
523         out[ 8] = in->m[2][2];
524         out[ 9] = in->m[0][3];
525         out[10] = in->m[1][3];
526         out[11] = in->m[2][3];
527 }
528
529 void Matrix4x4_FromArray12FloatGL(matrix4x4_t *out, const float in[12])
530 {
531         out->m[0][0] = in[0];
532         out->m[1][0] = in[1];
533         out->m[2][0] = in[2];
534         out->m[3][0] = 0;
535         out->m[0][1] = in[3];
536         out->m[1][1] = in[4];
537         out->m[2][1] = in[5];
538         out->m[3][1] = 0;
539         out->m[0][2] = in[6];
540         out->m[1][2] = in[7];
541         out->m[2][2] = in[8];
542         out->m[3][2] = 0;
543         out->m[0][3] = in[9];
544         out->m[1][3] = in[10];
545         out->m[2][3] = in[11];
546         out->m[3][3] = 1;
547 }
548
549 void Matrix4x4_ToArray12FloatD3D(const matrix4x4_t *in, float out[12])
550 {
551         out[ 0] = in->m[0][0];
552         out[ 1] = in->m[0][1];
553         out[ 2] = in->m[0][2];
554         out[ 3] = in->m[0][3];
555         out[ 4] = in->m[1][0];
556         out[ 5] = in->m[1][1];
557         out[ 6] = in->m[1][2];
558         out[ 7] = in->m[1][3];
559         out[ 8] = in->m[2][0];
560         out[ 9] = in->m[2][1];
561         out[10] = in->m[2][2];
562         out[11] = in->m[2][3];
563 }
564
565 void Matrix4x4_FromArray12FloatD3D(matrix4x4_t *out, const float in[12])
566 {
567         out->m[0][0] = in[0];
568         out->m[0][1] = in[1];
569         out->m[0][2] = in[2];
570         out->m[0][3] = in[3];
571         out->m[1][0] = in[4];
572         out->m[1][1] = in[5];
573         out->m[1][2] = in[6];
574         out->m[1][3] = in[7];
575         out->m[2][0] = in[8];
576         out->m[2][1] = in[9];
577         out->m[2][2] = in[10];
578         out->m[2][3] = in[11];
579         out->m[3][0] = 0;
580         out->m[3][1] = 0;
581         out->m[3][2] = 0;
582         out->m[3][3] = 1;
583 }
584
585 void Matrix4x4_FromOriginQuat(matrix4x4_t *m, double ox, double oy, double oz, double x, double y, double z, double w)
586 {
587         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;
588         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;
589         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;
590         m->m[3][0]=  0          ;m->m[3][1]=  0          ;m->m[3][2]=  0          ;m->m[3][3]=1;
591 }
592
593 // LordHavoc: I got this code from:
594 //http://www.doom3world.org/phpbb2/viewtopic.php?t=2884
595 void Matrix4x4_FromDoom3Joint(matrix4x4_t *m, double ox, double oy, double oz, double x, double y, double z)
596 {
597         double w = 1.0 - (x*x+y*y+z*z);
598         w = w > 0.0 ? -sqrt(w) : 0.0;
599         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;
600         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;
601         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;
602         m->m[3][0]=  0          ;m->m[3][1]=  0          ;m->m[3][2]=  0          ;m->m[3][3]=1;
603 }
604
605 void Matrix4x4_Blend (matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2, double blend)
606 {
607         double iblend = 1 - blend;
608         out->m[0][0] = in1->m[0][0] * iblend + in2->m[0][0] * blend;
609         out->m[0][1] = in1->m[0][1] * iblend + in2->m[0][1] * blend;
610         out->m[0][2] = in1->m[0][2] * iblend + in2->m[0][2] * blend;
611         out->m[0][3] = in1->m[0][3] * iblend + in2->m[0][3] * blend;
612         out->m[1][0] = in1->m[1][0] * iblend + in2->m[1][0] * blend;
613         out->m[1][1] = in1->m[1][1] * iblend + in2->m[1][1] * blend;
614         out->m[1][2] = in1->m[1][2] * iblend + in2->m[1][2] * blend;
615         out->m[1][3] = in1->m[1][3] * iblend + in2->m[1][3] * blend;
616         out->m[2][0] = in1->m[2][0] * iblend + in2->m[2][0] * blend;
617         out->m[2][1] = in1->m[2][1] * iblend + in2->m[2][1] * blend;
618         out->m[2][2] = in1->m[2][2] * iblend + in2->m[2][2] * blend;
619         out->m[2][3] = in1->m[2][3] * iblend + in2->m[2][3] * blend;
620         out->m[3][0] = in1->m[3][0] * iblend + in2->m[3][0] * blend;
621         out->m[3][1] = in1->m[3][1] * iblend + in2->m[3][1] * blend;
622         out->m[3][2] = in1->m[3][2] * iblend + in2->m[3][2] * blend;
623         out->m[3][3] = in1->m[3][3] * iblend + in2->m[3][3] * blend;
624 }
625
626
627 void Matrix4x4_Transform (const matrix4x4_t *in, const float v[3], float out[3])
628 {
629         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2] + in->m[0][3];
630         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2] + in->m[1][3];
631         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2] + in->m[2][3];
632 }
633
634 void Matrix4x4_Transform4 (const matrix4x4_t *in, const float v[4], float out[4])
635 {
636         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];
637         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];
638         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];
639         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];
640 }
641
642 void Matrix4x4_Transform3x3 (const matrix4x4_t *in, const float v[3], float out[3])
643 {
644         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2];
645         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2];
646         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2];
647 }
648
649 /*
650 void Matrix4x4_SimpleUntransform (const matrix4x4_t *in, const float v[3], float out[3])
651 {
652         double t[3];
653         t[0] = v[0] - in->m[0][3];
654         t[1] = v[1] - in->m[1][3];
655         t[2] = v[2] - in->m[2][3];
656         out[0] = t[0] * in->m[0][0] + t[1] * in->m[1][0] + t[2] * in->m[2][0];
657         out[1] = t[0] * in->m[0][1] + t[1] * in->m[1][1] + t[2] * in->m[2][1];
658         out[2] = t[0] * in->m[0][2] + t[1] * in->m[1][2] + t[2] * in->m[2][2];
659 }
660 */
661
662 // FIXME: optimize
663 void Matrix4x4_ConcatTranslate (matrix4x4_t *out, double x, double y, double z)
664 {
665         matrix4x4_t base, temp;
666         base = *out;
667         Matrix4x4_CreateTranslate(&temp, x, y, z);
668         Matrix4x4_Concat(out, &base, &temp);
669 }
670
671 // FIXME: optimize
672 void Matrix4x4_ConcatRotate (matrix4x4_t *out, double angle, double x, double y, double z)
673 {
674         matrix4x4_t base, temp;
675         base = *out;
676         Matrix4x4_CreateRotate(&temp, angle, x, y, z);
677         Matrix4x4_Concat(out, &base, &temp);
678 }
679
680 // FIXME: optimize
681 void Matrix4x4_ConcatScale (matrix4x4_t *out, double x)
682 {
683         matrix4x4_t base, temp;
684         base = *out;
685         Matrix4x4_CreateScale(&temp, x);
686         Matrix4x4_Concat(out, &base, &temp);
687 }
688
689 // FIXME: optimize
690 void Matrix4x4_ConcatScale3 (matrix4x4_t *out, double x, double y, double z)
691 {
692         matrix4x4_t base, temp;
693         base = *out;
694         Matrix4x4_CreateScale3(&temp, x, y, z);
695         Matrix4x4_Concat(out, &base, &temp);
696 }
697
698 void Matrix4x4_OriginFromMatrix (const matrix4x4_t *in, float *out)
699 {
700         out[0] = in->m[0][3];
701         out[1] = in->m[1][3];
702         out[2] = in->m[2][3];
703 }
704
705 double Matrix4x4_ScaleFromMatrix (const matrix4x4_t *in)
706 {
707         // we only support uniform scaling, so assume the first row is enough
708         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]);
709 }
710
711 void Matrix4x4_SetOrigin (matrix4x4_t *out, double x, double y, double z)
712 {
713         out->m[0][3] = x;
714         out->m[1][3] = y;
715         out->m[2][3] = z;
716 }
717
718 void Matrix4x4_AdjustOrigin (matrix4x4_t *out, double x, double y, double z)
719 {
720         out->m[0][3] += x;
721         out->m[1][3] += y;
722         out->m[2][3] += z;
723 }
724
725 void Matrix4x4_Scale (matrix4x4_t *out, double rotatescale, double originscale)
726 {
727         out->m[0][0] *= rotatescale;
728         out->m[0][1] *= rotatescale;
729         out->m[0][2] *= rotatescale;
730         out->m[0][3] *= originscale;
731         out->m[1][0] *= rotatescale;
732         out->m[1][1] *= rotatescale;
733         out->m[1][2] *= rotatescale;
734         out->m[1][3] *= originscale;
735         out->m[2][0] *= rotatescale;
736         out->m[2][1] *= rotatescale;
737         out->m[2][2] *= rotatescale;
738         out->m[2][3] *= originscale;
739 }