1
0
Fork 0

src/Viewer/sview.*: added damping to SviewStepAGL.

This commit is contained in:
Julian Smith 2020-12-21 10:40:08 +00:00
parent 0ede0401b7
commit cbe3ae5618
2 changed files with 138 additions and 97 deletions

View file

@ -146,7 +146,7 @@ SviewPosDir, e.g. translating the position and/or rotating the direction. */
struct SviewStep
{
/* Updates <posdir>. */
virtual void evaluate(SviewPosDir& posdir) = 0;
virtual void evaluate(SviewPosDir& posdir, double dt=0) = 0;
virtual void mouse_drag(double delta_x, double delta_y)
{
@ -222,7 +222,7 @@ struct SviewStepAircraft : SviewStep
{
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
if (m_callsign.update()) {
m_longitude = m_callsign.m_root->getNode("position/longitude-deg");
@ -274,7 +274,7 @@ struct SviewStepMove : SviewStep
SG_LOG(SG_VIEW, SG_INFO, "forward=" << forward << " up=" << up << " right=" << right);
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
/* These calculations are copied from View::recalcLookFrom(). */
@ -328,7 +328,7 @@ struct SviewStepRotate : SviewStep
SG_LOG(SG_VIEW, SG_INFO, "heading=" << heading << " pitch=" << pitch << " roll=" << roll);
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
/* Should we use SGQuatd to evaluate things? */
posdir.heading += m_heading;
@ -378,7 +378,7 @@ struct SviewStepDirectionMultiply : SviewStep
SG_LOG(SG_VIEW, SG_INFO, "heading=" << heading << " pitch=" << pitch << " roll=" << roll);
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
posdir.heading *= m_heading;
posdir.pitch *= m_pitch;
@ -405,7 +405,7 @@ to make current position be available as target later on, e.g. by
SviewStepFinalToTarget. */
struct SviewStepCopyToTarget : SviewStep
{
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
posdir.target = posdir.position;
}
@ -426,7 +426,7 @@ struct SviewStepNearestTower : SviewStep
m_description = "Nearest tower";
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
if (m_callsign.update()) {
m_latitude = m_callsign.m_root->getNode("sim/tower/latitude-deg", true /*create*/);
@ -461,7 +461,7 @@ final step if not SviewStepFinal. */
struct SviewStepFinalToTarget : SviewStep
{
/* Alters posdir.direction to point to posdir.target. */
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
/* See View::recalcLookAt(). */
@ -539,7 +539,7 @@ struct SviewStepFinal : SviewStep
{
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
/* See View::recalcLookFrom(). */
SGQuatd rotation = SGQuatd::fromYawPitchRollDeg(-m_heading, m_pitch, m_roll);
@ -591,17 +591,47 @@ struct SviewStepFinal : SviewStep
double m_default_roll = 0;
};
/* Generic damping support. Improved version of class in view.hxx and view.cxx.
We model dx/dt = (target-current)/damping_time, do damping_time is time for
value to change by a factor or e. */
struct Damping {
Damping(double damping_time, double current=0)
:
m_damping_time(damping_time),
m_current(current)
{}
double update(double target, double dt)
{
const double e = 2.718281828459045;
m_current = target - (target - m_current) * pow(e, -dt/m_damping_time);
return m_current;
}
double reset(double current)
{
m_current = current;
return m_current;
}
private:
double m_damping_time;
double m_current;
};
/* Change angle and field of view so that we can see an aircraft and the ground
immediately below it. */
struct SviewStepAGL : SviewStep
{
SviewStepAGL(const std::string& callsign)
SviewStepAGL(const std::string& callsign, double damping_time)
:
m_callsign(callsign)
m_callsign(callsign),
relative_height_ground_damping(damping_time)
{
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
if (m_callsign.update()) {
m_chase_distance = -25;
@ -636,10 +666,10 @@ struct SviewStepAGL : SviewStep
double h_distance = SGGeodesy::distanceM(posdir.position, posdir.target);
if (h_distance == 0) {
/* Not sure this should ever happen, but we need to handle this
/* Not sure this should ever happen, but we need to cope with this
here otherwise we'll get divide-by-zero. */
return;
}
else {
/* Find vertical region we want to be able to see. */
double relative_height_target = posdir.target.getElevationM() - posdir.position.getElevationM();
double relative_height_ground = ground_altitude - posdir.position.getElevationM();
@ -660,13 +690,12 @@ struct SviewStepAGL : SviewStep
double relative_height_target_plus = relative_height_target + aircraft_size_vertical;
double relative_height_ground_ = relative_height_ground;
//_lookat_agl_damping.updateTarget(relative_height_ground);
relative_height_ground = relative_height_ground_damping.update(relative_height_ground, dt);
if (relative_height_ground > relative_height_target) {
/* Damping of relative_height_ground can result in it being
temporarily above the aircraft, so we ensure the aircraft is
visible. */
//_lookat_agl_damping.reset(relative_height_ground_);
relative_height_ground = relative_height_ground_;
relative_height_ground = relative_height_ground_damping.reset(relative_height_ground_);
}
/* Not implemented yet: apply scaling from user field of view
@ -708,6 +737,7 @@ struct SviewStepAGL : SviewStep
t0 = t;
verbose = true;
}
}
if (verbose) SG_LOG(SG_VIEW, SG_ALERT, ""
<< " target0=" << target0
<< " fov_v=" << fov_v * 180/pi
@ -721,12 +751,11 @@ struct SviewStepAGL : SviewStep
<< " posdir.target=" << posdir.target
);
}
}
}
double m_chase_distance;
Callsign m_callsign;
double m_ground_altitude = 0;
Damping relative_height_ground_damping;
};
/* A step that takes the SviewPosDir's eye and target positions and treats
@ -746,7 +775,7 @@ struct SviewStepDouble : SviewStep
m_local_chase_distance = config->getDoubleValue("chase-distance");
m_angle_rad = config->getDoubleValue("angle") * pi / 180;
}
void evaluate(SviewPosDir& posdir) override
void evaluate(SviewPosDir& posdir, double dt) override
{
/*
We choose eye position so that we show the local aircraft a fixed
@ -854,7 +883,7 @@ struct SviewStepDouble : SviewStep
posdir_local.pitch = (hlr + rle) * 180 / pi;
posdir_local.roll = 0;
auto move = SviewStepMove(le, 0, 0);
move.evaluate(posdir_local);
move.evaluate(posdir_local, 0 /*dt*/);
/* At this point, posdir_local.position is eye position. We make
posdir_local.direction2 point from this eye position to halfway between
@ -865,7 +894,7 @@ struct SviewStepDouble : SviewStep
double hel = (hlr + rle) - pi;
posdir_local.pitch = (her + hel) / 2 * 180 / pi;
auto stepfinal = SviewStepFinal();
stepfinal.evaluate(posdir_local);
stepfinal.evaluate(posdir_local, 0 /*dt*/);
posdir = posdir_local;
if (debug) {
@ -904,11 +933,11 @@ struct SviewSteps
return add_step(std::shared_ptr<SviewStep>(step));
}
void evaluate(SviewPosDir& posdir, bool debug=false)
void evaluate(SviewPosDir& posdir, double dt, bool debug=false)
{
if (debug) SG_LOG(SG_VIEW, SG_ALERT, "evaluating m_name=" << m_name);
for (auto step: m_steps) {
step->evaluate(posdir);
step->evaluate(posdir, dt);
if (debug) SG_LOG(SG_VIEW, SG_ALERT, "posdir=" << posdir);
}
};
@ -1095,8 +1124,10 @@ struct SviewViewEyeTarget : SviewView
m_steps.add_step(new SviewStepNearestTower(callsign));
if (config->getBoolValue("view/config/lookat-agl")) {
double damping = config->getDoubleValue("view/config/lookat-agl-damping");
double damping_time = log(10) / damping;
SG_LOG(SG_VIEW, SG_ALERT, "lookat-agl");
m_steps.add_step(new SviewStepAGL(callsign));
m_steps.add_step(new SviewStepAGL(callsign, damping_time));
}
m_steps.add_step(new SviewStepFinalToTarget);
@ -1290,7 +1321,8 @@ struct SviewViewEyeTarget : SviewView
}
else if (!strcmp(type, "agl")) {
const char* callsign = step->getStringValue("callsign");
m_steps.add_step(new SviewStepAGL(callsign));
double damping_time = step->getDoubleValue("damping-time");
m_steps.add_step(new SviewStepAGL(callsign, damping_time));
}
else {
throw std::runtime_error(std::string() + "Unrecognised step name: '" + type + "'");
@ -1396,7 +1428,7 @@ struct SviewViewEyeTarget : SviewView
}
}
if (debug) SG_LOG(SG_VIEW, SG_INFO, "evaluating m_steps:");
m_steps.evaluate(posdir, debug);
m_steps.evaluate(posdir, dt, debug);
posdir_to_view(posdir);
return true;

View file

@ -89,6 +89,10 @@ config:
view:
A legacy <view>...</view> tree, e.g. deep copy of /sim/view[]
or /ai/models/multiplayer[]/set/sim/view[].
Note that agl damping_time is calculated as log(10) /
view/config/lookat-agl-damping, for backwards compatibility
with legacy view code.
callsign:
"" if user aircraft, else multiplayer aircraft's callsign.
view-number-raw:
@ -150,6 +154,11 @@ An sview-step is:
callsign:
Use chase distance of specified aircraft as a measure of
its size, to ensure entire aircraft is visible.
damping-time:
Ground level is damped as dx/dt =
(x_actual-x)/damping_time, and damping_time is the time in
seconds for the damped value to change by a factor of e
(2.71).
Examples: