Ref T245, a P3D version of follow aircraft, still experimental

* testing approaches camera, observer, and guessing view name
* SimObject code for camera/observer
* functions aircraft situation -> FSX formats
This commit is contained in:
Klaus Basan
2018-11-01 02:27:39 +01:00
parent af7c386a1c
commit b6ce9e0408
5 changed files with 160 additions and 36 deletions

View File

@@ -182,12 +182,28 @@ namespace BlackSimPlugin
//! Camera rotation;
const SIMCONNECT_DATA_PBH &cameraRotation() const { return m_cameraRotation; }
//! Camera position/rotation
void setCameraPositionAndRotation(const SIMCONNECT_DATA_XYZ &position, const SIMCONNECT_DATA_PBH &rotation)
{
m_cameraPosition = position;
m_cameraRotation = rotation;
}
//! Camera GUID
GUID getCameraGUID() const { return m_cameraGuid; }
//! Set camera GUID
void setCameraGUID(GUID guid) { m_cameraGuid = guid; m_camera = true; }
//! No camera anymore
void removeCamera() { m_camera = false; }
//! Set observer
void setObserverName(const QString &observer) { m_observerName = observer; }
//! Observer name
const QString &getObserverName() const { return m_observerName; }
//! Reset the state (like it was a new onject) without affecting interpolator and aircraft
void resetState();
@@ -288,6 +304,7 @@ namespace BlackSimPlugin
SIMCONNECT_DATA_XYZ m_cameraPosition;
SIMCONNECT_DATA_PBH m_cameraRotation;
QByteArray m_callsignByteArray;
QString m_observerName;
BlackMisc::Aviation::CAircraftLights m_currentLightsInSim { nullptr }; //!< current lights to know state for toggling
BlackMisc::Aviation::CAircraftLights m_lightsAsSent { nullptr }; //!< lights as sent to simulator
SIMCONNECT_PERIOD m_requestSimDataPeriod = SIMCONNECT_PERIOD_NEVER; //!< how often do we query ground elevation

View File

@@ -539,6 +539,18 @@ namespace BlackSimPlugin
return m_simConnectObjects.removeByOtherSimObject(trace.simObject);
}
void CSimulatorFsxCommon::removeCamera(CSimConnectObject &simObject)
{
// not in FSX
Q_UNUSED(simObject);
}
void CSimulatorFsxCommon::removeObserver(CSimConnectObject &simObject)
{
// not in FSX
Q_UNUSED(simObject);
}
bool CSimulatorFsxCommon::triggerAutoTraceSendId(qint64 traceTimeMs)
{
if (m_traceSendId) { return false; } // no need
@@ -1554,6 +1566,8 @@ namespace BlackSimPlugin
// call in SIM
const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectRemove);
this->removeCamera(simObject);
this->removeObserver(simObject);
const HRESULT result = SimConnect_AIRemoveObject(m_hSimConnect, static_cast<SIMCONNECT_OBJECT_ID>(simObject.getObjectId()), requestId);
if (isOk(result))
{
@@ -1968,6 +1982,16 @@ namespace BlackSimPlugin
return position;
}
SIMCONNECT_DATA_PBH CSimulatorFsxCommon::aircraftSituationToFsxPBH(const CAircraftSituation &situation)
{
// MSFS has inverted pitch and bank angles
SIMCONNECT_DATA_PBH pbh;
pbh.Pitch = -situation.getPitch().value(CAngleUnit::deg());
pbh.Bank = -situation.getBank().value(CAngleUnit::deg());
pbh.Heading = situation.getHeading().value(CAngleUnit::deg());
return pbh;
}
SIMCONNECT_DATA_INITPOSITION CSimulatorFsxCommon::coordinateToFsxPosition(const ICoordinateGeodetic &coordinate)
{
SIMCONNECT_DATA_INITPOSITION position;
@@ -1982,6 +2006,15 @@ namespace BlackSimPlugin
return position;
}
SIMCONNECT_DATA_LATLONALT CSimulatorFsxCommon::coordinateToFsxLatLonAlt(const ICoordinateGeodetic &coordinate)
{
SIMCONNECT_DATA_LATLONALT lla;
lla.Latitude = coordinate.latitude().value(CAngleUnit::deg());
lla.Longitude = coordinate.longitude().value(CAngleUnit::deg());
lla.Altitude = coordinate.geodeticHeight().value(CLengthUnit::ft()); // already corrected in interpolator if there is an underflow
return lla;
}
void CSimulatorFsxCommon::synchronizeTime(const CTime &zuluTimeSim, const CTime &localTimeSim)
{
if (!m_simTimeSynced) { return; }

View File

@@ -261,6 +261,12 @@ namespace BlackSimPlugin
//! Remove the CSimConnectObject linked in the trace
bool removeSimObjectForTrace(const TraceFsxSendId &trace);
//! Remove camera if any
virtual void removeCamera(CSimConnectObject &simObject);
//! Remove observer if any
virtual void removeObserver(CSimConnectObject &simObject);
//! Trace if required, log errors
HRESULT logAndTraceSendId(HRESULT hr, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
@@ -281,6 +287,20 @@ namespace BlackSimPlugin
static bool is64bit() { return (BlackConfig::CBuildConfig::buildWordSize() == 64); }
//! @}
//! Format conversion
//! \note must be valid situation
static SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation, bool sendGnd = true);
//! Format conversion
//! \note must be valid situation
static SIMCONNECT_DATA_PBH aircraftSituationToFsxPBH(const BlackMisc::Aviation::CAircraftSituation &situation);
//! Format conversion
static SIMCONNECT_DATA_INITPOSITION coordinateToFsxPosition(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
//! Format conversion
static SIMCONNECT_DATA_LATLONALT coordinateToFsxLatLonAlt(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
static constexpr qint64 AutoTraceOffsetMs = 10 * 1000; //!< how long do we trace?
HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object
DispatchProc m_dispatchProc = &CSimulatorFsxCommon::SimConnectProc; //!< called function for dispatch, can be overriden by specialized P3D function
@@ -454,13 +474,6 @@ namespace BlackSimPlugin
//! The SimConnect object for idxs
CSimConnectObject getSimObjectForObjectId(DWORD objectId) const;
//! Format conversion
//! \note must be valid situation
SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation, bool sendGnd = true);
//! Format conversion
SIMCONNECT_DATA_INITPOSITION coordinateToFsxPosition(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
//! Sync time with user's computer
void synchronizeTime(const BlackMisc::PhysicalQuantities::CTime &zuluTimeSim, const BlackMisc::PhysicalQuantities::CTime &localTimeSim);

View File

@@ -102,7 +102,7 @@ namespace BlackSimPlugin
const double latDeg = reference.latitude().value(CAngleUnit::deg());
const double lngDeg = reference.longitude().value(CAngleUnit::deg());
const double maxAltFt = hasHeight ? reference.geodeticHeight().value(CLengthUnit::ft()) : 50000;
const DWORD dwGridWidth = 1.0;
const DWORD dwGridWidth = 1.0;
const DWORD dwGridHeight = 1.0;
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimObjTerrainProbe(); // P3D we use new request id each time (no simobject)
@@ -136,55 +136,93 @@ namespace BlackSimPlugin
bool CSimulatorP3D::followAircraft(const CCallsign &callsign)
{
if (this->isShuttingDownOrDisconnected()) { return false; }
if (!CBuildConfig::isLocalDeveloperDebugBuild()) { return false; }
// Experimental code, suffering from bugs and also requiring
// P3D v4.2 (bugs in V4.1
CSimConnectObject &simObject = m_simConnectObjects[callsign];
const CAircraftModel model = simObject.getAircraft().getModel();
const QString viewName = "Commercial Jet-" + callsign.asString();
const char *view = viewName.toLatin1().constData();
CLogMessage(this).warning("Modelview %1") << viewName;
Q_UNUSED(model);
HRESULT hr = SimConnect_ChangeView(m_hSimConnect, view);
return isOk(hr);
/**
if (!simObject.hasValidRequestAndObjectId()) { return false; }
if (simObject.getCallsignByteArray().isEmpty()) { return false; }
const char *cs = simObject.getCallsignByteArray().constData();
HRESULT hr = s_false();
HRESULT hr = S_FALSE;
//
// Experimental code
//
/** version a
const char *cameraName = simObject.getCallsignByteArray().constData();
if (!simObject.hasCamera())
{
SIMCONNECT_DATA_XYZ position; position.x = 25; position.y = 25; position.z = 0;
SIMCONNECT_DATA_PBH rotation; rotation.Pitch = 0; rotation.Bank = 0; rotation.Heading = -90;
simObject.setCameraPositionAndRotation(position, rotation);
GUID guid;
CoCreateGuid(&guid);
const SIMCONNECT_CAMERA_TYPE cameraType = SIMCONNECT_CAMERA_TYPE_OBJECT_CENTER;
hr = SimConnect_CreateCameraDefinition(m_hSimConnect, guid, cameraType, cs, simObject.cameraPosition(), simObject.cameraRotation());
if (hr == S_OK)
// SIMCONNECT_CAMERA_TYPE_OBJECT_AI_VIRTUAL needs a P3D configuration
// SIMCONNECT_CAMERA_TYPE_LATLONALT_ORTHOGONAL is a top down view
// SIMCONNECT_CAMERA_TYPE_FIXED position at one place
const SIMCONNECT_CAMERA_TYPE cameraType = SIMCONNECT_CAMERA_TYPE_OBJECT_AI_CENTER;
hr = SimConnect_CreateCameraDefinition(m_hSimConnect, guid, cameraType, cameraName, simObject.cameraPosition(), simObject.cameraRotation());
if (isOk(hr))
{
const SIMCONNECT_OBJECT_ID objectId = static_cast<SIMCONNECT_OBJECT_ID>(simObject.getObjectId());
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimData();
hr = SimConnect_CreateCameraInstance(m_hSimConnect, guid, cs, objectId, requestId);
if (hr == S_OK)
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimObjAircraft();
hr = SimConnect_CreateCameraInstance(m_hSimConnect, guid, cameraName, objectId, requestId);
if (isOk(hr))
{
simObject.setCameraGUID(guid);
}
}
}
version a **/
/** version b
const CAircraftModel m = simObject.getAircraftModel();
const QString viewName = "Regional Jet-" + callsign.asString();
const QByteArray viewNameBA = viewName.toLatin1();
hr = SimConnect_ChangeView(m_hSimConnect, viewNameBA.constData());
**/
// Observer is P3D only, not FSX
const CAircraftSituation situation = m_lastSentSituations[callsign];
if (situation.isNull()) { return false; }
SIMCONNECT_DATA_OBSERVER obs;
SIMCONNECT_DATA_PBH pbh; pbh.Pitch = pbh.Bank = pbh.Heading = 0;
obs.Rotation = pbh;
obs.Position = coordinateToFsxLatLonAlt(situation);
obs.Regime = SIMCONNECT_OBSERVER_REGIME_GHOST;
obs.RotateOnTarget = TRUE;
obs.FocusFixed = TRUE;
obs.FieldOfViewH = 30; // deg.
obs.FieldOfViewV = 30; // deg.
obs.LinearStep = 20; // meters
obs.AngularStep = 10; // deg.
const char *observerName = simObject.getCallsignByteArray().constData();
hr = SimConnect_CreateObserver(m_hSimConnect, observerName, obs);
if (isOk(hr))
{
SIMCONNECT_DATA_XYZ offset;
offset.x = offset.y = 30;
offset.z = 0;
hr = SimConnect_ObserverAttachToEntityOn(m_hSimConnect, observerName, simObject.getObjectId(), offset);
if (isOk(hr))
{
SimConnect_SetObserverLookAt(m_hSimConnect, observerName, obs.Position);
// const QByteArray viewName = QStringLiteral("Observer %1").arg(callsign.asString()).toLatin1();
hr = SimConnect_OpenView(m_hSimConnect, observerName);
simObject.setObserverName(callsign.asString());
}
}
if (!simObject.hasCamera()) { return false; }
hr = SimConnect_OpenView(m_hSimConnect, cs);
return hr == S_OK;
**/
return isOk(hr);
}
HRESULT CSimulatorP3D::initEventsP3D()
{
HRESULT hr = S_OK;
if (hr != S_OK)
HRESULT hr = s_ok();
if (isFailure(hr))
{
CLogMessage(this).error("P3D plugin error: %1") << "initEventsP3D failed";
return hr;
@@ -192,6 +230,23 @@ namespace BlackSimPlugin
return hr;
}
void CSimulatorP3D::removeCamera(FsxCommon::CSimConnectObject &simObject)
{
if (!simObject.hasCamera()) { return; }
simObject.removeCamera();
// const char *cameraName = simObject.getCallsignByteArray().constData();
// SimConnect_DeleteCameraInstance(m_hSimConnect, simObject.getCameraGUID(), 0);
// SimConnect_CloseView(m_hSimConnect, cameraName);
}
void CSimulatorP3D::removeObserver(CSimConnectObject &simObject)
{
if (simObject.getObserverName().isEmpty()) { return; }
QByteArray viewName = simObject.getObserverName().toLatin1();
SimConnect_CloseView(m_hSimConnect, viewName.constData());
}
bool CSimulatorP3D::releaseAIControl(const CSimConnectObject &simObject, SIMCONNECT_DATA_REQUEST_ID requestId)
{
// completely remove AI control

View File

@@ -55,6 +55,12 @@ namespace BlackSimPlugin
virtual HRESULT initEventsP3D() override;
#ifdef Q_OS_WIN64
//! \copydoc FsxCommon::CSimulatorFsxCommon::removeCamera
virtual void removeCamera(FsxCommon::CSimConnectObject &simObject) override;
//! \copydoc FsxCommon::CSimulatorFsxCommon::removeObserver
virtual void removeObserver(FsxCommon::CSimConnectObject &simObject) override;
//! \copydoc FsxCommon::CSimulatorFsxCommon::releaseAIControl
//! \remark P3D API release of control
virtual bool releaseAIControl(const FsxCommon::CSimConnectObject &simObject, SIMCONNECT_DATA_REQUEST_ID requestId) override;