AnimatLab  2
Test
OsgMatrixUtil.cpp
1 #include "StdAfx.h"
2 #include "OsgMatrixUtil.h"
3 #include <iostream>
4 
5 namespace OsgAnimatSim
6 {
7 
8 void OsgMatrixUtil::Print(const osg::Matrix& matrix)
9 {
10  for (int i = 0; i < 4; ++i)
11  {
12  for (int j = 0; j < 4; ++j)
13  {
14  std::cout << "[" << matrix(i,j) << "]";
15  }
16  std::cout << std::endl;
17  }
18  std::cout << std::endl;
19 }
20 
21 
22 void OsgMatrixUtil::Print(const osg::Vec3& vec)
23 {
24  for (int i = 0; i < 3; ++i)
25  {
26  std::cout << "[" << vec[i] << "]";
27  }
28  std::cout << std::endl;
29 }
30 
31 
32 void OsgMatrixUtil::Print(const osg::Vec4& vec)
33 {
34  for (int i = 0; i < 4; ++i)
35  {
36  std::cout << "[" << vec[i] << "]";
37  }
38  std::cout << std::endl;
39 }
40 
41 
42 void OsgMatrixUtil::Transpose(osg::Matrix& dest, const osg::Matrix& src)
43 {
44  for (int i = 0; i < 4; ++i)
45  {
46  for (int j = 0; j < 4; ++j)
47  {
48  dest(i,j) = src(j,i);
49  }
50  }
51 }
52 
53 
54 osg::Vec3 OsgMatrixUtil::GetRow3(const osg::Matrix& matrix, int row)
55 {
56  return osg::Vec3(matrix(row,0), matrix(row, 1), matrix(row,2));
57 }
58 
59 
60 osg::Vec4 OsgMatrixUtil::GetRow4(const osg::Matrix& matrix, int row)
61 {
62  return osg::Vec4(matrix(row,0), matrix(row,1), matrix(row,2), matrix(row,3));
63 }
64 
65 
66 void OsgMatrixUtil::SetRow(osg::Matrix& matrix, const osg::Vec3& vec, int row)
67 {
68  for (int i = 0; i < 3; ++i)
69  {
70  matrix(row,i) = vec[i];
71  }
72 }
73 
74 
75 void OsgMatrixUtil::SetRow(osg::Matrix& matrix, const osg::Vec4& vec, int row)
76 {
77  for (int i = 0; i < 4; ++i)
78  {
79  matrix(row, i) = vec[i];
80  }
81 }
82 
83 
84 void OsgMatrixUtil::HprToMatrix(osg::Matrix& rotation, const osg::Vec3& hpr)
85 {
86  // implementation converted from plib's sg.cxx
87  // PLIB - A Suite of Portable Game Libraries
88  // Copyright (C) 1998,2002 Steve Baker
89  // For further information visit http://plib.sourceforge.net
90 
91 
92  double ch, sh, cp, sp, cr, sr, srsp, crsp, srcp;
93 
94  // this can't be smart for both 32 and 64 bit types.
96  const osg::Vec3::value_type magic_epsilon = (osg::Vec3::value_type)0.00001;
97 
98  if (osg::equivalent(hpr[0], (osg::Vec3::value_type)0.0, magic_epsilon))
99  {
100  ch = 1.0;
101  sh = 0.0;
102  }
103  else
104  {
105  sh = sinf(osg::DegreesToRadians(hpr[0]));
106  ch = cosf(osg::DegreesToRadians(hpr[0]));
107  }
108 
109  if (osg::equivalent(hpr[1], (osg::Vec3::value_type)0.0, magic_epsilon))
110  {
111  cp = 1.0;
112  sp = 0.0;
113  }
114  else
115  {
116  sp = sinf(osg::DegreesToRadians(hpr[1]));
117  cp = cosf(osg::DegreesToRadians(hpr[1]));
118  }
119 
120  if (osg::equivalent(hpr[2], (osg::Vec3::value_type)0.0, magic_epsilon))
121  {
122  cr = 1.0;
123  sr = 0.0;
124  srsp = 0.0;
125  srcp = 0.0;
126  crsp = sp;
127  }
128  else
129  {
130  sr = sinf(osg::DegreesToRadians(hpr[2]));
131  cr = cosf(osg::DegreesToRadians(hpr[2]));
132  srsp = sr * sp;
133  crsp = cr * sp;
134  srcp = sr * cp;
135  }
136 
137  rotation(0, 0) = ch * cr - sh * srsp;
138  rotation(1, 0) = -sh * cp;
139  rotation(2, 0) = sr * ch + sh * crsp;
140 
141  rotation(0, 1) = cr * sh + srsp * ch;
142  rotation(1, 1) = ch * cp;
143  rotation(2, 1) = sr * sh - crsp * ch;
144 
145  rotation(0, 2) = -srcp;
146  rotation(1, 2) = sp;
147  rotation(2, 2) = cr * cp;
148 
149  rotation(3, 0) = 0.0; // x trans
150  rotation(3, 1) = 0.0; // y trans
151  rotation(3, 2) = 0.0; // z trans
152 
153  rotation(0, 3) = 0.0;
154  rotation(1, 3) = 0.0;
155  rotation(2, 3) = 0.0;
156  rotation(3, 3) = 1.0;
157 }
158 
159 void OsgMatrixUtil::PositionAndHprRadToMatrix(osg::Matrix& rotation, const osg::Vec3& xyz, const osg::Vec3& hpr)
160 {
161  osg::Vec3 vHpr;
162  vHpr[0] = osg::RadiansToDegrees(hpr[0]);
163  vHpr[1] = osg::RadiansToDegrees(hpr[1]);
164  vHpr[2] = osg::RadiansToDegrees(hpr[2]);
165 
166  PositionAndHprToMatrix(rotation, xyz, vHpr);
167 }
168 
169 void OsgMatrixUtil::PositionAndHprToMatrix(osg::Matrix& rotation, const osg::Vec3& xyz, const osg::Vec3& hpr)
170 {
171  HprToMatrix(rotation, hpr);
172 
173  rotation(3, 0) = xyz[0];
174  rotation(3, 1) = xyz[1];
175  rotation(3, 2) = xyz[2];
176 }
177 
178 void OsgMatrixUtil::MatrixToHprRad(osg::Vec3& hpr, const osg::Matrix& rotation)
179 {
180  MatrixToHpr(hpr, rotation);
181  hpr[0] = osg::DegreesToRadians(hpr[0]);
182  hpr[1] = osg::DegreesToRadians(hpr[1]);
183  hpr[2] = osg::DegreesToRadians(hpr[2]);
184 }
185 
186 void OsgMatrixUtil::MatrixToHpr(osg::Vec3& hpr, const osg::Matrix& rotation)
187 {
188  // implementation converted from plib's sg.cxx
189  // PLIB - A Suite of Portable Game Libraries
190  // Copyright (C) 1998,2002 Steve Baker
191  // For further information visit http://plib.sourceforge.net
192 
193  osg::Matrix mat;
194 
195  osg::Vec3 col1(rotation(0, 0), rotation(0, 1), rotation(0, 2));
196  double s = col1.length();
197 
198  const double magic_epsilon = 0.00001;
199  if (s <= magic_epsilon)
200  {
201  hpr.set(0.0f, 0.0f, 0.0f);
202  return;
203  }
204 
205 
206  double oneOverS = 1.0f / s;
207  for (int i = 0; i < 3; ++i)
208  {
209  for (int j = 0; j < 3; ++j)
210  {
211  mat(i, j) = rotation(i, j) * oneOverS;
212  }
213  }
214 
215 
216  double sin_pitch = ClampUnity(mat(1, 2));
217  double pitch = asin(sin_pitch);
218  hpr[1] = osg::RadiansToDegrees(pitch);
219 
220  double cp = cos(pitch);
221 
222  if (cp > -magic_epsilon && cp < magic_epsilon)
223  {
224  double cr = ClampUnity(-mat(2,1));
225  double sr = ClampUnity(mat(0,1));
226 
227  if (hpr[1] < 0.f)
228  {
229  hpr[0] = 180.f;
230  }
231  else
232  {
233  hpr[0] = 0.0f;
234  }
235 
236  hpr[2] = osg::RadiansToDegrees(atan2(sr,cr));
237  }
238  else
239  {
240  double one_over_cp = 1.0 / cp;
241  double sr = ClampUnity(-mat(0,2) * one_over_cp);
242  double cr = ClampUnity( mat(2,2) * one_over_cp);
243  double sh = ClampUnity(-mat(1,0) * one_over_cp);
244  double ch = ClampUnity( mat(1,1) * one_over_cp);
245 
246  if ((osg::equivalent(sh,0.0,magic_epsilon) && osg::equivalent(ch,0.0,magic_epsilon)) ||
247  (osg::equivalent(sr,0.0,magic_epsilon) && osg::equivalent(cr,0.0,magic_epsilon)) )
248  {
249  cr = ClampUnity(-mat(2,1));
250  sr = ClampUnity(mat(0,1));;
251 
252  hpr[0] = 0.0f;
253  }
254  else
255  {
256  hpr[0] = osg::RadiansToDegrees(atan2(sh, ch));
257  }
258 
259  hpr[2] = osg::RadiansToDegrees(atan2(sr, cr));
260  }
261 }
262 
263 
265 {
266  if (x > 1.0f) { return 1.0f; }
267  if (x < -1.0f) { return -1.0f; }
268  return x;
269 }
270 
271 
272 void OsgMatrixUtil::MatrixToHprAndPosition(osg::Vec3& xyz, osg::Vec3& hpr, const osg::Matrix& rotation)
273 {
274  MatrixToHpr(hpr, rotation);
275  xyz[0] = rotation(3, 0);
276  xyz[1] = rotation(3, 1);
277  xyz[2] = rotation(3, 2);
278 }
279 
280 
281 void OsgMatrixUtil::TransformVec3(osg::Vec3& xyz, const osg::Matrix& transformMat)
282 {
283  TransformVec3(xyz, xyz, transformMat);
284 }
285 
286 
287 void OsgMatrixUtil::TransformVec3(osg::Vec3& vec_in, const osg::Vec3& xyz, const osg::Matrix& transformMat)
288 {
289  vec_in = osg::Matrix::transform3x3(xyz, transformMat);
290  vec_in[0] += transformMat(3,0);
291  vec_in[1] += transformMat(3,1);
292  vec_in[2] += transformMat(3,2);
293 }
294 
295 osg::Matrix OsgMatrixUtil::SetupMatrix(CStdFPoint &localPos, CStdFPoint &localRot)
296 {
297  osg::Vec3 vPos(localPos.x, localPos.y, localPos.z);
298  osg::Matrix osgLocalMatrix;
299  osgLocalMatrix.makeIdentity();
300  osgLocalMatrix.makeRotate(localRot.z, osg::Vec3d(0, 0, 1), localRot.y, osg::Vec3d(0, 1, 0), localRot.x, osg::Vec3d(1, 0, 0));
301  osgLocalMatrix.setTrans(vPos);
302  return osgLocalMatrix;
303 }
304 
305 //CStdFPoint OsgMatrixUtil::EulerRotationFromMatrix(osg::Matrix osgMT)
306 //{
307 // osg::Vec3 vEuler;
308 // OsgMatrixUtil::MatrixToHprRad(vEuler, osgMT);
309 // CStdFPoint vRot(vEuler[0], vEuler[1] ,vEuler[2]);
310 // vRot.ClearNearZero();
311 // return vRot;
312 //}
313 
314 
315 CStdFPoint OsgMatrixUtil::EulerRotationFromMatrix(osg::Matrix osgMT)
316 {
317  return EulerRotationFromMatrix_Static(osgMT);
318 }
319 
320 CStdFPoint OsgMatrixUtil::EulerRotationFromMatrix_Static (osg::Matrix osgMT)
321 {
322  //We need to transpose the matrix that osg provides for us in
323  //order to do the following calculations.
324  osg::Matrix3 osgMT3(osgMT(0, 0), osgMT(1, 0), osgMT(2, 0),
325  osgMT(0, 1), osgMT(1, 1), osgMT(2, 1),
326  osgMT(0, 2), osgMT(1, 2), osgMT(2, 2));
327 
328  // +- -+ +- -+
329  // | r00 r01 r02 | | cy*cz -cy*sz sy |
330  // | r10 r11 r12 | = | cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx |
331  // | r20 r21 r22 | | -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy |
332  // +- -+ +- -+
333  float xAngle=0, yAngle=0, zAngle=0;
334 
335  if (osgMT3(0, 2) < 1)
336  {
337  if (osgMT3(0, 2) > -1)
338  {
339  // y_angle = asin(r02)
340  // x_angle = atan2(-r12,r22)
341  // z_angle = atan2(-r01,r00)
342  yAngle = (float) asin((double) osgMT3(0, 2));
343  xAngle = (float) atan2((double) -osgMT3(1, 2), (double) osgMT3(2, 2));
344  zAngle = (float) atan2((double) -osgMT3(0, 1), (double) osgMT3(0, 0));
345  }
346  else
347  {
348  // y_angle = -pi/2
349  // z_angle - x_angle = atan2(r10,r11)
350  // WARNING. The solution is not unique. Choosing z_angle = 0.
351  yAngle = -(osg::PI/2);
352  xAngle = -atan2((double) osgMT3(1, 0), (double) osgMT3(1, 1));
353  zAngle = 0;
354  }
355  }
356  else
357  {
358  // y_angle = +pi/2
359  // z_angle + x_angle = atan2(r10,r11)
360  // WARNING. The solutions is not unique. Choosing z_angle = 0.
361  yAngle = osg::PI/2;
362  xAngle = atan2((double) osgMT3(1, 0), (double) osgMT3(1, 1));
363  zAngle = 0;
364  }
365 
366  CStdFPoint vRot(xAngle, yAngle, zAngle);
367  vRot.ClearNearZero();
368 
369  return vRot;
370 }
371 
372 
373 } //OsgAnimatSim
static void HprToMatrix(osg::Matrix &rotation, const osg::Vec3 &hpr)
Classes for implementing the cm-labs vortex physics engine for AnimatLab.
static void Print(const osg::Matrix &matrix)
Prints a matrix.
static void MatrixToHprRad(osg::Vec3 &hpr, const osg::Matrix &rotation)
static float ClampUnity(float x)
clamps a float from -1 to 1
static void PositionAndHprToMatrix(osg::Matrix &rotation, const osg::Vec3 &xyz, const osg::Vec3 &hpr)
static void TransformVec3(osg::Vec3 &xyz, const osg::Matrix &transformMat)
static void MatrixToHprAndPosition(osg::Vec3 &xyz, osg::Vec3 &hpr, const osg::Matrix &rotation)
static void MatrixToHpr(osg::Vec3 &hpr, const osg::Matrix &rotation)
static void Transpose(osg::Matrix &dest, const osg::Matrix &src)
transposes a matrix