rmath3d 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,95 @@
1
+ /* -*- C -*- */
2
+ #ifndef RMATHMTX3_H_INCLUDED
3
+ #define RMATHMTX3_H_INCLUDED
4
+
5
+ #include "RType.h"
6
+
7
+ struct RVec3;
8
+ struct RQuat;
9
+
10
+ typedef struct RMtx3
11
+ {
12
+ union
13
+ {
14
+ /* NOTE : column-major */
15
+ struct
16
+ {
17
+ rmReal e00, e10, e20;
18
+ rmReal e01, e11, e21;
19
+ rmReal e02, e12, e22;
20
+ };
21
+ rmReal e[9];
22
+ };
23
+ } RMtx3;
24
+
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
29
+ void RMtx3SetElements( RMtx3* out,
30
+ rmReal e00, rmReal e01, rmReal e02,
31
+ rmReal e10, rmReal e11, rmReal e12,
32
+ rmReal e20, rmReal e21, rmReal e22
33
+ );
34
+
35
+ void RMtx3SetElement( RMtx3* out, int row, int col, rmReal e );
36
+ rmReal RMtx3GetElement( const RMtx3* in, int row, int col );
37
+
38
+ void RMtx3GetRow( struct RVec3* out, const RMtx3* in, int row );
39
+ void RMtx3GetColumn( struct RVec3* out, const RMtx3* in, int col );
40
+
41
+ void RMtx3SetRow( struct RMtx3* out, const RVec3* in, int row );
42
+ void RMtx3SetColumn( struct RMtx3* out, const RVec3* in, int col );
43
+
44
+ void RMtx3Copy( RMtx3* out, const RMtx3* in );
45
+
46
+ void RMtx3Zero( RMtx3* out );
47
+ void RMtx3Identity( RMtx3* out );
48
+ rmReal RMtx3Determinant( const RMtx3* in );
49
+ void RMtx3Transpose( RMtx3* out, const RMtx3* in );
50
+ rmReal RMtx3Inverse( RMtx3* out, const RMtx3* in );
51
+
52
+ void RMtx3RotationX( RMtx3* out, rmReal radian );
53
+ void RMtx3RotationY( RMtx3* out, rmReal radian );
54
+ void RMtx3RotationZ( RMtx3* out, rmReal radian );
55
+ void RMtx3RotationAxis( RMtx3* out, const struct RVec3* axis, rmReal radian );
56
+ void RMtx3RotationQuaternion( RMtx3* out, const struct RQuat* q );
57
+ void RMtx3Scaling( RMtx3* out, rmReal sx, rmReal sy, rmReal sz );
58
+
59
+ int RMtx3Equal( const RMtx3* m1, const RMtx3* m2 );
60
+
61
+ void RMtx3Add( RMtx3* out, const RMtx3* m1, const RMtx3* m2 );
62
+ void RMtx3Sub( RMtx3* out, const RMtx3* m1, const RMtx3* m2 );
63
+ void RMtx3Mul( RMtx3* out, const RMtx3* m1, const RMtx3* m2 );
64
+ void RMtx3Scale( RMtx3* out, const RMtx3* m, rmReal f );
65
+
66
+ #ifdef __cplusplus
67
+ }
68
+ #endif
69
+
70
+
71
+ #endif
72
+
73
+ /*
74
+ RMath : Ruby math module for 3D Applications
75
+ Copyright (c) 2008- vaiorabbit <http://twitter.com/vaiorabbit>
76
+
77
+ This software is provided 'as-is', without any express or implied
78
+ warranty. In no event will the authors be held liable for any damages
79
+ arising from the use of this software.
80
+
81
+ Permission is granted to anyone to use this software for any purpose,
82
+ including commercial applications, and to alter it and redistribute it
83
+ freely, subject to the following restrictions:
84
+
85
+ 1. The origin of this software must not be misrepresented; you must not
86
+ claim that you wrote the original software. If you use this software
87
+ in a product, an acknowledgment in the product documentation would be
88
+ appreciated but is not required.
89
+
90
+ 2. Altered source versions must be plainly marked as such, and must not be
91
+ misrepresented as being the original software.
92
+
93
+ 3. This notice may not be removed or altered from any source
94
+ distribution.
95
+ */
@@ -0,0 +1,572 @@
1
+ #include <math.h>
2
+ #include <string.h>
3
+
4
+ #include "RVec3.h"
5
+ #include "RVec4.h"
6
+ #include "RQuat.h"
7
+ #include "RMtx3.h"
8
+ #include "RMtx4.h"
9
+
10
+ /* NOTE : column-major */
11
+ #define SET_ELEMENT(out, row, col, val) (out)->e[(col)*4+(row)] = (val)
12
+ #define GET_ELEMENT(in, row, col) ((in)->e[(col)*4+(row)])
13
+
14
+ void
15
+ RMtx4SetElement( RMtx4* out, int row, int col, rmReal e )
16
+ {
17
+ SET_ELEMENT( out, row, col, e );
18
+ }
19
+
20
+ rmReal
21
+ RMtx4GetElement( const RMtx4* in, int row, int col )
22
+ {
23
+ return GET_ELEMENT( in, row, col );
24
+ }
25
+
26
+ void
27
+ RMtx4GetRow( RVec4* out, const RMtx4* in, int row )
28
+ {
29
+ RVec4SetX( out, GET_ELEMENT( in, row, 0 ) );
30
+ RVec4SetY( out, GET_ELEMENT( in, row, 1 ) );
31
+ RVec4SetZ( out, GET_ELEMENT( in, row, 2 ) );
32
+ RVec4SetW( out, GET_ELEMENT( in, row, 3 ) );
33
+ }
34
+
35
+ void
36
+ RMtx4GetColumn( RVec4* out, const RMtx4* in, int col )
37
+ {
38
+ RVec4SetX( out, GET_ELEMENT( in, 0, col ) );
39
+ RVec4SetY( out, GET_ELEMENT( in, 1, col ) );
40
+ RVec4SetZ( out, GET_ELEMENT( in, 2, col ) );
41
+ RVec4SetW( out, GET_ELEMENT( in, 3, col ) );
42
+ }
43
+
44
+ void
45
+ RMtx4SetRow( RMtx4* out, const RVec4* in, int row )
46
+ {
47
+ SET_ELEMENT( out, row, 0, RVec4GetElement( in, 0 ) );
48
+ SET_ELEMENT( out, row, 1, RVec4GetElement( in, 1 ) );
49
+ SET_ELEMENT( out, row, 2, RVec4GetElement( in, 2 ) );
50
+ SET_ELEMENT( out, row, 3, RVec4GetElement( in, 3 ) );
51
+ }
52
+
53
+ void
54
+ RMtx4SetColumn( RMtx4* out, const RVec4* in, int col )
55
+ {
56
+ SET_ELEMENT( out, 0, col, RVec4GetElement( in, 0 ) );
57
+ SET_ELEMENT( out, 1, col, RVec4GetElement( in, 1 ) );
58
+ SET_ELEMENT( out, 2, col, RVec4GetElement( in, 2 ) );
59
+ SET_ELEMENT( out, 3, col, RVec4GetElement( in, 3 ) );
60
+ }
61
+
62
+ void
63
+ RMtx4GetUpper3x3( RMtx3* out, const RMtx4* in )
64
+ {
65
+ RMtx3SetElements( out,
66
+ GET_ELEMENT(in,0,0), GET_ELEMENT(in,0,1), GET_ELEMENT(in,0,2),
67
+ GET_ELEMENT(in,1,0), GET_ELEMENT(in,1,1), GET_ELEMENT(in,1,2),
68
+ GET_ELEMENT(in,2,0), GET_ELEMENT(in,2,1), GET_ELEMENT(in,2,2) );
69
+ }
70
+
71
+ void
72
+ RMtx4SetUpper3x3( RMtx4* out, const RMtx3* in )
73
+ {
74
+ SET_ELEMENT( out, 0, 0, RMtx3GetElement( in, 0, 0 ) );
75
+ SET_ELEMENT( out, 0, 1, RMtx3GetElement( in, 0, 1 ) );
76
+ SET_ELEMENT( out, 0, 2, RMtx3GetElement( in, 0, 2 ) );
77
+ SET_ELEMENT( out, 1, 0, RMtx3GetElement( in, 1, 0 ) );
78
+ SET_ELEMENT( out, 1, 1, RMtx3GetElement( in, 1, 1 ) );
79
+ SET_ELEMENT( out, 1, 2, RMtx3GetElement( in, 1, 2 ) );
80
+ SET_ELEMENT( out, 2, 0, RMtx3GetElement( in, 2, 0 ) );
81
+ SET_ELEMENT( out, 2, 1, RMtx3GetElement( in, 2, 1 ) );
82
+ SET_ELEMENT( out, 2, 2, RMtx3GetElement( in, 2, 2 ) );
83
+ }
84
+
85
+ void
86
+ RMtx4Copy( RMtx4* out, const RMtx4* in )
87
+ {
88
+ memmove( out, in, sizeof(RMtx4) );
89
+ }
90
+
91
+ void
92
+ RMtx4SetElements( RMtx4* out,
93
+ rmReal e00, rmReal e01, rmReal e02, rmReal e03,
94
+ rmReal e10, rmReal e11, rmReal e12, rmReal e13,
95
+ rmReal e20, rmReal e21, rmReal e22, rmReal e23,
96
+ rmReal e30, rmReal e31, rmReal e32, rmReal e33
97
+ )
98
+ {
99
+ SET_ELEMENT( out, 0, 0, e00 );
100
+ SET_ELEMENT( out, 0, 1, e01 );
101
+ SET_ELEMENT( out, 0, 2, e02 );
102
+ SET_ELEMENT( out, 0, 3, e03 );
103
+
104
+ SET_ELEMENT( out, 1, 0, e10 );
105
+ SET_ELEMENT( out, 1, 1, e11 );
106
+ SET_ELEMENT( out, 1, 2, e12 );
107
+ SET_ELEMENT( out, 1, 3, e13 );
108
+
109
+ SET_ELEMENT( out, 2, 0, e20 );
110
+ SET_ELEMENT( out, 2, 1, e21 );
111
+ SET_ELEMENT( out, 2, 2, e22 );
112
+ SET_ELEMENT( out, 2, 3, e23 );
113
+
114
+ SET_ELEMENT( out, 3, 0, e30 );
115
+ SET_ELEMENT( out, 3, 1, e31 );
116
+ SET_ELEMENT( out, 3, 2, e32 );
117
+ SET_ELEMENT( out, 3, 3, e33 );
118
+ }
119
+
120
+ void
121
+ RMtx4Zero( RMtx4* out )
122
+ {
123
+ int row, col;
124
+ for ( row = 0; row < 4; ++row )
125
+ for ( col = 0; col < 4; ++col )
126
+ SET_ELEMENT( out, row, col, 0.0f );
127
+ }
128
+
129
+ void
130
+ RMtx4Identity( RMtx4* out )
131
+ {
132
+ int row, col;
133
+ for ( row = 0; row < 4; ++row )
134
+ for ( col = 0; col < 4; ++col )
135
+ SET_ELEMENT( out, row, col, (row==col) ? 1.0f : 0.0f );
136
+ }
137
+
138
+ rmReal
139
+ RMtx4Determinant( const RMtx4* in )
140
+ {
141
+ #define I( r, c ) GET_ELEMENT( in, (r), (c) )
142
+ #define D( e00,e01,e02, e10,e11,e12, e20,e21,e22 ) \
143
+ ( (e00)*((e11)*(e22)-(e12)*(e21)) \
144
+ - (e01)*((e10)*(e22)-(e12)*(e20)) \
145
+ + (e02)*((e10)*(e21)-(e11)*(e20)) )
146
+
147
+ return
148
+ I(0,0) * D( I(1,1),I(1,2),I(1,3), I(2,1),I(2,2),I(2,3), I(3,1),I(3,2),I(3,3) ) -
149
+ I(0,1) * D( I(1,0),I(1,2),I(1,3), I(2,0),I(2,2),I(2,3), I(3,0),I(3,2),I(3,3) ) +
150
+ I(0,2) * D( I(1,0),I(1,1),I(1,3), I(2,0),I(2,1),I(2,3), I(3,0),I(3,1),I(3,3) ) -
151
+ I(0,3) * D( I(1,0),I(1,1),I(1,2), I(2,0),I(2,1),I(2,2), I(3,0),I(3,1),I(3,2) ) ;
152
+
153
+ #undef I
154
+ #undef D
155
+ }
156
+
157
+ void
158
+ RMtx4Transpose( RMtx4* out, const RMtx4* in )
159
+ {
160
+ int row, col;
161
+ RMtx4 tmp;
162
+ for ( row = 0; row < 4; ++row )
163
+ for ( col = 0; col < 4; ++col )
164
+ SET_ELEMENT( &tmp, row, col, GET_ELEMENT( in, col, row ) );
165
+
166
+ RMtx4Copy( out, &tmp );
167
+ }
168
+
169
+ rmReal
170
+ RMtx4Inverse( RMtx4* out, const RMtx4* in )
171
+ {
172
+ #define I( r, c ) GET_ELEMENT( in, (r), (c) )
173
+ #define R( r, c ) GET_ELEMENT( &result, (r), (c) )
174
+ #define D( e00,e01,e02, e10,e11,e12, e20,e21,e22 ) \
175
+ ( (e00)*((e11)*(e22)-(e12)*(e21)) \
176
+ - (e01)*((e10)*(e22)-(e12)*(e20)) \
177
+ + (e02)*((e10)*(e21)-(e11)*(e20)) )
178
+
179
+ RMtx4 result;
180
+ rmReal det;
181
+
182
+ SET_ELEMENT( &result, 0, 0,
183
+ D( I(1,1),I(1,2),I(1,3), I(2,1),I(2,2),I(2,3), I(3,1),I(3,2),I(3,3) ) );
184
+
185
+ SET_ELEMENT( &result, 0, 1,
186
+ -D( I(0,1),I(0,2),I(0,3), I(2,1),I(2,2),I(2,3), I(3,1),I(3,2),I(3,3) ) );
187
+
188
+ SET_ELEMENT( &result, 0, 2,
189
+ D( I(0,1),I(0,2),I(0,3), I(1,1),I(1,2),I(1,3), I(3,1),I(3,2),I(3,3) ) );
190
+
191
+ SET_ELEMENT( &result, 0, 3,
192
+ -D( I(0,1),I(0,2),I(0,3), I(1,1),I(1,2),I(1,3), I(2,1),I(2,2),I(2,3) ) );
193
+
194
+ SET_ELEMENT( &result, 1, 0,
195
+ -D( I(1,0),I(1,2),I(1,3), I(2,0),I(2,2),I(2,3), I(3,0),I(3,2),I(3,3) ) );
196
+
197
+ SET_ELEMENT( &result, 1, 1,
198
+ D( I(0,0),I(0,2),I(0,3), I(2,0),I(2,2),I(2,3), I(3,0),I(3,2),I(3,3) ) );
199
+
200
+ SET_ELEMENT( &result, 1, 2,
201
+ -D( I(0,0),I(0,2),I(0,3), I(1,0),I(1,2),I(1,3), I(3,0),I(3,2),I(3,3) ) );
202
+
203
+ SET_ELEMENT( &result, 1, 3,
204
+ D( I(0,0),I(0,2),I(0,3), I(1,0),I(1,2),I(1,3), I(2,0),I(2,2),I(2,3) ) );
205
+
206
+ SET_ELEMENT( &result, 2, 0,
207
+ D( I(1,0),I(1,1),I(1,3), I(2,0),I(2,1),I(2,3), I(3,0),I(3,1),I(3,3) ) );
208
+
209
+ SET_ELEMENT( &result, 2, 1,
210
+ -D( I(0,0),I(0,1),I(0,3), I(2,0),I(2,1),I(2,3), I(3,0),I(3,1),I(3,3) ) );
211
+
212
+ SET_ELEMENT( &result, 2, 2,
213
+ D( I(0,0),I(0,1),I(0,3), I(1,0),I(1,1),I(1,3), I(3,0),I(3,1),I(3,3) ) );
214
+
215
+ SET_ELEMENT( &result, 2, 3,
216
+ -D( I(0,0),I(0,1),I(0,3), I(1,0),I(1,1),I(1,3), I(2,0),I(2,1),I(2,3) ) );
217
+
218
+ SET_ELEMENT( &result, 3, 0,
219
+ -D( I(1,0),I(1,1),I(1,2), I(2,0),I(2,1),I(2,2), I(3,0),I(3,1),I(3,2) ) );
220
+
221
+ SET_ELEMENT( &result, 3, 1,
222
+ D( I(0,0),I(0,1),I(0,2), I(2,0),I(2,1),I(2,2), I(3,0),I(3,1),I(3,2) ) );
223
+
224
+ SET_ELEMENT( &result, 3, 2,
225
+ -D( I(0,0),I(0,1),I(0,2), I(1,0),I(1,1),I(1,2), I(3,0),I(3,1),I(3,2) ) );
226
+
227
+ SET_ELEMENT( &result, 3, 3,
228
+ D( I(0,0),I(0,1),I(0,2), I(1,0),I(1,1),I(1,2), I(2,0),I(2,1),I(2,2) ) );
229
+
230
+ det = I(0,0) * R(0,0) + I(0,1) * R(1,0) + I(0,2) * R(2,0) + I(0,3) * R(3,0);
231
+
232
+ if ( rmFabs(det) < RMATH_TOLERANCE )
233
+ return det;
234
+
235
+ RMtx4Scale( out, &result, 1.0f / det );
236
+
237
+ return det;
238
+
239
+ #undef I
240
+ #undef R
241
+ #undef D
242
+ }
243
+
244
+
245
+ void
246
+ RMtx4Translation( RMtx4* out, rmReal tx, rmReal ty, rmReal tz )
247
+ {
248
+ RMtx4Identity( out );
249
+ SET_ELEMENT( out, 0, 3, tx );
250
+ SET_ELEMENT( out, 1, 3, ty );
251
+ SET_ELEMENT( out, 2, 3, tz );
252
+ }
253
+
254
+ /* http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
255
+ http://en.wikipedia.org/wiki/Rotation_matrix
256
+ */
257
+ void
258
+ RMtx4RotationX( RMtx4* out, rmReal radian )
259
+ {
260
+ rmReal s = rmSin( radian );
261
+ rmReal c = rmCos( radian );
262
+
263
+ RMtx4Identity( out );
264
+ SET_ELEMENT( out, 1, 1, c );
265
+ SET_ELEMENT( out, 1, 2, -s );
266
+ SET_ELEMENT( out, 2, 1, s );
267
+ SET_ELEMENT( out, 2, 2, c );
268
+ }
269
+
270
+ /* http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
271
+ http://en.wikipedia.org/wiki/Rotation_matrix
272
+ */
273
+ void
274
+ RMtx4RotationY( RMtx4* out, rmReal radian )
275
+ {
276
+ rmReal s = rmSin( radian );
277
+ rmReal c = rmCos( radian );
278
+
279
+ RMtx4Identity( out );
280
+ SET_ELEMENT( out, 0, 0, c );
281
+ SET_ELEMENT( out, 0, 2, s );
282
+ SET_ELEMENT( out, 2, 0, -s );
283
+ SET_ELEMENT( out, 2, 2, c );
284
+ }
285
+
286
+ /* http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29
287
+ http://en.wikipedia.org/wiki/Rotation_matrix
288
+ */
289
+ void
290
+ RMtx4RotationZ( RMtx4* out, rmReal radian )
291
+ {
292
+ rmReal s = rmSin( radian );
293
+ rmReal c = rmCos( radian );
294
+
295
+ RMtx4Identity( out );
296
+ SET_ELEMENT( out, 0, 0, c );
297
+ SET_ELEMENT( out, 0, 1, -s );
298
+ SET_ELEMENT( out, 1, 0, s );
299
+ SET_ELEMENT( out, 1, 1, c );
300
+ }
301
+
302
+ /* http://en.wikipedia.org/wiki/Rotation_matrix
303
+ */
304
+ void
305
+ RMtx4RotationAxis( RMtx4* out, const RVec3* axis, rmReal radian )
306
+ {
307
+ rmReal s = rmSin( radian );
308
+ rmReal c = rmCos( radian );
309
+ rmReal C = 1.0f - c;
310
+ rmReal x = RVec3GetX( axis );
311
+ rmReal y = RVec3GetY( axis );
312
+ rmReal z = RVec3GetZ( axis );
313
+
314
+ RMtx4Identity( out );
315
+ SET_ELEMENT( out, 0, 0, x*x*C + c );
316
+ SET_ELEMENT( out, 0, 1, x*y*C - z*s );
317
+ SET_ELEMENT( out, 0, 2, z*x*C + y*s );
318
+ SET_ELEMENT( out, 1, 0, x*y*C + z*s );
319
+ SET_ELEMENT( out, 1, 1, y*y*C + c );
320
+ SET_ELEMENT( out, 1, 2, y*z*C - x*s );
321
+ SET_ELEMENT( out, 2, 0, z*x*C - y*s );
322
+ SET_ELEMENT( out, 2, 1, y*z*C + x*s );
323
+ SET_ELEMENT( out, 2, 2, z*z*C + c );
324
+ }
325
+
326
+ /* From Quaternion to Matrix and Back
327
+ http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
328
+ */
329
+ void
330
+ RMtx4RotationQuaternion( RMtx4* out, const struct RQuat* q )
331
+ {
332
+ rmReal x = RQuatGetX( q );
333
+ rmReal y = RQuatGetY( q );
334
+ rmReal z = RQuatGetZ( q );
335
+ rmReal w = RQuatGetW( q );
336
+
337
+ rmReal x2 = 2.0f * x;
338
+ rmReal y2 = 2.0f * y;
339
+ rmReal z2 = 2.0f * z;
340
+
341
+ rmReal xx2 = x * x2;
342
+ rmReal yy2 = y * y2;
343
+ rmReal zz2 = z * z2;
344
+
345
+ rmReal yz2 = y * z2;
346
+ rmReal wx2 = w * x2;
347
+ rmReal xy2 = x * y2;
348
+ rmReal wz2 = w * z2;
349
+ rmReal xz2 = x * z2;
350
+ rmReal wy2 = w * y2;
351
+
352
+ RMtx4Identity( out );
353
+ SET_ELEMENT( out, 0, 0, 1.0f - yy2 - zz2 );
354
+ SET_ELEMENT( out, 1, 0, xy2 + wz2 );
355
+ SET_ELEMENT( out, 2, 0, xz2 - wy2 );
356
+ SET_ELEMENT( out, 0, 1, xy2 - wz2 );
357
+ SET_ELEMENT( out, 1, 1, 1.0f - xx2 - zz2 );
358
+ SET_ELEMENT( out, 2, 1, yz2 + wx2 );
359
+ SET_ELEMENT( out, 0, 2, xz2 + wy2 );
360
+ SET_ELEMENT( out, 1, 2, yz2 - wx2 );
361
+ SET_ELEMENT( out, 2, 2, 1.0f - xx2 - yy2 );
362
+ }
363
+
364
+ void
365
+ RMtx4Scaling( RMtx4* out, rmReal sx, rmReal sy, rmReal sz )
366
+ {
367
+ RMtx4Identity( out );
368
+ SET_ELEMENT( out, 0, 0, sx );
369
+ SET_ELEMENT( out, 1, 1, sy );
370
+ SET_ELEMENT( out, 2, 2, sz );
371
+ }
372
+
373
+
374
+ int
375
+ RMtx4Equal( const RMtx4* m1, const RMtx4* m2 )
376
+ {
377
+ if ( 0 == memcmp( m1, m2, sizeof(RMtx4) ) )
378
+ return !0;
379
+ else
380
+ return 0;
381
+ }
382
+
383
+
384
+ void
385
+ RMtx4Add( RMtx4* out, const RMtx4* m1, const RMtx4* m2 )
386
+ {
387
+ int row, col;
388
+ RMtx4 tmp;
389
+ for ( row = 0; row < 4; ++row )
390
+ for ( col = 0; col < 4; ++col )
391
+ SET_ELEMENT( &tmp, row, col,
392
+ GET_ELEMENT( m1, row, col ) + GET_ELEMENT( m2, row, col ) );
393
+
394
+ RMtx4Copy( out, &tmp );
395
+ }
396
+
397
+ void
398
+ RMtx4Sub( RMtx4* out, const RMtx4* m1, const RMtx4* m2 )
399
+ {
400
+ int row, col;
401
+ for ( row = 0; row < 4; ++row )
402
+ for ( col = 0; col < 4; ++col )
403
+ SET_ELEMENT( out, row, col,
404
+ GET_ELEMENT( m1, row, col ) - GET_ELEMENT( m2, row, col ) );
405
+ }
406
+
407
+ void
408
+ RMtx4Mul( RMtx4* out, const RMtx4* m1, const RMtx4* m2 )
409
+ {
410
+ int row, col;
411
+ RMtx4 tmp;
412
+ for ( row = 0; row < 4; ++row )
413
+ {
414
+ for ( col = 0; col < 4; ++col )
415
+ {
416
+ int i;
417
+ rmReal sum = 0.0f;
418
+ for ( i = 0; i < 4; ++i )
419
+ {
420
+ sum += GET_ELEMENT( m1, row, i ) * GET_ELEMENT( m2, i, col );
421
+ }
422
+ SET_ELEMENT( &tmp, row, col, sum );
423
+ }
424
+ }
425
+
426
+ RMtx4Copy( out, &tmp );
427
+ }
428
+
429
+ void
430
+ RMtx4Scale( RMtx4* out, const RMtx4* m, rmReal f )
431
+ {
432
+ int row, col;
433
+ for ( row = 0; row < 4; ++row )
434
+ for ( col = 0; col < 4; ++col )
435
+ SET_ELEMENT( out, row, col,
436
+ GET_ELEMENT( m, row, col ) * f );
437
+ }
438
+
439
+ /* http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/glu/lookat.html
440
+ http://msdn.microsoft.com/en-us/library/bb205343.aspx
441
+ */
442
+ void
443
+ RMtx4LookAtRH( RMtx4* out, const RVec3* eye, const RVec3* at, const RVec3* up )
444
+ {
445
+ #define AX(i) RVec3GetElement( &axis_x, i )
446
+ #define AY(i) RVec3GetElement( &axis_y, i )
447
+ #define AZ(i) RVec3GetElement( &axis_z, i )
448
+
449
+ RVec3 axis_x, axis_y, axis_z;
450
+
451
+ RMtx4Identity( out );
452
+
453
+ RVec3Sub( &axis_z, eye, at );
454
+ RVec3Normalize( &axis_z, &axis_z );
455
+
456
+ RVec3Cross( &axis_x, up, &axis_z );
457
+ RVec3Normalize( &axis_x, &axis_x );
458
+
459
+ RVec3Cross( &axis_y, &axis_z, &axis_x );
460
+
461
+ SET_ELEMENT( out, 0, 0, AX(0) );
462
+ SET_ELEMENT( out, 0, 1, AX(1) );
463
+ SET_ELEMENT( out, 0, 2, AX(2) );
464
+ SET_ELEMENT( out, 0, 3, -RVec3Dot(&axis_x, eye) );
465
+
466
+ SET_ELEMENT( out, 1, 0, AY(0) );
467
+ SET_ELEMENT( out, 1, 1, AY(1) );
468
+ SET_ELEMENT( out, 1, 2, AY(2) );
469
+ SET_ELEMENT( out, 1, 3, -RVec3Dot(&axis_y, eye) );
470
+
471
+ SET_ELEMENT( out, 2, 0, AZ(0) );
472
+ SET_ELEMENT( out, 2, 1, AZ(1) );
473
+ SET_ELEMENT( out, 2, 2, AZ(2) );
474
+ SET_ELEMENT( out, 2, 3, -RVec3Dot(&axis_z, eye) );
475
+
476
+ #undef AX
477
+ #undef AY
478
+ #undef AZ
479
+ }
480
+
481
+ void
482
+ RMtx4PerspectiveRH( RMtx4* out, rmReal width, rmReal height, rmReal znear, rmReal zfar )
483
+ {
484
+ RMtx4PerspectiveOffCenterRH( out, -width/2.0f, width/2.0f, -height/2.0f, height/2.0f, znear, zfar );
485
+ }
486
+
487
+ /* http://pyopengl.sourceforge.net/documentation/manual/gluPerspective.3G.html
488
+ */
489
+ void
490
+ RMtx4PerspectiveFovRH( RMtx4* out, rmReal fovy_radian, rmReal aspect, rmReal znear, rmReal zfar )
491
+ {
492
+ rmReal f = rmTan( fovy_radian / 2.0f );
493
+ f = 1.0f / f;
494
+
495
+ RMtx4Identity( out );
496
+ SET_ELEMENT( out, 0, 0, f / aspect );
497
+ SET_ELEMENT( out, 1, 1, f );
498
+ SET_ELEMENT( out, 2, 2, (zfar+znear)/(znear-zfar) );
499
+ SET_ELEMENT( out, 2, 3, 2*zfar*znear/(znear-zfar) );
500
+ SET_ELEMENT( out, 3, 2, -1.0f );
501
+ SET_ELEMENT( out, 3, 3, 0.0f );
502
+ }
503
+
504
+ /* http://pyopengl.sourceforge.net/documentation/manual/glFrustum.3G.html
505
+ */
506
+ void
507
+ RMtx4PerspectiveOffCenterRH( RMtx4* out, rmReal left, rmReal right, rmReal bottom, rmReal top, rmReal znear, rmReal zfar )
508
+ {
509
+ rmReal A = (right+left) / (right-left);
510
+ rmReal B = (top+bottom) / (top-bottom);
511
+ rmReal C = -(zfar+znear) / (zfar-znear);
512
+ rmReal D = -(2*znear*zfar) / (zfar-znear);
513
+
514
+ RMtx4Identity( out );
515
+ SET_ELEMENT( out, 0, 0, 2*znear/(right-left) );
516
+ SET_ELEMENT( out, 0, 2, A );
517
+ SET_ELEMENT( out, 1, 1, 2*znear/(top-bottom) );
518
+ SET_ELEMENT( out, 1, 2, B );
519
+ SET_ELEMENT( out, 2, 2, C );
520
+ SET_ELEMENT( out, 2, 3, D );
521
+ SET_ELEMENT( out, 3, 2, -1.0f );
522
+ SET_ELEMENT( out, 3, 3, 0.0f );
523
+ }
524
+
525
+ void
526
+ RMtx4OrthoRH( RMtx4* out, rmReal width, rmReal height, rmReal znear, rmReal zfar )
527
+ {
528
+ RMtx4OrthoOffCenterRH( out, -width/2.0f, width/2.0f, -height/2.0f, height/2.0f, znear, zfar );
529
+ }
530
+
531
+ /* http://pyopengl.sourceforge.net/documentation/manual/glOrtho.3G.html
532
+ */
533
+ void
534
+ RMtx4OrthoOffCenterRH( RMtx4* out, rmReal left, rmReal right, rmReal bottom, rmReal top, rmReal znear, rmReal zfar )
535
+ {
536
+ rmReal tx = (right+left) / (right-left);
537
+ rmReal ty = (top+bottom) / (top-bottom);
538
+ rmReal tz = (zfar+znear) / (zfar-znear);
539
+
540
+ RMtx4Identity( out );
541
+ SET_ELEMENT( out, 0, 0, 2.0f/(right-left) );
542
+ SET_ELEMENT( out, 0, 3, tx );
543
+ SET_ELEMENT( out, 1, 1, 2.0f/(top-bottom) );
544
+ SET_ELEMENT( out, 1, 3, ty );
545
+ SET_ELEMENT( out, 2, 2, -2.0f/(zfar-znear) );
546
+ SET_ELEMENT( out, 2, 3, tz );
547
+ }
548
+
549
+
550
+ /*
551
+ RMath : Ruby math module for 3D Applications
552
+ Copyright (c) 2008- vaiorabbit <http://twitter.com/vaiorabbit>
553
+
554
+ This software is provided 'as-is', without any express or implied
555
+ warranty. In no event will the authors be held liable for any damages
556
+ arising from the use of this software.
557
+
558
+ Permission is granted to anyone to use this software for any purpose,
559
+ including commercial applications, and to alter it and redistribute it
560
+ freely, subject to the following restrictions:
561
+
562
+ 1. The origin of this software must not be misrepresented; you must not
563
+ claim that you wrote the original software. If you use this software
564
+ in a product, an acknowledgment in the product documentation would be
565
+ appreciated but is not required.
566
+
567
+ 2. Altered source versions must be plainly marked as such, and must not be
568
+ misrepresented as being the original software.
569
+
570
+ 3. This notice may not be removed or altered from any source
571
+ distribution.
572
+ */