]> icculus.org git repositories - divverent/darkplaces.git/blob - matrixlib.c
removed scr_conspeed, now always instantaneous console opening/closing
[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] = 0.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] = 0.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] = 0.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, float x, float y, float 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, float angle, float x, float y, float z)
225 {
226         float 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, float 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, float x, float y, float 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, float x, float y, float z, float pitch, float yaw, float roll, float 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_Blend (matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2, float blend)
434 {
435         float iblend = 1 - blend;
436         out->m[0][0] = in1->m[0][0] * iblend + in2->m[0][0] * blend;
437         out->m[0][1] = in1->m[0][1] * iblend + in2->m[0][1] * blend;
438         out->m[0][2] = in1->m[0][2] * iblend + in2->m[0][2] * blend;
439         out->m[0][3] = in1->m[0][3] * iblend + in2->m[0][3] * blend;
440         out->m[1][0] = in1->m[1][0] * iblend + in2->m[1][0] * blend;
441         out->m[1][1] = in1->m[1][1] * iblend + in2->m[1][1] * blend;
442         out->m[1][2] = in1->m[1][2] * iblend + in2->m[1][2] * blend;
443         out->m[1][3] = in1->m[1][3] * iblend + in2->m[1][3] * blend;
444         out->m[2][0] = in1->m[2][0] * iblend + in2->m[2][0] * blend;
445         out->m[2][1] = in1->m[2][1] * iblend + in2->m[2][1] * blend;
446         out->m[2][2] = in1->m[2][2] * iblend + in2->m[2][2] * blend;
447         out->m[2][3] = in1->m[2][3] * iblend + in2->m[2][3] * blend;
448         out->m[3][0] = in1->m[3][0] * iblend + in2->m[3][0] * blend;
449         out->m[3][1] = in1->m[3][1] * iblend + in2->m[3][1] * blend;
450         out->m[3][2] = in1->m[3][2] * iblend + in2->m[3][2] * blend;
451         out->m[3][3] = in1->m[3][3] * iblend + in2->m[3][3] * blend;
452 }
453
454
455 void Matrix4x4_Transform (const matrix4x4_t *in, const float v[3], float out[3])
456 {
457         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2] + in->m[0][3];
458         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2] + in->m[1][3];
459         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2] + in->m[2][3];
460 }
461
462 void Matrix4x4_Transform4 (const matrix4x4_t *in, const float v[4], float out[4])
463 {
464         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];
465         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];
466         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];
467         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];
468 }
469
470 void Matrix4x4_Transform3x3 (const matrix4x4_t *in, const float v[3], float out[3])
471 {
472         out[0] = v[0] * in->m[0][0] + v[1] * in->m[0][1] + v[2] * in->m[0][2];
473         out[1] = v[0] * in->m[1][0] + v[1] * in->m[1][1] + v[2] * in->m[1][2];
474         out[2] = v[0] * in->m[2][0] + v[1] * in->m[2][1] + v[2] * in->m[2][2];
475 }
476
477 /*
478 void Matrix4x4_SimpleUntransform (const matrix4x4_t *in, const float v[3], float out[3])
479 {
480         float t[3];
481         t[0] = v[0] - in->m[0][3];
482         t[1] = v[1] - in->m[1][3];
483         t[2] = v[2] - in->m[2][3];
484         out[0] = t[0] * in->m[0][0] + t[1] * in->m[1][0] + t[2] * in->m[2][0];
485         out[1] = t[0] * in->m[0][1] + t[1] * in->m[1][1] + t[2] * in->m[2][1];
486         out[2] = t[0] * in->m[0][2] + t[1] * in->m[1][2] + t[2] * in->m[2][2];
487 }
488 */
489
490 // FIXME: optimize
491 void Matrix4x4_ConcatTranslate (matrix4x4_t *out, float x, float y, float z)
492 {
493         matrix4x4_t base, temp;
494         base = *out;
495         Matrix4x4_CreateTranslate(&temp, x, y, z);
496         Matrix4x4_Concat(out, &base, &temp);
497 }
498
499 // FIXME: optimize
500 void Matrix4x4_ConcatRotate (matrix4x4_t *out, float angle, float x, float y, float z)
501 {
502         matrix4x4_t base, temp;
503         base = *out;
504         Matrix4x4_CreateRotate(&temp, angle, x, y, z);
505         Matrix4x4_Concat(out, &base, &temp);
506 }
507
508 // FIXME: optimize
509 void Matrix4x4_ConcatScale (matrix4x4_t *out, float x)
510 {
511         matrix4x4_t base, temp;
512         base = *out;
513         Matrix4x4_CreateScale(&temp, x);
514         Matrix4x4_Concat(out, &base, &temp);
515 }
516
517 // FIXME: optimize
518 void Matrix4x4_ConcatScale3 (matrix4x4_t *out, float x, float y, float z)
519 {
520         matrix4x4_t base, temp;
521         base = *out;
522         Matrix4x4_CreateScale3(&temp, x, y, z);
523         Matrix4x4_Concat(out, &base, &temp);
524 }
525
526 void Matrix4x4_OriginFromMatrix (const matrix4x4_t *in, float *out)
527 {
528         out[0] = in->m[0][3];
529         out[1] = in->m[1][3];
530         out[2] = in->m[2][3];
531 }
532
533 float Matrix4x4_ScaleFromMatrix (const matrix4x4_t *in)
534 {
535         // we only support uniform scaling, so assume the first row is enough
536         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]);
537 }
538