1
/**************************************************************************
3
algebra3.cpp, algebra3.h - C++ Vector and Matrix Algebra routines
5
There are three vector classes and two matrix classes: vec2, vec3,
8
All the standard arithmetic operations are defined, with '*'
9
for dot product of two vectors and multiplication of two matrices,
10
and '^' for cross product of two vectors.
12
Additional functions include length(), normalize(), homogenize for
13
vectors, and print(), set(), apply() for all classes.
15
There is a function transpose() for matrices, but note that it
16
does not actually change the matrix,
18
When multiplied with a matrix, a vector is treated as a row vector
19
if it precedes the matrix (v*M), and as a column vector if it
20
follows the matrix (M*v).
22
Matrices are stored in row-major form.
24
A vector of one dimension (2d, 3d, or 4d) can be cast to a vector
25
of a higher or lower dimension. If casting to a higher dimension,
26
the new component is set by default to 1.0, unless a value is
28
vec3 a(1.0, 2.0, 3.0 );
29
vec4 b( a, 4.0 ); // now b == {1.0, 2.0, 3.0, 4.0};
30
When casting to a lower dimension, the vector is homogenized in
31
the lower dimension. E.g., if a 4d {X,Y,Z,W} is cast to 3d, the
32
resulting vector is {X/W, Y/W, Z/W}. It is up to the user to
33
insure the fourth component is not zero before casting.
35
There are also the following function for building matrices:
36
identity2D(), translation2D(), rotation2D(),
37
scaling2D(), identity3D(), translation3D(),
38
rotation3D(), rotation3Drad(), scaling3D(),
42
---------------------------------------------------------------------
44
Author: Jean-Francois DOUEg
45
Revised: Paul Rademacher
46
Version 3.2 - Feb 1998
48
**************************************************************************/
54
/****************************************************************
56
* vec2 Member functions *
58
****************************************************************/
60
/******************** vec2 CONSTRUCTORS ********************/
63
{n[VX] = n[VY] = 0.0; }
65
vec2::vec2(const float x, const float y)
66
{ n[VX] = x; n[VY] = y; }
68
vec2::vec2(const float d)
69
{ n[VX] = n[VY] = d; }
71
vec2::vec2(const vec2& v)
72
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; }
74
vec2::vec2(const vec3& v) // it is up to caller to avoid divide-by-zero
75
{ n[VX] = v.n[VX]/v.n[VZ]; n[VY] = v.n[VY]/v.n[VZ]; };
77
vec2::vec2(const vec3& v, int dropAxis) {
79
case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; break;
80
case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; break;
81
default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; break;
86
/******************** vec2 ASSIGNMENT OPERATORS ******************/
88
vec2& vec2::operator = (const vec2& v)
89
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; return *this; }
91
vec2& vec2::operator += ( const vec2& v )
92
{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; return *this; }
94
vec2& vec2::operator -= ( const vec2& v )
95
{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; return *this; }
97
vec2& vec2::operator *= ( const float d )
98
{ n[VX] *= d; n[VY] *= d; return *this; }
100
vec2& vec2::operator /= ( const float d )
101
{ float d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; return *this; }
103
float& vec2::operator [] ( int i) {
104
if (i < VX || i > VY)
105
//VEC_ERROR("vec2 [] operator: illegal access; index = " << i << '\n')
106
VEC_ERROR("vec2 [] operator: illegal access" );
111
/******************** vec2 SPECIAL FUNCTIONS ********************/
113
float vec2::length(void)
114
{ return sqrt(length2()); }
116
float vec2::length2(void)
117
{ return n[VX]*n[VX] + n[VY]*n[VY]; }
119
vec2& vec2::normalize(void) // it is up to caller to avoid divide-by-zero
120
{ *this /= length(); return *this; }
122
vec2& vec2::apply(V_FCT_PTR fct)
123
{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); return *this; }
125
void vec2::set( float x, float y )
126
{ n[VX] = x; n[VY] = y; }
128
/******************** vec2 FRIENDS *****************************/
130
vec2 operator - (const vec2& a)
131
{ return vec2(-a.n[VX],-a.n[VY]); }
133
vec2 operator + (const vec2& a, const vec2& b)
134
{ return vec2(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY]); }
136
vec2 operator - (const vec2& a, const vec2& b)
137
{ return vec2(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY]); }
139
vec2 operator * (const vec2& a, const float d)
140
{ return vec2(d*a.n[VX], d*a.n[VY]); }
142
vec2 operator * (const float d, const vec2& a)
145
vec2 operator * (const mat3& a, const vec2& v) {
148
av.n[VX] = a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ];
149
av.n[VY] = a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ];
150
av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ];
154
vec2 operator * (const vec2& v, mat3& a)
155
{ return a.transpose() * v; }
157
vec3 operator * (const mat3& a, const vec3& v) {
161
a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ]*v.n[VZ];
163
a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ]*v.n[VZ];
165
a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ]*v.n[VZ];
169
vec3 operator * (const vec3& v, mat3& a)
170
{ return a.transpose() * v; }
172
float operator * (const vec2& a, const vec2& b)
173
{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]); }
175
vec2 operator / (const vec2& a, const float d)
176
{ float d_inv = 1./d; return vec2(a.n[VX]*d_inv, a.n[VY]*d_inv); }
178
vec3 operator ^ (const vec2& a, const vec2& b)
179
{ return vec3(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); }
181
int operator == (const vec2& a, const vec2& b)
182
{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); }
184
int operator != (const vec2& a, const vec2& b)
185
{ return !(a == b); }
187
/*ostream& operator << (ostream& s, vec2& v)
188
{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << " |"; }
191
/*istream& operator >> (istream& s, vec2& v) {
197
// The vectors can be formatted either as x y or | x y |
199
s >> v_tmp[VX] >> v_tmp[VY];
200
while (s >> c && isspace(c)) ;
206
s >> v_tmp[VX] >> v_tmp[VY];
214
void swap(vec2& a, vec2& b)
215
{ vec2 tmp(a); a = b; b = tmp; }
217
vec2 min_vec(const vec2& a, const vec2& b)
218
{ return vec2(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); }
220
vec2 max_vec(const vec2& a, const vec2& b)
221
{ return vec2(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); }
223
vec2 prod(const vec2& a, const vec2& b)
224
{ return vec2(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); }
226
/****************************************************************
228
* vec3 Member functions *
230
****************************************************************/
235
{n[VX] = n[VY] = n[VZ] = 0.0;}
237
vec3::vec3(const float x, const float y, const float z)
238
{ n[VX] = x; n[VY] = y; n[VZ] = z; }
240
vec3::vec3(const float d)
241
{ n[VX] = n[VY] = n[VZ] = d; }
243
vec3::vec3(const vec3& v)
244
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; }
246
vec3::vec3(const vec2& v)
247
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = 1.0; }
249
vec3::vec3(const vec2& v, float d)
250
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = d; }
252
vec3::vec3(const vec4& v) // it is up to caller to avoid divide-by-zero
253
{ n[VX] = v.n[VX] / v.n[VW]; n[VY] = v.n[VY] / v.n[VW];
254
n[VZ] = v.n[VZ] / v.n[VW]; }
256
vec3::vec3(const vec4& v, int dropAxis) {
258
case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break;
259
case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break;
260
case VZ: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VW]; break;
261
default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; break;
266
// ASSIGNMENT OPERATORS
268
vec3& vec3::operator = (const vec3& v)
269
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; return *this; }
271
vec3& vec3::operator += ( const vec3& v )
272
{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; return *this; }
274
vec3& vec3::operator -= ( const vec3& v )
275
{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; return *this; }
277
vec3& vec3::operator *= ( const float d )
278
{ n[VX] *= d; n[VY] *= d; n[VZ] *= d; return *this; }
280
vec3& vec3::operator /= ( const float d )
281
{ float d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv;
284
float& vec3::operator [] ( int i) {
285
if (i < VX || i > VZ)
286
//VEC_ERROR("vec3 [] operator: illegal access; index = " << i << '\n')
287
VEC_ERROR("vec3 [] operator: illegal access" );
295
float vec3::length(void)
296
{ return sqrt(length2()); }
298
float vec3::length2(void)
299
{ return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ]; }
301
vec3& vec3::normalize(void) // it is up to caller to avoid divide-by-zero
302
{ *this /= length(); return *this; }
304
vec3& vec3::homogenize(void) // it is up to caller to avoid divide-by-zero
305
{ n[VX] /= n[VZ]; n[VY] /= n[VZ]; n[VZ] = 1.0; return *this; }
307
vec3& vec3::apply(V_FCT_PTR fct)
308
{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]);
311
void vec3::set( float x, float y, float z ) // set vector
312
{ n[VX] = x; n[VY] = y; n[VZ] = z; }
314
void vec3::print( FILE *file, char *name ) // print vector to a file
316
fprintf( file, "%s: <%f, %f, %f>\n", name, n[VX], n[VY], n[VZ] );
321
vec3 operator - (const vec3& a)
322
{ return vec3(-a.n[VX],-a.n[VY],-a.n[VZ]); }
324
vec3 operator + (const vec3& a, const vec3& b)
325
{ return vec3(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ]); }
327
vec3 operator - (const vec3& a, const vec3& b)
328
{ return vec3(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY], a.n[VZ]-b.n[VZ]); }
330
vec3 operator * (const vec3& a, const float d)
331
{ return vec3(d*a.n[VX], d*a.n[VY], d*a.n[VZ]); }
333
vec3 operator * (const float d, const vec3& a)
336
vec3 operator * (const mat4& a, const vec3& v)
337
{ return a * vec4(v); }
339
vec3 operator * (const vec3& v, mat4& a)
340
{ return a.transpose() * v; }
342
float operator * (const vec3& a, const vec3& b)
343
{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]); }
345
vec3 operator / (const vec3& a, const float d)
346
{ float d_inv = 1./d; return vec3(a.n[VX]*d_inv, a.n[VY]*d_inv,
349
vec3 operator ^ (const vec3& a, const vec3& b) {
350
return vec3(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY],
351
a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ],
352
a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]);
355
int operator == (const vec3& a, const vec3& b)
356
{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]);
359
int operator != (const vec3& a, const vec3& b)
360
{ return !(a == b); }
362
/*ostream& operator << (ostream& s, vec3& v)
363
{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << " |"; }
365
istream& operator >> (istream& s, vec3& v) {
371
// The vectors can be formatted either as x y z or | x y z |
373
s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ];
374
while (s >> c && isspace(c)) ;
380
s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ];
388
void swap(vec3& a, vec3& b)
389
{ vec3 tmp(a); a = b; b = tmp; }
391
vec3 min_vec(const vec3& a, const vec3& b)
392
{ return vec3(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ],
395
vec3 max_vec(const vec3& a, const vec3& b)
396
{ return vec3(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ],
399
vec3 prod(const vec3& a, const vec3& b)
400
{ return vec3(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ]); }
402
/****************************************************************
404
* vec4 Member functions *
406
****************************************************************/
411
{n[VX] = n[VY] = n[VZ] = 0.0; n[VW] = 1.0; }
413
vec4::vec4(const float x, const float y, const float z, const float w)
414
{ n[VX] = x; n[VY] = y; n[VZ] = z; n[VW] = w; }
416
vec4::vec4(const float d)
417
{ n[VX] = n[VY] = n[VZ] = n[VW] = d; }
419
vec4::vec4(const vec4& v)
420
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW]; }
422
vec4::vec4(const vec3& v)
423
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = 1.0; }
425
vec4::vec4(const vec3& v, const float d)
426
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = d; }
429
// ASSIGNMENT OPERATORS
431
vec4& vec4::operator = (const vec4& v)
432
{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW];
435
vec4& vec4::operator += ( const vec4& v )
436
{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; n[VW] += v.n[VW];
439
vec4& vec4::operator -= ( const vec4& v )
440
{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; n[VW] -= v.n[VW];
443
vec4& vec4::operator *= ( const float d )
444
{ n[VX] *= d; n[VY] *= d; n[VZ] *= d; n[VW] *= d; return *this; }
446
vec4& vec4::operator /= ( const float d )
447
{ float d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv;
448
n[VW] *= d_inv; return *this; }
450
float& vec4::operator [] ( int i) {
451
if (i < VX || i > VW)
452
//VEC_ERROR("vec4 [] operator: illegal access; index = " << i << '\n')
453
VEC_ERROR("vec4 [] operator: illegal access" );
461
float vec4::length(void)
462
{ return sqrt(length2()); }
464
float vec4::length2(void)
465
{ return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ] + n[VW]*n[VW]; }
467
vec4& vec4::normalize(void) // it is up to caller to avoid divide-by-zero
468
{ *this /= length(); return *this; }
470
vec4& vec4::homogenize(void) // it is up to caller to avoid divide-by-zero
471
{ n[VX] /= n[VW]; n[VY] /= n[VW]; n[VZ] /= n[VW]; n[VW] = 1.0; return *this; }
473
vec4& vec4::apply(V_FCT_PTR fct)
474
{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]);
475
n[VW] = (*fct)(n[VW]); return *this; }
477
void vec4::print( FILE *file, char *name ) // print vector to a file
479
fprintf( file, "%s: <%f, %f, %f, %f>\n", name, n[VX], n[VY], n[VZ], n[VW] );
482
void vec4::set( float x, float y, float z, float a )
484
n[0] = x; n[1] = y; n[2] = z; n[3] = a;
490
vec4 operator - (const vec4& a)
491
{ return vec4(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); }
493
vec4 operator + (const vec4& a, const vec4& b)
494
{ return vec4(a.n[VX] + b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ],
495
a.n[VW] + b.n[VW]); }
497
vec4 operator - (const vec4& a, const vec4& b)
498
{ return vec4(a.n[VX] - b.n[VX], a.n[VY] - b.n[VY], a.n[VZ] - b.n[VZ],
499
a.n[VW] - b.n[VW]); }
501
vec4 operator * (const vec4& a, const float d)
502
{ return vec4(d*a.n[VX], d*a.n[VY], d*a.n[VZ], d*a.n[VW] ); }
504
vec4 operator * (const float d, const vec4& a)
507
vec4 operator * (const mat4& a, const vec4& v) {
508
#define ROWCOL(i) a.v[i].n[0]*v.n[VX] + a.v[i].n[1]*v.n[VY] \
509
+ a.v[i].n[2]*v.n[VZ] + a.v[i].n[3]*v.n[VW]
510
return vec4(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3));
514
vec4 operator * (const vec4& v, mat4& a)
515
{ return a.transpose() * v; }
517
float operator * (const vec4& a, const vec4& b)
518
{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ] +
521
vec4 operator / (const vec4& a, const float d)
522
{ float d_inv = 1./d; return vec4(a.n[VX]*d_inv, a.n[VY]*d_inv, a.n[VZ]*d_inv,
525
int operator == (const vec4& a, const vec4& b)
526
{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ])
527
&& (a.n[VW] == b.n[VW]); }
529
int operator != (const vec4& a, const vec4& b)
530
{ return !(a == b); }
532
/*ostream& operator << (ostream& s, vec4& v)
533
{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << ' '
534
<< v.n[VW] << " |"; }
536
istream& operator >> (istream& s, vec4& v) {
542
// The vectors can be formatted either as x y z w or | x y z w |
544
s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW];
545
while (s >> c && isspace(c)) ;
551
s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW];
558
void swap(vec4& a, vec4& b)
559
{ vec4 tmp(a); a = b; b = tmp; }
561
vec4 min_vec(const vec4& a, const vec4& b)
562
{ return vec4(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ],
563
b.n[VZ]), MIN(a.n[VW], b.n[VW])); }
565
vec4 max_vec(const vec4& a, const vec4& b)
566
{ return vec4(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ],
567
b.n[VZ]), MAX(a.n[VW], b.n[VW])); }
569
vec4 prod(const vec4& a, const vec4& b)
570
{ return vec4(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ],
571
a.n[VW] * b.n[VW]); }
574
/****************************************************************
576
* mat3 member functions *
578
****************************************************************/
582
mat3::mat3(void) { *this = identity2D(); }
584
mat3::mat3(const vec3& v0, const vec3& v1, const vec3& v2)
585
{ this->set( v0, v1, v2 ); };
587
mat3::mat3(const float d)
588
{ v[0] = v[1] = v[2] = vec3(d); }
590
mat3::mat3(const mat3& m)
591
{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; }
594
// ASSIGNMENT OPERATORS
596
mat3& mat3::operator = ( const mat3& m )
597
{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; return *this; }
599
mat3& mat3::operator += ( const mat3& m )
600
{ v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; return *this; }
602
mat3& mat3::operator -= ( const mat3& m )
603
{ v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; return *this; }
605
mat3& mat3::operator *= ( const float d )
606
{ v[0] *= d; v[1] *= d; v[2] *= d; return *this; }
608
mat3& mat3::operator /= ( const float d )
609
{ v[0] /= d; v[1] /= d; v[2] /= d; return *this; }
611
vec3& mat3::operator [] ( int i) {
612
if (i < VX || i > VZ)
613
//VEC_ERROR("mat3 [] operator: illegal access; index = " << i << '\n')
614
VEC_ERROR("mat3 [] operator: illegal access" );
618
void mat3::set( const vec3& v0, const vec3& v1, const vec3& v2 ) {
619
v[0] = v0; v[1] = v1; v[2] = v2;
624
mat3 mat3::transpose(void) {
625
return mat3(vec3(v[0][0], v[1][0], v[2][0]),
626
vec3(v[0][1], v[1][1], v[2][1]),
627
vec3(v[0][2], v[1][2], v[2][2]));
630
mat3 mat3::inverse(void) // Gauss-Jordan elimination with partial pivoting
632
mat3 a(*this), // As a evolves from original mat into identity
633
b(identity2D()); // b evolves from identity into inverse(a)
636
// Loop over cols of a from left to right, eliminating above and below diag
637
for (j=0; j<3; j++) { // Find largest pivot in column j among rows j..2
638
i1 = j; // Row with largest pivot candidate
639
for (i=j+1; i<3; i++)
640
if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
643
// Swap rows i1 and j in a and b to put pivot on diagonal
644
swap(a.v[i1], a.v[j]);
645
swap(b.v[i1], b.v[j]);
647
// Scale row j to have a unit diagonal
649
VEC_ERROR("mat3::inverse: singular matrix; can't invert\n");
650
b.v[j] /= a.v[j].n[j];
651
a.v[j] /= a.v[j].n[j];
653
// Eliminate off-diagonal elems in col j of a, doing identical ops to b
656
b.v[i] -= a.v[i].n[j]*b.v[j];
657
a.v[i] -= a.v[i].n[j]*a.v[j];
663
mat3& mat3::apply(V_FCT_PTR fct) {
673
mat3 operator - (const mat3& a)
674
{ return mat3(-a.v[0], -a.v[1], -a.v[2]); }
676
mat3 operator + (const mat3& a, const mat3& b)
677
{ return mat3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]); }
679
mat3 operator - (const mat3& a, const mat3& b)
680
{ return mat3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]); }
682
mat3 operator * (mat3& a, mat3& b) {
683
#define ROWCOL(i, j) \
684
a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + a.v[i].n[2]*b.v[2][j]
685
return mat3(vec3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)),
686
vec3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)),
687
vec3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2)));
691
mat3 operator * (const mat3& a, const float d)
692
{ return mat3(a.v[0] * d, a.v[1] * d, a.v[2] * d); }
694
mat3 operator * (const float d, const mat3& a)
697
mat3 operator / (const mat3& a, const float d)
698
{ return mat3(a.v[0] / d, a.v[1] / d, a.v[2] / d); }
700
int operator == (const mat3& a, const mat3& b)
701
{ return (a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]); }
703
int operator != (const mat3& a, const mat3& b)
704
{ return !(a == b); }
706
/*ostream& operator << (ostream& s, mat3& m)
707
{ return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ]; }
709
istream& operator >> (istream& s, mat3& m) {
712
s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ];
719
void swap(mat3& a, mat3& b)
720
{ mat3 tmp(a); a = b; b = tmp; }
722
void mat3::print( FILE *file, char *name )
726
fprintf( stderr, "%s:\n", name );
728
for( i = 0; i < 3; i++ )
730
fprintf( stderr, " " );
731
for( j = 0; j < 3; j++ )
733
fprintf( stderr, "%f ", v[i][j] );
735
fprintf( stderr, "\n" );
741
/****************************************************************
743
* mat4 member functions *
745
****************************************************************/
749
mat4::mat4(void) { *this = identity3D();}
751
mat4::mat4(const vec4& v0, const vec4& v1, const vec4& v2, const vec4& v3)
752
{ v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; }
754
mat4::mat4(const float d)
755
{ v[0] = v[1] = v[2] = v[3] = vec4(d); }
757
mat4::mat4(const mat4& m)
758
{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3]; }
760
mat4::mat4(const float a00, const float a01, const float a02, const float a03,
761
const float a10, const float a11, const float a12, const float a13,
762
const float a20, const float a21, const float a22, const float a23,
763
const float a30, const float a31, const float a32, const float a33 )
765
v[0][0] = a00; v[0][1] = a01; v[0][2] = a02; v[0][3] = a03;
766
v[1][0] = a10; v[1][1] = a11; v[1][2] = a12; v[1][3] = a13;
767
v[2][0] = a20; v[2][1] = a21; v[2][2] = a22; v[2][3] = a23;
768
v[3][0] = a30; v[3][1] = a31; v[3][2] = a32; v[3][3] = a33;
771
// ASSIGNMENT OPERATORS
773
mat4& mat4::operator = ( const mat4& m )
774
{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3];
777
mat4& mat4::operator += ( const mat4& m )
778
{ v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; v[3] += m.v[3];
781
mat4& mat4::operator -= ( const mat4& m )
782
{ v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; v[3] -= m.v[3];
785
mat4& mat4::operator *= ( const float d )
786
{ v[0] *= d; v[1] *= d; v[2] *= d; v[3] *= d; return *this; }
788
mat4& mat4::operator /= ( const float d )
789
{ v[0] /= d; v[1] /= d; v[2] /= d; v[3] /= d; return *this; }
791
vec4& mat4::operator [] ( int i) {
792
if (i < VX || i > VW)
793
//VEC_ERROR("mat4 [] operator: illegal access; index = " << i << '\n')
794
VEC_ERROR("mat4 [] operator: illegal access" );
798
// SPECIAL FUNCTIONS;
800
mat4 mat4::transpose(void) {
801
return mat4(vec4(v[0][0], v[1][0], v[2][0], v[3][0]),
802
vec4(v[0][1], v[1][1], v[2][1], v[3][1]),
803
vec4(v[0][2], v[1][2], v[2][2], v[3][2]),
804
vec4(v[0][3], v[1][3], v[2][3], v[3][3]));
807
mat4 mat4::inverse(void) // Gauss-Jordan elimination with partial pivoting
809
mat4 a(*this), // As a evolves from original mat into identity
810
b(identity3D()); // b evolves from identity into inverse(a)
813
// Loop over cols of a from left to right, eliminating above and below diag
814
for (j=0; j<4; j++) { // Find largest pivot in column j among rows j..3
815
i1 = j; // Row with largest pivot candidate
816
for (i=j+1; i<4; i++)
817
if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
820
// Swap rows i1 and j in a and b to put pivot on diagonal
821
swap(a.v[i1], a.v[j]);
822
swap(b.v[i1], b.v[j]);
824
// Scale row j to have a unit diagonal
826
VEC_ERROR("mat4::inverse: singular matrix; can't invert\n");
827
b.v[j] /= a.v[j].n[j];
828
a.v[j] /= a.v[j].n[j];
830
// Eliminate off-diagonal elems in col j of a, doing identical ops to b
833
b.v[i] -= a.v[i].n[j]*b.v[j];
834
a.v[i] -= a.v[i].n[j]*a.v[j];
840
mat4& mat4::apply(V_FCT_PTR fct)
841
{ v[VX].apply(fct); v[VY].apply(fct); v[VZ].apply(fct); v[VW].apply(fct);
845
void mat4::print( FILE *file, char *name )
849
fprintf( stderr, "%s:\n", name );
851
for( i = 0; i < 4; i++ )
853
fprintf( stderr, " " );
854
for( j = 0; j < 4; j++ )
856
fprintf( stderr, "%f ", v[i][j] );
858
fprintf( stderr, "\n" );
862
void mat4::swap_rows( int i, int j )
871
void mat4::swap_cols( int i, int j )
876
for(k=0; k<4; k++ ) {
886
mat4 operator - (const mat4& a)
887
{ return mat4(-a.v[0], -a.v[1], -a.v[2], -a.v[3]); }
889
mat4 operator + (const mat4& a, const mat4& b)
890
{ return mat4(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2],
894
mat4 operator - (const mat4& a, const mat4& b)
895
{ return mat4(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2], a.v[3] - b.v[3]); }
897
mat4 operator * (mat4& a, mat4& b) {
898
#define ROWCOL(i, j) a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + \
899
a.v[i].n[2]*b.v[2][j] + a.v[i].n[3]*b.v[3][j]
901
vec4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
902
vec4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
903
vec4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
904
vec4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
908
mat4 operator * (const mat4& a, const float d)
909
{ return mat4(a.v[0] * d, a.v[1] * d, a.v[2] * d, a.v[3] * d); }
911
mat4 operator * (const float d, const mat4& a)
914
mat4 operator / (const mat4& a, const float d)
915
{ return mat4(a.v[0] / d, a.v[1] / d, a.v[2] / d, a.v[3] / d); }
917
int operator == (const mat4& a, const mat4& b)
918
{ return ((a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]) &&
919
(a.v[3] == b.v[3])); }
921
int operator != (const mat4& a, const mat4& b)
922
{ return !(a == b); }
924
/*ostream& operator << (ostream& s, mat4& m)
925
{ return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ] << '\n' << m.v[VW]; }
927
istream& operator >> (istream& s, mat4& m)
931
s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ] >> m_tmp[VW];
937
void swap(mat4& a, mat4& b)
938
{ mat4 tmp(a); a = b; b = tmp; }
941
/****************************************************************
943
* 2D functions and 3D functions *
945
****************************************************************/
947
mat3 identity2D(void)
948
{ return mat3(vec3(1.0, 0.0, 0.0),
950
vec3(0.0, 0.0, 1.0)); }
952
mat3 translation2D(vec2& v)
953
{ return mat3(vec3(1.0, 0.0, v[VX]),
954
vec3(0.0, 1.0, v[VY]),
955
vec3(0.0, 0.0, 1.0)); }
957
mat3 rotation2D(vec2& Center, const float angleDeg) {
958
float angleRad = angleDeg * M_PI / 180.0,
962
return mat3(vec3(c, -s, Center[VX] * (1.0-c) + Center[VY] * s),
963
vec3(s, c, Center[VY] * (1.0-c) - Center[VX] * s),
964
vec3(0.0, 0.0, 1.0));
967
mat3 scaling2D(vec2& scaleVector)
968
{ return mat3(vec3(scaleVector[VX], 0.0, 0.0),
969
vec3(0.0, scaleVector[VY], 0.0),
970
vec3(0.0, 0.0, 1.0)); }
972
mat4 identity3D(void)
973
{ return mat4(vec4(1.0, 0.0, 0.0, 0.0),
974
vec4(0.0, 1.0, 0.0, 0.0),
975
vec4(0.0, 0.0, 1.0, 0.0),
976
vec4(0.0, 0.0, 0.0, 1.0)); }
978
mat4 translation3D(vec3& v)
979
{ return mat4(vec4(1.0, 0.0, 0.0, v[VX]),
980
vec4(0.0, 1.0, 0.0, v[VY]),
981
vec4(0.0, 0.0, 1.0, v[VZ]),
982
vec4(0.0, 0.0, 0.0, 1.0)); }
984
mat4 rotation3D(vec3& Axis, const float angleDeg) {
985
float angleRad = angleDeg * M_PI / 180.0,
991
return mat4(vec4(t * Axis[VX] * Axis[VX] + c,
992
t * Axis[VX] * Axis[VY] - s * Axis[VZ],
993
t * Axis[VX] * Axis[VZ] + s * Axis[VY],
995
vec4(t * Axis[VX] * Axis[VY] + s * Axis[VZ],
996
t * Axis[VY] * Axis[VY] + c,
997
t * Axis[VY] * Axis[VZ] - s * Axis[VX],
999
vec4(t * Axis[VX] * Axis[VZ] - s * Axis[VY],
1000
t * Axis[VY] * Axis[VZ] + s * Axis[VX],
1001
t * Axis[VZ] * Axis[VZ] + c,
1003
vec4(0.0, 0.0, 0.0, 1.0));
1006
mat4 rotation3Drad(vec3& Axis, const float angleRad) {
1007
float c = cos(angleRad),
1012
return mat4(vec4(t * Axis[VX] * Axis[VX] + c,
1013
t * Axis[VX] * Axis[VY] - s * Axis[VZ],
1014
t * Axis[VX] * Axis[VZ] + s * Axis[VY],
1016
vec4(t * Axis[VX] * Axis[VY] + s * Axis[VZ],
1017
t * Axis[VY] * Axis[VY] + c,
1018
t * Axis[VY] * Axis[VZ] - s * Axis[VX],
1020
vec4(t * Axis[VX] * Axis[VZ] - s * Axis[VY],
1021
t * Axis[VY] * Axis[VZ] + s * Axis[VX],
1022
t * Axis[VZ] * Axis[VZ] + c,
1024
vec4(0.0, 0.0, 0.0, 1.0));
1027
mat4 scaling3D(vec3& scaleVector)
1028
{ return mat4(vec4(scaleVector[VX], 0.0, 0.0, 0.0),
1029
vec4(0.0, scaleVector[VY], 0.0, 0.0),
1030
vec4(0.0, 0.0, scaleVector[VZ], 0.0),
1031
vec4(0.0, 0.0, 0.0, 1.0)); }
1033
mat4 perspective3D(const float d)
1034
{ return mat4(vec4(1.0, 0.0, 0.0, 0.0),
1035
vec4(0.0, 1.0, 0.0, 0.0),
1036
vec4(0.0, 0.0, 1.0, 0.0),
1037
vec4(0.0, 0.0, 1.0/d, 0.0)); }