rotation.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:7k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // rotation.cpp
  2. //
  3. // Implementation of basic RotationModel class hierarchy for describing
  4. // the orientation of objects over time.
  5. //
  6. // Copyright (C) 2006, Chris Laurel <claurel@shatters.net>
  7. //
  8. // This program is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU General Public License
  10. // as published by the Free Software Foundation; either version 2
  11. // of the License, or (at your option) any later version.
  12. #include "rotation.h"
  13. using namespace std;
  14. static const double ANGULAR_VELOCITY_DIFF_DELTA = 1.0 / 1440.0;
  15. // Choose a time interval for numerically differentiating orientation
  16. // to get the angular velocity for a rotation model.
  17. static double chooseDiffTimeDelta(const RotationModel& rm)
  18. {
  19.     if (rm.isPeriodic())
  20.         return rm.getPeriod() / 10000.0;
  21.     else
  22.         return ANGULAR_VELOCITY_DIFF_DELTA;
  23. }
  24. /***** RotationModel *****/
  25. /*! Return the angular velocity at the specified time (TDB). The default
  26.  *  implementation computes the angular velocity via differentiation.
  27.  */
  28. Vec3d
  29. RotationModel::angularVelocityAtTime(double tdb) const
  30. {
  31.     double dt = chooseDiffTimeDelta(*this);
  32. Quatd q0 = orientationAtTime(tdb);
  33. Quatd q1 = orientationAtTime(tdb + dt);
  34. Quatd dq = ~q1 * q0;
  35. if (fabs(dq.w) > 0.99999999)
  36. return Vec3d(0.0, 0.0, 0.0);
  37. Vec3d v(dq.x, dq.y, dq.z);
  38. v.normalize();
  39. return v * (2.0 * acos(dq.w) / dt);
  40. }
  41. /***** CachingRotationModel *****/
  42. CachingRotationModel::CachingRotationModel() :
  43.     lastTime(365.0),
  44.     spinCacheValid(false),
  45.     equatorCacheValid(false),
  46.     angularVelocityCacheValid(false)
  47. {
  48. }
  49. CachingRotationModel::~CachingRotationModel()
  50. {
  51. }
  52. Quatd
  53. CachingRotationModel::spin(double tjd) const
  54. {
  55.     if (tjd != lastTime)
  56.     {
  57.         lastTime = tjd;
  58.         lastSpin = computeSpin(tjd);
  59.         spinCacheValid = true;
  60.         equatorCacheValid = false;
  61.         angularVelocityCacheValid = false;
  62.     }
  63.     else if (!spinCacheValid)
  64.     {
  65.         lastSpin = computeSpin(tjd);
  66.         spinCacheValid = true;
  67.     }
  68.     
  69.     return lastSpin;
  70. }
  71. Quatd
  72. CachingRotationModel::equatorOrientationAtTime(double tjd) const
  73. {
  74.     if (tjd != lastTime)
  75.     {
  76.         lastTime = tjd;
  77.         lastEquator = computeEquatorOrientation(tjd);
  78.         spinCacheValid = false;
  79.         equatorCacheValid = true;
  80.         angularVelocityCacheValid = false;
  81.     }
  82.     else if (!equatorCacheValid)
  83.     {
  84.         lastEquator = computeEquatorOrientation(tjd);
  85.         equatorCacheValid = true;
  86.     }
  87.     
  88.     return lastEquator;    
  89. }
  90. Vec3d
  91. CachingRotationModel::angularVelocityAtTime(double tjd) const
  92. {
  93.     if (tjd != lastTime)
  94.     {
  95.         lastAngularVelocity = computeAngularVelocity(tjd);
  96.         lastTime = tjd;
  97.         spinCacheValid = false;
  98.         equatorCacheValid = false;
  99.         angularVelocityCacheValid = true;
  100.     }
  101.     else if (!angularVelocityCacheValid)
  102.     {
  103.         lastAngularVelocity = computeAngularVelocity(tjd);
  104.         angularVelocityCacheValid = true;
  105.     }
  106.     
  107.     return lastAngularVelocity;    
  108. }
  109. Vec3d
  110. CachingRotationModel::computeAngularVelocity(double tjd) const
  111. {
  112.     double dt = chooseDiffTimeDelta(*this);
  113.     Quatd q0 = orientationAtTime(tjd);
  114.     
  115.     // Call computeSpin/computeEquatorOrientation instead of orientationAtTime
  116.     // in order to avoid affecting the cache.
  117.     Quatd spin = computeSpin(tjd + dt);
  118.     Quatd equator = computeEquatorOrientation(tjd + dt);
  119. Quatd q1 = spin * equator;
  120.     Quatd dq = ~q1 * q0;
  121.     
  122. if (fabs(dq.w) > 0.99999999)
  123. return Vec3d(0.0, 0.0, 0.0);
  124.     
  125. Vec3d v(dq.x, dq.y, dq.z);
  126. v.normalize();
  127. return v * (2.0 * acos(dq.w) / dt);    
  128. }
  129. /***** ConstantOrientation implementation *****/
  130. ConstantOrientation::ConstantOrientation(const Quatd& q) :
  131.     orientation(q)
  132. {
  133. }
  134. ConstantOrientation::~ConstantOrientation()
  135. {
  136. }
  137. Quatd
  138. ConstantOrientation::spin(double) const
  139. {
  140.     return orientation;
  141. }
  142. Vec3d
  143. ConstantOrientation::angularVelocityAtTime(double /* tdb */) const
  144. {
  145. return Vec3d(0.0, 0.0, 0.0);
  146. }
  147. /***** UniformRotationModel implementation *****/
  148. UniformRotationModel::UniformRotationModel(double _period,
  149.                                            float _offset,
  150.                                            double _epoch,
  151.                                            float _inclination,
  152.                                            float _ascendingNode) :
  153.     period(_period),
  154.     offset(_offset),
  155.     epoch(_epoch),
  156.     inclination(_inclination),
  157.     ascendingNode(_ascendingNode)
  158. {
  159. }
  160. UniformRotationModel::~UniformRotationModel()
  161. {
  162. }
  163. bool
  164. UniformRotationModel::isPeriodic() const
  165. {
  166.     return true;
  167. }
  168. double
  169. UniformRotationModel::getPeriod() const
  170. {
  171.     return period;
  172. }
  173. Quatd
  174. UniformRotationModel::spin(double tjd) const
  175. {
  176.     double rotations = (tjd - epoch) / period;
  177.     double wholeRotations = floor(rotations);
  178.     double remainder = rotations - wholeRotations;
  179.     // TODO: This is the wrong place for this offset
  180.     // Add an extra half rotation because of the convention in all
  181.     // planet texture maps where zero deg long. is in the middle of
  182.     // the texture.
  183.     remainder += 0.5;
  184.     
  185.     return Quatd::yrotation(-remainder * 2 * PI - offset);
  186. }
  187. Quatd
  188. UniformRotationModel::equatorOrientationAtTime(double) const
  189. {
  190.     return Quatd::xrotation(-inclination) * Quatd::yrotation(-ascendingNode);
  191. }
  192. Vec3d
  193. UniformRotationModel::angularVelocityAtTime(double tdb) const
  194. {
  195. Vec3d v(0.0, 1.0, 0.0);
  196. v = v * equatorOrientationAtTime(tdb).toMatrix3();
  197. return v * (2.0 * PI / period);
  198. }
  199. /***** PrecessingRotationModel implementation *****/
  200. PrecessingRotationModel::PrecessingRotationModel(double _period,
  201.                                                  float _offset,
  202.                                                  double _epoch,
  203.                                                  float _inclination,
  204.                                                  float _ascendingNode,
  205.                                                  double _precPeriod) :
  206.     period(_period),
  207.     offset(_offset),
  208.     epoch(_epoch),
  209.     inclination(_inclination),
  210.     ascendingNode(_ascendingNode),
  211.     precessionPeriod(_precPeriod)
  212. {
  213. }
  214. PrecessingRotationModel::~PrecessingRotationModel()
  215. {
  216. }
  217. bool
  218. PrecessingRotationModel::isPeriodic() const
  219. {
  220.     return true;
  221. }
  222. double
  223. PrecessingRotationModel::getPeriod() const
  224. {
  225.     return period;
  226. }
  227. Quatd
  228. PrecessingRotationModel::spin(double tjd) const
  229. {
  230.     double rotations = (tjd - epoch) / period;
  231.     double wholeRotations = floor(rotations);
  232.     double remainder = rotations - wholeRotations;
  233.     // TODO: This is the wrong place for this offset
  234.     // Add an extra half rotation because of the convention in all
  235.     // planet texture maps where zero deg long. is in the middle of
  236.     // the texture.
  237.     remainder += 0.5;
  238.     
  239.     return Quatd::yrotation(-remainder * 2 * PI - offset);
  240. }
  241. Quatd
  242. PrecessingRotationModel::equatorOrientationAtTime(double tjd) const
  243. {
  244.     double nodeOfDate;
  245.     // A precession rate of zero indicates no precession
  246.     if (precessionPeriod == 0.0)
  247.         nodeOfDate = ascendingNode;
  248.     else
  249.         nodeOfDate = (double) ascendingNode -
  250.             (2.0 * PI / precessionPeriod) * (tjd - epoch);
  251.     return Quatd::xrotation(-inclination) * Quatd::yrotation(-nodeOfDate);
  252. }