+ if ( _from_model ) {
+ SGModelPlacement* placement = globals->get_aircraft_model()->get3DModel();
+ _position = placement->getPosition();
+ _heading_deg = placement->getHeadingDeg();
+ _pitch_deg = placement->getPitchDeg();
+ _roll_deg = placement->getRollDeg();
+ } else {
+ // update from our own data, just the rotation here...
+ dampEyeData(_roll_deg, _pitch_deg, _heading_deg);
+ }
+ SGQuatd geodEyeOr = SGQuatd::fromYawPitchRollDeg(_heading_deg,
+ _pitch_deg,
+ _roll_deg);
+ SGQuatd geodEyeHlOr = SGQuatd::fromLonLat(_position);
+
+ // the rotation offset, don't know why heading is negative here ...
+ mViewOffsetOr =
+ SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg + 180, _pitch_offset_deg,
+ _roll_offset_deg);
+
+ // Offsets to the eye position
+ SGVec3d eyeOff(-_offset_m.z(), _offset_m.x(), -_offset_m.y());
+ SGQuatd ec2eye = geodEyeHlOr*geodEyeOr;
+ SGVec3d eyeCart = SGVec3d::fromGeod(_position);
+ eyeCart += (ec2eye*mViewOffsetOr).backTransform(eyeOff);
+
+ SGVec3d atCart = SGVec3d::fromGeod(_target);
+
+ // add target offsets to at_position...
+ SGVec3d target_pos_off(-_target_offset_m.z(), _target_offset_m.x(),
+ -_target_offset_m.y());
+ target_pos_off = (geodTargetHlOr*geodTargetOr).backTransform(target_pos_off);
+ atCart += target_pos_off;
+ eyeCart += target_pos_off;
+
+ // Compute the eyepoints orientation and position
+ // wrt the earth centered frame - that is global coorinates
+ _absolute_view_pos = eyeCart;
+
+ // the view direction
+ SGVec3d dir = normalize(atCart - eyeCart);
+ // the up directon
+ SGVec3d up = ec2eye.backTransform(SGVec3d(0, 0, -1));
+ // rotate -dir to the 2-th unit vector
+ // rotate up to 1-th unit vector
+ // Note that this matches the OpenGL camera coordinate system
+ // with x-right, y-up, z-back.
+ mViewOrientation = SGQuatd::fromRotateTo(-dir, 2, up, 1);
+}
+
+void
+FGViewer::dampEyeData(double &roll_deg, double &pitch_deg, double &heading_deg)
+{
+ const double interval = 0.01;
+
+ static FGViewer *last_view = 0;
+ if (last_view != this) {
+ _damp_sync = 0.0;
+ _damped_roll_deg = roll_deg;
+ _damped_pitch_deg = pitch_deg;
+ _damped_heading_deg = heading_deg;
+ last_view = this;
+ return;
+ }
+
+ if (_damp_sync < interval) {
+ if (_damp_roll > 0.0)
+ roll_deg = _damped_roll_deg;
+ if (_damp_pitch > 0.0)
+ pitch_deg = _damped_pitch_deg;
+ if (_damp_heading > 0.0)
+ heading_deg = _damped_heading_deg;
+ return;
+ }