Move X-Plane interpolation into driver

ref T259
This commit is contained in:
Roland Winklmeier
2018-02-18 12:42:54 +01:00
committed by Klaus Basan
parent f3b48f75a1
commit 4db0b83310
8 changed files with 792 additions and 77 deletions

View File

@@ -21,6 +21,7 @@
#include <XPLM/XPLMProcessing.h>
#include <XPLM/XPLMUtilities.h>
#include <QDateTime>
#include <QDebug>
#include <QStringList>
#include <cstring>
#include <cmath>
@@ -74,6 +75,7 @@ namespace XSwiftBus
CTraffic::CTraffic(QObject *parent) :
QObject(parent)
{
XPLMRegisterDrawCallback(CTraffic::drawCallback, xplm_Phase_Airplanes, 0, this);
}
CTraffic::~CTraffic()
@@ -124,6 +126,21 @@ namespace XSwiftBus
m_initialized = false;
XPMPMultiplayerCleanup();
}
XPLMUnregisterDrawCallback(CTraffic::drawCallback, xplm_Phase_Airplanes, 0, this);
}
void CTraffic::emitSimFrame()
{
qint64 currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
// The draw callback is called twice for unknown reasons each frame. We can filter the second one by
// requiring a minimum offset of 5 ms (equal to 200 fps).
if (currentMSecsSinceEpoch > m_timestampLastSimFrame + 5)
{
emit simFrame();
m_timestampLastSimFrame = currentMSecsSinceEpoch;
}
}
int g_maxPlanes = 100;
@@ -258,6 +275,17 @@ namespace XSwiftBus
}
}
void CTraffic::setPlanePosition(const QString &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading)
{
const auto plane = m_planesByCallsign.value(callsign, nullptr);
plane->position.lat = latitude;
plane->position.lon = longitude;
plane->position.elevation = altitude;
plane->position.pitch = static_cast<float>(pitch);
plane->position.roll = static_cast<float>(roll);
plane->position.heading = static_cast<float>(heading);
}
void CTraffic::addPlaneSurfaces(const QString &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust,
double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround, qint64 relativeTime, qint64 timeOffset)
{
@@ -295,6 +323,32 @@ namespace XSwiftBus
}
}
void CTraffic::setPlaneSurfaces(const QString &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust,
double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround)
{
Q_UNUSED(onGround);
const auto plane = m_planesByCallsign.value(callsign, nullptr);
if (plane)
{
plane->hasSurfaces = true;
plane->targetGearPosition = gear;
plane->surfaces.flapRatio = flap;
plane->surfaces.spoilerRatio = spoiler;
plane->surfaces.speedBrakeRatio = speedBrake;
plane->surfaces.slatRatio = slat;
plane->surfaces.wingSweep = wingSweep;
plane->surfaces.thrust = thrust;
plane->surfaces.yokePitch = elevator;
plane->surfaces.yokeHeading = rudder;
plane->surfaces.yokeRoll = aileron;
plane->surfaces.lights.landLights = landLight;
plane->surfaces.lights.bcnLights = beaconLight;
plane->surfaces.lights.strbLights = strobeLight;
plane->surfaces.lights.navLights = navLight;
plane->surfaces.lights.flashPattern = lightPattern;
}
}
void CTraffic::setPlaneTransponder(const QString &callsign, int code, bool modeC, bool ident)
{
const auto plane = m_planesByCallsign.value(callsign, nullptr);
@@ -342,6 +396,20 @@ namespace XSwiftBus
switch (dataType)
{
case xpmpDataType_Position:
{
if (c_driverInterpolation)
{
const auto io_position = static_cast<XPMPPlanePosition_t *>(io_data);
io_position->lat = plane->position.lat;
io_position->lon = plane->position.lon;
io_position->elevation = plane->position.elevation;
io_position->pitch = plane->position.pitch;
io_position->roll = plane->position.roll;
io_position->heading = plane->position.heading;
std::strncpy(io_position->label, plane->label, sizeof(plane->label)); // fixme don't need to copy on every frame
return xpmpData_NewData;
}
else
{
BlackMisc::Simulation::CInterpolationAndRenderingSetup setup;
BlackMisc::Simulation::CInterpolationStatus status;
@@ -364,16 +432,23 @@ namespace XSwiftBus
return xpmpData_NewData;
}
}
case xpmpDataType_Surfaces:
if (plane->hasSurfaces)
{
const auto currentTime = QDateTime::currentMSecsSinceEpoch();
while (! plane->pendingSurfaces.isEmpty() && plane->pendingSurfaces.constFirst().first <= currentTime)
if (! c_driverInterpolation)
{
//! \todo if gear is currently retracted, look ahead and pull gear position from pendingSurfaces up to 5 seconds in the future
plane->pendingSurfaces.constFirst().second(plane);
plane->pendingSurfaces.pop_front();
while (! plane->pendingSurfaces.isEmpty() && plane->pendingSurfaces.constFirst().first <= currentTime)
{
//! \todo if gear is currently retracted, look ahead and pull gear position from pendingSurfaces up to 5 seconds in the future
plane->pendingSurfaces.constFirst().second(plane);
plane->pendingSurfaces.pop_front();
}
}
if (plane->surfaces.gearPosition != plane->targetGearPosition)
{
// interpolate gear position
@@ -412,6 +487,15 @@ namespace XSwiftBus
}
}
int CTraffic::drawCallback(XPLMDrawingPhase phase, int isBefore, void *refcon)
{
Q_UNUSED(phase);
Q_UNUSED(isBefore);
CTraffic *traffic = static_cast<CTraffic *>(refcon);
traffic->emitSimFrame();
return 1;
}
}
//! \endcond

View File

@@ -22,6 +22,7 @@
#include <QVector>
#include <QStringList>
#include "XPMPMultiplayer.h"
#include <XPLM/XPLMDisplay.h>
#include <functional>
#include <utility>
@@ -65,6 +66,10 @@ namespace XSwiftBus
//! Called by XPluginStart
static void initLegacyData();
signals:
//! Signal emitted for each simulator rendering frame
void simFrame();
public slots:
//! Initialize the multiplayer planes rendering and return true if successful
bool initialize();
@@ -99,13 +104,20 @@ namespace XSwiftBus
//! Remove all traffic aircraft
void removeAllPlanes();
//! Set the position of a traffic aircraft
//! Add the position of a traffic aircraft
void addPlanePosition(const QString &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading, qint64 relativeTime, qint64 timeOffset);
//! Set the flight control surfaces and lights of a traffic aircraft
//! Set the position of a traffic aircraft
void setPlanePosition(const QString &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading);
//! Add the flight control surfaces and lights of a traffic aircraft
void addPlaneSurfaces(const QString &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust,
double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround, qint64 relativeTime, qint64 timeOffset);
//! Set the flight control surfaces and lights of a traffic aircraft
void setPlaneSurfaces(const QString &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust,
double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround);
//! Set the transponder of a traffic aircraft
void setPlaneTransponder(const QString &callsign, int code, bool modeC, bool ident);
@@ -116,6 +128,10 @@ namespace XSwiftBus
bool m_initialized = false;
bool m_enabled = false;
static constexpr bool c_driverInterpolation = true;
void emitSimFrame();
static int preferences(const char *section, const char *name, int def);
static float preferences(const char *section, const char *name, float def);
@@ -137,16 +153,20 @@ namespace XSwiftBus
float targetGearPosition = 0;
qint64 prevSurfacesLerpTime = 0;
XPMPPlaneRadar_t xpdr;
XPMPPlanePosition_t position;
Plane(void *id_, QString callsign_, QString aircraftIcao_, QString airlineIcao_, QString livery_);
};
QHash<QString, Plane *> m_planesByCallsign;
QHash<void *, Plane *> m_planesById;
qint64 m_timestampLastSimFrame = QDateTime::currentMSecsSinceEpoch();
int getPlaneData(void *id, int dataType, void *io_data);
static int getPlaneData(void *id, int dataType, void *io_data, void *self)
{
return static_cast<CTraffic *>(self)->getPlaneData(id, dataType, io_data);
}
static int drawCallback(XPLMDrawingPhase phase, int isBefore, void *refcon);
};
}