+ /// Return a quaternion rotation from the earth centered to the
+ /// OpenGL/viewer horizontal local frame from given longitude and latitude.
+ /// This frame matches the usual OpenGL axis directions. That is the target
+ /// frame has an x-axis pointing eastwards, y-axis pointing up and y z-axis
+ /// pointing south.
+ static SGQuat viewHLRad(T lon, T lat)
+ {
+ // That bails down to a 3-2-1 euler sequence lon+pi/2, 0, -lat-pi
+ // what is here is again the hand optimized version ...
+ SGQuat q;
+ T xd2 = -T(0.5)*lat - T(0.5)*SGMisc<T>::pi();
+ T zd2 = T(0.5)*lon + T(0.25)*SGMisc<T>::pi();
+ T Szd2 = sin(zd2);
+ T Sxd2 = sin(xd2);
+ T Czd2 = cos(zd2);
+ T Cxd2 = cos(xd2);
+ q.w() = Cxd2*Czd2;
+ q.x() = Sxd2*Czd2;
+ q.y() = Sxd2*Szd2;
+ q.z() = Cxd2*Szd2;
+ return q;
+ }
+ /// Like the above provided for convenience
+ static SGQuat viewHLDeg(T lon, T lat)
+ { return viewHLRad(SGMisc<T>::deg2rad(lon), SGMisc<T>::deg2rad(lat)); }
+ /// Like the above provided for convenience
+ static SGQuat viewHL(const SGGeod& geod)
+ { return viewHLRad(geod.getLongitudeRad(), geod.getLatitudeRad()); }
+
+ /// Convert a quaternion rotation from the simulation frame
+ /// to the view (OpenGL) frame. That is it just swaps the axis part of
+ /// this current quaternion.
+ /// That proves useful when you want to use the euler 3-2-1 sequence
+ /// for the usual heading/pitch/roll sequence within the context of
+ /// OpenGL/viewer frames.
+ static SGQuat simToView(const SGQuat& q)
+ { return SGQuat(q.y(), -q.z(), -q.x(), q.w()); }
+