absence_thelab

view src/common/n3dmath.cpp @ 0:1cffe3409164

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 23 Oct 2014 01:46:07 +0300
parents
children
line source
1 #include "n3dmath.h"
3 #define fsin (float)sin
4 #define fcos (float)cos
6 float frand(float range) {
7 return ((float)rand() / (float)RAND_MAX) * range;
8 }
10 Vector3::Vector3() {
11 x = y = z = 0.0f;
12 }
14 Vector3::Vector3(float x, float y, float z) {
15 this->x = x;
16 this->y = y;
17 this->z = z;
18 }
19 /* inlined
20 float Vector3::DotProduct(const Vector3 &vec) const {
21 return x * vec.x + y * vec.y + z * vec.z;
22 }
24 float DotProduct(const Vector3 &vec1, const Vector3 &vec2) {
25 return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z;
26 }
28 Vector3 Vector3::CrossProduct(const Vector3 &vec) const {
29 return Vector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
30 }
32 Vector3 CrossProduct(const Vector3 &vec1, const Vector3 &vec2) {
33 return Vector3(vec1.y * vec2.z - vec1.z * vec2.y, vec1.z * vec2.x - vec1.x * vec2.z, vec1.x * vec2.y - vec1.y * vec2.x);
34 }
36 Vector3 Vector3::operator +(const Vector3 &vec) const {
37 return Vector3(x + vec.x, y + vec.y, z + vec.z);
38 }
40 Vector3 Vector3::operator -(const Vector3 &vec) const {
41 return Vector3(x - vec.x, y - vec.y, z - vec.z);
42 }
44 Vector3 Vector3::operator *(float scalar) const {
45 return Vector3(x * scalar, y * scalar, z * scalar);
46 }
48 Vector3 Vector3::operator /(float scalar) const {
49 return Vector3(x / scalar, y / scalar, z / scalar);
50 }
52 void Vector3::operator +=(const Vector3 &vec) {
53 x += vec.x;
54 y += vec.y;
55 z += vec.z;
56 }
58 void Vector3::operator -=(const Vector3 &vec) {
59 x -= vec.x;
60 y -= vec.y;
61 z -= vec.z;
62 }
64 void Vector3::operator *=(float scalar) {
65 x *= scalar;
66 y *= scalar;
67 z *= scalar;
68 }
70 void Vector3::operator /=(float scalar) {
71 x /= scalar;
72 y /= scalar;
73 z /= scalar;
74 }
76 Vector3 Vector3::operator -() const {
77 return Vector3(-x, -y, -z);
78 }
80 bool Vector3::operator >(const Vector3 &vec) const {
81 return LengthSq() > vec.LengthSq();
82 }
84 bool Vector3::operator <(const Vector3 &vec) const {
85 return LengthSq() < vec.LengthSq();
86 }
88 bool Vector3::operator >(float len) const {
89 return LengthSq() > len;
90 }
92 bool Vector3::operator <(float len) const {
93 return LengthSq() < len;
94 }
96 bool Vector3::operator ==(const Vector3 &vec) const {
97 return ((*this - vec).Length() < XSmallNumber);
98 }
100 bool Vector3::operator ==(float len) const {
101 return ((this->Length() - len) < XSmallNumber);
102 }
104 Vector3::operator Vector2() const {
105 return Vector2(x, y);
106 }
108 Vector3::operator Vector4() const {
109 return Vector4(x, y, z, 1.0f);
110 }
113 float Vector3::Length() const {
114 return (float)sqrt(x*x + y*y + z*z);
115 }
117 float Vector3::LengthSq() const {
118 return x*x + y*y + z*z;
119 }
121 void Vector3::Normalize() {
122 float len = (float)sqrt(x*x + y*y + z*z);
123 x /= len;
124 y /= len;
125 z /= len;
126 }
128 Vector3 Vector3::Normalized() const {
129 float len = (float)sqrt(x*x + y*y + z*z);
130 return Vector3(x / len, y / len, z / len);
131 }
133 Vector3 Vector3::Reflection(const Vector3 &normal) const {
134 return normal * this->DotProduct(normal) * 2.0f - *this;
135 }
136 */
137 Vector3 Vector3::Refraction(const Vector3 &normal, float FromIOR, float ToIOR) const {
138 float m = FromIOR / ToIOR;
139 Vector3 dir = *this;
140 dir.Normalize();
141 float CosAngleIncoming = dir.DotProduct(normal);
142 float CosAngleRefr = (1.0f / (m*m)) * (float)sqrt(1.0f - m*m * (1 - CosAngleIncoming * CosAngleIncoming));
144 return dir * m - normal * (CosAngleRefr + m * CosAngleIncoming);
145 }
147 void Vector3::Transform(const Matrix4x4 &mat) {
148 // assume row vectors
149 float nx = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + mat.m[3][0];
150 float ny = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + mat.m[3][1];
151 z = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + mat.m[3][2];
152 x = nx;
153 y = ny;
154 }
156 void Vector3::Transform(const Quaternion &quat) {
157 Quaternion vq(0.0f, *this);
158 vq = quat * vq * quat.Inverse();
159 *this = vq.v;
160 }
162 // direct transformations
164 void Vector3::Translate(float x, float y, float z) {
165 this->x += x;
166 this->y += y;
167 this->z += z;
168 }
170 void Vector3::Rotate(float x, float y, float z) {
172 Matrix4x4 xform;
173 xform.SetRotation(x, y, z);
175 Transform(xform);
176 }
178 void Vector3::Rotate(const Vector3 &axis, float angle) {
180 Matrix4x4 xform;
181 xform.SetRotation(axis, angle);
183 Transform(xform);
184 }
186 void Vector3::Scale(float x, float y, float z) {
187 this->x *= x;
188 this->y *= y;
189 this->z *= z;
190 }
192 float &Vector3::operator [](int index) {
193 return !index ? x : index == 1 ? y : z;
194 }
196 std::ostream &operator <<(std::ostream &out, const Vector3 &vec) {
197 out << vec.x << ", " << vec.y << ", " << vec.z;
198 return out;
199 }
201 // ------------- Vector4 implementation ---------------
203 Vector4::Vector4() {
204 x = y = z = 0.0f;
205 }
207 Vector4::Vector4(const Vector4 &vec) {
208 x = vec.x;
209 y = vec.y;
210 z = vec.z;
211 w = vec.w;
212 }
214 Vector4::Vector4(const Vector3 &vec) {
215 x = vec.x;
216 y = vec.y;
217 z = vec.z;
218 w = 1.0f;
219 }
221 Vector4::Vector4(float x, float y, float z, float w) {
222 this->x = x;
223 this->y = y;
224 this->z = z;
225 this->w = w;
226 }
228 float Vector4::DotProduct(const Vector4 &vec) const {
229 return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
230 }
232 float DotProduct(const Vector4 &vec1, const Vector4 &vec2) {
233 return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z + vec1.w * vec2.w;
234 }
236 Vector4 Vector4::CrossProduct(const Vector4 &vec1, const Vector4 &vec2) const {
237 float A, B, C, D, E, F; // Intermediate Values
238 Vector4 result;
240 // Calculate intermediate values.
241 A = (vec1.x * vec2.y) - (vec1.y * vec2.x);
242 B = (vec1.x * vec2.z) - (vec1.z * vec2.x);
243 C = (vec1.x * vec2.w) - (vec1.w * vec2.x);
244 D = (vec1.y * vec2.z) - (vec1.z * vec2.y);
245 E = (vec1.y * vec2.w) - (vec1.w * vec2.y);
246 F = (vec1.z * vec2.w) - (vec1.w * vec2.z);
248 // Calculate the result-vector components.
249 result.x = (y * F) - (z * E) + (w * D);
250 result.y = - (x * F) + (z * C) - (w * B);
251 result.z = (x * E) - (y * C) + (w * A);
252 result.w = - (x * D) + (y * B) - (z * A);
253 return result;
254 }
256 Vector4 CrossProduct(const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3) {
257 float A, B, C, D, E, F; // Intermediate Values
258 Vector4 result;
260 // Calculate intermediate values.
261 A = (vec2.x * vec3.y) - (vec2.y * vec3.x);
262 B = (vec2.x * vec3.z) - (vec2.z * vec3.x);
263 C = (vec2.x * vec3.w) - (vec2.w * vec3.x);
264 D = (vec2.y * vec3.z) - (vec2.z * vec3.y);
265 E = (vec2.y * vec3.w) - (vec2.w * vec3.y);
266 F = (vec2.z * vec3.w) - (vec2.w * vec3.z);
268 // Calculate the result-vector components.
269 result.x = (vec1.y * F) - (vec1.z * E) + (vec1.w * D);
270 result.y = - (vec1.x * F) + (vec1.z * C) - (vec1.w * B);
271 result.z = (vec1.x * E) - (vec1.y * C) + (vec1.w * A);
272 result.w = - (vec1.x * D) + (vec1.y * B) - (vec1.z * A);
273 return result;
274 }
276 Vector4 Vector4::operator +(const Vector4 &vec) const {
277 return Vector4(x + vec.x, y + vec.y, z + vec.z, w + vec.w);
278 }
280 Vector4 Vector4::operator -(const Vector4 &vec) const {
281 return Vector4(x - vec.x, y - vec.y, z - vec.z, w - vec.w);
282 }
284 Vector4 Vector4::operator *(float scalar) const {
285 return Vector4(x * scalar, y * scalar, z * scalar, w * scalar);
286 }
288 Vector4 Vector4::operator /(float scalar) const {
289 return Vector4(x / scalar, y / scalar, z / scalar, w / scalar);
290 }
292 void Vector4::operator +=(const Vector4 &vec) {
293 x += vec.x;
294 y += vec.y;
295 z += vec.z;
296 w += vec.w;
297 }
299 void Vector4::operator -=(const Vector4 &vec) {
300 x -= vec.x;
301 y -= vec.y;
302 z -= vec.z;
303 w -= vec.w;
304 }
306 void Vector4::operator *=(float scalar) {
307 x *= scalar;
308 y *= scalar;
309 z *= scalar;
310 w *= scalar;
311 }
313 void Vector4::operator /=(float scalar) {
314 x /= scalar;
315 y /= scalar;
316 z /= scalar;
317 w /= scalar;
318 }
320 Vector4 Vector4::operator -() const {
321 return Vector4(-x, -y, -z, -w);
322 }
325 bool Vector4::operator >(const Vector4 &vec) const {
326 return LengthSq() > vec.LengthSq();
327 }
329 bool Vector4::operator <(const Vector4 &vec) const {
330 return LengthSq() < vec.LengthSq();
331 }
333 bool Vector4::operator >(float len) const {
334 return LengthSq() > len;
335 }
337 bool Vector4::operator <(float len) const {
338 return LengthSq() < len;
339 }
341 bool Vector4::operator ==(const Vector4 &vec) const {
342 return ((*this - vec).Length() < XSmallNumber);
343 }
345 bool Vector4::operator ==(float len) const {
346 return ((this->Length() - len) < XSmallNumber);
347 }
349 Vector4::operator Vector3() const {
350 return Vector3(x, y, z);
351 }
354 float Vector4::Length() const {
355 return (float)sqrt(x*x + y*y + z*z + w*w);
356 }
358 float Vector4::LengthSq() const {
359 return x*x + y*y + z*z + w*w;
360 }
362 void Vector4::Normalize() {
363 float len = (float)sqrt(x*x + y*y + z*z + w*w);
364 x /= len;
365 y /= len;
366 z /= len;
367 w /= len;
368 }
370 Vector4 Vector4::Normalized() const {
371 float len = (float)sqrt(x*x + y*y + z*z + w*w);
372 return Vector4(x / len, y / len, z / len, w / len);
373 }
375 void Vector4::Transform(const Matrix4x4 &mat) {
376 // assume row vectors
377 float nx = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0];
378 float ny = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1];
379 float nz = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2];
380 w = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3];
381 x = nx;
382 y = ny;
383 z = nz;
384 }
387 // Direct transformations on the vector
388 void Vector4::Translate(float x, float y, float z, float w) {
389 x += x;
390 y += y;
391 z += z;
392 w += w;
393 }
395 void Vector4::Rotate(float x, float y, float z) {
396 Matrix4x4 xform;
397 xform.SetRotation(x, y, z);
398 Transform(xform);
399 }
401 void Vector4::Rotate(const Vector3 &axis, float angle) {
402 Matrix4x4 xform;
403 xform.SetRotation(axis, angle);
404 Transform(xform);
405 }
407 void Vector4::Scale(float x, float y, float z, float w) {
408 this->x *= x;
409 this->y *= y;
410 this->z *= z;
411 this->w *= w;
412 }
414 float &Vector4::operator [](int index) {
415 return !index ? x : index == 1 ? y : index == 2 ? z : w;
416 }
418 std::ostream &operator <<(std::ostream &out, const Vector4 &vec) {
419 out << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w;
420 return out;
421 }
423 // ------------- Vector2 implementation ---------------
425 Vector2::Vector2() {
426 x = y = 0.0f;
427 }
429 Vector2::Vector2(const Vector2 &vec) {
430 x = vec.x;
431 y = vec.y;
432 }
434 Vector2::Vector2(float x, float y) {
435 this->x = x;
436 this->y = y;
437 }
439 float Vector2::DotProduct(const Vector2 &vec) const {
440 return x * vec.x + y * vec.y;
441 }
443 float DotProduct(const Vector2 &vec1, const Vector2 &vec2) {
444 return vec1.x * vec2.x + vec1.y + vec2.y;
445 }
447 Vector2 Vector2::operator +(const Vector2 &vec) const {
448 return Vector2(x + vec.x, y + vec.y);
449 }
451 Vector2 Vector2::operator -(const Vector2 &vec) const {
452 return Vector2(x - vec.x, y - vec.y);
453 }
455 Vector2 Vector2::operator *(float scalar) const {
456 return Vector2(x * scalar, y * scalar);
457 }
459 Vector2 Vector2::operator /(float scalar) const {
460 return Vector2(x / scalar, y / scalar);
461 }
463 void Vector2::operator +=(const Vector2 &vec) {
464 x += vec.x;
465 y += vec.y;
466 }
468 void Vector2::operator -=(const Vector2 &vec) {
469 x -= vec.x;
470 y -= vec.y;
471 }
473 void Vector2::operator *=(float scalar) {
474 x *= scalar;
475 y *= scalar;
476 }
478 void Vector2::operator /=(float scalar) {
479 x /= scalar;
480 y /= scalar;
481 }
483 Vector2 Vector2::operator -() const {
484 return Vector2(-x, -y);
485 }
487 bool Vector2::operator >(const Vector2 &vec) const {
488 return LengthSq() > vec.LengthSq();
489 }
491 bool Vector2::operator <(const Vector2 &vec) const {
492 return LengthSq() < vec.LengthSq();
493 }
495 bool Vector2::operator >(float len) const {
496 return LengthSq() > len;
497 }
499 bool Vector2::operator <(float len) const {
500 return LengthSq() < len;
501 }
503 bool Vector2::operator ==(const Vector2 &vec) const {
504 return ((*this - vec).Length() < XSmallNumber);
505 }
507 bool Vector2::operator ==(float len) const {
508 return ((this->Length() - len) < XSmallNumber);
509 }
511 Vector2::operator Vector3() const {
512 return Vector3(x, y, 1.0f);
513 }
515 float Vector2::Length() const {
516 return (float)sqrt(x * x + y * y);
517 }
519 float Vector2::LengthSq() const {
520 return x * x + y * y;
521 }
523 void Vector2::Normalize() {
524 float len = (float)sqrt(x * x + y * y);
525 x /= len;
526 y /= len;
527 }
529 Vector2 Vector2::Normalized() const {
530 float len = (float)sqrt(x * x + y * y);
531 return Vector2(x / len, y / len);
532 }
534 //Vector2 Vector2::Reflection(const Vector2 &normal) const;
535 //Vector2 Vector2::Refraction(const Vector2 &normal, float FromIOR, float ToIOR) const;
537 void Vector2::Transform(const Matrix3x3 &mat) {
538 float nx = x * mat.m[0][0] + y * mat.m[1][0] + mat.m[2][0];
539 y = x * mat.m[0][1] + y * mat.m[1][1] + mat.m[2][1];
540 x = nx;
541 }
543 void Vector2::Translate(float x, float y) {
544 this->x += x;
545 this->y += y;
546 }
548 void Vector2::Rotate(float angle) {
549 Matrix3x3 xform;
550 xform.SetRotation(angle);
552 Transform(xform);
553 }
555 void Vector2::Scale(float x, float y) {
556 this->x *= x;
557 this->y *= y;
558 }
560 float &Vector2::operator [](int index) {
561 return !index ? x : y;
562 }
564 std::ostream &operator <<(std::ostream &out, const Vector2 &vec) {
565 out << vec.x << ", " << vec.y;
566 return out;
567 }
570 // --------------- Quaternion implementation ---------------
572 Quaternion::Quaternion() {
573 s = 1.0f;
574 v.x = v.y = v.z = 0.0f;
575 }
577 Quaternion::Quaternion(float s, float x, float y, float z) {
578 v.x = x;
579 v.y = y;
580 v.z = z;
581 this->s = s;
582 }
584 Quaternion::Quaternion(float s, const Vector3 &v) {
585 this->s = s;
586 this->v = v;
587 }
589 Quaternion Quaternion::operator +(const Quaternion &quat) const {
590 return Quaternion(s + quat.s, v + quat.v);
591 }
593 Quaternion Quaternion::operator -(const Quaternion &quat) const {
594 return Quaternion(s - quat.s, v - quat.v);
595 }
597 Quaternion Quaternion::operator -() const {
598 return Quaternion(-s, -v);
599 }
601 // Quaternion Multiplication:
602 // Q1*Q2 = [s1*s2 - v1.v2, s1*v2 + s2*v1 + v1(x)v2]
603 Quaternion Quaternion::operator *(const Quaternion &quat) const {
604 Quaternion newq;
605 newq.s = s * quat.s - DotProduct(v, quat.v);
606 newq.v = quat.v * s + v * quat.s + CrossProduct(v, quat.v);
607 return newq;
608 }
610 void Quaternion::operator +=(const Quaternion &quat) {
611 *this = Quaternion(s + quat.s, v + quat.v);
612 }
614 void Quaternion::operator -=(const Quaternion &quat) {
615 *this = Quaternion(s - quat.s, v - quat.v);
616 }
618 void Quaternion::operator *=(const Quaternion &quat) {
619 *this = *this * quat;
620 }
622 void Quaternion::ResetIdentity() {
623 s = 1.0f;
624 v.x = v.y = v.z = 0.0f;
625 }
627 Quaternion Quaternion::Conjugate() const {
628 return Quaternion(s, -v);
629 }
631 float Quaternion::Length() const {
632 return (float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
633 }
635 // Q * ~Q = ||Q||^2
636 float Quaternion::LengthSq() const {
637 return v.x*v.x + v.y*v.y + v.z*v.z + s*s;
638 }
640 void Quaternion::Normalize() {
641 float len = (float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
642 v.x /= len;
643 v.y /= len;
644 v.z /= len;
645 s /= len;
646 }
648 Quaternion Quaternion::Normalized() const {
649 Quaternion nq = *this;
650 float len = (float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
651 nq.v.x /= len;
652 nq.v.y /= len;
653 nq.v.z /= len;
654 nq.s /= len;
655 return nq;
656 }
658 // Quaternion Inversion: Q^-1 = ~Q / ||Q||^2
659 Quaternion Quaternion::Inverse() const {
660 Quaternion inv = Conjugate();
661 float lensq = LengthSq();
662 inv.v /= lensq;
663 inv.s /= lensq;
665 return inv;
666 }
669 void Quaternion::SetRotation(const Vector3 &axis, float angle) {
670 float HalfAngle = angle / 2.0f;
671 s = cosf(HalfAngle);
672 v = axis * sinf(HalfAngle);
673 }
675 void Quaternion::Rotate(const Vector3 &axis, float angle) {
676 Quaternion q;
677 float HalfAngle = angle / 2.0f;
678 q.s = cosf(HalfAngle);
679 q.v = axis * sinf(HalfAngle);
681 *this *= q;
682 }
685 Matrix3x3 Quaternion::GetRotationMatrix() const {
686 return Matrix3x3(1.0f - 2.0f * v.y*v.y - 2.0f * v.z*v.z, 2.0f * v.x * v.y + 2.0f * s * v.z, 2.0f * v.z * v.x - 2.0f * s * v.y,
687 2.0f * v.x * v.y - 2.0f * s * v.z, 1.0f - 2.0f * v.x*v.x - 2.0f * v.z*v.z, 2.0f * v.y * v.z + 2.0f * s * v.x,
688 2.0f * v.z * v.x + 2.0f * s * v.y, 2.0f * v.y * v.z - 2.0f * s * v.x, 1.0f - 2.0f * v.x*v.x - 2.0f * v.y*v.y);
689 }
692 // ------------- Matrix implementation ---------------
694 Matrix4x4::Matrix4x4() {
695 memset(m, 0, 16*sizeof(float));
696 m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
697 }
699 Matrix4x4::Matrix4x4(const Matrix4x4 &mat) {
700 memcpy(m, mat.m, 16*sizeof(float));
701 }
703 Matrix4x4::Matrix4x4(const Matrix3x3 &mat) {
704 for(int i=0; i<3; i++) {
705 for(int j=0; j<3; j++) {
706 m[i][j] = mat.m[i][j];
707 }
708 }
709 m[3][0] = m[3][1] = m[3][2] = m[0][3] = m[1][3] = m[2][3] = 0.0f;
710 m[3][3] = 1.0f;
711 }
713 Matrix4x4::Matrix4x4( float m00, float m01, float m02, float m03,
714 float m10, float m11, float m12, float m13,
715 float m20, float m21, float m22, float m23,
716 float m30, float m31, float m32, float m33 ) {
718 memcpy(m, &m00, 16*sizeof(float)); // arguments are adjacent in stack
719 }
721 Matrix4x4 Matrix4x4::operator +(const Matrix4x4 &mat) const {
723 Matrix4x4 tmp;
725 const float *op1 = (float*)m;
726 const float *op2 = (float*)mat.m;
727 float *dst = (float*)tmp.m;
729 for(int i=0; i<16; i++) *dst++ = *op1++ + *op2++;
731 return tmp;
732 }
734 Matrix4x4 Matrix4x4::operator -(const Matrix4x4 &mat) const {
736 Matrix4x4 tmp;
738 const float *op1 = (float*)m;
739 const float *op2 = (float*)mat.m;
740 float *dst = (float*)tmp.m;
742 for(int i=0; i<16; i++) *dst++ = *op1++ - *op2++;
744 return tmp;
745 }
747 Matrix4x4 Matrix4x4::operator *(float scalar) const {
749 Matrix4x4 tmp;
751 const float *op1 = (float*)m;
752 float *dst = (float*)tmp.m;
754 for(int i=0; i<16; i++) *dst++ = *op1++ * scalar;
756 return tmp;
757 }
759 Matrix4x4 Matrix4x4::operator *(const Matrix4x4 &mat) const {
760 Matrix4x4 tmp;
762 for(int i=0; i<4; i++) {
763 for(int j=0; j<4; j++) {
764 tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j] + m[i][3]*mat.m[3][j];
765 }
766 }
768 return tmp;
769 }
771 void Matrix4x4::operator +=(const Matrix4x4 &mat) {
773 const float *op2 = (float*)mat.m;
774 float *dst = (float*)m;
776 for(int i=0; i<16; i++) *dst++ += *op2++;
777 }
779 void Matrix4x4::operator -=(const Matrix4x4 &mat) {
781 const float *op2 = (float*)mat.m;
782 float *dst = (float*)m;
784 for(int i=0; i<16; i++) *dst++ -= *op2++;
785 }
787 void Matrix4x4::operator *=(float scalar) {
789 float *dst = (float*)m;
791 for(int i=0; i<16; i++) *dst++ *= scalar;
792 }
794 void Matrix4x4::operator *=(const Matrix4x4 &mat) {
795 Matrix4x4 tmp;
797 for(int i=0; i<4; i++) {
798 for(int j=0; j<4; j++) {
799 tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j] + m[i][3]*mat.m[3][j];
800 }
801 }
803 memcpy(m, tmp.m, 16*sizeof(float));
804 }
807 void Matrix4x4::ResetIdentity() {
808 memset(m, 0, 16*sizeof(float));
809 m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
810 }
813 // Transformations (assuming column vectors)
815 void Matrix4x4::Translate(float x, float y, float z) {
817 Matrix4x4 tmp( 1, 0, 0, 0,
818 0, 1, 0, 0,
819 0, 0, 1, 0,
820 x, y, z, 1 );
821 *this *= tmp;
822 }
824 void Matrix4x4::Rotate(float x, float y, float z) {
826 *this *= Matrix4x4( 1, 0, 0, 0,
827 0, fcos(x), fsin(x), 0,
828 0, -fsin(x), fcos(x), 0,
829 0, 0, 0, 1 );
831 *this *= Matrix4x4( fcos(y), 0, -fsin(y), 0,
832 0, 1, 0, 0,
833 fsin(y), 0, fcos(y), 0,
834 0, 0, 0, 1 );
836 *this *= Matrix4x4( fcos(z), fsin(z), 0, 0,
837 -fsin(z), fcos(z), 0, 0,
838 0, 0, 1, 0,
839 0, 0, 0, 1 );
840 }
842 void Matrix4x4::Rotate(const Vector3 &axis, float angle) {
844 float sina = fsin(angle);
845 float cosa = fcos(angle);
846 float invcosa = 1-cosa;
847 float nxsq = axis.x * axis.x;
848 float nysq = axis.y * axis.y;
849 float nzsq = axis.z * axis.z;
851 Matrix4x4 xform;
852 xform.m[0][0] = nxsq + (1-nxsq) * cosa;
853 xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
854 xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
855 xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
856 xform.m[1][1] = nysq + (1-nysq) * cosa;
857 xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
858 xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
859 xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
860 xform.m[2][2] = nzsq + (1-nzsq) * cosa;
862 *this *= xform;
863 }
865 void Matrix4x4::Scale(float x, float y, float z) {
867 Matrix4x4 xform(x, 0, 0, 0,
868 0, y, 0, 0,
869 0, 0, z, 0,
870 0, 0, 0, 1 );
871 *this *= xform;
872 }
875 //////////////////////////////
877 void Matrix4x4::SetTranslation(float x, float y, float z) {
879 *this = Matrix4x4( 1, 0, 0, 0,
880 0, 1, 0, 0,
881 0, 0, 1, 0,
882 x, y, z, 1 );
883 }
885 void Matrix4x4::SetRotation(float x, float y, float z) {
887 *this = Matrix4x4( 1, 0, 0, 0,
888 0, fcos(x), fsin(x), 0,
889 0, -fsin(x), fcos(x), 0,
890 0, 0, 0, 1 );
892 *this *= Matrix4x4( fcos(y), 0, -fsin(y), 0,
893 0, 1, 0, 0,
894 fsin(y), 0, fcos(y), 0,
895 0, 0, 0, 1 );
897 *this *= Matrix4x4( fcos(z), fsin(z), 0, 0,
898 -fsin(z), fcos(z), 0, 0,
899 0, 0, 1, 0,
900 0, 0, 0, 1 );
901 }
903 void Matrix4x4::SetRotation(const Vector3 &axis, float angle) {
905 // caching of multiply used function results (opt)
906 float sina = fsin(angle);
907 float cosa = fcos(angle);
908 float invcosa = 1-cosa;
909 float nxsq = axis.x * axis.x;
910 float nysq = axis.y * axis.y;
911 float nzsq = axis.z * axis.z;
913 Matrix4x4 xform;
914 xform.m[0][0] = nxsq + (1-nxsq) * cosa;
915 xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
916 xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
917 xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
918 xform.m[1][1] = nysq + (1-nysq) * cosa;
919 xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
920 xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
921 xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
922 xform.m[2][2] = nzsq + (1-nzsq) * cosa;
924 *this = xform;
925 }
927 void Matrix4x4::SetScaling(float x, float y, float z) {
929 Matrix4x4 xform(x, 0, 0, 0,
930 0, y, 0, 0,
931 0, 0, z, 0,
932 0, 0, 0, 1 );
933 *this = xform;
934 }
936 void Matrix4x4::SetColumnVector(const Vector4 &vec, int columnindex) {
938 m[0][columnindex] = vec.x;
939 m[1][columnindex] = vec.y;
940 m[2][columnindex] = vec.z;
941 m[3][columnindex] = vec.w;
942 }
944 void Matrix4x4::SetRowVector(const Vector4 &vec, int rowindex) {
946 m[rowindex][0] = vec.x;
947 m[rowindex][1] = vec.y;
948 m[rowindex][2] = vec.z;
949 m[rowindex][3] = vec.w;
950 }
952 Vector4 Matrix4x4::GetColumnVector(int columnindex) const {
954 return Vector4(m[0][columnindex], m[1][columnindex], m[2][columnindex], m[3][columnindex]);
955 }
957 Vector4 Matrix4x4::GetRowVector(int rowindex) const {
959 return Vector4(m[rowindex][0], m[rowindex][1], m[rowindex][2], m[rowindex][3]);
960 }
962 // other operations on matrices
964 void Matrix4x4::Transpose() {
965 Matrix4x4 mat = *this;
967 for(int i=0; i<4; i++) {
968 for(int j=0; j<4; j++) {
969 m[i][j] = mat.m[j][i];
970 }
971 }
972 }
974 Matrix4x4 Matrix4x4::Transposed() const {
975 Matrix4x4 mat = *this;
977 for(int i=0; i<4; i++) {
978 for(int j=0; j<4; j++) {
979 mat.m[i][j] = m[j][i];
980 }
981 }
983 return mat;
984 }
987 float Matrix4x4::Determinant() const {
989 float det11 = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
990 (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
991 (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
993 float det12 = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
994 (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
995 (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
997 float det13 = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
998 (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
999 (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
1001 float det14 = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
1002 (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
1003 (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
1005 return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14;
1009 Matrix4x4 Matrix4x4::Adjoint() const {
1011 Matrix4x4 coef;
1013 coef.m[0][0] = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
1014 (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
1015 (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
1016 coef.m[0][1] = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
1017 (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
1018 (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
1019 coef.m[0][2] = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
1020 (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
1021 (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
1022 coef.m[0][3] = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
1023 (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
1024 (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
1026 coef.m[1][0] = (m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
1027 (m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
1028 (m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
1029 coef.m[1][1] = (m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
1030 (m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
1031 (m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
1032 coef.m[1][2] = (m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
1033 (m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
1034 (m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
1035 coef.m[1][3] = (m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
1036 (m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
1037 (m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
1039 coef.m[2][0] = (m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
1040 (m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) +
1041 (m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2]));
1042 coef.m[2][1] = (m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
1043 (m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
1044 (m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2]));
1045 coef.m[2][2] = (m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) -
1046 (m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
1047 (m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
1048 coef.m[2][3] = (m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) -
1049 (m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) +
1050 (m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
1052 coef.m[3][0] = (m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
1053 (m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) +
1054 (m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]));
1055 coef.m[3][1] = (m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
1056 (m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
1057 (m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2]));
1058 coef.m[3][2] = (m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) -
1059 (m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
1060 (m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
1061 coef.m[3][3] = (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) -
1062 (m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) +
1063 (m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
1065 coef.Transpose();
1067 float *elem = (float*)coef.m;
1068 for(int i=0; i<4; i++) {
1069 for(int j=0; j<4; j++) {
1070 coef.m[i][j] = j%2 ? -coef.m[i][j] : coef.m[i][j];
1071 if(i%2) coef.m[i][j] = -coef.m[i][j];
1075 return coef;
1078 Matrix4x4 Matrix4x4::Inverse() const {
1080 Matrix4x4 AdjMat = Adjoint();
1082 return AdjMat * (1.0f / Determinant());
1086 // --------- 3 by 3 matrices implementation --------------
1088 Matrix3x3::Matrix3x3() {
1089 memset(m, 0, 9 * sizeof(float));
1090 m[0][0] = m[1][1] = m[2][2] = 1.0f;
1093 Matrix3x3::Matrix3x3(const Matrix3x3 &mat) {
1094 memcpy(m, mat.m, 9 * sizeof(float));
1097 Matrix3x3::Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) {
1098 memcpy(m, &m00, 9*sizeof(float)); // arguments are adjacent in stack
1101 Matrix3x3 Matrix3x3::operator +(const Matrix3x3 &mat) const {
1102 Matrix3x3 tmp;
1104 const float *op1 = (float*)m;
1105 const float *op2 = (float*)mat.m;
1106 float *dst = (float*)tmp.m;
1108 for(int i=0; i<9; i++) *dst++ = *op1++ + *op2++;
1110 return tmp;
1113 Matrix3x3 Matrix3x3::operator -(const Matrix3x3 &mat) const {
1114 Matrix3x3 tmp;
1116 const float *op1 = (float*)m;
1117 const float *op2 = (float*)mat.m;
1118 float *dst = (float*)tmp.m;
1120 for(int i=0; i<9; i++) *dst++ = *op1++ - *op2++;
1122 return tmp;
1125 Matrix3x3 Matrix3x3::operator *(const Matrix3x3 &mat) const {
1126 Matrix3x3 tmp;
1128 for(int i=0; i<3; i++) {
1129 for(int j=0; j<3; j++) {
1130 tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j];
1134 return tmp;
1137 Matrix3x3 Matrix3x3::operator *(float scalar) const {
1138 Matrix3x3 tmp;
1140 const float *op1 = (float*)m;
1141 float *dst = (float*)tmp.m;
1143 for(int i=0; i<9; i++) *dst++ = *op1++ * scalar;
1145 return tmp;
1148 void Matrix3x3::operator +=(const Matrix3x3 &mat) {
1149 const float *op = (float*)mat.m;
1150 float *dst = (float*)m;
1152 for(int i=0; i<9; i++) *dst++ += *op++;
1155 void Matrix3x3::operator -=(const Matrix3x3 &mat) {
1156 const float *op = (float*)mat.m;
1157 float *dst = (float*)m;
1159 for(int i=0; i<9; i++) *dst++ -= *op++;
1162 void Matrix3x3::operator *=(const Matrix3x3 &mat) {
1163 Matrix4x4 tmp;
1165 for(int i=0; i<3; i++) {
1166 for(int j=0; j<3; j++) {
1167 tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j];
1171 memcpy(m, tmp.m, 9*sizeof(float));
1174 void Matrix3x3::operator *=(float scalar) {
1175 float *dst = (float*)m;
1177 for(int i=0; i<9; i++) *dst++ *= scalar;
1181 void Matrix3x3::ResetIdentity() {
1182 memset(m, 0, 9 * sizeof(float));
1183 m[0][0] = m[1][1] = m[2][2] = 1.0f;
1186 void Matrix3x3::Translate(float x, float y) {
1187 Matrix3x3 tmp( 1, 0, 0,
1188 0, 1, 0,
1189 x, y, 1 );
1190 *this *= tmp;
1193 void Matrix3x3::Rotate(float angle) {
1194 Matrix3x3 tmp( fcos(angle), fsin(angle), 0,
1195 -fsin(angle), fcos(angle), 0,
1196 0, 0, 1 );
1197 *this *= tmp;
1200 void Matrix3x3::Scale(float x, float y) {
1201 Matrix3x3 tmp( x, 0, 0,
1202 0, y, 0,
1203 0, 0, 1);
1205 *this *= tmp;
1208 void Matrix3x3::SetTranslation(float x, float y) {
1209 Matrix3x3( 1, 0, 0,
1210 0, 1, 0,
1211 x, y, 1 );
1214 void Matrix3x3::SetRotation(float angle) {
1215 Matrix3x3( fcos(angle), fsin(angle), 0,
1216 -fsin(angle), fcos(angle), 0,
1217 0, 0, 1 );
1220 void Matrix3x3::SetScaling(float x, float y) {
1221 Matrix3x3( x, 0, 0,
1222 0, y, 0,
1223 0, 0, 1 );
1226 void Matrix3x3::SetColumnVector(const Vector3 &vec, int columnindex) {
1227 m[columnindex][0] = vec.x;
1228 m[columnindex][1] = vec.y;
1229 m[columnindex][2] = vec.z;
1232 void Matrix3x3::SetRowVector(const Vector3 &vec, int rowindex) {
1233 m[0][rowindex] = vec.x;
1234 m[1][rowindex] = vec.y;
1235 m[2][rowindex] = vec.z;
1238 Vector3 Matrix3x3::GetColumnVector(int columnindex) const {
1239 return Vector3(m[columnindex][0], m[columnindex][1], m[columnindex][2]);
1242 Vector3 Matrix3x3::GetRowVector(int rowindex) const {
1243 return Vector3(m[0][rowindex], m[1][rowindex], m[2][rowindex]);
1246 void Matrix3x3::Transpose() {
1247 Matrix3x3 mat = *this;
1249 for(int i=0; i<3; i++) {
1250 for(int j=0; j<3; j++) {
1251 m[i][j] = mat.m[j][i];
1256 Matrix3x3 Matrix3x3::Transposed() const {
1257 Matrix3x3 mat;
1259 for(int i=0; i<3; i++) {
1260 for(int j=0; j<3; j++) {
1261 mat.m[i][j] = m[j][i];
1265 return mat;
1269 void Matrix3x3::OrthoNormalize() {
1270 Vector3 i, j, k;
1271 i = GetRowVector(0);
1272 j = GetRowVector(1);
1273 k = GetRowVector(2);
1275 i = CrossProduct(j, k);
1276 j = CrossProduct(k, i);
1277 k = CrossProduct(i, j);
1279 SetRowVector(i, 0);
1280 SetRowVector(j, 1);
1281 SetRowVector(k, 2);
1284 Matrix3x3 Matrix3x3::OrthoNormalized() {
1285 Vector3 i, j, k;
1286 i = GetRowVector(0);
1287 j = GetRowVector(1);
1288 k = GetRowVector(2);
1290 i = CrossProduct(j, k);
1291 j = CrossProduct(k, i);
1292 k = CrossProduct(i, j);
1294 Matrix3x3 newmat;
1295 newmat.SetRowVector(i, 0);
1296 newmat.SetRowVector(j, 1);
1297 newmat.SetRowVector(k, 2);
1299 return newmat;
1304 // ----------- Ray implementation --------------
1305 Ray::Ray() {
1306 Origin = Vector3(0.0f, 0.0f, 0.0f);
1307 Direction = Vector3(0.0f, 0.0f, 1.0f);
1308 Energy = 1.0f;
1309 CurrentIOR = 1.0f;
1312 Ray::Ray(const Vector3 &origin, const Vector3 &direction) {
1313 Origin = origin;
1314 Direction = direction;
1317 // ----------- Base implementation --------------
1318 Base::Base() {
1319 i = Vector3(1, 0, 0);
1320 j = Vector3(0, 1, 0);
1321 k = Vector3(0, 0, 1);
1324 Base::Base(const Vector3 &i, const Vector3 &j, const Vector3 &k) {
1325 this->i = i;
1326 this->j = j;
1327 this->k = k;
1330 Base::Base(const Vector3 &dir, bool LeftHanded) {
1331 k = dir;
1332 j = VECTOR3_J;
1333 i = CrossProduct(j, k);
1334 j = CrossProduct(k, i);
1338 void Base::Rotate(float x, float y, float z) {
1339 Matrix4x4 RotMat;
1340 RotMat.SetRotation(x, y, z);
1341 i.Transform(RotMat);
1342 j.Transform(RotMat);
1343 k.Transform(RotMat);
1346 void Base::Rotate(const Vector3 &axis, float angle) {
1347 Quaternion q;
1348 q.SetRotation(axis, angle);
1349 i.Transform(q);
1350 j.Transform(q);
1351 k.Transform(q);
1354 void Base::Rotate(const Matrix4x4 &mat) {
1355 i.Transform(mat);
1356 j.Transform(mat);
1357 k.Transform(mat);
1360 void Base::Rotate(const Quaternion &quat) {
1361 i.Transform(quat);
1362 j.Transform(quat);
1363 k.Transform(quat);
1366 Matrix3x3 Base::CreateRotationMatrix() const {
1367 return Matrix3x3( i.x, i.y, i.z,
1368 j.x, j.y, j.z,
1369 k.x, k.y, k.z);