32#include <simgear/compiler.h>
35#include <simgear/debug/logstream.hxx>
36#include <simgear/constants.h>
37#include <simgear/scene/model/placement.hxx>
38#include <simgear/scene/util/OsgMath.hxx>
39#include <simgear/structure/event_mgr.hxx>
58View::View( ViewType Type,
bool from_model,
int from_model_index,
59 bool at_model,
int at_model_index,
60 double damp_roll,
double damp_pitch,
double damp_heading,
61 double x_offset_m,
double y_offset_m,
double z_offset_m,
62 double heading_offset_deg,
double pitch_offset_deg,
63 double roll_offset_deg,
64 double fov_deg,
double aspect_ratio_multiplier,
65 double target_x_offset_m,
double target_y_offset_m,
66 double target_z_offset_m,
double near_m,
bool internal,
67 bool lookat_agl,
double lookat_agl_damping,
75 _target_heading_deg(0),
76 _lookat_agl_damping(lookat_agl_damping , 0 , 0 ),
77 _lookat_agl_ground_altitude(0),
78 _scaling_type(FG_SCALING_MAX)
80 _absolute_view_pos = SGVec3d(0, 0, 0);
82 _from_model = from_model;
83 _from_model_index = from_model_index;
85 _at_model_index = at_model_index;
88 _lookat_agl = lookat_agl;
89 _view_index = view_index;
91 _dampFactor = SGVec3d::zeros();
92 _dampOutput = SGVec3d::zeros();
93 _dampTarget = SGVec3d::zeros();
96 _dampFactor[0] = 1.0 / pow(10.0, fabs(damp_roll));
98 _dampFactor[1] = 1.0 / pow(10.0, fabs(damp_pitch));
99 if (damp_heading > 0.0)
100 _dampFactor[2] = 1.0 / pow(10.0, fabs(damp_heading));
102 _offset_m.x() = x_offset_m;
103 _offset_m.y() = y_offset_m;
104 _offset_m.z() = z_offset_m;
105 _configOffset_m = _offset_m;
107 _heading_offset_deg = heading_offset_deg;
108 _pitch_offset_deg = pitch_offset_deg;
109 _roll_offset_deg = roll_offset_deg;
110 _goal_heading_offset_deg = heading_offset_deg;
111 _goal_pitch_offset_deg = pitch_offset_deg;
112 _goal_roll_offset_deg = roll_offset_deg;
114 _configHeadingOffsetDeg = heading_offset_deg;
115 _configPitchOffsetDeg = pitch_offset_deg;
116 _configRollOffsetDeg = roll_offset_deg;
124 _configFOV_deg = _fov_deg;
126 _fov_user_deg = _fov_deg;
128 _aspect_ratio_multiplier = aspect_ratio_multiplier;
129 _target_offset_m.x() = target_x_offset_m;
130 _target_offset_m.y() = target_y_offset_m;
131 _target_offset_m.z() = target_z_offset_m;
132 _configTargetOffset_m = _target_offset_m;
134 _ground_level_nearplane_m = near_m;
137 resetOffsetsAndFOV();
142 double aspect_ratio_multiplier
143 =
fgGetDouble(
"/sim/current-view/aspect-ratio-multiplier");
147 bool internal = config->getParent()->getBoolValue(
"internal",
false);
149 std::string root = config->getPath();
157 bool from_model = config->getBoolValue(
"from-model");
158 int from_model_index = config->getIntValue(
"from-model-idx");
160 double x_offset_m = config->getDoubleValue(
"x-offset-m");
161 double y_offset_m = config->getDoubleValue(
"y-offset-m");
162 double z_offset_m = config->getDoubleValue(
"z-offset-m");
164 double heading_offset_deg = config->getDoubleValue(
"heading-offset-deg");
166 double pitch_offset_deg = config->getDoubleValue(
"pitch-offset-deg");
168 double roll_offset_deg = config->getDoubleValue(
"roll-offset-deg");
171 double fov_deg = config->getDoubleValue(
"default-field-of-view-deg");
172 double near_m = config->getDoubleValue(
"ground-level-nearplane-m");
176 std::string type = config->getParent()->getStringValue(
"type");
177 if (type ==
"lookat") {
178 bool at_model = config->getBoolValue(
"at-model");
179 int at_model_index = config->getIntValue(
"at-model-idx");
181 double damp_roll = config->getDoubleValue(
"at-model-roll-damping");
182 double damp_pitch = config->getDoubleValue(
"at-model-pitch-damping");
183 double damp_heading = config->getDoubleValue(
"at-model-heading-damping");
185 double target_x_offset_m = config->getDoubleValue(
"target-x-offset-m");
186 double target_y_offset_m = config->getDoubleValue(
"target-y-offset-m");
187 double target_z_offset_m = config->getDoubleValue(
"target-z-offset-m");
188 bool lookat_agl = config->getBoolValue(
"lookat-agl");
189 double lookat_agl_damping = config->getDoubleValue(
"lookat-agl-damping");
191 v =
new View (
FG_LOOKAT, from_model, from_model_index,
192 at_model, at_model_index,
193 damp_roll, damp_pitch, damp_heading,
194 x_offset_m, y_offset_m,z_offset_m,
195 heading_offset_deg, pitch_offset_deg,
196 roll_offset_deg, fov_deg, aspect_ratio_multiplier,
197 target_x_offset_m, target_y_offset_m,
198 target_z_offset_m, near_m, internal, lookat_agl,
199 lookat_agl_damping, view_index );
201 v =
new View (
FG_LOOKFROM, from_model, from_model_index,
202 false, 0, 0.0, 0.0, 0.0,
203 x_offset_m, y_offset_m, z_offset_m,
204 heading_offset_deg, pitch_offset_deg,
205 roll_offset_deg, fov_deg, aspect_ratio_multiplier,
206 0, 0, 0, near_m, internal,
false, 0.0, view_index );
209 v->_name = config->getParent()->getStringValue(
"name");
210 v->_typeString = type;
211 v->_configHeadingOffsetDeg = config->getDoubleValue(
"default-heading-offset-deg");
221 _tiedProperties.Untie();
236 _tiedProperties.setRoot(
fgGetNode(
"/sim/current-view",
true));
237 _tiedProperties.Tie(
"heading-offset-deg",
this,
239 &View::setHeadingOffset_deg_property,
244 _tiedProperties.Tie(
"goal-heading-offset-deg",
this,
245 &View::getGoalHeadingOffset_deg,
251 _tiedProperties.Tie(
"pitch-offset-deg",
this,
253 &View::setPitchOffset_deg_property,
256 _tiedProperties.Tie(
"goal-pitch-offset-deg",
this,
257 &View::getGoalPitchOffset_deg,
258 &View::setGoalPitchOffset_deg,
261 _tiedProperties.Tie(
"roll-offset-deg",
this,
263 &View::setRollOffset_deg_property,
266 _tiedProperties.Tie(
"goal-roll-offset-deg",
this,
267 &View::getGoalRollOffset_deg,
268 &View::setGoalRollOffset_deg,
273 _tiedProperties.Tie(
"field-of-view",
this,
274 &View::get_fov_user, &View::set_fov_user,
279 _tiedProperties.Tie(
"aspect-ratio-multiplier",
this,
280 &View::get_aspect_ratio_multiplier,
281 &View::set_aspect_ratio_multiplier,
284 _tiedProperties.Tie(
"ground-level-nearplane-m",
this,
285 &View::getNear_m, &View::setNear_m,
false);
289 _tiedProperties.Tie(
"viewer-lon-deg",
this, &View::getLon_deg);
290 _tiedProperties.Tie(
"viewer-lat-deg",
this, &View::getLat_deg);
291 _tiedProperties.Tie(
"viewer-elev-ft",
this, &View::getElev_ft);
308 _tiedProperties.Tie(
"debug/orientation-w",
this, &View::getOrientation_w);
309 _tiedProperties.Tie(
"debug/orientation-x",
this, &View::getOrientation_x);
310 _tiedProperties.Tie(
"debug/orientation-y",
this, &View::getOrientation_y);
311 _tiedProperties.Tie(
"debug/orientation-z",
this, &View::getOrientation_z);
313 _tiedProperties.Tie(
"debug/orientation_offset-w",
this,
314 &View::getOrOffset_w);
315 _tiedProperties.Tie(
"debug/orientation_offset-x",
this,
316 &View::getOrOffset_x);
317 _tiedProperties.Tie(
"debug/orientation_offset-y",
this,
318 &View::getOrOffset_y);
319 _tiedProperties.Tie(
"debug/orientation_offset-z",
this,
320 &View::getOrOffset_z);
322 _tiedProperties.Tie(
"debug/frame-w",
this, &View::getFrame_w);
323 _tiedProperties.Tie(
"debug/frame-x",
this, &View::getFrame_x);
324 _tiedProperties.Tie(
"debug/frame-y",
this, &View::getFrame_y);
325 _tiedProperties.Tie(
"debug/frame-z",
this, &View::getFrame_z);
330 _tiedProperties.Tie(
"raw-orientation", 0,
this, &View::getRawOrientation_w);
331 _tiedProperties.Tie(
"raw-orientation", 1,
this, &View::getRawOrientation_x);
332 _tiedProperties.Tie(
"raw-orientation", 2,
this, &View::getRawOrientation_y);
333 _tiedProperties.Tie(
"raw-orientation", 3,
this, &View::getRawOrientation_z);
335 _tiedProperties.Tie(
"viewer-x-m",
this, &View::getAbsolutePosition_x);
336 _tiedProperties.Tie(
"viewer-y-m",
this, &View::getAbsolutePosition_y);
337 _tiedProperties.Tie(
"viewer-z-m",
this, &View::getAbsolutePosition_z);
341 _tiedProperties.getRoot()->setStringValue(
"name", _name);
342 _tiedProperties.getRoot()->setStringValue(
"type", _typeString);
343 _tiedProperties.getRoot()->setBoolValue(
"internal", _internal);
345 SGPropertyNode_ptr config = _tiedProperties.getRoot()->getChild(
"config", 0,
true);
346 config->setBoolValue(
"from-model", _from_model);
347 config->setDoubleValue(
"heading-offset-deg", _configHeadingOffsetDeg);
348 config->setDoubleValue(
"pitch-offset-deg", _configPitchOffsetDeg);
349 config->setDoubleValue(
"roll-offset-deg", _configRollOffsetDeg);
350 config->setDoubleValue(
"default-field-of-view-deg", _configFOV_deg);
356 _tiedProperties.Untie();
361 _target_offset_m = _configTargetOffset_m;
362 _offset_m = _configOffset_m;
363 _adjust_offset_m = _configOffset_m;
364 _pitch_offset_deg = _configPitchOffsetDeg;
365 _heading_offset_deg = _configHeadingOffsetDeg;
366 _roll_offset_deg = _configRollOffsetDeg;
367 _fov_deg = _configFOV_deg;
382 _internal = internal;
386View::setPosition (
const SGGeod& geod)
393View::setTargetPosition (
const SGGeod& geod)
400View::setRoll_deg (
double roll_deg)
403 _roll_deg = roll_deg;
407View::setPitch_deg (
double pitch_deg)
410 _pitch_deg = pitch_deg;
414View::setHeading_deg (
double heading_deg)
417 _heading_deg = heading_deg;
421View::setOrientation (
double roll_deg,
double pitch_deg,
double heading_deg)
424 _roll_deg = roll_deg;
425 _pitch_deg = pitch_deg;
426 _heading_deg = heading_deg;
430View::setTargetRoll_deg (
double target_roll_deg)
433 _target_roll_deg = target_roll_deg;
437View::setTargetPitch_deg (
double target_pitch_deg)
440 _target_pitch_deg = target_pitch_deg;
444View::setTargetHeading_deg (
double target_heading_deg)
447 _target_heading_deg = target_heading_deg;
451View::setTargetOrientation (
double target_roll_deg,
double target_pitch_deg,
double target_heading_deg)
454 _target_roll_deg = target_roll_deg;
455 _target_pitch_deg = target_pitch_deg;
456 _target_heading_deg = target_heading_deg;
463 _offset_m.x() = x_offset_m;
470 _offset_m.y() = y_offset_m;
477 _offset_m.z() = z_offset_m;
484 _target_offset_m.x() = target_x_offset_m;
491 _target_offset_m.y() = target_y_offset_m;
498 _target_offset_m.z() = target_z_offset_m;
505 _adjust_offset_m.x() = x_offset_m;
512 _adjust_offset_m.y() = y_offset_m;
519 _adjust_offset_m.z() = z_offset_m;
526 _offset_m.x() = x_offset_m;
527 _offset_m.y() = y_offset_m;
528 _offset_m.z() = z_offset_m;
532View::setRollOffset_deg (
double roll_offset_deg)
535 _roll_offset_deg = roll_offset_deg;
539View::setPitchOffset_deg (
double pitch_offset_deg)
542 _pitch_offset_deg = pitch_offset_deg;
549 if (_at_model && (_offset_m.x() == 0.0)&&(_offset_m.z() == 0.0))
553 _heading_offset_deg = 0.0;
556 _heading_offset_deg = heading_offset_deg;
560View::setHeadingOffset_deg_property (
double heading_offset_deg)
567View::setPitchOffset_deg_property (
double pitch_offset_deg)
569 setPitchOffset_deg(pitch_offset_deg);
570 setGoalPitchOffset_deg(pitch_offset_deg);
574View::setRollOffset_deg_property (
double roll_offset_deg)
576 setRollOffset_deg(roll_offset_deg);
577 setGoalRollOffset_deg(roll_offset_deg);
581View::setGoalRollOffset_deg (
double goal_roll_offset_deg)
584 _goal_roll_offset_deg = goal_roll_offset_deg;
588View::setGoalPitchOffset_deg (
double goal_pitch_offset_deg)
591 _goal_pitch_offset_deg = goal_pitch_offset_deg;
596 if ( _goal_pitch_offset_deg < -89.999 ) {
597 _goal_pitch_offset_deg = -89.999;
599 if ( _goal_pitch_offset_deg > 89.999 ) {
600 _goal_pitch_offset_deg = 89.999;
609 if (_at_model && (_offset_m.x() == 0.0)&&(_offset_m.z() == 0.0))
613 _goal_heading_offset_deg = 0.0;
617 _goal_heading_offset_deg = goal_heading_offset_deg;
618 while ( _goal_heading_offset_deg < 0.0 ) {
619 _goal_heading_offset_deg += 360;
621 while ( _goal_heading_offset_deg > 360 ) {
622 _goal_heading_offset_deg -= 360;
627View::setOrientationOffsets (
double roll_offset_deg,
double pitch_offset_deg,
double heading_offset_deg)
630 _roll_offset_deg = roll_offset_deg;
631 _pitch_offset_deg = pitch_offset_deg;
632 _heading_offset_deg = heading_offset_deg;
670 position = SGGeod::fromDegFt(
713 const SGVec3d* adjust,
718 if (root ==
"/" || root ==
"") {
732 offset_m.x() =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/view[(/sim/current-view/view-number-raw)]/config/target-x-offset-m)");
733 offset_m.y() =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/view[(/sim/current-view/view-number-raw)]/config/target-y-offset-m)");
734 offset_m.z() =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/view[(/sim/current-view/view-number-raw)]/config/target-z-offset-m)");
737 offset_m.x() =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/view[(/sim/current-view/view-number-raw)]/config/x-offset-m)");
738 offset_m.y() =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/view[(/sim/current-view/view-number-raw)]/config/y-offset-m)");
739 offset_m.z() =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/view[(/sim/current-view/view-number-raw)]/config/z-offset-m)");
743 SGVec3d offset = *adjust;
765View::recalcLookFrom ()
788 _position = SGGeod::fromDegFt(
793 head =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-heading-deg-path))");
794 pitch =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-pitch-deg-path))");
795 roll =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-roll-deg-path))");
803 set_fov(_fov_user_deg);
807 SGQuatd hlOr = SGQuatd::fromLonLat(_position);
810 SGQuatd hlToBody = SGQuatd::fromYawPitchRollDeg(head, pitch, roll);
814 = SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg, _pitch_offset_deg,
819 SGQuatd ec2body = hlOr*hlToBody;
822 SGVec3d position = SGVec3d::fromGeod(_position);
826 SGQuatd q(-0.5, -0.5, 0.5, 0.5);
828 _absolute_view_pos = position + (ec2body*q).backTransform(offset_m);
829 mViewOrientation = ec2body*mViewOffsetOr*q;
839void View::handleAGL()
847 double ground_altitude = 0;
848 const simgear::BVHMaterial* material = NULL;
849 SGGeod target_plus = _target;
850 target_plus.setElevationM(target_plus.getElevationM() + 1);
854 _lookat_agl_ground_altitude = ground_altitude;
864 ground_altitude = _lookat_agl_ground_altitude;
865 SG_LOG(SG_VIEW, SG_DEBUG,
"get_elevation_m() failed. _target=" << _target <<
"\n");
868 double h_distance = SGGeodesy::distanceM(_position, _target);
869 if (h_distance == 0) {
873 set_fov(_fov_user_deg);
877 double relative_height_target = _target.getElevationM() - _position.getElevationM();
878 double relative_height_ground = ground_altitude - _position.getElevationM();
890 relative_height_ground -= 2;
892 double chase_distance_m;
894 if (root ==
"/" || root ==
"") {
899 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/set/sim/chase-distance-m)",
903 if (chase_distance_m == 0) {
907 chase_distance_m = -25;
909 double aircraft_size_vertical = fabs(chase_distance_m) * 0.3;
910 double aircraft_size_horizontal = fabs(chase_distance_m) * 0.9;
912 double relative_height_target_plus = relative_height_target + aircraft_size_vertical;
913 double relative_height_ground_ = relative_height_ground;
914 _lookat_agl_damping.updateTarget(relative_height_ground);
915 if (relative_height_ground > relative_height_target) {
919 _lookat_agl_damping.reset(relative_height_ground_);
920 relative_height_ground = relative_height_ground_;
926 double delta = relative_height_target_plus - relative_height_ground;
927 delta *= (_fov_user_deg / _configFOV_deg);
928 relative_height_ground = relative_height_target_plus - delta;
931 double angle_v_target = atan(relative_height_target_plus / h_distance);
932 double angle_v_ground = atan(relative_height_ground / h_distance);
936 double angle_v_mid = (angle_v_target + angle_v_ground) / 2;
937 _target.setElevationM(_position.getElevationM() + h_distance * tan(angle_v_mid));
942 double fov_v = fabs(angle_v_target - angle_v_ground);
943 double fov_v_deg = fov_v / 3.1415 * 180;
952 fov_h = 2 * atan(aircraft_size_horizontal / 2 / h_distance);
953 double fov_h_deg = fov_h / 3.1415 * 180;
955 double correction_v = fov_v_deg /
get_v_fov();
956 double correction_h = fov_h_deg /
get_h_fov();
957 double correction = std::max(correction_v, correction_h);
958 if (correction > 1) {
959 fov_v_deg *= correction;
963 SG_LOG(SG_VIEW, SG_DEBUG,
""
964 <<
" fov_v_deg=" << fov_v_deg
965 <<
" _position=" << _position
966 <<
" _target=" << _target
967 <<
" ground_altitude=" << ground_altitude
968 <<
" relative_height_target_plus=" << relative_height_target_plus
969 <<
" relative_height_ground=" << relative_height_ground
970 <<
" chase_distance_m=" << chase_distance_m
990 double eye_heading =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-heading-deg-path))");
991 double eye_roll =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-roll-deg-path))");
992 double eye_pitch =
ViewPropertyEvaluator::getDoubleValue(
"((/sim/view[(/sim/current-view/view-number-raw)]/config/root)/(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-pitch-deg-path))");
994 setDampTarget(eye_roll, eye_pitch, eye_heading);
995 getDampOutput(eye_roll, eye_pitch, eye_heading);
997 SGQuatd geodTargetOr = SGQuatd::fromYawPitchRollDeg(_target_heading_deg,
1000 SGQuatd geodTargetHlOr = SGQuatd::fromLonLat(_target);
1002 SGVec3d target_pos_off;
1004 target_pos_off = SGVec3d(
1005 -target_pos_off.z(),
1009 target_pos_off = (geodTargetHlOr*geodTargetOr).backTransform(target_pos_off);
1011 SGVec3d targetCart = SGVec3d::fromGeod(_target);
1012 SGVec3d targetCart2 = targetCart + target_pos_off;
1013 SGGeodesy::SGCartToGeod(targetCart2, _target);
1015 _position = _target;
1019 _position.setLongitudeDeg(
1021 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-lon-deg-path))",
1022 _position.getLongitudeDeg()
1025 _position.setLatitudeDeg(
1027 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-lat-deg-path))",
1028 _position.getLatitudeDeg()
1031 _position.setElevationFt(
1033 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)(/sim/view[(/sim/current-view/view-number-raw)]/config/eye-alt-ft-path))",
1034 _position.getElevationFt()
1039 _target.setLongitudeDeg(
1041 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)(/sim/view[(/sim/current-view/view-number-raw)]/config/target-lon-deg-path))",
1042 _target.getLongitudeDeg()
1045 _target.setLatitudeDeg(
1047 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)(/sim/view[(/sim/current-view/view-number-raw)]/config/target-lat-deg-path))",
1048 _target.getLatitudeDeg()
1051 _target.setElevationFt(
1053 "((/sim/view[(/sim/current-view/view-number-raw)]/config/root)(/sim/view[(/sim/current-view/view-number-raw)]/config/target-alt-ft-path))",
1054 _target.getElevationFt()
1062 set_fov(_fov_user_deg);
1065 SGQuatd geodEyeOr = SGQuatd::fromYawPitchRollDeg(eye_heading, eye_pitch, eye_roll);
1066 SGQuatd geodEyeHlOr = SGQuatd::fromLonLat(_position);
1070 SGQuatd::fromYawPitchRollDeg(-_heading_offset_deg + 180, _pitch_offset_deg,
1075 SGVec3d eyeOff(-_offset_m.z(), _offset_m.x(), -_offset_m.y());
1076 SGQuatd ec2eye = geodEyeHlOr*geodEyeOr;
1077 SGVec3d eyeCart = SGVec3d::fromGeod(_position);
1078 eyeCart += (ec2eye*mViewOffsetOr).backTransform(eyeOff);
1080 SGVec3d atCart = SGVec3d::fromGeod(_target);
1085 _absolute_view_pos = eyeCart;
1088 SGVec3d dir = normalize(atCart - eyeCart);
1090 SGVec3d up = ec2eye.backTransform(SGVec3d(0, 0, -1));
1095 mViewOrientation = SGQuatd::fromRotateTo(-dir, 2, up, 1);
1099View::setDampTarget(
double roll,
double pitch,
double heading)
1101 _dampTarget = SGVec3d(roll, pitch, heading);
1105View::getDampOutput(
double& roll,
double& pitch,
double& heading)
1107 roll = _dampOutput[0];
1108 pitch = _dampOutput[1];
1109 heading = _dampOutput[2];
1114View::updateDampOutput(
double dt)
1116 static View *last_view = 0;
1117 if ((last_view !=
this) || (dt > 1.0)) {
1118 _dampOutput = _dampTarget;
1123 const double interval = 0.01;
1124 while (dt > interval) {
1126 for (
unsigned int i=0;
i<3; ++
i) {
1127 if (_dampFactor[
i] <= 0.0) {
1129 _dampOutput[
i] = _dampTarget[
i];
1133 double d = _dampOutput[
i] - _dampTarget[
i];
1135 _dampOutput[
i] -= 360.0;
1136 }
else if (d < -180.0) {
1137 _dampOutput[
i] += 360.0;
1140 _dampOutput[
i] = (_dampTarget[
i] * _dampFactor[
i]) +
1141 (_dampOutput[
i] * (1.0 - _dampFactor[
i]));
1149View::Damping::Damping(
double damping,
double min,
double max)
1150: _id(NULL), _min(
min), _max(max), _target(0), _factor(pow(10, -damping)), _current(0)
1154void View::Damping::setTarget(
double target)
1159void View::Damping::update(
double dt,
void*
id)
1161 if (
id != _id || dt > 1.0) {
1166 const double interval = 0.01;
1167 while (dt > interval) {
1169 if (_factor <= 0.0) {
1175 double d = _current - _target;
1178 _current -= (_max - _min);
1179 }
else if (d < _min) {
1180 _current += (_max - _min);
1184 _current = (_target * _factor) + _current * (1.0 - _factor);
1190double View::Damping::get()
1195void View::Damping::updateTarget(
double& io)
1201void View::Damping::reset(
double target)
1211 switch (_scaling_type) {
1215 if (aspectRatio < 1.0) {
1221 atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS)
1222 / (aspectRatio*_aspect_ratio_multiplier))
1223 * SG_RADIANS_TO_DEGREES * 2;
1237 switch (_scaling_type) {
1240 atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS)
1241 * (aspectRatio*_aspect_ratio_multiplier))
1242 * SG_RADIANS_TO_DEGREES * 2;
1244 if (aspectRatio < 1.0) {
1247 atan(tan(_fov_deg/2 * SG_DEGREES_TO_RADIANS)
1248 * (aspectRatio*_aspect_ratio_multiplier))
1249 * SG_RADIANS_TO_DEGREES * 2;
1264 updateDampOutput(dt);
1265 _lookat_agl_damping.update(dt, NULL );
1268 int dt_ms = int(dt * 1000);
1269 for (
i = 0;
i < dt_ms;
i++ ) {
1270 if ( fabs( _goal_heading_offset_deg - _heading_offset_deg) < 1 ) {
1276 if ( _goal_heading_offset_deg > _heading_offset_deg )
1278 if ( _goal_heading_offset_deg - _heading_offset_deg < 180 ){
1279 incHeadingOffset_deg( 0.5 );
1281 incHeadingOffset_deg( -0.5 );
1284 if ( _heading_offset_deg - _goal_heading_offset_deg < 180 ){
1285 incHeadingOffset_deg( -0.5 );
1287 incHeadingOffset_deg( 0.5 );
1290 if ( _heading_offset_deg > 360 ) {
1291 incHeadingOffset_deg( -360 );
1292 }
else if ( _heading_offset_deg < 0 ) {
1293 incHeadingOffset_deg( 360 );
1298 for (
i = 0;
i < dt_ms;
i++ ) {
1299 if ( fabs( _goal_pitch_offset_deg - _pitch_offset_deg ) < 1 ) {
1300 setPitchOffset_deg( _goal_pitch_offset_deg );
1305 if ( _goal_pitch_offset_deg > _pitch_offset_deg )
1307 incPitchOffset_deg( 1.0 );
1309 incPitchOffset_deg( -1.0 );
1311 if ( _pitch_offset_deg > 90 ) {
1312 setPitchOffset_deg(90);
1313 }
else if ( _pitch_offset_deg < -90 ) {
1314 setPitchOffset_deg( -90 );
1320 for (
i = 0;
i < dt_ms;
i++ ) {
1321 if ( fabs( _goal_roll_offset_deg - _roll_offset_deg ) < 1 ) {
1322 setRollOffset_deg( _goal_roll_offset_deg );
1327 if ( _goal_roll_offset_deg > _roll_offset_deg )
1329 incRollOffset_deg( 1.0 );
1331 incRollOffset_deg( -1.0 );
1333 if ( _roll_offset_deg > 90 ) {
1334 setRollOffset_deg(90);
1335 }
else if ( _roll_offset_deg < -90 ) {
1336 setRollOffset_deg( -90 );
1343double View::getAbsolutePosition_x()
const
1345 return _absolute_view_pos.x();
1348double View::getAbsolutePosition_y()
const
1350 return _absolute_view_pos.y();
1353double View::getAbsolutePosition_z()
const
1355 return _absolute_view_pos.z();
1358double View::getRawOrientation_w()
const
1360 return mViewOrientation.w();
1363double View::getRawOrientation_x()
const
1365 return mViewOrientation.x();
1368double View::getRawOrientation_y()
const
1370 return mViewOrientation.y();
1373double View::getRawOrientation_z()
const
1375 return mViewOrientation.z();
1385 return SGQuatd(-0.5, -0.5, 0.5, 0.5);
1408double View::getFrame_w()
const
1410 return ((mViewOrientation*conj(
fsb2sta())*conj(mViewOffsetOr))).w();
1413double View::getFrame_x()
const
1415 return ((mViewOrientation*conj(
fsb2sta())*conj(mViewOffsetOr))).x();
1418double View::getFrame_y()
const
1420 return ((mViewOrientation*conj(
fsb2sta())*conj(mViewOffsetOr))).y();
1423double View::getFrame_z()
const
1425 return ((mViewOrientation*conj(
fsb2sta())*conj(mViewOffsetOr))).z();
1437double View::getOrOffset_w()
const{
1438 return mViewOffsetOr.w();
1440double View::getOrOffset_x()
const{
1441 return mViewOffsetOr.x();
1443double View::getOrOffset_y()
const{
1444 return mViewOffsetOr.y();
1446double View::getOrOffset_z()
const{
1447 return mViewOffsetOr.z();
1477double View::getOrientation_w()
const{
1478 return (mViewOrientation * conj(
fsb2sta())).w();
1480double View::getOrientation_x()
const{
1481 return (mViewOrientation * conj(
fsb2sta())).x();
1483double View::getOrientation_y()
const{
1484 return (mViewOrientation * conj(
fsb2sta())).y();
1486double View::getOrientation_z()
const{
1487 return (mViewOrientation * conj(
fsb2sta())).z();
1495double View::getLon_deg()
const
1497 return _position.getLongitudeDeg();
1500double View::getLat_deg()
const
1502 return _position.getLatitudeDeg();
1505double View::getElev_ft()
const
1507 return _position.getElevationFt();
1512SGSubsystemMgr::Registrant<View> registrantView;
FGScenery * get_scenery() const
bool get_elevation_m(const SGGeod &geod, double &alt, const simgear::BVHMaterial **material, const osg::Node *butNotFrom=0)
Compute the elevation of the scenery at geodetic latitude lat, geodetic longitude lon and not higher ...
static CameraGroup * getDefault()
Get the default CameraGroup.
double getMasterAspectRatio() const
get aspect ratio of master camera's viewport
void setTargetYOffset_m(double y_offset_m)
void setHeadingOffset_deg(double heading_offset_deg)
void setTargetZOffset_m(double z_offset_m)
void setAdjustXOffset_m(double x_adjust_offset_m)
double getPitchOffset_deg() const
void setYOffset_m(double y_offset_m)
void setAdjustZOffset_m(double z_adjust_offset_m)
double getAdjustZOffset_m() const
double getTargetYOffset_m() const
void setZOffset_m(double z_offset_m)
void update(double dt) override
void setAdjustYOffset_m(double y_adjust_offset_m)
void setPositionOffsets(double x_offset_m, double y_offset_m, double z_offset_m)
double getTargetXOffset_m() const
double getHeadingOffset_deg() const
void resetOffsetsAndFOV()
double getRollOffset_deg() const
void setGoalHeadingOffset_deg(double goal_heading_offset_deg)
double getAdjustYOffset_m() const
double getAdjustXOffset_m() const
void setTargetXOffset_m(double x_offset_m)
static View * createFromProperties(SGPropertyNode_ptr props, int view_index=-1)
double getTargetZOffset_m() const
void setInternal(bool internal)
double get_aspect_ratio() const
void setXOffset_m(double x_offset_m)
void fgSetArchivable(const char *name, bool state)
Set the state of the archive attribute for a property.
const std::string & getStringValue(const char *spec)
double getDoubleValue(const char *spec, double default_)
bool getBoolValue(const char *spec, bool default_)
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
static void getAircraftPositionOrientation(SGGeod &position, double &head, double &pitch, double &roll)
static const SGQuatd fsb2sta()
static void getViewOffsets(bool target_infix, const SGVec3d *adjust, SGVec3d &offset_m)