1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/* Homepage http://facetracknoir.sourceforge.net/home/default.htm *
* *
* ISC License (ISC) *
* *
* Copyright (c) 2015, Wim Vriend *
* *
* Permission to use, copy, modify, and/or distribute this software for any *
* purpose with or without fee is hereby granted, provided that the above *
* copyright notice and this permission notice appear in all copies. *
*/
#include "ftnoir_protocol_fsuipc.h"
#include "api/plugin-api.hpp"
#include <cmath>
fsuipc::fsuipc() = default;
fsuipc::~fsuipc()
{
FSUIPC_Close();
}
template<typename t>
int fsuipc::scale(t x, t min_x, t max_x)
{
t local_x = x;
if (local_x > max_x)
{
local_x = max_x;
}
if (local_x < min_x)
{
local_x = min_x;
}
t y = (16383 * local_x) / max_x;
return (int) y;
}
#if 0
template<typename t>
static bool check_float_fresh(t x, t y)
{
constexpr t eps = t(1e-4);
return std::fabs(x - y) >= eps;
}
#endif
void fsuipc::pose(const double *headpose, const double*)
{
DWORD result;
WORD FSZoom;
// cm, X and Y are not working for FS2002/2004!
double pos_z = headpose[TZ];
state pitch, yaw, roll; // NOLINT(cppcoreguidelines-pro-type-member-init)
// offsets derived from freetrack
pitch.Control = 66503;
pitch.Value = scale(-headpose[Pitch], -180., 180.); // degrees
yaw.Control = 66504;
yaw.Value = scale(headpose[Yaw], -180., 180.);
roll.Control = 66505;
roll.Value = scale(headpose[Roll], -180., 180.);
#if 0
// Only do this when the data has changed. This way, the HAT-switch can be used when tracking is OFF.
if (check_float_fresh(prevRotX, virtRotX) ||
check_float_fresh(prevRotY, virtRotY) ||
check_float_fresh(prevRotZ, virtRotZ) ||
check_float_fresh(prevPosX, virtPosX) ||
check_float_fresh(prevPosY, virtPosY) ||
check_float_fresh(prevPosZ, virtPosZ))
#endif
{
FSUIPC_Open(SIM_ANY, &result);
//
// Check the FS-version
//
if (((result == FSUIPC_ERR_OK) || (result == FSUIPC_ERR_OPEN)) &&
((FSUIPC_FS_Version == SIM_FS2K2) || (FSUIPC_FS_Version == SIM_FS2K4)))
{
// Write the 4! DOF-data to FS. Only rotations and zoom are possible.
FSUIPC_Write(0x3110, 8, &pitch, &result);
FSUIPC_Write(0x3110, 8, &yaw, &result);
FSUIPC_Write(0x3110, 8, &roll, &result);
FSZoom = WORD(pos_z + 64);
FSUIPC_Write(0x832E, 2, &FSZoom, &result);
//
// Write the data, in one go!
//
FSUIPC_Process(&result);
if (result == FSUIPC_ERR_SENDMSG)
{
// FSUIPC checks for already open connections and returns FSUIPC_ERR_OPEN in that case
// the connection scope is global for the process. this is why above code doesn't
// leak resources or have logic errors. see: http://www.purebasic.fr/english/viewtopic.php?t=31112
FSUIPC_Close();
}
}
}
#if 0
prevPosX = virtPosX;
prevPosY = virtPosY;
prevPosZ = virtPosZ;
prevRotX = virtRotX;
prevRotY = virtRotY;
prevRotZ = virtRotZ;
#endif
}
module_status fsuipc::initialize()
{
#if 0
FSUIPCLib.setFileName( s.LocationOfDLL );
FSUIPCLib.setLoadHints(QLibrary::PreventUnloadHint);
if (!FSUIPCLib.load())
return error(tr("Can't load fsuipc at '%1'").arg(s.LocationOfDLL));
else
return status_ok();
#else
return {};
#endif
}
OPENTRACK_DECLARE_PROTOCOL(fsuipc, FSUIPCControls, fsuipcDll)
|