summaryrefslogtreecommitdiffhomepage
path: root/opentrack
diff options
context:
space:
mode:
Diffstat (limited to 'opentrack')
-rw-r--r--opentrack/ftnoir_keyboardshortcuts.ui210
-rw-r--r--opentrack/global-shortcuts.cpp68
-rw-r--r--opentrack/main-settings.hpp15
-rw-r--r--opentrack/mappings.hpp49
-rw-r--r--opentrack/mingw-version-script.txt8
-rw-r--r--opentrack/options.hpp123
-rw-r--r--opentrack/plugin-support.cpp71
-rw-r--r--opentrack/plugin-support.h17
-rw-r--r--opentrack/pose.hpp24
-rw-r--r--opentrack/posix-version-script.txt8
-rw-r--r--opentrack/quat.hpp66
-rw-r--r--opentrack/shortcuts.cpp117
-rw-r--r--opentrack/shortcuts.h97
-rw-r--r--opentrack/simple-mat.hpp155
-rw-r--r--opentrack/state.hpp23
-rw-r--r--opentrack/timer.hpp11
-rw-r--r--opentrack/tracker.cpp216
-rw-r--r--opentrack/tracker.h41
-rw-r--r--opentrack/work.hpp18
19 files changed, 684 insertions, 653 deletions
diff --git a/opentrack/ftnoir_keyboardshortcuts.ui b/opentrack/ftnoir_keyboardshortcuts.ui
deleted file mode 100644
index f576d8fb..00000000
--- a/opentrack/ftnoir_keyboardshortcuts.ui
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>UICKeyboardShortcutDialog</class>
- <widget class="QWidget" name="UICKeyboardShortcutDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>415</width>
- <height>143</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Keyboard shortcuts</string>
- </property>
- <property name="windowIcon">
- <iconset>
- <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="0">
- <widget class="QLabel" name="textLabel2_5">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Toggle</string>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="textLabel2_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Center</string>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="chkToggleShift">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Shift</string>
- </property>
- </widget>
- </item>
- <item row="2" column="4">
- <widget class="QComboBox" name="cbxToggleKey">
- <property name="minimumSize">
- <size>
- <width>90</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Select Number</string>
- </property>
- <property name="insertPolicy">
- <enum>QComboBox::InsertAlphabetically</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QCheckBox" name="chkCenterAlt">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Alt</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QCheckBox" name="chkToggleCtrl">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Ctrl</string>
- </property>
- </widget>
- </item>
- <item row="0" column="4">
- <widget class="QLabel" name="textLabel2_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Keyboard</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QCheckBox" name="chkToggleAlt">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Alt</string>
- </property>
- </widget>
- </item>
- <item row="3" column="3" colspan="2">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QCheckBox" name="chkCenterCtrl">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Ctrl</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="chkCenterShift">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Shift</string>
- </property>
- </widget>
- </item>
- <item row="1" column="4">
- <widget class="QComboBox" name="cbxCenterKey">
- <property name="minimumSize">
- <size>
- <width>90</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Select Number</string>
- </property>
- <property name="insertPolicy">
- <enum>QComboBox::InsertAlphabetically</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
- <slots>
- <slot>startEngineClicked()</slot>
- <slot>stopEngineClicked()</slot>
- <slot>cameraSettingsClicked()</slot>
- </slots>
-</ui>
diff --git a/opentrack/global-shortcuts.cpp b/opentrack/global-shortcuts.cpp
new file mode 100644
index 00000000..7569fd9a
--- /dev/null
+++ b/opentrack/global-shortcuts.cpp
@@ -0,0 +1,68 @@
+#include <QList>
+#include <QString>
+
+extern QList<QString> global_key_sequences;
+extern QList<int> global_windows_key_sequences;
+
+#if defined(_WIN32)
+# ifndef DIRECTINPUT_VERSION
+# define DIRECTINPUT_VERSION 0x800
+# endif
+# include <windows.h>
+# include <dinput.h>
+
+QList<int> global_windows_key_sequences =
+ QList<int>()
+ << 0
+ << DIK_F1
+ << DIK_F2
+ << DIK_F3
+ << DIK_F4
+ << DIK_F5
+ << DIK_F6
+ << DIK_F7
+ << DIK_F8
+ << DIK_F9
+ << DIK_F10
+ << DIK_F11
+ << DIK_F12
+ << DIK_LEFT
+ << DIK_RIGHT
+ << DIK_UP
+ << DIK_DOWN
+ << DIK_PGUP
+ << DIK_PGDN
+ << DIK_HOME
+ << DIK_END
+ << DIK_BACK
+ << DIK_DELETE
+ << DIK_RETURN;
+#endif
+
+QList<QString> global_key_sequences =
+ QList<QString>()
+ << ""
+ << "F1"
+ << "F2"
+ << "F3"
+ << "F4"
+ << "F5"
+ << "F6"
+ << "F7"
+ << "F8"
+ << "F9"
+ << "F10"
+ << "F11"
+ << "F12"
+ << "Left"
+ << "Right"
+ << "Up"
+ << "Down"
+ << "PgUp"
+ << "PgDown"
+ << "Home"
+ << "End"
+ << "Del"
+;
+
+
diff --git a/opentrack/main-settings.hpp b/opentrack/main-settings.hpp
index e41a23c9..0468aeb1 100644
--- a/opentrack/main-settings.hpp
+++ b/opentrack/main-settings.hpp
@@ -12,7 +12,7 @@ struct axis_opts {
value<int> src;
axis_opts(pbundle b, QString pfx, int idx) :
zero(b, n(pfx, "zero-pos"), 0),
- invert(b, n(pfx, "invert-axis"), false),
+ invert(b, n(pfx, "invert-sign"), false),
altp(b, n(pfx, "alt-axis-sign"), false),
src(b, n(pfx, "source-index"), idx)
{}
@@ -27,8 +27,11 @@ struct main_settings {
value<QString> tracker_dll, tracker2_dll, filter_dll, protocol_dll;
axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll;
value<bool> tcomp_p, tcomp_tz;
- main_settings(pbundle b) :
- b(b),
+ value<bool> tray_enabled;
+ value<int> camera_yaw, camera_pitch;
+ value<bool> center_at_startup;
+ main_settings() :
+ b(bundle("opentrack-ui")),
tracker_dll(b, "tracker-dll", ""),
tracker2_dll(b, "tracker2-dll", ""),
filter_dll(b, "filter-dll", ""),
@@ -40,6 +43,10 @@ struct main_settings {
a_pitch(b, "pitch", Pitch),
a_roll(b, "roll", Roll),
tcomp_p(b, "compensate-translation", true),
- tcomp_tz(b, "compensate-translation-disable-z-axis", false)
+ tcomp_tz(b, "compensate-translation-disable-z-axis", false),
+ tray_enabled(b, "use-system-tray", false),
+ camera_yaw(b, "camera-yaw", 0),
+ camera_pitch(b, "camera-pitch", 0),
+ center_at_startup(b, "center-at-startup", true)
{}
};
diff --git a/opentrack/mappings.hpp b/opentrack/mappings.hpp
index 86126db9..3336dcd8 100644
--- a/opentrack/mappings.hpp
+++ b/opentrack/mappings.hpp
@@ -10,23 +10,18 @@ class Mapping {
public:
Mapping(QString primary,
QString secondary,
- int maxInput1,
- int maxOutput1,
- int maxInput2,
- int maxOutput2,
+ int max_x,
+ int max_y,
axis_opts& opts) :
- curve(maxInput1, maxOutput1),
- curveAlt(maxInput2, maxOutput2),
+ curve(max_x, max_y),
+ curveAlt(max_x, max_y),
opts(opts),
name1(primary),
name2(secondary)
{
- // XXX TODO move all this qsettings boilerplate into a single header -sh 20141004
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- QSettings iniFile(currentFile, QSettings::IniFormat);
- curve.loadSettings(iniFile, primary);
- curveAlt.loadSettings(iniFile, secondary);
+ mem<QSettings> iniFile = group::ini_file();
+ curve.loadSettings(*iniFile, primary);
+ curveAlt.loadSettings(*iniFile, secondary);
}
Map curve;
Map curveAlt;
@@ -40,12 +35,12 @@ private:
public:
Mappings(std::vector<axis_opts*> opts) :
axes {
- Mapping("tx","tx_alt", 100, 100, 100, 100, *opts[TX]),
- Mapping("ty","ty_alt", 100, 100, 100, 100, *opts[TY]),
- Mapping("tz","tz_alt", 100, 100, 100, 100, *opts[TZ]),
- Mapping("rx", "rx_alt", 180, 180, 180, 180, *opts[Yaw]),
- Mapping("ry", "ry_alt", 180, 180, 180, 180, *opts[Pitch]),
- Mapping("rz", "rz_alt", 180, 180, 180, 180, *opts[Roll])
+ Mapping("tx","tx_alt", 100, 100, *opts[TX]),
+ Mapping("ty","ty_alt", 100, 100, *opts[TY]),
+ Mapping("tz","tz_alt", 100, 100, *opts[TZ]),
+ Mapping("rx", "rx_alt", 180, 180, *opts[Yaw]),
+ Mapping("ry", "ry_alt", 180, 180, *opts[Pitch]),
+ Mapping("rz", "rz_alt", 180, 180, *opts[Roll])
}
{}
@@ -54,29 +49,25 @@ public:
void load_mappings()
{
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
+ mem<QSettings> iniFile = group::ini_file();
for (int i = 0; i < 6; i++)
{
- axes[i].curve.loadSettings(iniFile, axes[i].name1);
- axes[i].curveAlt.loadSettings(iniFile, axes[i].name2);
+ axes[i].curve.loadSettings(*iniFile, axes[i].name1);
+ axes[i].curveAlt.loadSettings(*iniFile, axes[i].name2);
}
}
void save_mappings()
{
- QSettings settings("opentrack");
- QString currentFile = settings.value("SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini").toString();
- QSettings iniFile(currentFile, QSettings::IniFormat);
+ mem<QSettings> iniFile = group::ini_file();
for (int i = 0; i < 6; i++)
{
- axes[i].curve.saveSettings(iniFile, axes[i].name1);
- axes[i].curveAlt.saveSettings(iniFile, axes[i].name2);
+ axes[i].curve.saveSettings(*iniFile, axes[i].name1);
+ axes[i].curveAlt.saveSettings(*iniFile, axes[i].name2);
}
}
-
+
void invalidate_unsaved()
{
for (int i = 0; i < 6; i++)
diff --git a/opentrack/mingw-version-script.txt b/opentrack/mingw-version-script.txt
new file mode 100644
index 00000000..fe20ad37
--- /dev/null
+++ b/opentrack/mingw-version-script.txt
@@ -0,0 +1,8 @@
+{
+ global:
+ GetDialog?0;
+ GetConstructor?0;
+ GetMetadata?0;
+ local:
+ *;
+};
diff --git a/opentrack/options.hpp b/opentrack/options.hpp
index 6c15d729..5eae754f 100644
--- a/opentrack/options.hpp
+++ b/opentrack/options.hpp
@@ -26,17 +26,21 @@
#include <QSlider>
#include <QLineEdit>
#include <QLabel>
+#include <QTabWidget>
#include <QCoreApplication>
#include <cinttypes>
#include <QDebug>
+#include <memory>
+template<typename t> using mem = std::shared_ptr<t>;
+
namespace options {
template<typename k, typename v>
using map = std::map<k, v>;
using std::string;
-
+
template<typename t>
// don't elide usages of the function, qvariant default implicit
// conversion results in nonsensical runtime behavior -sh
@@ -77,12 +81,6 @@ namespace options {
private:
map<string, QVariant> kvs;
string name;
- static const QString ini_pathname()
- {
- QSettings settings(group::org);
- return settings.value("SettingsFile",
- QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- }
public:
group(const string& name) : name(name)
{
@@ -97,8 +95,8 @@ namespace options {
}
conf.endGroup();
}
- static constexpr const char* org = "opentrack";
-
+ static constexpr const char* org = "opentrack-2.3";
+
void save()
{
QSettings s(ini_pathname(), QSettings::IniFormat);
@@ -110,26 +108,41 @@ namespace options {
s.setValue(k, i.second);
}
s.endGroup();
+ s.sync();
}
-
+
template<typename t>
t get(const string& k)
{
return qcruft_to_t<t>(kvs[k]);
}
-
+
void put(const string& s, const QVariant& d)
{
kvs[s] = d;
}
-
+
bool contains(const string& s)
{
return kvs.count(s) != 0;
}
+
+ static constexpr const char* filename_key = "settings-file";
+ static constexpr const char* default_path = "/settings/default.ini";
+
+ static const QString ini_pathname()
+ {
+ QSettings settings(group::org);
+ return settings.value(filename_key, QCoreApplication::applicationDirPath() + default_path).toString();
+ }
+ static const mem<QSettings> ini_file()
+ {
+ return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat);
+ }
};
class impl_bundle : public QObject {
+ Q_OBJECT
protected:
QMutex mtx;
const string group_name;
@@ -138,6 +151,9 @@ namespace options {
bool modified;
impl_bundle(const impl_bundle&) = delete;
impl_bundle& operator=(const impl_bundle&) = delete;
+ signals:
+ void reloading();
+ void saving();
public:
impl_bundle(const string& group_name) :
mtx(QMutex::Recursive),
@@ -147,28 +163,29 @@ namespace options {
modified(false)
{
}
-
+
string name() { return group_name; }
-
+
void reload() {
- QMutexLocker l(&mtx);
- saved = group(group_name);
- transient = saved;
- modified = false;
+ {
+ QMutexLocker l(&mtx);
+ saved = group(group_name);
+ transient = saved;
+ modified = false;
+ }
+ emit reloading();
}
-
- bool store_kv(const string& name, const QVariant& datum)
+
+ void store_kv(const string& name, const QVariant& datum)
{
QMutexLocker l(&mtx);
-
+
auto old = transient.get<QVariant>(name);
if (!transient.contains(name) || datum != old)
{
modified = true;
transient.put(name, datum);
- return true;
}
- return false;
}
bool contains(const string& name)
{
@@ -183,10 +200,13 @@ namespace options {
}
void save()
{
- QMutexLocker l(&mtx);
- modified = false;
- saved = transient;
- transient.save();
+ {
+ QMutexLocker l(&mtx);
+ modified = false;
+ saved = transient;
+ transient.save();
+ }
+ emit saving();
}
bool modifiedp() {
@@ -194,9 +214,9 @@ namespace options {
return modified;
}
};
-
+
class opt_bundle;
-
+
namespace
{
template<typename k, typename v, typename cnt = int>
@@ -210,51 +230,52 @@ namespace options {
map<k, tt> implsgl_data;
public:
opt_singleton() : implsgl_mtx(QMutex::Recursive) {}
-
+
static opt_singleton<k, v>& datum()
{
static auto ret = std::make_shared<opt_singleton<k, v>>();
return *ret;
}
-
+
pbundle bundle(const k& key)
{
QMutexLocker l(&implsgl_mtx);
-
+
if (implsgl_data.count(key) != 0)
return std::get<1>(implsgl_data[key]);
+ qDebug() << "bundle +" << QString::fromStdString(key);
+
auto shr = std::make_shared<v>(key);
implsgl_data[key] = tt(cnt(1), shr);
return shr;
}
-
+
void bundle_decf(const k& key)
{
QMutexLocker l(&implsgl_mtx);
-
+
if (--std::get<0>(implsgl_data[key]) == 0)
implsgl_data.erase(key);
}
-
+
~opt_singleton() { implsgl_data.clear(); }
};
-
+
using pbundle = std::shared_ptr<opt_bundle>;
using t_fact = opt_singleton<string, opt_bundle>;
}
-
+
static inline t_fact::pbundle bundle(const string name) { return t_fact::datum().bundle(name); }
-
+
class opt_bundle : public impl_bundle
{
public:
opt_bundle() : impl_bundle("i-have-no-name") {}
opt_bundle(const string& group_name) : impl_bundle(group_name)
{
- qDebug() << "bundle +" << QString::fromStdString(group_name);
}
-
+
~opt_bundle()
{
qDebug() << "bundle -" << QString::fromStdString(group_name);
@@ -281,16 +302,18 @@ namespace options {
template<typename t>
void store(const t& datum)
{
- if (b->store_kv(self_name, datum))
- emit valueChanged(static_cast<t>(datum));
+ b->store_kv(self_name, datum);
+ emit valueChanged(static_cast<t>(datum));
}
public slots:
DEFINE_SLOT(double)
DEFINE_SLOT(int)
DEFINE_SLOT(QString)
DEFINE_SLOT(bool)
+ public slots:
+ virtual void reload() = 0;
};
-
+
static inline string string_from_qstring(const QString& datum)
{
auto tmp = datum.toUtf8();
@@ -309,6 +332,9 @@ namespace options {
static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection;
value(pbundle b, const string& name, t def) : base_value(b, name)
{
+ QObject::connect(b.get(), SIGNAL(reloading()),
+ this, SLOT(reload()),
+ DIRECT_CONNTYPE);
if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)
*this = def;
}
@@ -319,6 +345,9 @@ namespace options {
{
return b->get<t>(self_name);
}
+ void reload() override {
+ *this = static_cast<t>(*this);
+ }
};
template<typename t, typename q>
@@ -389,4 +418,12 @@ namespace options {
lb->setText(v);
base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE);
}
+
+ template<>
+ inline void tie_setting(value<int>& v, QTabWidget* t)
+ {
+ t->setCurrentIndex(v);
+ base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE);
+ }
}
diff --git a/opentrack/plugin-support.cpp b/opentrack/plugin-support.cpp
index ec56b1e1..2c129906 100644
--- a/opentrack/plugin-support.cpp
+++ b/opentrack/plugin-support.cpp
@@ -5,6 +5,8 @@
#include <QFile>
#include <QDir>
+#include <iostream>
+
#ifndef _WIN32
# include <dlfcn.h>
#endif
@@ -14,16 +16,19 @@ SelectedLibraries::~SelectedLibraries()
}
template<typename t>
-static ptr<t> make_instance(ptr<dylib> lib)
+static mem<t> make_instance(mem<dylib> lib)
{
- ptr<t> ret = nullptr;
- if (lib && lib->Constructor)
- ret = ptr<t>(reinterpret_cast<t*>(reinterpret_cast<CTOR_FUNPTR>(lib->Constructor)()));
- //qDebug() << "lib" << (lib ? lib->filename : "<null>") << "ptr" << (intptr_t)ret.get();
+ mem<t> ret;
+ if (lib != nullptr && lib->Constructor)
+ {
+ qDebug() << "dylib" << (lib ? lib->filename : "<null>") << "ptr" << (intptr_t) lib->Constructor;
+ std::cout.flush();
+ ret = mem<t>(reinterpret_cast<t*>(reinterpret_cast<CTOR_FUNPTR>(lib->Constructor)()));
+ }
return ret;
}
-SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibtr f) :
+SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) :
pTracker(nullptr),
pFilter(nullptr),
pProtocol(nullptr),
@@ -32,20 +37,19 @@ SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibt
pTracker = make_instance<ITracker>(t);
pProtocol = make_instance<IProtocol>(p);
pFilter = make_instance<IFilter>(f);
-
- if (!pTracker|| !pProtocol)
+
+ if (!pTracker || !pProtocol)
{
- qDebug() << "load failure tracker" << (intptr_t)pTracker.get() << "protocol" << (intptr_t)pProtocol.get();
+ qDebug() << "dylib load failure";
+ return;
+ }
+
+ if(!pProtocol->correct())
+ {
+ qDebug() << "protocol load failure";
return;
}
- if (pProtocol)
- if(!pProtocol->correct())
- {
- qDebug() << "protocol load failure";
- return;
- }
-
pTracker->start_tracker(frame);
correct = true;
@@ -67,7 +71,7 @@ SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibt
# define LIB_PREFIX "lib"
#endif
-static bool get_metadata(ptr<dylib> lib, QString& name, QIcon& icon)
+static bool get_metadata(mem<dylib> lib, QString& name, QIcon& icon)
{
Metadata* meta;
if (!lib->Meta || ((meta = lib->Meta()), !meta))
@@ -78,7 +82,7 @@ static bool get_metadata(ptr<dylib> lib, QString& name, QIcon& icon)
return true;
}
-QList<ptr<dylib>> dylib::enum_libraries()
+QList<mem<dylib>> dylib::enum_libraries()
{
#define BASE "opentrack-"
#define SUFF "-*."
@@ -86,11 +90,11 @@ QList<ptr<dylib>> dylib::enum_libraries()
BASE "tracker" SUFF,
BASE "proto" SUFF };
const Type filters_t[] = { Filter, Tracker, Protocol };
-
+
QDir settingsDir( QCoreApplication::applicationDirPath() );
-
- QList<ptr<dylib>> ret;
-
+
+ QList<mem<dylib>> ret;
+
for (int i = 0; i < 3; i++)
{
QString filter = filters_n[i];
@@ -110,7 +114,7 @@ QList<ptr<dylib>> dylib::enum_libraries()
ret.push_back(lib);
}
}
-
+
return ret;
}
@@ -123,12 +127,12 @@ dylib::dylib(const QString& filename, Type t) :
// otherwise dlopen opens the calling executable
if (filename.size() == 0)
return;
-
+
this->filename = filename;
#if defined(_WIN32)
QString fullPath = QCoreApplication::applicationDirPath() + "/" + this->filename;
handle = new QLibrary(fullPath);
-
+
struct _foo {
static bool die(QLibrary*& l, bool failp)
{
@@ -141,18 +145,18 @@ dylib::dylib(const QString& filename, Type t) :
return failp;
}
};
-
+
if (_foo::die(handle, !handle->load()))
return;
-
+
Dialog = (CTOR_FUNPTR) handle->resolve("GetDialog");
if (_foo::die(handle, !Dialog))
return;
-
+
Constructor = (CTOR_FUNPTR) handle->resolve("GetConstructor");
if (_foo::die(handle, !Constructor))
return;
-
+
Meta = (METADATA_FUNPTR) handle->resolve("GetMetadata");
if (_foo::die(handle, !Meta))
return;
@@ -199,9 +203,9 @@ dylib::dylib(const QString& filename, Type t) :
(void) _foo::err(handle);
}
#endif
-
- auto m = ptr<Metadata>(Meta());
-
+
+ auto m = mem<Metadata>(Meta());
+
icon = m->icon();
name = m->name();
}
@@ -209,7 +213,8 @@ dylib::dylib(const QString& filename, Type t) :
dylib::~dylib()
{
#if defined(_WIN32)
- handle->unload();
+ if (handle)
+ delete handle;
#else
if (handle)
(void) dlclose(handle);
diff --git a/opentrack/plugin-support.h b/opentrack/plugin-support.h
index 238aeb53..a2b6d403 100644
--- a/opentrack/plugin-support.h
+++ b/opentrack/plugin-support.h
@@ -1,6 +1,7 @@
#pragma once
#include "plugin-api.hpp"
+#include "options.hpp"
#include <QWidget>
#include <QDebug>
@@ -9,8 +10,6 @@
#include <QFrame>
#include <QList>
-#include <memory>
-template<typename t> using ptr = std::shared_ptr<t>;
extern "C" typedef void* (*CTOR_FUNPTR)(void);
extern "C" typedef Metadata* (*METADATA_FUNPTR)(void);
@@ -20,7 +19,7 @@ struct dylib {
dylib(const QString& filename, Type t);
~dylib();
- static QList<ptr<dylib>> enum_libraries();
+ static QList<mem<dylib>> enum_libraries();
Type type;
QString filename;
@@ -40,12 +39,12 @@ private:
};
struct SelectedLibraries {
- using dylibtr = ptr<dylib>;
- ptr<ITracker> pTracker;
- ptr<IFilter> pFilter;
- ptr<IProtocol> pProtocol;
- SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibtr f);
+ using dylibptr = mem<dylib>;
+ mem<ITracker> pTracker;
+ mem<IFilter> pFilter;
+ mem<IProtocol> pProtocol;
+ SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f);
SelectedLibraries() : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) {}
~SelectedLibraries();
bool correct;
-}; \ No newline at end of file
+};
diff --git a/opentrack/pose.hpp b/opentrack/pose.hpp
index 41e984f5..93d467a9 100644
--- a/opentrack/pose.hpp
+++ b/opentrack/pose.hpp
@@ -2,7 +2,6 @@
#include <utility>
#include <algorithm>
-#include "./quat.hpp"
#include "./plugin-api.hpp"
class Pose {
@@ -13,32 +12,11 @@ private:
double axes[6];
public:
- Pose() : axes {0,0,0, 0,0,0 } {}
+ Pose() : axes {0,0,0, 0,0,0} {}
inline operator double*() { return axes; }
inline operator const double*() const { return axes; }
inline double& operator()(int i) { return axes[i]; }
inline double operator()(int i) const { return axes[i]; }
-
- Quat quat() const
- {
- return Quat(axes[Yaw]*d2r, axes[Pitch]*d2r, axes[Roll]*d2r);
- }
-
- static Pose fromQuat(const Quat& q)
- {
- Pose ret;
- q.to_euler_degrees(ret(Yaw), ret(Pitch), ret(Roll));
- return ret;
- }
-
- Pose operator&(const Pose& B) const
- {
- const Quat q = quat() * B.quat().inv();
- Pose ret = fromQuat(q);
- for (int i = TX; i < TX + 3; i++)
- ret(i) = axes[i] - B.axes[i];
- return ret;
- }
};
diff --git a/opentrack/posix-version-script.txt b/opentrack/posix-version-script.txt
new file mode 100644
index 00000000..97edb9aa
--- /dev/null
+++ b/opentrack/posix-version-script.txt
@@ -0,0 +1,8 @@
+{
+ global:
+ GetDialog;
+ GetConstructor;
+ GetMetadata;
+ local:
+ *;
+}; \ No newline at end of file
diff --git a/opentrack/quat.hpp b/opentrack/quat.hpp
deleted file mode 100644
index 6d777b28..00000000
--- a/opentrack/quat.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * 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.
- */
-
-#pragma once
-#include <cmath>
-
-class Quat {
-private:
- static constexpr double pi = 3.141592653;
- static constexpr double r2d = 180./pi;
- double a,b,c,d; // quaternion coefficients
-public:
- Quat() : a(1.),b(0.),c(0.),d(0.) {}
- Quat(double yaw, double pitch, double roll) { from_euler_rads(yaw, pitch, roll); }
- Quat(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {}
-
- Quat inv(){
- return Quat(a,-b,-c, -d);
- }
-
- // conversions
- // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
- void from_euler_rads(double yaw, double pitch, double roll)
- {
-
- const double sin_phi = sin(roll/2.);
- const double cos_phi = cos(roll/2.);
- const double sin_the = sin(pitch/2.);
- const double cos_the = cos(pitch/2.);
- const double sin_psi = sin(yaw/2.);
- const double cos_psi = cos(yaw/2.);
-
- a = cos_phi*cos_the*cos_psi + sin_phi*sin_the*sin_psi;
- b = sin_phi*cos_the*cos_psi - cos_phi*sin_the*sin_psi;
- c = cos_phi*sin_the*cos_psi + sin_phi*cos_the*sin_psi;
- d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi;
- }
-
- void to_euler_rads(double& yaw, double& pitch, double& roll) const
- {
- roll = atan2(2.*(a*b + c*d), 1. - 2.*(b*b + c*c));
- pitch = asin(2.*(a*c - b*d));
- yaw = atan2(2.*(a*d + b*c), 1. - 2.*(c*c + d*d));
- }
-
- void to_euler_degrees(double& yaw, double& pitch, double& roll) const
- {
- to_euler_rads(yaw, pitch, roll);
- yaw *= r2d;
- pitch *= r2d;
- roll *= r2d;
- }
-
- const Quat operator*(const Quat& B) const
- {
- const Quat& A = *this;
- return Quat(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication
- A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c,
- A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b,
- A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a);
- }
-};
diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp
index d1cfa503..e81b6bb0 100644
--- a/opentrack/shortcuts.cpp
+++ b/opentrack/shortcuts.cpp
@@ -1,42 +1,19 @@
#include "shortcuts.h"
+#include <QMutexLocker>
-KeyboardShortcutDialog::KeyboardShortcutDialog()
-{
- ui.setupUi( this );
-
- connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
- connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
-
- for ( int i = 0; i < global_key_sequences.size(); i++) {
- ui.cbxCenterKey->addItem(global_key_sequences.at(i));
- ui.cbxToggleKey->addItem(global_key_sequences.at(i));
- }
- tie_setting(s.center.key_index, ui.cbxCenterKey);
- tie_setting(s.center.alt, ui.chkCenterAlt);
- tie_setting(s.center.shift, ui.chkCenterShift);
- tie_setting(s.center.ctrl, ui.chkCenterCtrl);
-
- tie_setting(s.toggle.key_index, ui.cbxToggleKey);
- tie_setting(s.toggle.alt, ui.chkToggleAlt);
- tie_setting(s.toggle.shift, ui.chkToggleShift);
- tie_setting(s.toggle.ctrl, ui.chkToggleCtrl);
-}
+#if defined(_WIN32)
+#include <windows.h>
-void KeyboardShortcutDialog::doOK() {
- s.b->save();
- this->close();
- emit reload();
-}
+void KeybindingWorker::set_keys(Key kCenter_, Key kToggle_, Key kZero_)
+{
+ QMutexLocker l(&mtx);
-void KeyboardShortcutDialog::doCancel() {
- s.b->reload();
- close();
+ kCenter = kCenter_;
+ kToggle = kToggle_;
+ kZero = kZero_;
}
-#if defined(_WIN32)
-#include <windows.h>
-
KeybindingWorker::~KeybindingWorker() {
should_quit = true;
wait();
@@ -48,8 +25,8 @@ KeybindingWorker::~KeybindingWorker() {
din->Release();
}
-KeybindingWorker::KeybindingWorker(Key keyCenter, Key keyToggle, WId handle) :
- din(0), dinkeyboard(0), kCenter(keyCenter), kToggle(keyToggle), should_quit(true)
+KeybindingWorker::KeybindingWorker(Key keyCenter, Key keyToggle, Key keyZero, WId handle, Shortcuts& sc) :
+ sc(sc), din(0), dinkeyboard(0), kCenter(keyCenter), kToggle(keyToggle), kZero(keyZero), should_quit(true)
{
if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) {
qDebug() << "setup DirectInput8 Creation failed!" << GetLastError();
@@ -94,7 +71,8 @@ static bool isKeyPressed( const Key *key, const BYTE *keystate ) {
bool ctrl;
bool alt;
- if (keystate[key->keycode] & 0x80) {
+ if (key->keycode != 0 && keystate[key->keycode] & 0x80)
+ {
shift = ( (keystate[DIK_LSHIFT] & 0x80) || (keystate[DIK_RSHIFT] & 0x80) );
ctrl = ( (keystate[DIK_LCONTROL] & 0x80) || (keystate[DIK_RCONTROL] & 0x80) );
alt = ( (keystate[DIK_LALT] & 0x80) || (keystate[DIK_RALT] & 0x80) );
@@ -108,12 +86,9 @@ static bool isKeyPressed( const Key *key, const BYTE *keystate ) {
return false;
}
-#define PROCESS_KEY(k, s) \
- if (isKeyPressed(&k, keystate) && (!k.ever_pressed ? (k.timer.start(), k.ever_pressed = true) : k.timer.restart() > 100)) \
- emit s;
-
void KeybindingWorker::run() {
BYTE keystate[256];
+
while (!should_quit)
{
if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) {
@@ -122,10 +97,19 @@ void KeybindingWorker::run() {
continue;
}
- PROCESS_KEY(kCenter, center());
- PROCESS_KEY(kToggle, toggle());
+ QMutexLocker l(&mtx);
- Sleep(25);
+ if (isKeyPressed(&kCenter, keystate) && kCenter.should_process())
+ emit sc.center();
+
+ if (isKeyPressed(&kToggle, keystate) && kToggle.should_process())
+ emit sc.toggle();
+
+ if (isKeyPressed(&kZero, keystate) && kZero.should_process())
+ emit sc.zero();
+
+ // keypresses get dropped with high values
+ Sleep(15);
}
}
#endif
@@ -156,16 +140,47 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k)
}
}
#else
+ key = K();
int idx = k.key_index;
- if (idx > 0)
+ key.keycode = 0;
+ key.shift = key.alt = key.ctrl = 0;
+ if (idx > 0 && idx < global_windows_key_sequences.size())
+ key.keycode = global_windows_key_sequences[idx];
+ key.shift = k.shift;
+ key.alt = k.alt;
+ key.ctrl = k.ctrl;
+#endif
+}
+
+void Shortcuts::reload() {
+#ifndef _WIN32
+ if (keyCenter)
{
- key.keycode = 0;
- key.shift = key.alt = key.ctrl = 0;
- if (idx < global_windows_key_sequences.size())
- key.keycode = global_windows_key_sequences[idx];
- key.shift = k.shift;
- key.alt = k.alt;
- key.ctrl = k.ctrl;
+ keyCenter->setShortcut(QKeySequence::UnknownKey);
+ keyCenter->setEnabled(false);
+ }
+ if (keyToggle)
+ {
+ keyToggle->setShortcut(QKeySequence::UnknownKey);
+ keyToggle->setEnabled(false);
+ }
+ if (keyZero)
+ {
+ keyZero->setShortcut(QKeySequence::UnknownKey);
+ keyZero->setEnabled(false);
}
#endif
-} \ No newline at end of file
+ bind_keyboard_shortcut(keyCenter, s.center);
+ bind_keyboard_shortcut(keyToggle, s.toggle);
+ bind_keyboard_shortcut(keyZero, s.zero);
+#ifdef _WIN32
+ bool is_new = keybindingWorker == nullptr;
+ if (is_new)
+ {
+ keybindingWorker = std::make_shared<KeybindingWorker>(keyCenter, keyToggle, keyZero, handle, *this);
+ keybindingWorker->start();
+ }
+ else
+ keybindingWorker->set_keys(keyCenter, keyToggle, keyZero);
+#endif
+}
diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h
index 8fe1a39b..4d4b19d3 100644
--- a/opentrack/shortcuts.h
+++ b/opentrack/shortcuts.h
@@ -1,4 +1,5 @@
#pragma once
+#include <QObject>
#include <QWidget>
#include <QElapsedTimer>
#include <QThread>
@@ -6,11 +7,12 @@
#include <QCheckBox>
#include <QComboBox>
#include <QSettings>
+#include <QMutex>
#include "qxt-mini/QxtGlobalShortcut"
#include "opentrack/plugin-support.h"
#include "opentrack/options.hpp"
-#include "ui_ftnoir_keyboardshortcuts.h"
+#include "opentrack/main-settings.hpp"
using namespace options;
@@ -40,112 +42,89 @@ struct Key {
bool shift;
bool ctrl;
bool alt;
- bool ever_pressed;
QElapsedTimer timer;
public:
- Key() : keycode(0), shift(false), ctrl(false), alt(false), ever_pressed(false)
+ Key() : keycode(0), shift(false), ctrl(false), alt(false)
{
}
+
+ bool should_process()
+ {
+ return !timer.isValid() ? (timer.start(), true) : timer.restart() > 100;
+ }
};
#else
typedef unsigned char BYTE;
struct Key { int foo; };
#endif
+struct Shortcuts;
+
struct KeybindingWorker : public QThread {
- Q_OBJECT
#ifdef _WIN32
private:
+ Shortcuts& sc;
LPDIRECTINPUT8 din;
LPDIRECTINPUTDEVICE8 dinkeyboard;
Key kCenter;
Key kToggle;
+ Key kZero;
+ QMutex mtx;
public:
volatile bool should_quit;
~KeybindingWorker();
- KeybindingWorker(Key keyCenter, Key keyToggle, WId handle);
- void run();
+ KeybindingWorker(Key keyCenter, Key keyToggle, Key keyZero, WId handle, Shortcuts& sc);
+ void run();
+ void set_keys(Key kCenter, Key kToggle, Key kZero);
#else
public:
- KeybindingWorker(Key, Key, WId) {}
- void run() {}
+ KeybindingWorker(Key, Key, Key, WId) {}
+ void run() {}
#endif
-signals:
- void center();
- void toggle();
};
+struct Shortcuts : public QObject {
+ Q_OBJECT
-struct Shortcuts {
+public:
using K =
#ifndef _WIN32
- ptr<QxtGlobalShortcut>
+ mem<QxtGlobalShortcut>
#else
Key
#endif
;
-
+
K keyCenter;
K keyToggle;
+ K keyZero;
WId handle;
#ifdef _WIN32
- ptr<KeybindingWorker> keybindingWorker;
+ mem<KeybindingWorker> keybindingWorker;
#endif
-
+
struct settings {
pbundle b;
- key_opts center, toggle;
+ key_opts center, toggle, zero;
+ main_settings s_main;
settings() :
b(bundle("keyboard-shortcuts")),
center(b, "center"),
- toggle(b, "toggle")
+ toggle(b, "toggle"),
+ zero(b, "zero")
{}
} s;
- Shortcuts(WId handle) : handle(handle)
- {
- reload();
- }
+ Shortcuts(WId handle) : handle(handle) { reload(); }
- void reload()
- {
-#ifndef _WIN32
- if (keyCenter)
- {
- keyCenter->setShortcut(QKeySequence::UnknownKey);
- keyCenter->setEnabled(false);
- }
- if (keyToggle)
- {
- keyToggle->setShortcut(QKeySequence::UnknownKey);
- keyToggle->setEnabled(false);
- }
-#endif
- bind_keyboard_shortcut(keyCenter, s.center);
- bind_keyboard_shortcut(keyToggle, s.toggle);
-#ifdef _WIN32
- keybindingWorker = nullptr;
- keybindingWorker = std::make_shared<KeybindingWorker>(keyCenter, keyToggle, handle);
- keybindingWorker->start();
-#endif
- }
+ void reload();
private:
void bind_keyboard_shortcut(K &key, key_opts& k);
-};
-
-class KeyboardShortcutDialog: public QWidget
-{
- Q_OBJECT
-public:
- KeyboardShortcutDialog();
-private:
- Ui::UICKeyboardShortcutDialog ui;
- Shortcuts::settings s;
- ptr<Shortcuts> sc;
signals:
- void reload();
-private slots:
- void doOK();
- void doCancel();
+ void center();
+ void toggle();
+ void zero();
};
+
+
diff --git a/opentrack/simple-mat.hpp b/opentrack/simple-mat.hpp
new file mode 100644
index 00000000..158cb30d
--- /dev/null
+++ b/opentrack/simple-mat.hpp
@@ -0,0 +1,155 @@
+#pragma once
+#include <initializer_list>
+
+template<typename num, int h, int w>
+struct Mat
+{
+ num data[h][w];
+
+ Mat<num, h, w> operator+(const Mat<num, h, w>& other) const
+ {
+ Mat<num, h, w> ret;
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret(j, i) = this->operator ()(j, i) + other(j, i);
+ return ret;
+ }
+
+ Mat<num, h, w> operator-(const Mat<num, h, w>& other) const
+ {
+ Mat<num, h, w> ret;
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret(j, i) = this->operator ()(j, i) - other(j, i);
+ return ret;
+ }
+
+ template<int p>
+ Mat<num, w, p> operator*(const Mat<num, w, p>& other) const
+ {
+ Mat<num, w, p> ret;
+ for (int j = 0; j < w; j++)
+ for (int i = 0; i < p; i++)
+ {
+ num sum = num(0);
+
+ for (int k = 0; k < h; k++)
+ sum += data[j][k]*other.data[k][i];
+
+ ret.data[j][i] = sum;
+ }
+
+ return ret;
+ }
+
+ num operator()(int j, int i) const { return data[j][i]; }
+ num& operator()(int j, int i) { return data[j][i]; }
+
+ Mat(std::initializer_list<num>&& list)
+ {
+ auto iter = list.begin();
+ for (int i = 0; i < h; i++)
+ for (int j = 0; j < w; j++)
+ data[i][j] = *iter++;
+ }
+
+ Mat()
+ {
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ data[j][i] = 0;
+ }
+
+ Mat(const num* mem)
+ {
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ data[j][i] = mem[i*h+j];
+ }
+
+ // XXX add more operators as needed, third-party dependencies mostly
+ // not needed merely for matrix algebra -sh 20141030
+
+ static Mat<num, h, h> eye()
+ {
+ Mat<num, h, h> ret;
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret.data[j][i] = 0;
+
+ for (int i = 0; i < h; i++)
+ ret.data[i][i] = 1;
+
+ return ret;
+ }
+
+ Mat<num, w, h> t() const
+ {
+ Mat<num, w, h> ret;
+
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret.data[i][j] = data[j][i];
+
+ return ret;
+ }
+
+ template<int h_, int w_> using dmat = Mat<double, h_, w_>;
+
+ // http://stackoverflow.com/a/18436193
+ static dmat<3, 1> rmat_to_euler(const dmat<3, 3>& R)
+ {
+ static constexpr double pi = 3.141592653;
+ const double up = 90 * pi / 180.;
+ static constexpr double bound = 1. - 2e-4;
+ if (R(0, 2) > bound)
+ {
+ double roll = atan(R(1, 0) / R(2, 0));
+ return dmat<3, 1>({0., up, roll});
+ }
+ if (R(0, 2) < -bound)
+ {
+ double roll = atan(R(1, 0) / R(2, 0));
+ return dmat<3, 1>({0., -up, roll});
+ }
+ double pitch = asin(-R(0, 2));
+ double roll = atan2(R(1, 2), R(2, 2));
+ double yaw = atan2(R(0, 1), R(0, 0));
+ return dmat<3, 1>({yaw, pitch, roll});
+ }
+
+ // tait-bryan angles, not euler
+ static dmat<3, 3> euler_to_rmat(const double* input)
+ {
+ static constexpr double pi = 3.141592653;
+ auto H = input[0] * pi / 180;
+ auto P = input[1] * pi / 180;
+ auto B = input[2] * pi / 180;
+
+ const auto c1 = cos(H);
+ const auto s1 = sin(H);
+ const auto c2 = cos(P);
+ const auto s2 = sin(P);
+ const auto c3 = cos(B);
+ const auto s3 = sin(B);
+
+ double foo[] = {
+ // z
+ c1 * c2,
+ c1 * s2 * s3 - c3 * s1,
+ s1 * s3 + c1 * c3 * s2,
+ // y
+ c2 * s1,
+ c1 * c3 + s1 * s2 * s3,
+ c3 * s1 * s2 - c1 * s3,
+ // x
+ -s2,
+ c2 * s3,
+ c2 * c3
+ };
+
+ return dmat<3, 3>(foo);
+ }
+};
+
+template<int h, int w> using dmat = Mat<double, h, w>;
diff --git a/opentrack/state.hpp b/opentrack/state.hpp
index 7fde64dc..2c37e5eb 100644
--- a/opentrack/state.hpp
+++ b/opentrack/state.hpp
@@ -12,18 +12,18 @@ struct Modules {
tracker_modules(filter(dylib::Tracker)),
protocol_modules(filter(dylib::Protocol))
{}
- QList<ptr<dylib>>& filters() { return filter_modules; }
- QList<ptr<dylib>>& trackers() { return tracker_modules; }
- QList<ptr<dylib>>& protocols() { return protocol_modules; }
+ QList<mem<dylib>>& filters() { return filter_modules; }
+ QList<mem<dylib>>& trackers() { return tracker_modules; }
+ QList<mem<dylib>>& protocols() { return protocol_modules; }
private:
- QList<ptr<dylib>> module_list;
- QList<ptr<dylib>> filter_modules;
- QList<ptr<dylib>> tracker_modules;
- QList<ptr<dylib>> protocol_modules;
+ QList<mem<dylib>> module_list;
+ QList<mem<dylib>> filter_modules;
+ QList<mem<dylib>> tracker_modules;
+ QList<mem<dylib>> protocol_modules;
- QList<ptr<dylib>> filter(dylib::Type t)
+ QList<mem<dylib>> filter(dylib::Type t)
{
- QList<ptr<dylib>> ret;
+ QList<mem<dylib>> ret;
for (auto x : module_list)
if (x->type == t)
ret.push_back(x);
@@ -35,14 +35,11 @@ struct Work;
struct State {
State() :
- b(bundle("opentrack-ui")),
- s(b),
pose(std::vector<axis_opts*>{&s.a_x, &s.a_y, &s.a_z, &s.a_yaw, &s.a_pitch, &s.a_roll})
{}
Modules modules;
SelectedLibraries libs;
- pbundle b;
main_settings s;
Mappings pose;
- ptr<Work> work;
+ mem<Work> work;
};
diff --git a/opentrack/timer.hpp b/opentrack/timer.hpp
index 628365c9..eb956213 100644
--- a/opentrack/timer.hpp
+++ b/opentrack/timer.hpp
@@ -2,6 +2,9 @@
#include <ctime>
#if defined (_WIN32)
# include <windows.h>
+# ifndef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC -1
+# endif
static inline void opentrack_clock_gettime(int, struct timespec* ts)
{
static LARGE_INTEGER freq;
@@ -50,12 +53,8 @@ public:
Timer() {
start();
}
- long start() {
- struct timespec cur;
- (void) clock_gettime(CLOCK_MONOTONIC, &cur);
- long ret = conv(cur);
- state = cur;
- return ret;
+ void start() {
+ (void) clock_gettime(CLOCK_MONOTONIC, &state);
}
long elapsed() {
struct timespec cur;
diff --git a/opentrack/tracker.cpp b/opentrack/tracker.cpp
index 8f1854e9..f70dd819 100644
--- a/opentrack/tracker.cpp
+++ b/opentrack/tracker.cpp
@@ -12,9 +12,8 @@
* originally written by Wim Vriend.
*/
-#include <opencv2/core/core.hpp>
-#include "./tracker.h"
+#include "tracker.h"
#include <cmath>
#include <algorithm>
@@ -25,10 +24,13 @@
Tracker::Tracker(main_settings& s, Mappings &m, SelectedLibraries &libs) :
s(s),
m(m),
- centerp(false),
+ centerp(s.center_at_startup),
enabledp(true),
+ zero_(false),
should_quit(false),
- libs(libs)
+ libs(libs),
+ r_b(dmat<3,3>::eye()),
+ t_b {0,0,0}
{
}
@@ -38,112 +40,145 @@ Tracker::~Tracker()
wait();
}
-double Tracker::map(double pos, Mapping& axis) {
+double Tracker::map(double pos, Mapping& axis)
+{
bool altp = (pos < 0) && axis.opts.altp;
axis.curve.setTrackingActive( !altp );
axis.curveAlt.setTrackingActive( altp );
auto& fc = altp ? axis.curveAlt : axis.curve;
- double invert = axis.opts.invert ? -1 : 1;
- return invert * (fc.getValue(pos) + axis.opts.zero);
-}
-
-static cv::Matx33d euler_to_rmat(const double* input)
-{
- static constexpr double pi = 3.141592653;
- const auto H = input[0] * pi / -180;
- const auto P = input[1] * pi / -180;
- const auto B = input[2] * pi / 180;
-
- const auto cosH = cos(H);
- const auto sinH = sin(H);
- const auto cosP = cos(P);
- const auto sinP = sin(P);
- const auto cosB = cos(B);
- const auto sinB = sin(B);
-
- double foo[] = {
- cosH * cosB - sinH * sinP * sinB,
- - sinB * cosP,
- sinH * cosB + cosH * sinP * sinB,
- cosH * sinB + sinH * sinP * cosB,
- cosB * cosP,
- sinB * sinH - cosH * sinP * cosB,
- - sinH * cosP,
- - sinP,
- cosH * cosP,
- };
-
- return cv::Matx33d(foo);
+ return fc.getValue(pos) + axis.opts.zero;
}
-void Tracker::t_compensate(const double* input, double* output, bool rz)
+void Tracker::t_compensate(const rmat& rmat, const double* xyz, double* output, bool rz)
{
- const cv::Matx33d rmat = euler_to_rmat(&input[Yaw]);
- const cv::Vec3d tvec(input);
- const cv::Vec3d ret = rmat * tvec;
-
- const int max = !rz ? 3 : 2;
-
- for (int i = 0; i < max; i++)
- output[i] = ret(i);
+ // TY is really yaw axis. need swapping accordingly.
+ dmat<3, 1> tvec({ xyz[2], -xyz[0], -xyz[1] });
+ const dmat<3, 1> ret = rmat * tvec;
+ if (!rz)
+ output[2] = ret(0, 0);
+ else
+ output[2] = xyz[2];
+ output[1] = -ret(2, 0);
+ output[0] = -ret(1, 0);
}
void Tracker::logic()
{
- libs.pTracker->data(newpose);
+ bool inverts[6] = {
+ m(0).opts.invert,
+ m(1).opts.invert,
+ m(2).opts.invert,
+ m(3).opts.invert,
+ m(4).opts.invert,
+ m(5).opts.invert,
+ };
- Pose final_raw_;
-
- if (enabledp)
- {
+ static constexpr double pi = 3.141592653;
+ static constexpr double r2d = 180. / pi;
+
+ Pose value, raw;
+
+ if (!zero_)
for (int i = 0; i < 6; i++)
{
- auto& axis = m(i);
- int k = axis.opts.src;
- if (k < 0 || k >= 6)
- {
- final_raw_(i) = 0;
- continue;
- }
- // not really raw, after axis remap -sh
- final_raw_(i) = newpose[k];
+ value(i) = newpose[i];
+ raw(i) = newpose[i];
+ }
+ else
+ {
+ auto mat = rmat::rmat_to_euler(r_b);
+
+ for (int i = 0; i < 3; i++)
+ {
+ raw(i+3) = value(i+3) = mat(i, 0) * r2d;
+ raw(i) = value(i) = t_b[i];
}
- final_raw = final_raw_;
}
+
+ const double off[] = {
+ s.camera_yaw,
+ s.camera_pitch,
+ 0.
+ };
+ const rmat cam = rmat::euler_to_rmat(off);
+ rmat r = rmat::euler_to_rmat(&value[Yaw]);
+ dmat<3, 1> t { value(0), value(1), value(2) };
- Pose filtered_pose;
+ r = cam * r;
+ t = cam * t;
- if (libs.pFilter)
- libs.pFilter->filter(final_raw, filtered_pose);
- else
- filtered_pose = final_raw;
+ bool can_center = false;
if (centerp)
{
+ for (int i = 0; i < 6; i++)
+ if (fabs(newpose[i]) != 0)
+ {
+ can_center = true;
+ break;
+ }
+ }
+
+ if (can_center)
+ {
centerp = false;
- raw_center = final_raw;
+ for (int i = 0; i < 3; i++)
+ t_b[i] = t(i, 0);
+ r_b = r;
}
- Pose raw_centered = filtered_pose & raw_center;
+ {
+ double tmp[3] = { t(0, 0) - t_b[0], t(1, 0) - t_b[1], t(2, 0) - t_b[2] };
+ t_compensate(cam, tmp, tmp, false);
+ const rmat m_ = r * r_b.t();
+ const dmat<3, 1> euler = rmat::rmat_to_euler(m_);
+ for (int i = 0; i < 3; i++)
+ {
+ value(i) = tmp[i];
+ value(i+3) = euler(i, 0) * r2d;
+ }
+ }
- Pose mapped_pose_precomp;
+ for (int i = 3; i < 6; i++)
+ value(i) = map(value(i), m(i));
- for (int i = 0; i < 6; i++)
- mapped_pose_precomp(i) = map(raw_centered(i), m(i));
+ {
+ Pose tmp = value;
+
+ if (libs.pFilter)
+ libs.pFilter->filter(tmp, value);
+ }
+
+ if (s.tcomp_p)
+ t_compensate(rmat::euler_to_rmat(&value[Yaw]),
+ value,
+ value,
+ s.tcomp_tz);
- Pose mapped_pose;
+ for (int i = 0; i < 3; i++)
+ value(i) = map(value(i), m(i));
- mapped_pose = mapped_pose_precomp;
- if (s.tcomp_p)
- t_compensate(mapped_pose_precomp, mapped_pose, s.tcomp_tz);
+ for (int i = 0; i < 6; i++)
+ value[i] *= inverts[i] ? -1. : 1.;
- libs.pProtocol->pose(mapped_pose);
+ Pose output_pose_;
+ for (int i = 0; i < 6; i++)
{
- QMutexLocker foo(&mtx);
- output_pose = mapped_pose;
- raw_6dof = final_raw;
+ auto& axis = m(i);
+ int k = axis.opts.src;
+ if (k < 0 || k >= 6)
+ output_pose_(i) = 0;
+ else
+ output_pose_(i) = value(k);
}
+
+
+ libs.pProtocol->pose(output_pose_);
+
+ QMutexLocker foo(&mtx);
+ output_pose = output_pose_;
+ raw_6dof = raw;
}
void Tracker::run() {
@@ -156,13 +191,28 @@ void Tracker::run() {
while (!should_quit)
{
t.start();
-
+
+ double tmp[6] {0,0,0, 0,0,0};
+ libs.pTracker->data(tmp);
+
+ if (enabledp)
+ for (int i = 0; i < 6; i++)
+ newpose[i] = tmp[i];
+
logic();
- double q = sleep_ms * 1000L;
- q -= t.elapsed();
- q = std::max(0., q);
- usleep((long)q);
+ long q = sleep_ms * 1000L - t.elapsed()/1000L;
+ usleep(std::max(1L, q));
+ }
+
+ {
+ // do one last pass with origin pose
+ for (int i = 0; i < 6; i++)
+ newpose[i] = 0;
+ logic();
+ // filter may inhibit exact origin
+ Pose p;
+ libs.pProtocol->pose(p);
}
#if defined(_WIN32)
diff --git a/opentrack/tracker.h b/opentrack/tracker.h
index 462f4e50..ace9fa3c 100644
--- a/opentrack/tracker.h
+++ b/opentrack/tracker.h
@@ -1,16 +1,16 @@
#pragma once
-#include <atomic>
#include <vector>
-#include "./timer.hpp"
-#include "./plugin-support.h"
-#include "./mappings.hpp"
-#include "./pose.hpp"
+#include "timer.hpp"
+#include "plugin-support.h"
+#include "mappings.hpp"
+#include "pose.hpp"
+#include "simple-mat.hpp"
#include "../qfunctionconfigurator/functionconfig.h"
-#include "./main-settings.hpp"
-#include "./options.hpp"
+#include "main-settings.hpp"
+#include "options.hpp"
#include <QMutex>
#include <QThread>
@@ -21,26 +21,35 @@ private:
QMutex mtx;
main_settings& s;
Mappings& m;
-
+
Timer t;
- Pose output_pose, raw_6dof, raw_center, final_raw;
+ Pose output_pose, raw_6dof;
+
double newpose[6];
- std::atomic<bool> centerp;
- std::atomic<bool> enabledp;
- std::atomic<bool> should_quit;
+ volatile bool centerp;
+ volatile bool enabledp;
+ volatile bool zero_;
+ volatile bool should_quit;
SelectedLibraries const& libs;
+
+ using rmat = dmat<3, 3>;
+ dmat<3, 3> r_b;
+ double t_b[3];
+
double map(double pos, Mapping& axis);
void logic();
-
- static void t_compensate(const double* input, double* output, bool rz);
+
+ void t_compensate(const dmat<3, 3>& rmat, const double* ypr, double* output, bool rz);
void run() override;
+
public:
Tracker(main_settings& s, Mappings& m, SelectedLibraries& libs);
~Tracker();
void get_raw_and_mapped_poses(double* mapped, double* raw) const;
void start() { QThread::start(); }
- void toggle_enabled() { enabledp.store(!enabledp.load()); }
- void center() { centerp.store(!centerp.load()); }
+ void toggle_enabled() { enabledp = !enabledp; }
+ void center() { centerp = !centerp; }
+ void zero() { zero_ = !zero_; }
};
diff --git a/opentrack/work.hpp b/opentrack/work.hpp
index d0130018..b93c71b6 100644
--- a/opentrack/work.hpp
+++ b/opentrack/work.hpp
@@ -13,10 +13,10 @@ struct Work
{
main_settings& s;
SelectedLibraries libs;
- ptr<Tracker> tracker;
- ptr<Shortcuts> sc;
+ mem<Tracker> tracker;
+ mem<Shortcuts> sc;
WId handle;
-
+
Work(main_settings& s, Mappings& m, SelectedLibraries& libs, QObject* recv, WId handle) :
s(s), libs(libs),
tracker(std::make_shared<Tracker>(s, m, libs)),
@@ -26,22 +26,24 @@ struct Work
#ifndef _WIN32
QObject::connect(sc->keyCenter.get(), SIGNAL(activated()), recv, SLOT(shortcutRecentered()));
QObject::connect(sc->keyToggle.get(), SIGNAL(activated()), recv, SLOT(shortcutToggled()));
+ QObject::connect(sc->keyZero.get(), SIGNAL(activated()), recv, SLOT(shortcutZeroed()));
#else
- QObject::connect(sc->keybindingWorker.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered()));
- QObject::connect(sc->keybindingWorker.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled()));
+ QObject::connect(sc.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered()));
+ QObject::connect(sc.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled()));
+ QObject::connect(sc.get(), SIGNAL(zero()), recv, SLOT(shortcutZeroed()));
#endif
tracker->start();
}
-
+
void reload_shortcuts()
{
sc->reload();
}
-
+
~Work()
{
// order matters, otherwise use-after-free -sh
tracker = nullptr;
libs = SelectedLibraries();
- }
+ }
};