summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt27
-rw-r--r--facetracknoir/ui.cpp2
-rw-r--r--ftnoir_protocol_sc/ftnoir_protocol_sc.h39
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.cpp152
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.h41
-rw-r--r--ftnoir_tracker_ht/ht-api.h6
-rw-r--r--ftnoir_tracker_ht/stdafx.h13
7 files changed, 163 insertions, 117 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c858587..b483000d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -153,8 +153,10 @@ SET(SDK_RIFT "" CACHE PATH "libOVR path for Oculus Rift")
set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Aruco paper marker tracker static library path")
+set(SDK_HT "" CACHE FILEPATH "Path to headtracker library")
+set(SDK_HT_FLANDMARK "" CACHE FILEPATH "Path to flandmark library for headtracker")
+
if(WIN32)
- set(SDK_SIMCONNECT "" CACHE PATH "SimConnect SDK path for MS FSX")
set(SDK_FSUIPC "" CACHE PATH "FSUIPC for older MS FSX path")
endif()
@@ -305,10 +307,8 @@ if(SDK_FSUIPC)
#target_link_directories(${SDK_FSUIPC})
endif()
-if(SDK_SIMCONNECT)
+if(WIN32)
opentrack_library(opentrack-proto-simconnect ftnoir_protocol_sc)
- target_link_libraries(opentrack-proto-simconnect ${SDK_SIMCONNECT}/lib/SimConnect.lib)
- include_directories(opentrack-proto-simconnect SYSTEM PUBLIC ${SDK_SIMCONNECT}/inc)
endif()
if(WIN32)
@@ -371,11 +371,13 @@ if(OpenCV_FOUND)
target_link_libraries(opentrack-filter-kalman ${OpenCV_LIBS})
target_include_directories(opentrack-filter-kalman SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS})
- opentrack_library(opentrack-tracker-ht ftnoir_tracker_ht)
- target_link_libraries(opentrack-tracker-ht opentrack-compat)
- link_with_dinput8(opentrack-tracker-ht)
- target_link_libraries(opentrack-tracker-ht ${OpenCV_LIBS})
- target_include_directories(opentrack-tracker-ht SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS})
+ if(SDK_HT AND SDK_HT_FLANDMARK)
+ opentrack_library(opentrack-tracker-ht ftnoir_tracker_ht)
+ target_link_libraries(opentrack-tracker-ht opentrack-compat ${SDK_HT} ${SDK_HT_FLANDMARK})
+ link_with_dinput8(opentrack-tracker-ht)
+ target_link_libraries(opentrack-tracker-ht ${OpenCV_LIBS})
+ target_include_directories(opentrack-tracker-ht SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS})
+ endif()
endif()
link_with_dinput8(opentrack-tracker-joystick)
@@ -491,8 +493,6 @@ if(NOT WIN32)
endif()
target_link_libraries(opentrack opentrack-api opentrack-version opentrack-pose-widget opentrack-spline-widget)
-
-
if(APPLE)
SET_TARGET_PROPERTIES(opentrack-qxt-mini PROPERTIES LINK_FLAGS "-framework Carbon -framework CoreFoundation")
endif()
@@ -520,11 +520,6 @@ if(SDK_XPLANE)
install(TARGETS opentrack-xplane-plugin RUNTIME DESTINATION . LIBRARY DESTINATION . )
endif()
-if(WIN32)
- install(DIRECTORY ${CMAKE_SOURCE_DIR}/bin/tracker-ht DESTINATION .)
- #install(TARGETS freetrackclient RUNTIME DESTINATION . LIBRARY DESTINATION . )
-endif()
-
install(DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty-notices DESTINATION .)
install(FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll" DESTINATION . ${opentrack-perms})
diff --git a/facetracknoir/ui.cpp b/facetracknoir/ui.cpp
index 7a412bdb..6afb3475 100644
--- a/facetracknoir/ui.cpp
+++ b/facetracknoir/ui.cpp
@@ -84,6 +84,8 @@ MainWindow::MainWindow() :
det_timer.start(1000);
ensure_tray();
+
+ set_working_directory();
}
MainWindow::~MainWindow()
diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.h b/ftnoir_protocol_sc/ftnoir_protocol_sc.h
index cbdee7de..034a8e09 100644
--- a/ftnoir_protocol_sc/ftnoir_protocol_sc.h
+++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.h
@@ -27,16 +27,7 @@
* must be treated as such... *
********************************************************************************/
#pragma once
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0502
#include "opentrack/plugin-api.hpp"
-//
-// Prevent the SimConnect manifest from being merged in the application-manifest
-// This is necessary to run FaceTrackNoIR on a PC without FSX
-//
-#define SIMCONNECT_H_NOMANIFEST
-#include <windows.h>
-#include <SimConnect.h>
#include "ui_ftnoir_sccontrols.h"
#include <QThread>
@@ -48,12 +39,7 @@
#include <QFile>
#include "opentrack/options.hpp"
using namespace options;
-
-typedef HRESULT (WINAPI *importSimConnect_Open)(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex);
-typedef HRESULT (WINAPI *importSimConnect_Close)(HANDLE hSimConnect);
-typedef HRESULT (WINAPI *importSimConnect_CameraSetRelative6DOF)(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg);
-typedef HRESULT (WINAPI *importSimConnect_CallDispatch)(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext);
-typedef HRESULT (WINAPI *importSimConnect_SubscribeToSystemEvent)(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName);
+#include <windows.h>
struct settings : opts {
value<int> sxs_manifest;
@@ -75,6 +61,25 @@ public:
return "FS2004/FSX";
}
private:
+ enum { SIMCONNECT_RECV_ID_EVENT_FRAME = 7 };
+
+ #pragma pack(push, 1)
+ struct SIMCONNECT_RECV
+ {
+ DWORD dwSize;
+ DWORD dwVersion;
+ DWORD dwID;
+ };
+ #pragma pack(pop)
+
+ typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV*, DWORD, void*);
+
+ typedef HRESULT (WINAPI *importSimConnect_Open)(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex);
+ typedef HRESULT (WINAPI *importSimConnect_Close)(HANDLE hSimConnect);
+ typedef HRESULT (WINAPI *importSimConnect_CameraSetRelative6DOF)(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg);
+ typedef HRESULT (WINAPI *importSimConnect_CallDispatch)(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext);
+ typedef HRESULT (WINAPI *importSimConnect_SubscribeToSystemEvent)(HANDLE hSimConnect, DWORD EventID, const char * SystemEventName);
+
void run() override;
volatile bool should_stop;
@@ -85,13 +90,13 @@ private:
volatile float virtSCRotY;
volatile float virtSCRotZ;
- importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL
+ importSimConnect_Open simconnect_open;
importSimConnect_Close simconnect_close;
importSimConnect_CameraSetRelative6DOF simconnect_set6DOF;
importSimConnect_CallDispatch simconnect_calldispatch;
importSimConnect_SubscribeToSystemEvent simconnect_subscribetosystemevent;
- HANDLE hSimConnect; // Handle to SimConnect
+ HANDLE hSimConnect;
static void CALLBACK processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext);
settings s;
QLibrary SCClientLib;
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
index 3d142dcb..deb90ee5 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
@@ -44,49 +44,49 @@ void Tracker::load_settings(ht_config_t* config)
config->classification_delay = 500;
config->field_of_view = s.fov;
- config->pyrlk_pyramids = 0;
- config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
config->max_keypoints = 150;
- config->keypoint_distance = 3.5;
+ config->keypoint_distance = 3.4;
config->force_fps = nframes;
config->camera_index = camera_name_to_index(s.camera_name);
- config->ransac_num_iters = 100;
- config->ransac_max_reprojection_error = 10;
- config->ransac_max_inlier_error = 10;
- config->ransac_abs_max_mean_error = 14;
- config->ransac_max_mean_error = 8;
+
+ config->ransac_max_reprojection_error = 8;
+ config->ransac_max_inlier_error = 8;
+
+ config->pyrlk_pyramids = 0;
+ config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
+
+ config->ransac_max_mean_error = 999;
+ config->ransac_abs_max_mean_error = 999;
+
config->debug = 0;
- config->ransac_min_features = 0.8;
+ config->ransac_min_features = 0.85;
+ config->ransac_num_iters = 300;
+
int res = s.resolution;
if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
res = 0;
resolution_tuple r = resolution_choices[res];
config->force_width = r.width;
config->force_height = r.height;
- config->flandmark_delay = 500;
+ config->flandmark_delay = 50;
for (int i = 0; i < 5; i++)
config->dist_coeffs[i] = 0;
}
Tracker::Tracker() :
- lck_shm(HT_SHM_NAME, HT_MUTEX_NAME, sizeof(ht_shm_t)),
- shm(reinterpret_cast<ht_shm_t*>(lck_shm.ptr())),
+ ht(nullptr),
+ ypr {0,0,0, 0,0,0},
videoWidget(nullptr),
- layout(nullptr)
+ layout(nullptr),
+ should_stop(false)
{
- shm->terminate = 0;
- shm->result.filled = false;
}
Tracker::~Tracker()
{
- if (shm) {
- shm->terminate = true;
- subprocess.waitForFinished(5000);
- }
- subprocess.kill();
- if (shm)
- shm->terminate = true;
+ should_stop = true;
+ wait();
+ ht_free_context(ht);
if (layout)
delete layout;
if (videoWidget)
@@ -105,41 +105,81 @@ void Tracker::start_tracker(QFrame* videoframe)
videoframe->setLayout(layout);
videoWidget->show();
this->layout = layout;
- load_settings(&shm->config);
- shm->frame.channels = shm->frame.width = shm->frame.height = 0;
- shm->pause = shm->terminate = shm->running = false;
- shm->timer = 0;
- shm->result.filled = false;
- subprocess.setProcessChannelMode(QProcess::ForwardedChannels);
- subprocess.setWorkingDirectory(QCoreApplication::applicationDirPath() + "/tracker-ht");
-#if defined(_WIN32)
- subprocess.start("\"" + QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir" + "\"");
-#else
- subprocess.start(QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir");
-#endif
+
+ load_settings(&conf);
+ ht = ht_make_context(&conf, nullptr);
+ start();
+}
+
+void Tracker::run()
+{
+ while (!should_stop)
+ {
+ ht_result_t euler;
+ euler.filled = false;
+ {
+ QMutexLocker l(&camera_mtx);
+
+ if (!ht_cycle(ht, &euler))
+ break;
+ }
+ if (euler.filled)
+ {
+ QMutexLocker l(&ypr_mtx);
+ ypr[TX] = euler.tx;
+ ypr[TY] = euler.ty;
+ ypr[TZ] = euler.tz;
+ ypr[Yaw] = euler.rotx;
+ ypr[Pitch] = euler.roty;
+ ypr[Roll] = euler.rotz;
+ }
+ {
+ const cv::Mat frame_ = ht_get_bgr_frame(ht);
+ if (frame_.cols <= HT_MAX_VIDEO_WIDTH && frame_.rows <= HT_MAX_VIDEO_HEIGHT && frame_.channels() <= HT_MAX_VIDEO_CHANNELS)
+ {
+ QMutexLocker l(&frame_mtx);
+
+ const int cols = frame_.cols;
+ const int rows = frame_.rows;
+ const int pitch = cols * 3;
+ for (int y = 0; y < rows; y++)
+ {
+ for (int x = 0; x < cols; x++)
+ {
+ unsigned char* dest = &frame.frame[y * pitch + 3 * x];
+ const cv::Vec3b& elt = frame_.at<cv::Vec3b>(y, x);
+ const cv::Scalar elt2 = static_cast<cv::Scalar>(elt);
+ dest[0] = elt2.val[0];
+ dest[1] = elt2.val[1];
+ dest[2] = elt2.val[2];
+ }
+ }
+ frame.channels = frame_.channels();
+ frame.width = frame_.cols;
+ frame.height = frame_.rows;
+ }
+ }
+ }
}
-void Tracker::data(double *data)
+void Tracker::data(double* data)
{
- lck_shm.lock();
- shm->timer = 0;
- if (shm->frame.width > 0)
{
- videoWidget->update_image(shm->frame.frame, shm->frame.width, shm->frame.height);
- //memcpy(foo, shm->frame.frame, shm->frame.width * shm->frame.height * 3);
- shm->frame.width = 0;
+ QMutexLocker l(&frame_mtx);
+
+ if (frame.width > 0)
+ {
+ videoWidget->update_image(frame.frame, frame.width, frame.height);
+ frame.width = 0;
+ }
}
- if (shm->result.filled) {
- data[Yaw] = shm->result.rotx;
- data[Pitch] = shm->result.roty;
- data[Roll] = shm->result.rotz;
- data[TX] = shm->result.tx;
- data[TY] = shm->result.ty;
- data[TZ] = shm->result.tz;
- } else {
- shm->pause = false;
+
+ {
+ QMutexLocker l(&ypr_mtx);
+
+ for (int i = 0; i < 6; i++)
+ data[i] = ypr[i];
}
- lck_shm.unlock();
}
extern "C" OPENTRACK_EXPORT Metadata* GetMetadata()
@@ -157,7 +197,7 @@ extern "C" OPENTRACK_EXPORT ITrackerDialog* GetDialog( )
return new TrackerControls;
}
-TrackerControls::TrackerControls()
+TrackerControls::TrackerControls() : tracker(nullptr)
{
ui.setupUi(this);
ui.cameraName->clear();
@@ -187,5 +227,11 @@ void TrackerControls::doCancel()
void TrackerControls::camera_settings()
{
- open_camera_settings(nullptr, s.camera_name, nullptr);
+ if (tracker)
+ {
+ cv::VideoCapture* cap = ht_capture(tracker->ht);
+ open_camera_settings(cap, s.camera_name, &tracker->camera_mtx);
+ }
+ else
+ open_camera_settings(nullptr, s.camera_name, nullptr);
}
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.h b/ftnoir_tracker_ht/ftnoir_tracker_ht.h
index 348fc246..b2fcb147 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.h
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.h
@@ -5,10 +5,8 @@
* copyright notice and this permission notice appear in all copies.
*/
-#ifndef FTNOIR_TRACKER_HT_H
-#define FTNOIR_TRACKER_HT_H
+#pragma once
-#include "stdafx.h"
#include "headtracker-ftnoir.h"
#include "ui_ht-trackercontrols.h"
#include "ht_video_widget.h"
@@ -18,6 +16,12 @@
#include "opentrack/plugin-api.hpp"
#include "opentrack/opencv-camera-dialog.hpp"
+#include <QThread>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QHBoxLayout>
+#include <QString>
+
using namespace options;
struct settings : opts {
@@ -33,42 +37,47 @@ struct settings : opts {
{}
};
-class Tracker : public QObject, public ITracker
+class Tracker : public QThread, public ITracker
{
Q_OBJECT
public:
Tracker();
~Tracker() override;
+ void run() override;
void start_tracker(QFrame* frame);
void data(double *data);
void load_settings(ht_config_t* config);
+ headtracker_t* ht;
+ QMutex camera_mtx;
private:
+ double ypr[6];
settings s;
- PortableLockedShm lck_shm;
- ht_shm_t* shm;
- QProcess subprocess;
+ ht_config_t conf;
HTVideoWidget* videoWidget;
QHBoxLayout* layout;
+ QMutex ypr_mtx, frame_mtx;
+ ht_video_t frame;
+ volatile bool should_stop;
};
-// Widget that has controls for FTNoIR protocol client-settings.
class TrackerControls : public ITrackerDialog, protected camera_dialog<Tracker>
{
Q_OBJECT
public:
- explicit TrackerControls();
- void register_tracker(ITracker *) {}
- void unregister_tracker() {}
-
+ TrackerControls();
+ void register_tracker(ITracker * t)
+ {
+ tracker = static_cast<Tracker*>(t);
+ }
+ void unregister_tracker() {
+ tracker = nullptr;
+ }
private:
Ui::Form ui;
settings s;
-
+ Tracker* tracker;
private slots:
void doOK();
void doCancel();
void camera_settings();
};
-
-#endif
-
diff --git a/ftnoir_tracker_ht/ht-api.h b/ftnoir_tracker_ht/ht-api.h
index 4f88a6a3..4629a00b 100644
--- a/ftnoir_tracker_ht/ht-api.h
+++ b/ftnoir_tracker_ht/ht-api.h
@@ -9,7 +9,8 @@
#if !defined(_WIN32) && !defined(_isnan)
# define _isnan isnan
#endif
-//#include <opencv2/core.hpp>
+#include <opencv2/core.hpp>
+#include <opencv2/highgui.hpp>
struct ht_context;
typedef struct ht_context headtracker_t;
@@ -44,6 +45,7 @@ typedef struct {
HT_API(headtracker_t*) ht_make_context(const ht_config_t* config, const char* filename);
HT_API(void) ht_free_context(headtracker_t* ctx);
-//HT_API(const cv::Mat) ht_get_bgr_frame(headtracker_t* ctx);
+HT_API(const cv::Mat) ht_get_bgr_frame(headtracker_t* ctx);
HT_API(bool) ht_cycle(headtracker_t* ctx, ht_result_t* euler);
HT_API(void) ht_reset(headtracker_t* ctx);
+HT_API(cv::VideoCapture*) ht_capture(headtracker_t* ctx);
diff --git a/ftnoir_tracker_ht/stdafx.h b/ftnoir_tracker_ht/stdafx.h
index 6f1539b7..e69de29b 100644
--- a/ftnoir_tracker_ht/stdafx.h
+++ b/ftnoir_tracker_ht/stdafx.h
@@ -1,13 +0,0 @@
-#include <QWidget>
-#include <QMessageBox>
-#include <QProcess>
-#include <QImage>
-#include <QLabel>
-#include <QCoreApplication>
-#include <QIcon>
-#include <QHBoxLayout>
-#include <QTimer>
-#include <QPainter>
-#include <QPaintEvent>
-#include <QList>
-#include <QString>