Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "Matrix.h"
7 : #include "Quaternion.h"
8 : #include "Tools.h"
9 : #include <algorithm>
10 : #include <ostream>
11 : #include <math.h>
12 : #include <float.h> // for FLT_EPSILON
13 :
14 : #include "mozilla/FloatingPoint.h" // for UnspecifiedNaN
15 :
16 : using namespace std;
17 :
18 :
19 : namespace mozilla {
20 : namespace gfx {
21 :
22 : /* Force small values to zero. We do this to avoid having sin(360deg)
23 : * evaluate to a tiny but nonzero value.
24 : */
25 : double
26 0 : FlushToZero(double aVal)
27 : {
28 : // XXX Is double precision really necessary here
29 0 : if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON) {
30 0 : return 0.0f;
31 : } else {
32 0 : return aVal;
33 : }
34 : }
35 :
36 : /* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
37 : * undefined or very large, SafeTangent returns a manageably large value
38 : * of the correct sign.
39 : */
40 : double
41 0 : SafeTangent(double aTheta)
42 : {
43 : // XXX Is double precision really necessary here
44 0 : const double kEpsilon = 0.0001;
45 :
46 : /* tan(theta) = sin(theta)/cos(theta); problems arise when
47 : * cos(theta) is too close to zero. Limit cos(theta) to the
48 : * range [-1, -epsilon] U [epsilon, 1].
49 : */
50 :
51 0 : double sinTheta = sin(aTheta);
52 0 : double cosTheta = cos(aTheta);
53 :
54 0 : if (cosTheta >= 0 && cosTheta < kEpsilon) {
55 0 : cosTheta = kEpsilon;
56 0 : } else if (cosTheta < 0 && cosTheta >= -kEpsilon) {
57 0 : cosTheta = -kEpsilon;
58 : }
59 0 : return FlushToZero(sinTheta / cosTheta);
60 : }
61 :
62 : template<> Matrix
63 0 : Matrix::Rotation(Float aAngle)
64 : {
65 0 : Matrix newMatrix;
66 :
67 0 : Float s = sinf(aAngle);
68 0 : Float c = cosf(aAngle);
69 :
70 0 : newMatrix._11 = c;
71 0 : newMatrix._12 = s;
72 0 : newMatrix._21 = -s;
73 0 : newMatrix._22 = c;
74 :
75 0 : return newMatrix;
76 : }
77 :
78 : template<> MatrixDouble
79 0 : MatrixDouble::Rotation(Double aAngle)
80 : {
81 0 : MatrixDouble newMatrix;
82 :
83 0 : Double s = sin(aAngle);
84 0 : Double c = cos(aAngle);
85 :
86 0 : newMatrix._11 = c;
87 0 : newMatrix._12 = s;
88 0 : newMatrix._21 = -s;
89 0 : newMatrix._22 = c;
90 :
91 0 : return newMatrix;
92 : }
93 :
94 : template<> Matrix4x4
95 0 : MatrixDouble::operator*(const Matrix4x4& aMatrix) const
96 : {
97 0 : Matrix4x4 resultMatrix;
98 :
99 0 : resultMatrix._11 = this->_11 * aMatrix._11 + this->_12 * aMatrix._21;
100 0 : resultMatrix._12 = this->_11 * aMatrix._12 + this->_12 * aMatrix._22;
101 0 : resultMatrix._13 = this->_11 * aMatrix._13 + this->_12 * aMatrix._23;
102 0 : resultMatrix._14 = this->_11 * aMatrix._14 + this->_12 * aMatrix._24;
103 :
104 0 : resultMatrix._21 = this->_21 * aMatrix._11 + this->_22 * aMatrix._21;
105 0 : resultMatrix._22 = this->_21 * aMatrix._12 + this->_22 * aMatrix._22;
106 0 : resultMatrix._23 = this->_21 * aMatrix._13 + this->_22 * aMatrix._23;
107 0 : resultMatrix._24 = this->_21 * aMatrix._14 + this->_22 * aMatrix._24;
108 :
109 0 : resultMatrix._31 = aMatrix._31;
110 0 : resultMatrix._32 = aMatrix._32;
111 0 : resultMatrix._33 = aMatrix._33;
112 0 : resultMatrix._34 = aMatrix._34;
113 :
114 0 : resultMatrix._41 = this->_31 * aMatrix._11 + this->_32 * aMatrix._21 + aMatrix._41;
115 0 : resultMatrix._42 = this->_31 * aMatrix._12 + this->_32 * aMatrix._22 + aMatrix._42;
116 0 : resultMatrix._43 = this->_31 * aMatrix._13 + this->_32 * aMatrix._23 + aMatrix._43;
117 0 : resultMatrix._44 = this->_31 * aMatrix._14 + this->_32 * aMatrix._24 + aMatrix._44;
118 :
119 0 : return resultMatrix;
120 : }
121 :
122 : } // namespace gfx
123 : } // namespace mozilla
|