1
0
Fork 0

src/Viewer/sview.*: Added damping to chase views.

This commit is contained in:
Julian Smith 2020-12-21 14:54:53 +00:00
parent cbe3ae5618
commit d9e535913e
2 changed files with 93 additions and 43 deletions

View file

@ -141,6 +141,51 @@ struct SviewPosDir
}; };
/* 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 {
/* If m_wrap_max is non-zero, we wrap to ensure values are always between 0
and m_wrap_max. E.g. use m_wrap_max=360 for an angle. */
Damping(double damping_time, double wrap_max=0, double current=0)
:
m_damping_time(damping_time),
m_current(current),
m_wrap_max(wrap_max)
{}
/* Updates and returns new smoothed value. */
double update(double dt, double target)
{
const double e = 2.718281828459045;
double delta = target - m_current;
if (m_wrap_max) {
if (delta < -m_wrap_max/2) delta += m_wrap_max;
if (delta >= m_wrap_max/2) delta -= m_wrap_max;
}
m_current = target - delta * pow(e, -dt/m_damping_time);
if (m_wrap_max) {
if (m_current < 0) m_current += m_wrap_max;
if (m_current >= m_wrap_max) m_current -= m_wrap_max;
}
return m_current;
}
/* Forces current value to be <current>. */
double reset(double current)
{
m_current = current;
return m_current;
}
private:
double m_damping_time;
double m_current;
double m_wrap_max;
};
/* Abstract base class for a single view step. A view step modifies a /* Abstract base class for a single view step. A view step modifies a
SviewPosDir, e.g. translating the position and/or rotating the direction. */ SviewPosDir, e.g. translating the position and/or rotating the direction. */
struct SviewStep struct SviewStep
@ -318,22 +363,32 @@ E.g. can be used to preserve direction (relative to aircraft) of Helicopter
view at the time it was cloned. */ view at the time it was cloned. */
struct SviewStepRotate : SviewStep struct SviewStepRotate : SviewStep
{ {
SviewStepRotate(double heading, double pitch, double roll, bool fixed=false) SviewStepRotate(
double heading,
double pitch,
double roll,
bool fixed=false,
double damping_heading=0,
double damping_pitch=0,
double damping_roll=0
)
: :
m_heading(heading), m_heading(heading),
m_pitch(pitch), m_pitch(pitch),
m_roll(roll), m_roll(roll),
m_fixed(fixed) m_fixed(fixed),
m_damping_heading(damping_heading, 360 /*m_wrap_max*/),
m_damping_pitch(damping_pitch, 360 /*m_wrap_max*/),
m_damping_roll(damping_roll, 360 /*m_wrap_max*/)
{ {
SG_LOG(SG_VIEW, SG_INFO, "heading=" << heading << " pitch=" << pitch << " roll=" << roll); SG_LOG(SG_VIEW, SG_INFO, "heading=" << heading << " pitch=" << pitch << " roll=" << roll);
} }
void evaluate(SviewPosDir& posdir, double dt) override void evaluate(SviewPosDir& posdir, double dt) override
{ {
/* Should we use SGQuatd to evaluate things? */ posdir.heading = m_damping_heading.update(dt, posdir.heading + m_heading);
posdir.heading += m_heading; posdir.pitch = m_damping_pitch.update(dt, posdir.pitch + m_pitch);
posdir.pitch += m_pitch; posdir.roll = m_damping_roll.update(dt, posdir.roll + m_roll);
posdir.roll += m_roll;
} }
void mouse_drag(double delta_x, double delta_y) override void mouse_drag(double delta_x, double delta_y) override
@ -364,6 +419,9 @@ struct SviewStepRotate : SviewStep
double m_pitch; double m_pitch;
double m_roll; double m_roll;
bool m_fixed; bool m_fixed;
Damping m_damping_heading;
Damping m_damping_pitch;
Damping m_damping_roll;
}; };
/* Multiply heading, pitch and roll by constants. */ /* Multiply heading, pitch and roll by constants. */
@ -592,34 +650,6 @@ struct SviewStepFinal : SviewStep
}; };
/* 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 /* Change angle and field of view so that we can see an aircraft and the ground
immediately below it. */ immediately below it. */
struct SviewStepAGL : SviewStep struct SviewStepAGL : SviewStep
@ -690,7 +720,7 @@ struct SviewStepAGL : SviewStep
double relative_height_target_plus = relative_height_target + aircraft_size_vertical; double relative_height_target_plus = relative_height_target + aircraft_size_vertical;
double relative_height_ground_ = relative_height_ground; double relative_height_ground_ = relative_height_ground;
relative_height_ground = relative_height_ground_damping.update(relative_height_ground, dt); relative_height_ground = relative_height_ground_damping.update(dt, relative_height_ground);
if (relative_height_ground > relative_height_target) { if (relative_height_ground > relative_height_target) {
/* Damping of relative_height_ground can result in it being /* Damping of relative_height_ground can result in it being
temporarily above the aircraft, so we ensure the aircraft is temporarily above the aircraft, so we ensure the aircraft is
@ -1075,6 +1105,14 @@ struct SviewView
static int s_id; static int s_id;
}; };
/* Converts legacy damping values (e.g. at-model-heading-damping) to a damping
time suitable for use by our Damping class. */
static double legacy_damping_time(double damping)
{
if (damping <= 0) return 0;
return 1 / damping;
}
int SviewView::s_id = 0; int SviewView::s_id = 0;
/* A view defined by a series of steps that defines an eye and a target. Used /* A view defined by a series of steps that defines an eye and a target. Used
@ -1125,7 +1163,7 @@ struct SviewViewEyeTarget : SviewView
if (config->getBoolValue("view/config/lookat-agl")) { if (config->getBoolValue("view/config/lookat-agl")) {
double damping = config->getDoubleValue("view/config/lookat-agl-damping"); double damping = config->getDoubleValue("view/config/lookat-agl-damping");
double damping_time = log(10) / damping; double damping_time = log(10) * legacy_damping_time(damping);
SG_LOG(SG_VIEW, SG_ALERT, "lookat-agl"); SG_LOG(SG_VIEW, SG_ALERT, "lookat-agl");
m_steps.add_step(new SviewStepAGL(callsign, damping_time)); m_steps.add_step(new SviewStepAGL(callsign, damping_time));
} }
@ -1156,7 +1194,7 @@ struct SviewViewEyeTarget : SviewView
} }
else { else {
SG_LOG(SG_VIEW, SG_INFO, "not eye-fixed"); SG_LOG(SG_VIEW, SG_INFO, "not eye-fixed");
/* E.g. Pilot view or Helicopter view. */ /* E.g. Pilot view and Helicopter/Chase views. */
SGPropertyNode* global_sim_view = globals->get_props() SGPropertyNode* global_sim_view = globals->get_props()
->getNode("sim/view", config->getIntValue("view-number-raw")); ->getNode("sim/view", config->getIntValue("view-number-raw"));
@ -1182,9 +1220,7 @@ struct SviewViewEyeTarget : SviewView
aircraft's heading, pitch and roll; this enables us to mimic aircraft's heading, pitch and roll; this enables us to mimic
Helicopter and Chase views. In theory we should evaluate the Helicopter and Chase views. In theory we should evaluate the
specified paths, but in practise we only need to multiply specified paths, but in practise we only need to multiply
current values by 0 or 1. current values by 0 or 1. */
todo: add damping. */
assert(global_sim_view); assert(global_sim_view);
m_steps.add_step(new SviewStepDirectionMultiply( m_steps.add_step(new SviewStepDirectionMultiply(
global_sim_view->getStringValue("config/eye-heading-deg-path")[0] ? 1 : 0, global_sim_view->getStringValue("config/eye-heading-deg-path")[0] ? 1 : 0,
@ -1197,10 +1233,18 @@ struct SviewViewEyeTarget : SviewView
viewing system's Helicopter view etc, increments to viewing system's Helicopter view etc, increments to
heading-offset-deg and pitch-offset-deg actually correspond heading-offset-deg and pitch-offset-deg actually correspond
to a decreasing actual heading and pitch values. */ to a decreasing actual heading and pitch values. */
double damping_heading = legacy_damping_time(config->getDoubleValue("view/config/at-model-heading-damping"));
double damping_pitch = legacy_damping_time(config->getDoubleValue("view/config/at-model-pitch-damping"));
double damping_roll = legacy_damping_time(config->getDoubleValue("view/config/at-model-roll-damping"));
m_steps.add_step(new SviewStepRotate( m_steps.add_step(new SviewStepRotate(
-globals->get_props()->getDoubleValue("sim/current-view/heading-offset-deg"), -globals->get_props()->getDoubleValue("sim/current-view/heading-offset-deg"),
-globals->get_props()->getDoubleValue("sim/current-view/pitch-offset-deg"), -globals->get_props()->getDoubleValue("sim/current-view/pitch-offset-deg"),
globals->get_props()->getDoubleValue("sim/current-view/roll-offset-deg") globals->get_props()->getDoubleValue("sim/current-view/roll-offset-deg"),
false /*fixed*/,
damping_heading,
damping_pitch,
damping_roll
)); ));
/* Add step that moves eye away from aircraft. /* Add step that moves eye away from aircraft.
@ -1208,14 +1252,16 @@ struct SviewViewEyeTarget : SviewView
fgdata:defaults.xml) which is -ve, e.g. -25m. */ fgdata:defaults.xml) which is -ve, e.g. -25m. */
m_steps.add_step(new SviewStepMove( m_steps.add_step(new SviewStepMove(
config->getDoubleValue("view/config/z-offset-m"), config->getDoubleValue("view/config/z-offset-m"),
config->getDoubleValue("view/config/y-offset-m"), -config->getDoubleValue("view/config/y-offset-m"),
config->getDoubleValue("view/config/x-offset-m") config->getDoubleValue("view/config/x-offset-m")
)); ));
m_steps.add_step(new SviewStepFinalToTarget);
/* Finally add a step that converts /* Finally add a step that converts
lat,lon,height,heading,pitch,roll into SGVec3d position and lat,lon,height,heading,pitch,roll into SGVec3d position and
SGQuatd orientation. */ SGQuatd orientation. */
m_steps.add_step(new SviewStepFinal); //m_steps.add_step(new SviewStepFinal);
} }
else { else {
/* E.g. pilot view. /* E.g. pilot view.

View file

@ -105,6 +105,10 @@ config:
pitch pitch
roll roll
zoom-delta: modification to default zoom. zoom-delta: modification to default zoom.
Chase view seems to be slightly different from the real legacy
view, possibly because the viewpoint correction config/y-offset-m
is applied after rotation instead of before.
"sview" or not specified: "sview" or not specified:
List of sview-step's. List of sview-step's.