Tactics: Western Philosophers Vs. Musicians  0.12
A turn-based tactical game combining rules and gameplay elements inspired by Final Fantasy Tactics and the Mayfair Exponential Game System. Unlike most games of this type, motion is in full, grid-less 3D.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MMatrix3x3.h
Go to the documentation of this file.
1 // Copyright (C) 2004-2007 Dylan Blair
3 //
4 // email: dblair@alumni.cs.utexas.edu
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 
21 #ifndef MMATRIX3X3_H
22 #define MMATRIX3X3_H
23 
24 #include "MPoint.h"
25 
26 namespace OpenSkyNet {
27  namespace Math {
28  class Matrix3x3;
29  Matrix3x3 operator*(const Matrix3x3& lhs_, const Matrix3x3& rhs_);
30 
32  class Matrix3x3 {
33  Math::Point<> _columns[3];
34  public:
36  _columns[0][0] = 1.0f;
37  _columns[1][1] = 1.0f;
38  _columns[2][2] = 1.0f;
39  }
40 
41  Matrix3x3(const Math::Point<>& localXAxis_, const Math::Point<>& localYAxis_, const Math::Point<>& localZAxis_) {
42  _columns[0] = localXAxis_;
43  _columns[1] = localYAxis_;
44  _columns[2] = localZAxis_;
45  }
46 
49  inline Math::Point<>& col(int i_) { return _columns[i_]; }
50  inline const Math::Point<>& col(int i_) const { return _columns[i_]; }
52 
53  inline float getDeterminant() const {
54  return (col(0)[0]*col(1)[1]*col(2)[2] +
55  col(1)[0]*col(2)[1]*col(0)[2] +
56  col(2)[0]*col(0)[1]*col(1)[2] -
57  col(0)[0]*col(2)[1]*col(1)[2] -
58  col(1)[0]*col(0)[1]*col(2)[2] -
59  col(2)[0]*col(1)[1]*col(0)[2]);
60  }
61 
62  inline void cofactor() {
63  Matrix3x3 tmp(*this);
64  col(0)[0] = tmp.col(1)[1]*tmp.col(2)[2] - tmp.col(1)[2]*tmp.col(2)[1];
65  col(0)[1] = -(tmp.col(1)[0]*tmp.col(2)[2] - tmp.col(1)[2]*tmp.col(2)[0]);
66  col(0)[2] = tmp.col(1)[0]*tmp.col(2)[1] - tmp.col(1)[1]*tmp.col(2)[0];
67 
68  col(1)[0] = -(tmp.col(0)[1]*tmp.col(2)[2] - tmp.col(0)[2]*tmp.col(2)[1]);
69  col(1)[1] = tmp.col(0)[0]*tmp.col(2)[2] - tmp.col(0)[2]*tmp.col(2)[0];
70  col(1)[2] = -(tmp.col(0)[0]*tmp.col(2)[1] - tmp.col(0)[1]*tmp.col(2)[0]);
71 
72  col(2)[0] = tmp.col(0)[1]*tmp.col(1)[2] - tmp.col(0)[2]*tmp.col(1)[1];
73  col(2)[1] = -(tmp.col(0)[0]*tmp.col(1)[2] - tmp.col(0)[2]*tmp.col(1)[0]);
74  col(2)[2] = tmp.col(0)[0]*tmp.col(1)[1] - tmp.col(0)[1]*tmp.col(1)[0];
75  }
76 
77  inline void transpose() {
78  float tmp = col(0)[1];
79  col(0)[1] = col(1)[0];
80  col(1)[0] = tmp;
81 
82  tmp = col(0)[2];
83  col(0)[2] = col(2)[0];
84  col(2)[0] = tmp;
85 
86  tmp = col(1)[2];
87  col(1)[2] = col(2)[1];
88  col(2)[1] = tmp;
89  }
90 
92  inline void orthonormalize() {
93  col(0).normalize();
94 
95  col(1) = col(1) - col(0) * col(0).getDot3(col(1));
96  col(1).normalize();
97 
98  col(2) = col(2) - col(0) * col(0).getDot3(col(2)) - col(1) * col(1).getDot3(col(2));
99  col(2).normalize();
100  }
101 
102  inline void invert() {
103  float invDet = 1.0f / getDeterminant();
104  cofactor();
105  transpose();
106  col(0) *= invDet;
107  col(1) *= invDet;
108  col(2) *= invDet;
109  orthonormalize();
110  }
111 
112  inline Matrix3x3 getInverse() const {
113  float invDet = 1.0f / getDeterminant();
114  Matrix3x3 result(*this);
115  result.cofactor();
116  result.transpose();
117  result.col(0) *= invDet;
118  result.col(1) *= invDet;
119  result.col(2) *= invDet;
120  result.orthonormalize();
121  return result;
122  }
123  };
124 
126 
129  inline Matrix3x3 getRotation(const Math::Point<>& axis_, float radians_) {
130  Matrix3x3 rotMat;
131  float cosAngle = cosf(radians_);
132  float sinAngle = sinf(radians_);
133  float oneMinusCos = 1.0f - cosAngle;
134 
135  rotMat.col(0)[0] = cosAngle + oneMinusCos * axis_.x() * axis_.x();
136  rotMat.col(0)[1] = oneMinusCos * axis_.x() * axis_.y() + axis_.z() * sinAngle;
137  rotMat.col(0)[2] = oneMinusCos * axis_.x() * axis_.z() - axis_.y() * sinAngle;
138 
139  rotMat.col(1)[0] = oneMinusCos * axis_.x() * axis_.y() - axis_.z() * sinAngle;
140  rotMat.col(1)[1] = cosAngle + oneMinusCos * axis_.y() * axis_.y();
141  rotMat.col(1)[2] = oneMinusCos * axis_.y() * axis_.z() + axis_.x() * sinAngle;
142 
143  rotMat.col(2)[0] = oneMinusCos * axis_.x() * axis_.z() + axis_.y() * sinAngle;
144  rotMat.col(2)[1] = oneMinusCos * axis_.y() * axis_.z() - axis_.x() * sinAngle;
145  rotMat.col(2)[2] = cosAngle + oneMinusCos * axis_.z() * axis_.z();
146 
147  return rotMat;
148  }
149 
153  inline void getAxisAngle(const Matrix3x3& rot_, Math::Point<>& axis_, float& radians_) {
154  if (((fabs(rot_.col(1)[0] - rot_.col(0)[1]) < CLOSE_TO_ZERO) &&
155  (fabs(rot_.col(2)[0] - rot_.col(0)[2]) < CLOSE_TO_ZERO)) &&
156  (fabs(rot_.col(2)[1] - rot_.col(1)[2]) < CLOSE_TO_ZERO)) {
157  // singularity found
158  if (Point<>(rot_.col(0)[0],rot_.col(1)[1],rot_.col(2)[2]).equals(Point<>(1.0f,1.0f,1.0f),CLOSE_TO_ZERO)) {
159  radians_ = 0.0f;
160  // axis is arbitrary
161  axis_ = Math::g_xAxis;
162  }
163  else {
164  // otherwise this singularity is angle = 180
165  radians_ = PI;
166 
167  assert(!((rot_.col(0)[0] + 1.0f) / 2.0f < 0.0f));
168  assert(!((rot_.col(1)[1] + 1.0f) / 2.0f < 0.0f));
169  assert(!((rot_.col(2)[2] + 1.0f) / 2.0f < 0.0f));
170 
171  axis_ = Point<>(sqrt((rot_.col(0)[0] + 1.0f) / 2.0f),
172  sqrt((rot_.col(1)[1] + 1.0f) / 2.0f),
173  sqrt((rot_.col(2)[2] + 1.0f) / 2.0f));
174  bool isXZero = (fabs(axis_.x()) < CLOSE_TO_ZERO);
175  bool isYZero = (fabs(axis_.y()) < CLOSE_TO_ZERO);
176  bool isZZero = (fabs(axis_.z()) < CLOSE_TO_ZERO);
177  bool isXYPos = (rot_.col(1)[0] > CLOSE_TO_ZERO);
178  bool isXZPos = (rot_.col(2)[0] > CLOSE_TO_ZERO);
179  bool isYZPos = (rot_.col(2)[1] > CLOSE_TO_ZERO);
180  if (isXZero && !isYZero && !isZZero) {
181  if (!isYZPos) axis_.y() = -axis_.y();
182  } else if (isYZero && !isZZero) {
183  if (!isXZPos) axis_.z() = -axis_.z();
184  } else if (isZZero) {
185  if (!isXYPos) axis_.x() = -axis_.x();
186  }
187  }
188  }
189  else {
190  radians_ = acos((rot_.col(0)[0] + rot_.col(1)[1] + rot_.col(2)[2] - 1.0f) / 2.0f);
191  axis_ = Point<>((rot_.col(1)[2] - rot_.col(2)[1]),
192  (rot_.col(2)[0] - rot_.col(0)[2]),
193  (rot_.col(0)[1] - rot_.col(1)[0]));
194  axis_.normalize();
195  }
196  }
197 
199  inline Math::Point<> operator*(const Math::Point<>& lhs_, const Matrix3x3& rhs_) {
200  Math::Point<> result;
201  result.x() = lhs_.x() * rhs_.col(0)[0] + lhs_.y() * rhs_.col(1)[0] + lhs_.z() * rhs_.col(2)[0];
202  result.y() = lhs_.x() * rhs_.col(0)[1] + lhs_.y() * rhs_.col(1)[1] + lhs_.z() * rhs_.col(2)[1];
203  result.z() = lhs_.x() * rhs_.col(0)[2] + lhs_.y() * rhs_.col(1)[2] + lhs_.z() * rhs_.col(2)[2];
204  return result;
205  }
206 
208  inline Matrix3x3 operator*(const Matrix3x3& lhs_, const Matrix3x3& rhs_) {
209  Matrix3x3 result;
210  result.col(0)[0] = rhs_.col(0)[0]*lhs_.col(0)[0] + rhs_.col(1)[0]*lhs_.col(0)[1] + rhs_.col(2)[0]*lhs_.col(0)[2];
211  result.col(0)[1] = rhs_.col(0)[1]*lhs_.col(0)[0] + rhs_.col(1)[1]*lhs_.col(0)[1] + rhs_.col(2)[1]*lhs_.col(0)[2];
212  result.col(0)[2] = rhs_.col(0)[2]*lhs_.col(0)[0] + rhs_.col(1)[2]*lhs_.col(0)[1] + rhs_.col(2)[2]*lhs_.col(0)[2];
213 
214  result.col(1)[0] = rhs_.col(0)[0]*lhs_.col(1)[0] + rhs_.col(1)[0]*lhs_.col(1)[1] + rhs_.col(2)[0]*lhs_.col(1)[2];
215  result.col(1)[1] = rhs_.col(0)[1]*lhs_.col(1)[0] + rhs_.col(1)[1]*lhs_.col(1)[1] + rhs_.col(2)[1]*lhs_.col(1)[2];
216  result.col(1)[2] = rhs_.col(0)[2]*lhs_.col(1)[0] + rhs_.col(1)[2]*lhs_.col(1)[1] + rhs_.col(2)[2]*lhs_.col(1)[2];
217 
218  result.col(2)[0] = rhs_.col(0)[0]*lhs_.col(2)[0] + rhs_.col(1)[0]*lhs_.col(2)[1] + rhs_.col(2)[0]*lhs_.col(2)[2];
219  result.col(2)[1] = rhs_.col(0)[1]*lhs_.col(2)[0] + rhs_.col(1)[1]*lhs_.col(2)[1] + rhs_.col(2)[1]*lhs_.col(2)[2];
220  result.col(2)[2] = rhs_.col(0)[2]*lhs_.col(2)[0] + rhs_.col(1)[2]*lhs_.col(2)[1] + rhs_.col(2)[2]*lhs_.col(2)[2];
221 
222  return result;
223  }
224  }
225 }
226 
227 #endif //MMATRIX3X3_H
Matrix3x3(const Math::Point<> &localXAxis_, const Math::Point<> &localYAxis_, const Math::Point<> &localZAxis_)
Definition: MMatrix3x3.h:41
Matrix3x3 operator*(const Matrix3x3 &lhs_, const Matrix3x3 &rhs_)
Definition: MMatrix3x3.h:208
void getAxisAngle(const Matrix3x3 &rot_, Math::Point<> &axis_, float &radians_)
Definition: MMatrix3x3.h:153
void normalize()
Definition: MPoint.h:139
T & y()
Definition: MPoint.h:65
const Matrix3x3 g_identityMatrix3x3
Definition: MMatrix3x3.cpp:5
T & x()
Definition: MPoint.h:64
void invert()
Definition: MMatrix3x3.h:102
void cofactor()
Definition: MMatrix3x3.h:62
Matrix3x3 getInverse() const
Definition: MMatrix3x3.h:112
void orthonormalize()
Definition: MMatrix3x3.h:92
T & z()
Definition: MPoint.h:66
void transpose()
Definition: MMatrix3x3.h:77
Definition: MPoint.h:33
const Point g_xAxis(1.0f, 0.0f, 0.0f)
Definition: MPoint.h:215
Matrix3x3()
Definition: MMatrix3x3.h:35
const Math::Point & col(int i_) const
Definition: MMatrix3x3.h:50
Definition: MMatrix3x3.h:32
T getDot3(const Point< T > &rhs_) const
Definition: MPoint.h:202
Matrix3x3 getRotation(const Math::Point<> &axis_, float radians_)
Definition: MMatrix3x3.h:129
const float PI(3.14159265f)
const float CLOSE_TO_ZERO(0.00001f)
float float rot_[3]
Definition: ViewerApp.h:31
Math::Point & col(int i_)
Definition: MMatrix3x3.h:49
float getDeterminant() const
Definition: MMatrix3x3.h:53