From 10c826c917707025c709bca237709f77ecbea6c7 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 29 Oct 2015 11:27:07 +0100 Subject: rift 025: fix name --- ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h b/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h index 717cbe84..2bd5024b 100644 --- a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h +++ b/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h @@ -57,7 +57,7 @@ private slots: class FTNoIR_TrackerDll : public Metadata { public: - QString name() { return QString("Oculus Rift DK1 -- HMD"); } + QString name() { return QString("Oculus Rift runtime 0.2.5 -- HMD"); } QIcon icon() { return QIcon(":/images/rift_tiny.png"); } }; -- cgit v1.2.3 From 28a39e38963dd85db1a8eda3edffbeb302ef4d3d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 29 Oct 2015 12:40:45 +0100 Subject: rift-080: forgot ovr_Initialize() --- .../ftnoir_tracker_rift_080.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp b/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp index 5495e0e3..889ac8c3 100644 --- a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp +++ b/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp @@ -21,18 +21,24 @@ Rift_Tracker::~Rift_Tracker() void Rift_Tracker::start_tracker(QFrame*) { - ovrGraphicsLuid luid; - ovrResult result = ovr_Create(&hmd, &luid); - if (OVR_SUCCESS(result)) { - ovr_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation); + ovrInitParams args = {0}; + if (!OVR_SUCCESS(ovr_Initialize(&args))) + goto error; } - else { - // XXX need change ITracker et al api to allow for failure reporting - // this qmessagebox doesn't give any relevant details either -sh 20141012 - QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); + ovrGraphicsLuid luid = {0}; + ovrResult res = ovr_Create(&hmd, &luid); + if (OVR_SUCCESS(res)) + { + ovr_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation); + } + else + goto error; } + return; +error: + QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); } void Rift_Tracker::data(double *data) -- cgit v1.2.3 From d6a54431d178632a2bf466c9904f74abd143afe6 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 30 Oct 2015 05:16:02 +0100 Subject: cmake: switch to GNU CC 5.2.0 in mingw-w64 toolchain file --- cmake/mingw-w64.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/mingw-w64.cmake b/cmake/mingw-w64.cmake index 8604dafb..02ab66cb 100644 --- a/cmake/mingw-w64.cmake +++ b/cmake/mingw-w64.cmake @@ -7,7 +7,7 @@ SET(CMAKE_SYSTEM_NAME Windows) SET(CMAKE_SYSTEM_VERSION 1) # specify the cross compiler -set(c /c/mingw-w64/i686-4.9.2-posix-sjlj-rt_v4-rev4/mingw32/bin/i686-w64-mingw32-) +set(c /c/mingw-w64/i686-5.2.0-posix-sjlj-rt_v4-rev0/mingw32/bin/i686-w64-mingw32-) SET(CMAKE_C_COMPILER ${c}gcc) SET(CMAKE_CXX_COMPILER ${c}g++) -- cgit v1.2.3 From aa066bdd4622d4f6824fee864f6be6806813f04d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 30 Oct 2015 07:37:41 +0100 Subject: move to subdirectory-based build system Closes #224 --- CMakeLists.txt | 636 +--------- bin/settings/facetracknoir supported games.csv | 576 --------- cmake/opentrack-install.cmake | 27 + cmake/opentrack-macros.cmake | 79 ++ cmake/opentrack-platform.cmake | 60 + cmake/opentrack-policy.cmake | 10 + cmake/opentrack-qt.cmake | 5 + cmake/opentrack-rift.cmake | 37 + cmake/opentrack-tarball.cmake | 23 + cmake/opentrack-version.cmake | 33 + csv/CMakeLists.txt | 4 + facetracknoir/CMakeLists.txt | 62 + facetracknoir/main.ui | 2 +- facetracknoir/mapping.ui | 2 +- filter-accela/CMakeLists.txt | 2 + filter-accela/ftnoir_accela_filtercontrols.ui | 300 +++++ filter-accela/ftnoir_filter_accela.cpp | 108 ++ filter-accela/ftnoir_filter_accela.h | 79 ++ filter-accela/ftnoir_filter_accela_dialog.cpp | 105 ++ filter-ewma2/CMakeLists.txt | 1 + filter-ewma2/ftnoir_ewma_filtercontrols.ui | 372 ++++++ filter-ewma2/ftnoir_filter_ewma2.cpp | 81 ++ filter-ewma2/ftnoir_filter_ewma2.h | 66 ++ filter-ewma2/ftnoir_filter_ewma2_dialog.cpp | 43 + filter-kalman/CMakeLists.txt | 4 + filter-kalman/ftnoir_filter_kalman.h | 73 ++ filter-kalman/ftnoir_kalman_filtercontrols.ui | 116 ++ filter-kalman/kalman.cpp | 129 ++ .../ftnoir_accela_filtercontrols.ui | 300 ----- ftnoir_filter_accela/ftnoir_filter_accela.cpp | 108 -- ftnoir_filter_accela/ftnoir_filter_accela.h | 79 -- .../ftnoir_filter_accela_dialog.cpp | 105 -- ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui | 372 ------ ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp | 81 -- ftnoir_filter_ewma2/ftnoir_filter_ewma2.h | 66 -- ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp | 43 - ftnoir_filter_kalman/ftnoir_filter_kalman.h | 73 -- .../ftnoir_kalman_filtercontrols.ui | 116 -- ftnoir_filter_kalman/kalman.cpp | 129 -- ftnoir_protocol_fg/fg-protocol.qrc | 5 - ftnoir_protocol_fg/fgtypes.h | 27 - ftnoir_protocol_fg/ftnoir_fgcontrols.ui | 143 --- ftnoir_protocol_fg/ftnoir_protocol_fg.cpp | 38 - ftnoir_protocol_fg/ftnoir_protocol_fg.h | 69 -- ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp | 46 - ftnoir_protocol_fg/images/flightgear.png | Bin 979 -> 0 bytes ftnoir_protocol_fsuipc/fsuipc-protocol.qrc | 5 - ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui | 134 --- ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp | 149 --- ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h | 90 -- .../ftnoir_protocol_fsuipc_dialog.cpp | 43 - ftnoir_protocol_fsuipc/images/fs9.png | Bin 758 -> 0 bytes ftnoir_protocol_fsuipc/images/fs91.png | Bin 1644 -> 0 bytes ftnoir_protocol_ft/ft-protocol.qrc | 5 - ftnoir_protocol_ft/ftnoir_ftcontrols.ui | 182 --- ftnoir_protocol_ft/ftnoir_protocol_ft.cpp | 166 --- ftnoir_protocol_ft/ftnoir_protocol_ft.h | 90 -- ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp | 60 - ftnoir_protocol_ft/images/freetrack.png | Bin 1773 -> 0 bytes ftnoir_protocol_ftn/ftnoir_ftncontrols.ui | 266 ----- ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp | 34 - ftnoir_protocol_ftn/ftnoir_protocol_ftn.h | 69 -- ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp | 42 - .../ftnoir_libevdev_controls.ui | 111 -- .../ftnoir_protocol_libevdev.cpp | 97 -- .../ftnoir_protocol_libevdev.h | 57 - .../ftnoir_protocol_libevdev_dialog.cpp | 21 - ftnoir_protocol_libevdev/images/linux.png | Bin 668 -> 0 bytes ftnoir_protocol_libevdev/libevdev-protocol.qrc | 5 - ftnoir_protocol_mouse/ftnoir_mousecontrols.ui | 188 --- ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp | 54 - ftnoir_protocol_mouse/ftnoir_protocol_mouse.h | 59 - .../ftnoir_protocol_mouse_dialog.cpp | 24 - ftnoir_protocol_mouse/images/mouse.png | Bin 1169 -> 0 bytes ftnoir_protocol_mouse/win32-mouse-protocol.qrc | 5 - ftnoir_protocol_sc/ftnoir-protocol-sc.rc | 4 - ftnoir_protocol_sc/ftnoir_protocol_sc.cpp | 189 --- ftnoir_protocol_sc/ftnoir_protocol_sc.h | 108 -- ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp | 35 - ftnoir_protocol_sc/ftnoir_sccontrols.ui | 72 -- ftnoir_protocol_sc/images/fsx.png | Bin 813 -> 0 bytes ftnoir_protocol_sc/images/fsx1.png | Bin 1920 -> 0 bytes ftnoir_protocol_sc/sc-protocol.qrc | 5 - ftnoir_protocol_sc/scserver.manifest | 13 - ftnoir_protocol_sc/scserver_acceleration.manifest | 13 - ftnoir_protocol_sc/scserver_sp2.manifest | 13 - ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp | 33 - ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h | 91 -- .../ftnoir_protocol_vjoy_dialog.cpp | 22 - ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui | 113 -- ftnoir_protocol_vjoy/images/vjoy.png | Bin 694 -> 0 bytes ftnoir_protocol_vjoy/vjoy-protocol.qrc | 5 - ftnoir_protocol_vjoy/vjoy.def | 5 - ftnoir_protocol_wine/ftnoir_protocol_wine.cpp | 59 - ftnoir_protocol_wine/ftnoir_protocol_wine.h | 57 - .../ftnoir_protocol_wine_dialog.cpp | 19 - ftnoir_protocol_wine/ftnoir_winecontrols.ui | 170 --- ftnoir_protocol_wine/images/wine.png | Bin 376 -> 0 bytes .../opentrack-wrapper-wine-main.cxx | 80 -- .../opentrack-wrapper-wine-posix.cxx | 7 - .../opentrack-wrapper-wine-windows.cxx | 40 - ftnoir_protocol_wine/wine-protocol.qrc | 5 - ftnoir_protocol_wine/wine-shm.h | 20 - ftnoir_tracker_aruco/ar_video_widget.cpp | 67 -- ftnoir_tracker_aruco/ar_video_widget.h | 33 - ftnoir_tracker_aruco/aruco-tracker.qrc | 5 - ftnoir_tracker_aruco/aruco-trackercontrols.ui | 281 ----- ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp | 444 ------- ftnoir_tracker_aruco/ftnoir_tracker_aruco.h | 99 -- ftnoir_tracker_aruco/images/aruco.png | Bin 987 -> 0 bytes ftnoir_tracker_aruco/include/aruco.h | 134 --- ftnoir_tracker_aruco/include/arucofidmarkers.h | 119 -- ftnoir_tracker_aruco/include/board.h | 168 --- ftnoir_tracker_aruco/include/boarddetector.h | 138 --- ftnoir_tracker_aruco/include/cameraparameters.h | 138 --- ftnoir_tracker_aruco/include/cvdrawingutils.h | 52 - ftnoir_tracker_aruco/include/exports.h | 46 - ftnoir_tracker_aruco/include/marker.h | 143 --- ftnoir_tracker_aruco/include/markerdetector.h | 359 ------ ftnoir_tracker_aruco/trans_calib.cpp | 41 - ftnoir_tracker_aruco/trans_calib.h | 39 - ftnoir_tracker_freepie-udp/freepie-udp-controls.ui | 285 ----- ftnoir_tracker_freepie-udp/freepie-udp-res.qrc | 5 - .../ftnoir_tracker_freepie-udp.cpp | 119 -- .../ftnoir_tracker_freepie-udp.h | 69 -- .../ftnoir_tracker_freepie-udp_dialog.cpp | 30 - ftnoir_tracker_freepie-udp/glovepie.png | Bin 3584 -> 0 bytes ftnoir_tracker_hatire/ftnoir_arduino_type.h | 32 - ftnoir_tracker_hatire/ftnoir_hat.qrc | 7 - ftnoir_tracker_hatire/ftnoir_hatcontrols.ui | 1253 -------------------- ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp | 597 ---------- ftnoir_tracker_hatire/ftnoir_tracker_hat.h | 157 --- .../ftnoir_tracker_hat_dialog.cpp | 411 ------- ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h | 116 -- .../ftnoir_tracker_hat_settings.cpp | 146 --- .../ftnoir_tracker_hat_settings.h | 68 -- ftnoir_tracker_hatire/images/hat.ico | Bin 1150 -> 0 bytes ftnoir_tracker_hatire/images/hat.png | Bin 249 -> 0 bytes ftnoir_tracker_hatire/images/hat_logo.png | Bin 15210 -> 0 bytes ftnoir_tracker_ht/ftnoir_tracker_ht.cpp | 225 ---- ftnoir_tracker_ht/ftnoir_tracker_ht.h | 90 -- ftnoir_tracker_ht/headtracker-ftnoir.h | 24 - ftnoir_tracker_ht/ht-api.h | 51 - ftnoir_tracker_ht/ht-tracker.qrc | 5 - ftnoir_tracker_ht/ht-trackercontrols.ui | 157 --- ftnoir_tracker_ht/ht_video_widget.cpp | 53 - ftnoir_tracker_ht/ht_video_widget.h | 39 - ftnoir_tracker_ht/images/ht.png | Bin 2010 -> 0 bytes .../ftnoir_hydra_clientcontrols.ui | 53 - ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp | 46 - ftnoir_tracker_hydra/ftnoir_tracker_hydra.h | 46 - .../ftnoir_tracker_hydra_dialog.cpp | 22 - .../ftnoir_tracker_joystick.cpp | 253 ---- ftnoir_tracker_joystick/ftnoir_tracker_joystick.h | 106 -- .../ftnoir_tracker_joystick_controls.ui | 492 -------- .../ftnoir_tracker_joystick_dialog.cpp | 69 -- ftnoir_tracker_pt/FTNoIR_PT_Controls.ui | 1220 ------------------- ftnoir_tracker_pt/Resources/Logo_IR.png | Bin 10386 -> 0 bytes ftnoir_tracker_pt/Resources/cap_front.png | Bin 1164 -> 0 bytes ftnoir_tracker_pt/Resources/cap_side.png | Bin 1733 -> 0 bytes ftnoir_tracker_pt/Resources/clip_front.png | Bin 571 -> 0 bytes ftnoir_tracker_pt/Resources/clip_side.png | Bin 2677 -> 0 bytes ftnoir_tracker_pt/camera.cpp | 145 --- ftnoir_tracker_pt/camera.h | 95 -- ftnoir_tracker_pt/doc/index.htm | 262 ---- ftnoir_tracker_pt/doc/logo.png | Bin 10386 -> 0 bytes ftnoir_tracker_pt/doc/ptrack.ico | Bin 4286 -> 0 bytes ftnoir_tracker_pt/doc/settings1.png | Bin 25013 -> 0 bytes ftnoir_tracker_pt/doc/settings2.png | Bin 26841 -> 0 bytes ftnoir_tracker_pt/doc/settings3.png | Bin 29547 -> 0 bytes ftnoir_tracker_pt/doc/style.css | 131 -- ftnoir_tracker_pt/ftnoir_tracker_pt.cpp | 219 ---- ftnoir_tracker_pt/ftnoir_tracker_pt.h | 86 -- ftnoir_tracker_pt/ftnoir_tracker_pt.qrc | 9 - ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp | 182 --- ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h | 51 - ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h | 71 -- ftnoir_tracker_pt/point_extractor.cpp | 180 --- ftnoir_tracker_pt/point_extractor.h | 33 - ftnoir_tracker_pt/point_tracker.cpp | 267 ----- ftnoir_tracker_pt/point_tracker.h | 147 --- ftnoir_tracker_pt/pt_video_widget.cpp | 55 - ftnoir_tracker_pt/pt_video_widget.h | 47 - ftnoir_tracker_pt/trans_calib.cpp | 41 - ftnoir_tracker_pt/trans_calib.h | 39 - ftnoir_tracker_rift_025/ftnoir_rift_025.qrc | 7 - .../ftnoir_rift_clientcontrols_025.ui | 176 --- .../ftnoir_tracker_rift_025.cpp | 92 -- ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h | 63 - .../ftnoir_tracker_rift_dialog_025.cpp | 26 - ftnoir_tracker_rift_025/images/medium.png | Bin 5764 -> 0 bytes ftnoir_tracker_rift_025/images/rift_medium.png | Bin 5764 -> 0 bytes ftnoir_tracker_rift_025/images/rift_small.png | Bin 1212 -> 0 bytes ftnoir_tracker_rift_025/images/rift_tiny.png | Bin 624 -> 0 bytes ftnoir_tracker_rift_025/images/small.png | Bin 1212 -> 0 bytes ftnoir_tracker_rift_025/images/tiny.png | Bin 624 -> 0 bytes ftnoir_tracker_rift_042/ftnoir_rift_042.qrc | 7 - .../ftnoir_rift_clientcontrols_042.ui | 176 --- .../ftnoir_tracker_rift_042.cpp | 71 -- ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.h | 60 - .../ftnoir_tracker_rift_dialog_042.cpp | 26 - ftnoir_tracker_rift_042/images/medium.png | Bin 5764 -> 0 bytes ftnoir_tracker_rift_042/images/rift_medium.png | Bin 5764 -> 0 bytes ftnoir_tracker_rift_042/images/rift_small.png | Bin 1212 -> 0 bytes ftnoir_tracker_rift_042/images/rift_tiny.png | Bin 624 -> 0 bytes ftnoir_tracker_rift_042/images/small.png | Bin 1212 -> 0 bytes ftnoir_tracker_rift_042/images/tiny.png | Bin 624 -> 0 bytes ftnoir_tracker_rift_080/ftnoir_rift_080.qrc | 7 - .../ftnoir_rift_clientcontrols_080.ui | 176 --- .../ftnoir_tracker_rift_080.cpp | 75 -- ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.h | 60 - .../ftnoir_tracker_rift_dialog_080.cpp | 26 - ftnoir_tracker_rift_080/images/medium.png | Bin 5764 -> 0 bytes ftnoir_tracker_rift_080/images/rift_medium.png | Bin 5764 -> 0 bytes ftnoir_tracker_rift_080/images/rift_small.png | Bin 1212 -> 0 bytes ftnoir_tracker_rift_080/images/rift_tiny.png | Bin 624 -> 0 bytes ftnoir_tracker_rift_080/images/small.png | Bin 1212 -> 0 bytes ftnoir_tracker_rift_080/images/tiny.png | Bin 624 -> 0 bytes ftnoir_tracker_rs/README.md | 16 - ftnoir_tracker_rs/ftnoir_tracker_rs.cpp | 111 -- ftnoir_tracker_rs/ftnoir_tracker_rs.h | 46 - ftnoir_tracker_rs/ftnoir_tracker_rs_controls.cpp | 40 - ftnoir_tracker_rs/ftnoir_tracker_rs_controls.h | 23 - ftnoir_tracker_rs/ftnoir_tracker_rs_controls.ui | 67 -- ftnoir_tracker_rs/images/RS.png | Bin 4770 -> 0 bytes ftnoir_tracker_rs/images/intel-16x16.png | Bin 637 -> 0 bytes .../intel_rs_sdk_runtime_websetup_6.0.21.6598.exe | Bin 780456 -> 0 bytes .../rs_impl/bin/opentrack-tracker-rs-impl.exe | Bin 83968 -> 0 bytes ftnoir_tracker_rs/rs_impl/build.bat | 2 - .../rs_impl/ftnoir_tracker_rs_impl.cpp | 151 --- ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.h | 19 - ftnoir_tracker_rs/rs_impl/udp_sender.cpp | 53 - ftnoir_tracker_rs/rs_tracker.qrc | 6 - ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui | 208 ---- ftnoir_tracker_udp/ftnoir_tracker_udp.cpp | 70 -- ftnoir_tracker_udp/ftnoir_tracker_udp.h | 60 - ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp | 26 - opentrack-compat/CMakeLists.txt | 4 + opentrack/CMakeLists.txt | 10 + opentrack/mappings.hpp | 2 +- opentrack/tracker.h | 2 +- pose-widget/CMakeLists.txt | 6 + protocol-fg/CMakeLists.txt | 1 + protocol-fg/fg-protocol.qrc | 5 + protocol-fg/fgtypes.h | 27 + protocol-fg/ftnoir_fgcontrols.ui | 143 +++ protocol-fg/ftnoir_protocol_fg.cpp | 38 + protocol-fg/ftnoir_protocol_fg.h | 69 ++ protocol-fg/ftnoir_protocol_fg_dialog.cpp | 46 + protocol-fg/images/flightgear.png | Bin 0 -> 979 bytes protocol-fsuipc/CMakeLists.txt | 11 + protocol-fsuipc/fsuipc-protocol.qrc | 5 + protocol-fsuipc/ftnoir_fsuipccontrols.ui | 134 +++ protocol-fsuipc/ftnoir_protocol_fsuipc.cpp | 149 +++ protocol-fsuipc/ftnoir_protocol_fsuipc.h | 90 ++ protocol-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp | 43 + protocol-fsuipc/images/fs9.png | Bin 0 -> 758 bytes protocol-fsuipc/images/fs91.png | Bin 0 -> 1644 bytes protocol-ft/CMakeLists.txt | 4 + protocol-ft/ft-protocol.qrc | 5 + protocol-ft/ftnoir_ftcontrols.ui | 182 +++ protocol-ft/ftnoir_protocol_ft.cpp | 166 +++ protocol-ft/ftnoir_protocol_ft.h | 90 ++ protocol-ft/ftnoir_protocol_ft_dialog.cpp | 60 + protocol-ft/images/freetrack.png | Bin 0 -> 1773 bytes protocol-ftn/CMakeLists.txt | 1 + protocol-ftn/ftnoir_ftncontrols.ui | 266 +++++ protocol-ftn/ftnoir_protocol_ftn.cpp | 34 + protocol-ftn/ftnoir_protocol_ftn.h | 69 ++ protocol-ftn/ftnoir_protocol_ftn_dialog.cpp | 42 + protocol-libevdev/CMakeLists.txt | 10 + protocol-libevdev/ftnoir_libevdev_controls.ui | 111 ++ protocol-libevdev/ftnoir_protocol_libevdev.cpp | 97 ++ protocol-libevdev/ftnoir_protocol_libevdev.h | 57 + .../ftnoir_protocol_libevdev_dialog.cpp | 21 + protocol-libevdev/images/linux.png | Bin 0 -> 668 bytes protocol-libevdev/libevdev-protocol.qrc | 5 + protocol-mouse/CMakeLists.txt | 3 + protocol-mouse/ftnoir_mousecontrols.ui | 188 +++ protocol-mouse/ftnoir_protocol_mouse.cpp | 54 + protocol-mouse/ftnoir_protocol_mouse.h | 59 + protocol-mouse/ftnoir_protocol_mouse_dialog.cpp | 24 + protocol-mouse/images/mouse.png | Bin 0 -> 1169 bytes protocol-mouse/win32-mouse-protocol.qrc | 5 + protocol-sc/CMakeLists.txt | 3 + protocol-sc/ftnoir-protocol-sc.rc | 4 + protocol-sc/ftnoir_protocol_sc.cpp | 189 +++ protocol-sc/ftnoir_protocol_sc.h | 108 ++ protocol-sc/ftnoir_protocol_sc_dialog.cpp | 35 + protocol-sc/ftnoir_sccontrols.ui | 72 ++ protocol-sc/images/fsx.png | Bin 0 -> 813 bytes protocol-sc/images/fsx1.png | Bin 0 -> 1920 bytes protocol-sc/sc-protocol.qrc | 5 + protocol-sc/scserver.manifest | 13 + protocol-sc/scserver_acceleration.manifest | 13 + protocol-sc/scserver_sp2.manifest | 13 + protocol-vjoy/CMakeLists.txt | 14 + protocol-vjoy/ftnoir_protocol_vjoy.cpp | 33 + protocol-vjoy/ftnoir_protocol_vjoy.h | 91 ++ protocol-vjoy/ftnoir_protocol_vjoy_dialog.cpp | 22 + protocol-vjoy/ftnoir_vjoy_controls.ui | 113 ++ protocol-vjoy/images/vjoy.png | Bin 0 -> 694 bytes protocol-vjoy/vjoy-protocol.qrc | 5 + protocol-vjoy/vjoy.def | 5 + protocol-wine/CMakeLists.txt | 26 + protocol-wine/ftnoir_protocol_wine.cpp | 59 + protocol-wine/ftnoir_protocol_wine.h | 57 + protocol-wine/ftnoir_protocol_wine_dialog.cpp | 19 + protocol-wine/ftnoir_winecontrols.ui | 170 +++ protocol-wine/images/wine.png | Bin 0 -> 376 bytes protocol-wine/opentrack-wrapper-wine-main.cxx | 80 ++ protocol-wine/opentrack-wrapper-wine-posix.cxx | 7 + protocol-wine/opentrack-wrapper-wine-windows.cxx | 40 + protocol-wine/wine-protocol.qrc | 5 + protocol-wine/wine-shm.h | 20 + .../broken/qfunctionconfiguratorplugin.cpp | 111 -- .../broken/qfunctionconfiguratorplugin.h | 36 - qfunctionconfigurator/functionconfig.cpp | 249 ---- qfunctionconfigurator/functionconfig.h | 75 -- qfunctionconfigurator/qfunctionconfigurator.cpp | 440 ------- qfunctionconfigurator/qfunctionconfigurator.h | 75 -- settings/facetracknoir supported games.csv | 576 +++++++++ spline-widget/CMakeLists.txt | 6 + .../broken/qfunctionconfiguratorplugin.cpp | 111 ++ spline-widget/broken/qfunctionconfiguratorplugin.h | 36 + spline-widget/functionconfig.cpp | 249 ++++ spline-widget/functionconfig.h | 75 ++ spline-widget/qfunctionconfigurator.cpp | 440 +++++++ spline-widget/qfunctionconfigurator.h | 75 ++ tracker-aruco/CMakeLists.txt | 8 + tracker-aruco/ar_video_widget.cpp | 67 ++ tracker-aruco/ar_video_widget.h | 33 + tracker-aruco/aruco-tracker.qrc | 5 + tracker-aruco/aruco-trackercontrols.ui | 281 +++++ tracker-aruco/ftnoir_tracker_aruco.cpp | 444 +++++++ tracker-aruco/ftnoir_tracker_aruco.h | 99 ++ tracker-aruco/images/aruco.png | Bin 0 -> 987 bytes tracker-aruco/include/aruco.h | 134 +++ tracker-aruco/include/arucofidmarkers.h | 119 ++ tracker-aruco/include/board.h | 168 +++ tracker-aruco/include/boarddetector.h | 138 +++ tracker-aruco/include/cameraparameters.h | 138 +++ tracker-aruco/include/cvdrawingutils.h | 52 + tracker-aruco/include/exports.h | 46 + tracker-aruco/include/marker.h | 143 +++ tracker-aruco/include/markerdetector.h | 359 ++++++ tracker-aruco/trans_calib.cpp | 41 + tracker-aruco/trans_calib.h | 39 + tracker-freepie-udp/CMakeLists.txt | 1 + tracker-freepie-udp/freepie-udp-controls.ui | 285 +++++ tracker-freepie-udp/freepie-udp-res.qrc | 5 + tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp | 119 ++ tracker-freepie-udp/ftnoir_tracker_freepie-udp.h | 69 ++ .../ftnoir_tracker_freepie-udp_dialog.cpp | 30 + tracker-freepie-udp/glovepie.png | Bin 0 -> 3584 bytes tracker-hatire/CMakeLists.txt | 5 + tracker-hatire/ftnoir_arduino_type.h | 32 + tracker-hatire/ftnoir_hat.qrc | 7 + tracker-hatire/ftnoir_hatcontrols.ui | 1253 ++++++++++++++++++++ tracker-hatire/ftnoir_tracker_hat.cpp | 597 ++++++++++ tracker-hatire/ftnoir_tracker_hat.h | 157 +++ tracker-hatire/ftnoir_tracker_hat_dialog.cpp | 411 +++++++ tracker-hatire/ftnoir_tracker_hat_dialog.h | 116 ++ tracker-hatire/ftnoir_tracker_hat_settings.cpp | 146 +++ tracker-hatire/ftnoir_tracker_hat_settings.h | 68 ++ tracker-hatire/images/hat.ico | Bin 0 -> 1150 bytes tracker-hatire/images/hat.png | Bin 0 -> 249 bytes tracker-hatire/images/hat_logo.png | Bin 0 -> 15210 bytes tracker-ht/CMakeLists.txt | 11 + tracker-ht/ftnoir_tracker_ht.cpp | 225 ++++ tracker-ht/ftnoir_tracker_ht.h | 90 ++ tracker-ht/headtracker-ftnoir.h | 24 + tracker-ht/ht-api.h | 51 + tracker-ht/ht-tracker.qrc | 5 + tracker-ht/ht-trackercontrols.ui | 157 +++ tracker-ht/ht_video_widget.cpp | 53 + tracker-ht/ht_video_widget.h | 39 + tracker-ht/images/ht.png | Bin 0 -> 2010 bytes tracker-hydra/CMakeLists.txt | 44 + tracker-hydra/ftnoir_hydra_clientcontrols.ui | 53 + tracker-hydra/ftnoir_tracker_hydra.cpp | 46 + tracker-hydra/ftnoir_tracker_hydra.h | 46 + tracker-hydra/ftnoir_tracker_hydra_dialog.cpp | 22 + tracker-joystick/CMakeLists.txt | 4 + tracker-joystick/ftnoir_tracker_joystick.cpp | 253 ++++ tracker-joystick/ftnoir_tracker_joystick.h | 106 ++ .../ftnoir_tracker_joystick_controls.ui | 492 ++++++++ .../ftnoir_tracker_joystick_dialog.cpp | 69 ++ tracker-pt/CMakeLists.txt | 5 + tracker-pt/FTNoIR_PT_Controls.ui | 1220 +++++++++++++++++++ tracker-pt/Resources/Logo_IR.png | Bin 0 -> 10386 bytes tracker-pt/Resources/cap_front.png | Bin 0 -> 1164 bytes tracker-pt/Resources/cap_side.png | Bin 0 -> 1733 bytes tracker-pt/Resources/clip_front.png | Bin 0 -> 571 bytes tracker-pt/Resources/clip_side.png | Bin 0 -> 2677 bytes tracker-pt/camera.cpp | 145 +++ tracker-pt/camera.h | 95 ++ tracker-pt/doc/index.htm | 262 ++++ tracker-pt/doc/logo.png | Bin 0 -> 10386 bytes tracker-pt/doc/ptrack.ico | Bin 0 -> 4286 bytes tracker-pt/doc/settings1.png | Bin 0 -> 25013 bytes tracker-pt/doc/settings2.png | Bin 0 -> 26841 bytes tracker-pt/doc/settings3.png | Bin 0 -> 29547 bytes tracker-pt/doc/style.css | 131 ++ tracker-pt/ftnoir_tracker_pt.cpp | 219 ++++ tracker-pt/ftnoir_tracker_pt.h | 86 ++ tracker-pt/ftnoir_tracker_pt.qrc | 9 + tracker-pt/ftnoir_tracker_pt_dialog.cpp | 182 +++ tracker-pt/ftnoir_tracker_pt_dialog.h | 51 + tracker-pt/ftnoir_tracker_pt_settings.h | 71 ++ tracker-pt/point_extractor.cpp | 180 +++ tracker-pt/point_extractor.h | 33 + tracker-pt/point_tracker.cpp | 267 +++++ tracker-pt/point_tracker.h | 147 +++ tracker-pt/pt_video_widget.cpp | 55 + tracker-pt/pt_video_widget.h | 47 + tracker-pt/trans_calib.cpp | 41 + tracker-pt/trans_calib.h | 39 + tracker-rift-025/CMakeLists.txt | 3 + tracker-rift-025/ftnoir_rift_025.qrc | 7 + tracker-rift-025/ftnoir_rift_clientcontrols_025.ui | 176 +++ tracker-rift-025/ftnoir_tracker_rift_025.cpp | 92 ++ tracker-rift-025/ftnoir_tracker_rift_025.h | 63 + .../ftnoir_tracker_rift_dialog_025.cpp | 26 + tracker-rift-025/images/medium.png | Bin 0 -> 5764 bytes tracker-rift-025/images/rift_medium.png | Bin 0 -> 5764 bytes tracker-rift-025/images/rift_small.png | Bin 0 -> 1212 bytes tracker-rift-025/images/rift_tiny.png | Bin 0 -> 624 bytes tracker-rift-025/images/small.png | Bin 0 -> 1212 bytes tracker-rift-025/images/tiny.png | Bin 0 -> 624 bytes tracker-rift-042/CMakeLists.txt | 3 + tracker-rift-042/ftnoir_rift_042.qrc | 7 + tracker-rift-042/ftnoir_rift_clientcontrols_042.ui | 176 +++ tracker-rift-042/ftnoir_tracker_rift_042.cpp | 71 ++ tracker-rift-042/ftnoir_tracker_rift_042.h | 60 + .../ftnoir_tracker_rift_dialog_042.cpp | 26 + tracker-rift-042/images/medium.png | Bin 0 -> 5764 bytes tracker-rift-042/images/rift_medium.png | Bin 0 -> 5764 bytes tracker-rift-042/images/rift_small.png | Bin 0 -> 1212 bytes tracker-rift-042/images/rift_tiny.png | Bin 0 -> 624 bytes tracker-rift-042/images/small.png | Bin 0 -> 1212 bytes tracker-rift-042/images/tiny.png | Bin 0 -> 624 bytes tracker-rift-080/CMakeLists.txt | 3 + tracker-rift-080/ftnoir_rift_080.qrc | 7 + tracker-rift-080/ftnoir_rift_clientcontrols_080.ui | 176 +++ tracker-rift-080/ftnoir_tracker_rift_080.cpp | 75 ++ tracker-rift-080/ftnoir_tracker_rift_080.h | 60 + .../ftnoir_tracker_rift_dialog_080.cpp | 26 + tracker-rift-080/images/medium.png | Bin 0 -> 5764 bytes tracker-rift-080/images/rift_medium.png | Bin 0 -> 5764 bytes tracker-rift-080/images/rift_small.png | Bin 0 -> 1212 bytes tracker-rift-080/images/rift_tiny.png | Bin 0 -> 624 bytes tracker-rift-080/images/small.png | Bin 0 -> 1212 bytes tracker-rift-080/images/tiny.png | Bin 0 -> 624 bytes tracker-rs/CMakeLists.txt | 5 + tracker-rs/README.md | 16 + tracker-rs/ftnoir_tracker_rs.cpp | 111 ++ tracker-rs/ftnoir_tracker_rs.h | 46 + tracker-rs/ftnoir_tracker_rs_controls.cpp | 40 + tracker-rs/ftnoir_tracker_rs_controls.h | 23 + tracker-rs/ftnoir_tracker_rs_controls.ui | 67 ++ tracker-rs/images/RS.png | Bin 0 -> 4770 bytes tracker-rs/images/intel-16x16.png | Bin 0 -> 637 bytes .../intel_rs_sdk_runtime_websetup_6.0.21.6598.exe | Bin 0 -> 780456 bytes .../rs_impl/bin/opentrack-tracker-rs-impl.exe | Bin 0 -> 83968 bytes tracker-rs/rs_impl/build.bat | 2 + tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp | 151 +++ tracker-rs/rs_impl/ftnoir_tracker_rs_impl.h | 19 + tracker-rs/rs_impl/udp_sender.cpp | 53 + tracker-rs/rs_tracker.qrc | 6 + tracker-udp/CMakeLists.txt | 1 + tracker-udp/ftnoir_ftnclientcontrols.ui | 208 ++++ tracker-udp/ftnoir_tracker_udp.cpp | 70 ++ tracker-udp/ftnoir_tracker_udp.h | 60 + tracker-udp/ftnoir_tracker_udp_dialog.cpp | 26 + x-plane-plugin/CMakeLists.txt | 29 + 476 files changed, 19652 insertions(+), 19668 deletions(-) delete mode 100644 bin/settings/facetracknoir supported games.csv create mode 100644 cmake/opentrack-install.cmake create mode 100644 cmake/opentrack-macros.cmake create mode 100644 cmake/opentrack-platform.cmake create mode 100644 cmake/opentrack-policy.cmake create mode 100644 cmake/opentrack-qt.cmake create mode 100644 cmake/opentrack-rift.cmake create mode 100644 cmake/opentrack-tarball.cmake create mode 100644 cmake/opentrack-version.cmake create mode 100644 csv/CMakeLists.txt create mode 100644 facetracknoir/CMakeLists.txt create mode 100644 filter-accela/CMakeLists.txt create mode 100644 filter-accela/ftnoir_accela_filtercontrols.ui create mode 100644 filter-accela/ftnoir_filter_accela.cpp create mode 100644 filter-accela/ftnoir_filter_accela.h create mode 100644 filter-accela/ftnoir_filter_accela_dialog.cpp create mode 100644 filter-ewma2/CMakeLists.txt create mode 100644 filter-ewma2/ftnoir_ewma_filtercontrols.ui create mode 100644 filter-ewma2/ftnoir_filter_ewma2.cpp create mode 100644 filter-ewma2/ftnoir_filter_ewma2.h create mode 100644 filter-ewma2/ftnoir_filter_ewma2_dialog.cpp create mode 100644 filter-kalman/CMakeLists.txt create mode 100644 filter-kalman/ftnoir_filter_kalman.h create mode 100644 filter-kalman/ftnoir_kalman_filtercontrols.ui create mode 100644 filter-kalman/kalman.cpp delete mode 100644 ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui delete mode 100644 ftnoir_filter_accela/ftnoir_filter_accela.cpp delete mode 100644 ftnoir_filter_accela/ftnoir_filter_accela.h delete mode 100644 ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp delete mode 100644 ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui delete mode 100644 ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp delete mode 100644 ftnoir_filter_ewma2/ftnoir_filter_ewma2.h delete mode 100644 ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp delete mode 100644 ftnoir_filter_kalman/ftnoir_filter_kalman.h delete mode 100644 ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui delete mode 100644 ftnoir_filter_kalman/kalman.cpp delete mode 100644 ftnoir_protocol_fg/fg-protocol.qrc delete mode 100644 ftnoir_protocol_fg/fgtypes.h delete mode 100644 ftnoir_protocol_fg/ftnoir_fgcontrols.ui delete mode 100644 ftnoir_protocol_fg/ftnoir_protocol_fg.cpp delete mode 100644 ftnoir_protocol_fg/ftnoir_protocol_fg.h delete mode 100644 ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp delete mode 100644 ftnoir_protocol_fg/images/flightgear.png delete mode 100644 ftnoir_protocol_fsuipc/fsuipc-protocol.qrc delete mode 100644 ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui delete mode 100644 ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp delete mode 100644 ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h delete mode 100644 ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp delete mode 100644 ftnoir_protocol_fsuipc/images/fs9.png delete mode 100644 ftnoir_protocol_fsuipc/images/fs91.png delete mode 100644 ftnoir_protocol_ft/ft-protocol.qrc delete mode 100644 ftnoir_protocol_ft/ftnoir_ftcontrols.ui delete mode 100644 ftnoir_protocol_ft/ftnoir_protocol_ft.cpp delete mode 100644 ftnoir_protocol_ft/ftnoir_protocol_ft.h delete mode 100644 ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp delete mode 100644 ftnoir_protocol_ft/images/freetrack.png delete mode 100644 ftnoir_protocol_ftn/ftnoir_ftncontrols.ui delete mode 100644 ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp delete mode 100644 ftnoir_protocol_ftn/ftnoir_protocol_ftn.h delete mode 100644 ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp delete mode 100644 ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui delete mode 100644 ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp delete mode 100644 ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h delete mode 100644 ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp delete mode 100644 ftnoir_protocol_libevdev/images/linux.png delete mode 100644 ftnoir_protocol_libevdev/libevdev-protocol.qrc delete mode 100644 ftnoir_protocol_mouse/ftnoir_mousecontrols.ui delete mode 100644 ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp delete mode 100644 ftnoir_protocol_mouse/ftnoir_protocol_mouse.h delete mode 100644 ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp delete mode 100644 ftnoir_protocol_mouse/images/mouse.png delete mode 100644 ftnoir_protocol_mouse/win32-mouse-protocol.qrc delete mode 100644 ftnoir_protocol_sc/ftnoir-protocol-sc.rc delete mode 100644 ftnoir_protocol_sc/ftnoir_protocol_sc.cpp delete mode 100644 ftnoir_protocol_sc/ftnoir_protocol_sc.h delete mode 100644 ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp delete mode 100644 ftnoir_protocol_sc/ftnoir_sccontrols.ui delete mode 100644 ftnoir_protocol_sc/images/fsx.png delete mode 100644 ftnoir_protocol_sc/images/fsx1.png delete mode 100644 ftnoir_protocol_sc/sc-protocol.qrc delete mode 100644 ftnoir_protocol_sc/scserver.manifest delete mode 100644 ftnoir_protocol_sc/scserver_acceleration.manifest delete mode 100644 ftnoir_protocol_sc/scserver_sp2.manifest delete mode 100644 ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp delete mode 100644 ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h delete mode 100644 ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp delete mode 100644 ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui delete mode 100644 ftnoir_protocol_vjoy/images/vjoy.png delete mode 100644 ftnoir_protocol_vjoy/vjoy-protocol.qrc delete mode 100644 ftnoir_protocol_vjoy/vjoy.def delete mode 100644 ftnoir_protocol_wine/ftnoir_protocol_wine.cpp delete mode 100644 ftnoir_protocol_wine/ftnoir_protocol_wine.h delete mode 100644 ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp delete mode 100644 ftnoir_protocol_wine/ftnoir_winecontrols.ui delete mode 100644 ftnoir_protocol_wine/images/wine.png delete mode 100644 ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx delete mode 100644 ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx delete mode 100644 ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx delete mode 100644 ftnoir_protocol_wine/wine-protocol.qrc delete mode 100644 ftnoir_protocol_wine/wine-shm.h delete mode 100644 ftnoir_tracker_aruco/ar_video_widget.cpp delete mode 100644 ftnoir_tracker_aruco/ar_video_widget.h delete mode 100644 ftnoir_tracker_aruco/aruco-tracker.qrc delete mode 100644 ftnoir_tracker_aruco/aruco-trackercontrols.ui delete mode 100644 ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp delete mode 100644 ftnoir_tracker_aruco/ftnoir_tracker_aruco.h delete mode 100644 ftnoir_tracker_aruco/images/aruco.png delete mode 100644 ftnoir_tracker_aruco/include/aruco.h delete mode 100644 ftnoir_tracker_aruco/include/arucofidmarkers.h delete mode 100644 ftnoir_tracker_aruco/include/board.h delete mode 100644 ftnoir_tracker_aruco/include/boarddetector.h delete mode 100644 ftnoir_tracker_aruco/include/cameraparameters.h delete mode 100644 ftnoir_tracker_aruco/include/cvdrawingutils.h delete mode 100644 ftnoir_tracker_aruco/include/exports.h delete mode 100644 ftnoir_tracker_aruco/include/marker.h delete mode 100644 ftnoir_tracker_aruco/include/markerdetector.h delete mode 100644 ftnoir_tracker_aruco/trans_calib.cpp delete mode 100644 ftnoir_tracker_aruco/trans_calib.h delete mode 100644 ftnoir_tracker_freepie-udp/freepie-udp-controls.ui delete mode 100644 ftnoir_tracker_freepie-udp/freepie-udp-res.qrc delete mode 100644 ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp delete mode 100644 ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h delete mode 100644 ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp delete mode 100644 ftnoir_tracker_freepie-udp/glovepie.png delete mode 100644 ftnoir_tracker_hatire/ftnoir_arduino_type.h delete mode 100644 ftnoir_tracker_hatire/ftnoir_hat.qrc delete mode 100644 ftnoir_tracker_hatire/ftnoir_hatcontrols.ui delete mode 100644 ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp delete mode 100644 ftnoir_tracker_hatire/ftnoir_tracker_hat.h delete mode 100644 ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.cpp delete mode 100644 ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h delete mode 100644 ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp delete mode 100644 ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.h delete mode 100644 ftnoir_tracker_hatire/images/hat.ico delete mode 100644 ftnoir_tracker_hatire/images/hat.png delete mode 100644 ftnoir_tracker_hatire/images/hat_logo.png delete mode 100644 ftnoir_tracker_ht/ftnoir_tracker_ht.cpp delete mode 100644 ftnoir_tracker_ht/ftnoir_tracker_ht.h delete mode 100644 ftnoir_tracker_ht/headtracker-ftnoir.h delete mode 100644 ftnoir_tracker_ht/ht-api.h delete mode 100644 ftnoir_tracker_ht/ht-tracker.qrc delete mode 100644 ftnoir_tracker_ht/ht-trackercontrols.ui delete mode 100644 ftnoir_tracker_ht/ht_video_widget.cpp delete mode 100644 ftnoir_tracker_ht/ht_video_widget.h delete mode 100644 ftnoir_tracker_ht/images/ht.png delete mode 100644 ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui delete mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp delete mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra.h delete mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp delete mode 100644 ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp delete mode 100644 ftnoir_tracker_joystick/ftnoir_tracker_joystick.h delete mode 100644 ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui delete mode 100644 ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp delete mode 100644 ftnoir_tracker_pt/FTNoIR_PT_Controls.ui delete mode 100644 ftnoir_tracker_pt/Resources/Logo_IR.png delete mode 100644 ftnoir_tracker_pt/Resources/cap_front.png delete mode 100644 ftnoir_tracker_pt/Resources/cap_side.png delete mode 100644 ftnoir_tracker_pt/Resources/clip_front.png delete mode 100644 ftnoir_tracker_pt/Resources/clip_side.png delete mode 100644 ftnoir_tracker_pt/camera.cpp delete mode 100644 ftnoir_tracker_pt/camera.h delete mode 100644 ftnoir_tracker_pt/doc/index.htm delete mode 100644 ftnoir_tracker_pt/doc/logo.png delete mode 100644 ftnoir_tracker_pt/doc/ptrack.ico delete mode 100644 ftnoir_tracker_pt/doc/settings1.png delete mode 100644 ftnoir_tracker_pt/doc/settings2.png delete mode 100644 ftnoir_tracker_pt/doc/settings3.png delete mode 100644 ftnoir_tracker_pt/doc/style.css delete mode 100644 ftnoir_tracker_pt/ftnoir_tracker_pt.cpp delete mode 100644 ftnoir_tracker_pt/ftnoir_tracker_pt.h delete mode 100644 ftnoir_tracker_pt/ftnoir_tracker_pt.qrc delete mode 100644 ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp delete mode 100644 ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h delete mode 100644 ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h delete mode 100644 ftnoir_tracker_pt/point_extractor.cpp delete mode 100644 ftnoir_tracker_pt/point_extractor.h delete mode 100644 ftnoir_tracker_pt/point_tracker.cpp delete mode 100644 ftnoir_tracker_pt/point_tracker.h delete mode 100644 ftnoir_tracker_pt/pt_video_widget.cpp delete mode 100644 ftnoir_tracker_pt/pt_video_widget.h delete mode 100644 ftnoir_tracker_pt/trans_calib.cpp delete mode 100644 ftnoir_tracker_pt/trans_calib.h delete mode 100644 ftnoir_tracker_rift_025/ftnoir_rift_025.qrc delete mode 100644 ftnoir_tracker_rift_025/ftnoir_rift_clientcontrols_025.ui delete mode 100644 ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.cpp delete mode 100644 ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h delete mode 100644 ftnoir_tracker_rift_025/ftnoir_tracker_rift_dialog_025.cpp delete mode 100644 ftnoir_tracker_rift_025/images/medium.png delete mode 100644 ftnoir_tracker_rift_025/images/rift_medium.png delete mode 100644 ftnoir_tracker_rift_025/images/rift_small.png delete mode 100644 ftnoir_tracker_rift_025/images/rift_tiny.png delete mode 100644 ftnoir_tracker_rift_025/images/small.png delete mode 100644 ftnoir_tracker_rift_025/images/tiny.png delete mode 100644 ftnoir_tracker_rift_042/ftnoir_rift_042.qrc delete mode 100644 ftnoir_tracker_rift_042/ftnoir_rift_clientcontrols_042.ui delete mode 100644 ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.cpp delete mode 100644 ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.h delete mode 100644 ftnoir_tracker_rift_042/ftnoir_tracker_rift_dialog_042.cpp delete mode 100644 ftnoir_tracker_rift_042/images/medium.png delete mode 100644 ftnoir_tracker_rift_042/images/rift_medium.png delete mode 100644 ftnoir_tracker_rift_042/images/rift_small.png delete mode 100644 ftnoir_tracker_rift_042/images/rift_tiny.png delete mode 100644 ftnoir_tracker_rift_042/images/small.png delete mode 100644 ftnoir_tracker_rift_042/images/tiny.png delete mode 100644 ftnoir_tracker_rift_080/ftnoir_rift_080.qrc delete mode 100644 ftnoir_tracker_rift_080/ftnoir_rift_clientcontrols_080.ui delete mode 100644 ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp delete mode 100644 ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.h delete mode 100644 ftnoir_tracker_rift_080/ftnoir_tracker_rift_dialog_080.cpp delete mode 100644 ftnoir_tracker_rift_080/images/medium.png delete mode 100644 ftnoir_tracker_rift_080/images/rift_medium.png delete mode 100644 ftnoir_tracker_rift_080/images/rift_small.png delete mode 100644 ftnoir_tracker_rift_080/images/rift_tiny.png delete mode 100644 ftnoir_tracker_rift_080/images/small.png delete mode 100644 ftnoir_tracker_rift_080/images/tiny.png delete mode 100644 ftnoir_tracker_rs/README.md delete mode 100644 ftnoir_tracker_rs/ftnoir_tracker_rs.cpp delete mode 100644 ftnoir_tracker_rs/ftnoir_tracker_rs.h delete mode 100644 ftnoir_tracker_rs/ftnoir_tracker_rs_controls.cpp delete mode 100644 ftnoir_tracker_rs/ftnoir_tracker_rs_controls.h delete mode 100644 ftnoir_tracker_rs/ftnoir_tracker_rs_controls.ui delete mode 100644 ftnoir_tracker_rs/images/RS.png delete mode 100644 ftnoir_tracker_rs/images/intel-16x16.png delete mode 100644 ftnoir_tracker_rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe delete mode 100644 ftnoir_tracker_rs/rs_impl/bin/opentrack-tracker-rs-impl.exe delete mode 100644 ftnoir_tracker_rs/rs_impl/build.bat delete mode 100644 ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.cpp delete mode 100644 ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.h delete mode 100644 ftnoir_tracker_rs/rs_impl/udp_sender.cpp delete mode 100644 ftnoir_tracker_rs/rs_tracker.qrc delete mode 100644 ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui delete mode 100644 ftnoir_tracker_udp/ftnoir_tracker_udp.cpp delete mode 100644 ftnoir_tracker_udp/ftnoir_tracker_udp.h delete mode 100644 ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp create mode 100644 opentrack-compat/CMakeLists.txt create mode 100644 opentrack/CMakeLists.txt create mode 100644 pose-widget/CMakeLists.txt create mode 100644 protocol-fg/CMakeLists.txt create mode 100644 protocol-fg/fg-protocol.qrc create mode 100644 protocol-fg/fgtypes.h create mode 100644 protocol-fg/ftnoir_fgcontrols.ui create mode 100644 protocol-fg/ftnoir_protocol_fg.cpp create mode 100644 protocol-fg/ftnoir_protocol_fg.h create mode 100644 protocol-fg/ftnoir_protocol_fg_dialog.cpp create mode 100644 protocol-fg/images/flightgear.png create mode 100644 protocol-fsuipc/CMakeLists.txt create mode 100644 protocol-fsuipc/fsuipc-protocol.qrc create mode 100644 protocol-fsuipc/ftnoir_fsuipccontrols.ui create mode 100644 protocol-fsuipc/ftnoir_protocol_fsuipc.cpp create mode 100644 protocol-fsuipc/ftnoir_protocol_fsuipc.h create mode 100644 protocol-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp create mode 100644 protocol-fsuipc/images/fs9.png create mode 100644 protocol-fsuipc/images/fs91.png create mode 100644 protocol-ft/CMakeLists.txt create mode 100644 protocol-ft/ft-protocol.qrc create mode 100644 protocol-ft/ftnoir_ftcontrols.ui create mode 100644 protocol-ft/ftnoir_protocol_ft.cpp create mode 100644 protocol-ft/ftnoir_protocol_ft.h create mode 100644 protocol-ft/ftnoir_protocol_ft_dialog.cpp create mode 100644 protocol-ft/images/freetrack.png create mode 100644 protocol-ftn/CMakeLists.txt create mode 100644 protocol-ftn/ftnoir_ftncontrols.ui create mode 100644 protocol-ftn/ftnoir_protocol_ftn.cpp create mode 100644 protocol-ftn/ftnoir_protocol_ftn.h create mode 100644 protocol-ftn/ftnoir_protocol_ftn_dialog.cpp create mode 100644 protocol-libevdev/CMakeLists.txt create mode 100644 protocol-libevdev/ftnoir_libevdev_controls.ui create mode 100644 protocol-libevdev/ftnoir_protocol_libevdev.cpp create mode 100644 protocol-libevdev/ftnoir_protocol_libevdev.h create mode 100644 protocol-libevdev/ftnoir_protocol_libevdev_dialog.cpp create mode 100644 protocol-libevdev/images/linux.png create mode 100644 protocol-libevdev/libevdev-protocol.qrc create mode 100644 protocol-mouse/CMakeLists.txt create mode 100644 protocol-mouse/ftnoir_mousecontrols.ui create mode 100644 protocol-mouse/ftnoir_protocol_mouse.cpp create mode 100644 protocol-mouse/ftnoir_protocol_mouse.h create mode 100644 protocol-mouse/ftnoir_protocol_mouse_dialog.cpp create mode 100644 protocol-mouse/images/mouse.png create mode 100644 protocol-mouse/win32-mouse-protocol.qrc create mode 100644 protocol-sc/CMakeLists.txt create mode 100644 protocol-sc/ftnoir-protocol-sc.rc create mode 100644 protocol-sc/ftnoir_protocol_sc.cpp create mode 100644 protocol-sc/ftnoir_protocol_sc.h create mode 100644 protocol-sc/ftnoir_protocol_sc_dialog.cpp create mode 100644 protocol-sc/ftnoir_sccontrols.ui create mode 100644 protocol-sc/images/fsx.png create mode 100644 protocol-sc/images/fsx1.png create mode 100644 protocol-sc/sc-protocol.qrc create mode 100644 protocol-sc/scserver.manifest create mode 100644 protocol-sc/scserver_acceleration.manifest create mode 100644 protocol-sc/scserver_sp2.manifest create mode 100644 protocol-vjoy/CMakeLists.txt create mode 100644 protocol-vjoy/ftnoir_protocol_vjoy.cpp create mode 100644 protocol-vjoy/ftnoir_protocol_vjoy.h create mode 100644 protocol-vjoy/ftnoir_protocol_vjoy_dialog.cpp create mode 100644 protocol-vjoy/ftnoir_vjoy_controls.ui create mode 100644 protocol-vjoy/images/vjoy.png create mode 100644 protocol-vjoy/vjoy-protocol.qrc create mode 100644 protocol-vjoy/vjoy.def create mode 100644 protocol-wine/CMakeLists.txt create mode 100644 protocol-wine/ftnoir_protocol_wine.cpp create mode 100644 protocol-wine/ftnoir_protocol_wine.h create mode 100644 protocol-wine/ftnoir_protocol_wine_dialog.cpp create mode 100644 protocol-wine/ftnoir_winecontrols.ui create mode 100644 protocol-wine/images/wine.png create mode 100644 protocol-wine/opentrack-wrapper-wine-main.cxx create mode 100644 protocol-wine/opentrack-wrapper-wine-posix.cxx create mode 100644 protocol-wine/opentrack-wrapper-wine-windows.cxx create mode 100644 protocol-wine/wine-protocol.qrc create mode 100644 protocol-wine/wine-shm.h delete mode 100644 qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp delete mode 100644 qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h delete mode 100644 qfunctionconfigurator/functionconfig.cpp delete mode 100644 qfunctionconfigurator/functionconfig.h delete mode 100644 qfunctionconfigurator/qfunctionconfigurator.cpp delete mode 100644 qfunctionconfigurator/qfunctionconfigurator.h create mode 100644 settings/facetracknoir supported games.csv create mode 100644 spline-widget/CMakeLists.txt create mode 100644 spline-widget/broken/qfunctionconfiguratorplugin.cpp create mode 100644 spline-widget/broken/qfunctionconfiguratorplugin.h create mode 100644 spline-widget/functionconfig.cpp create mode 100644 spline-widget/functionconfig.h create mode 100644 spline-widget/qfunctionconfigurator.cpp create mode 100644 spline-widget/qfunctionconfigurator.h create mode 100644 tracker-aruco/CMakeLists.txt create mode 100644 tracker-aruco/ar_video_widget.cpp create mode 100644 tracker-aruco/ar_video_widget.h create mode 100644 tracker-aruco/aruco-tracker.qrc create mode 100644 tracker-aruco/aruco-trackercontrols.ui create mode 100644 tracker-aruco/ftnoir_tracker_aruco.cpp create mode 100644 tracker-aruco/ftnoir_tracker_aruco.h create mode 100644 tracker-aruco/images/aruco.png create mode 100644 tracker-aruco/include/aruco.h create mode 100644 tracker-aruco/include/arucofidmarkers.h create mode 100644 tracker-aruco/include/board.h create mode 100644 tracker-aruco/include/boarddetector.h create mode 100644 tracker-aruco/include/cameraparameters.h create mode 100644 tracker-aruco/include/cvdrawingutils.h create mode 100644 tracker-aruco/include/exports.h create mode 100644 tracker-aruco/include/marker.h create mode 100644 tracker-aruco/include/markerdetector.h create mode 100644 tracker-aruco/trans_calib.cpp create mode 100644 tracker-aruco/trans_calib.h create mode 100644 tracker-freepie-udp/CMakeLists.txt create mode 100644 tracker-freepie-udp/freepie-udp-controls.ui create mode 100644 tracker-freepie-udp/freepie-udp-res.qrc create mode 100644 tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp create mode 100644 tracker-freepie-udp/ftnoir_tracker_freepie-udp.h create mode 100644 tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp create mode 100644 tracker-freepie-udp/glovepie.png create mode 100644 tracker-hatire/CMakeLists.txt create mode 100644 tracker-hatire/ftnoir_arduino_type.h create mode 100644 tracker-hatire/ftnoir_hat.qrc create mode 100644 tracker-hatire/ftnoir_hatcontrols.ui create mode 100644 tracker-hatire/ftnoir_tracker_hat.cpp create mode 100644 tracker-hatire/ftnoir_tracker_hat.h create mode 100644 tracker-hatire/ftnoir_tracker_hat_dialog.cpp create mode 100644 tracker-hatire/ftnoir_tracker_hat_dialog.h create mode 100644 tracker-hatire/ftnoir_tracker_hat_settings.cpp create mode 100644 tracker-hatire/ftnoir_tracker_hat_settings.h create mode 100644 tracker-hatire/images/hat.ico create mode 100644 tracker-hatire/images/hat.png create mode 100644 tracker-hatire/images/hat_logo.png create mode 100644 tracker-ht/CMakeLists.txt create mode 100644 tracker-ht/ftnoir_tracker_ht.cpp create mode 100644 tracker-ht/ftnoir_tracker_ht.h create mode 100644 tracker-ht/headtracker-ftnoir.h create mode 100644 tracker-ht/ht-api.h create mode 100644 tracker-ht/ht-tracker.qrc create mode 100644 tracker-ht/ht-trackercontrols.ui create mode 100644 tracker-ht/ht_video_widget.cpp create mode 100644 tracker-ht/ht_video_widget.h create mode 100644 tracker-ht/images/ht.png create mode 100644 tracker-hydra/CMakeLists.txt create mode 100644 tracker-hydra/ftnoir_hydra_clientcontrols.ui create mode 100644 tracker-hydra/ftnoir_tracker_hydra.cpp create mode 100644 tracker-hydra/ftnoir_tracker_hydra.h create mode 100644 tracker-hydra/ftnoir_tracker_hydra_dialog.cpp create mode 100644 tracker-joystick/CMakeLists.txt create mode 100644 tracker-joystick/ftnoir_tracker_joystick.cpp create mode 100644 tracker-joystick/ftnoir_tracker_joystick.h create mode 100644 tracker-joystick/ftnoir_tracker_joystick_controls.ui create mode 100644 tracker-joystick/ftnoir_tracker_joystick_dialog.cpp create mode 100644 tracker-pt/CMakeLists.txt create mode 100644 tracker-pt/FTNoIR_PT_Controls.ui create mode 100644 tracker-pt/Resources/Logo_IR.png create mode 100644 tracker-pt/Resources/cap_front.png create mode 100644 tracker-pt/Resources/cap_side.png create mode 100644 tracker-pt/Resources/clip_front.png create mode 100644 tracker-pt/Resources/clip_side.png create mode 100644 tracker-pt/camera.cpp create mode 100644 tracker-pt/camera.h create mode 100644 tracker-pt/doc/index.htm create mode 100644 tracker-pt/doc/logo.png create mode 100644 tracker-pt/doc/ptrack.ico create mode 100644 tracker-pt/doc/settings1.png create mode 100644 tracker-pt/doc/settings2.png create mode 100644 tracker-pt/doc/settings3.png create mode 100644 tracker-pt/doc/style.css create mode 100644 tracker-pt/ftnoir_tracker_pt.cpp create mode 100644 tracker-pt/ftnoir_tracker_pt.h create mode 100644 tracker-pt/ftnoir_tracker_pt.qrc create mode 100644 tracker-pt/ftnoir_tracker_pt_dialog.cpp create mode 100644 tracker-pt/ftnoir_tracker_pt_dialog.h create mode 100644 tracker-pt/ftnoir_tracker_pt_settings.h create mode 100644 tracker-pt/point_extractor.cpp create mode 100644 tracker-pt/point_extractor.h create mode 100644 tracker-pt/point_tracker.cpp create mode 100644 tracker-pt/point_tracker.h create mode 100644 tracker-pt/pt_video_widget.cpp create mode 100644 tracker-pt/pt_video_widget.h create mode 100644 tracker-pt/trans_calib.cpp create mode 100644 tracker-pt/trans_calib.h create mode 100644 tracker-rift-025/CMakeLists.txt create mode 100644 tracker-rift-025/ftnoir_rift_025.qrc create mode 100644 tracker-rift-025/ftnoir_rift_clientcontrols_025.ui create mode 100644 tracker-rift-025/ftnoir_tracker_rift_025.cpp create mode 100644 tracker-rift-025/ftnoir_tracker_rift_025.h create mode 100644 tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp create mode 100644 tracker-rift-025/images/medium.png create mode 100644 tracker-rift-025/images/rift_medium.png create mode 100644 tracker-rift-025/images/rift_small.png create mode 100644 tracker-rift-025/images/rift_tiny.png create mode 100644 tracker-rift-025/images/small.png create mode 100644 tracker-rift-025/images/tiny.png create mode 100644 tracker-rift-042/CMakeLists.txt create mode 100644 tracker-rift-042/ftnoir_rift_042.qrc create mode 100644 tracker-rift-042/ftnoir_rift_clientcontrols_042.ui create mode 100644 tracker-rift-042/ftnoir_tracker_rift_042.cpp create mode 100644 tracker-rift-042/ftnoir_tracker_rift_042.h create mode 100644 tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp create mode 100644 tracker-rift-042/images/medium.png create mode 100644 tracker-rift-042/images/rift_medium.png create mode 100644 tracker-rift-042/images/rift_small.png create mode 100644 tracker-rift-042/images/rift_tiny.png create mode 100644 tracker-rift-042/images/small.png create mode 100644 tracker-rift-042/images/tiny.png create mode 100644 tracker-rift-080/CMakeLists.txt create mode 100644 tracker-rift-080/ftnoir_rift_080.qrc create mode 100644 tracker-rift-080/ftnoir_rift_clientcontrols_080.ui create mode 100644 tracker-rift-080/ftnoir_tracker_rift_080.cpp create mode 100644 tracker-rift-080/ftnoir_tracker_rift_080.h create mode 100644 tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp create mode 100644 tracker-rift-080/images/medium.png create mode 100644 tracker-rift-080/images/rift_medium.png create mode 100644 tracker-rift-080/images/rift_small.png create mode 100644 tracker-rift-080/images/rift_tiny.png create mode 100644 tracker-rift-080/images/small.png create mode 100644 tracker-rift-080/images/tiny.png create mode 100644 tracker-rs/CMakeLists.txt create mode 100644 tracker-rs/README.md create mode 100644 tracker-rs/ftnoir_tracker_rs.cpp create mode 100644 tracker-rs/ftnoir_tracker_rs.h create mode 100644 tracker-rs/ftnoir_tracker_rs_controls.cpp create mode 100644 tracker-rs/ftnoir_tracker_rs_controls.h create mode 100644 tracker-rs/ftnoir_tracker_rs_controls.ui create mode 100644 tracker-rs/images/RS.png create mode 100644 tracker-rs/images/intel-16x16.png create mode 100644 tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe create mode 100644 tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe create mode 100644 tracker-rs/rs_impl/build.bat create mode 100644 tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp create mode 100644 tracker-rs/rs_impl/ftnoir_tracker_rs_impl.h create mode 100644 tracker-rs/rs_impl/udp_sender.cpp create mode 100644 tracker-rs/rs_tracker.qrc create mode 100644 tracker-udp/CMakeLists.txt create mode 100644 tracker-udp/ftnoir_ftnclientcontrols.ui create mode 100644 tracker-udp/ftnoir_tracker_udp.cpp create mode 100644 tracker-udp/ftnoir_tracker_udp.h create mode 100644 tracker-udp/ftnoir_tracker_udp_dialog.cpp create mode 100644 x-plane-plugin/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index a444bce3..0b43189c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,615 +1,31 @@ project(opentrack) cmake_minimum_required(VERSION 2.8.11) -cmake_policy(SET CMP0020 NEW) -if(POLICY CMP0058) - cmake_policy(SET CMP0058 OLD) -endif() -if(POLICY CMP0028) - cmake_policy(SET CMP0028 OLD) -endif() -if(POLICY CMP0042) - cmake_policy(SET CMP0042 NEW) -endif() - -include(CMakeParseArguments) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/) -include(GetGitRevisionDescription) -find_package(Git QUIET) -if(GIT_FOUND) - git_describe(OPENTRACK_COMMIT --tags --always --dirty) - git_describe(OPENTRACK_TAG_EXACT --tag --exact) -endif() - -file(WRITE ${CMAKE_BINARY_DIR}/opentrack-version.h "#define OPENTRACK_VERSION \"${OPENTRACK_COMMIT}\"") - -## start crapola - -set(version-string " -#include \"opentrack-compat/export.hpp\" - -#ifdef __cplusplus -extern \"C\" -#endif -OPENTRACK_EXPORT -const char* opentrack_version; - -const char* opentrack_version = \"${OPENTRACK_COMMIT}\"; -") - -set(crapola-ver) -if(EXISTS ${CMAKE_BINARY_DIR}/version.cc) - file(READ ${CMAKE_BINARY_DIR}/version.cc crapola-ver) -endif() - -if(NOT (crapola-ver STREQUAL version-string)) - file(WRITE ${CMAKE_BINARY_DIR}/version.cc "${version-string}") -endif() - -## end crapola - -SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -SET(CMAKE_SKIP_INSTALL_RPATH FALSE) -SET(CMAKE_SKIP_RPATH FALSE) -SET(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_AUTOMOC OFF) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -find_package(OpenCV 3.0) - -find_package(Qt5 REQUIRED COMPONENTS Core Xml Network Widgets Gui QUIET) -find_package(Qt5 COMPONENTS SerialPort QUIET) -include_directories(SYSTEM ${Qt5Core_INCLUDE_DIRS} ${Qt5Xml_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}) -add_definitions(${Qt5Core_DEFINITIONS} ${Qt5Xml_DEFINITIONS} ${Qt5Gui_DEFINITIONS} ${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS}) - -if(MSVC) - add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS) -endif() - -set(MY_QT_LIBS ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Xml_LIBRARIES}) - -# note, hatire supports both ftnoir and opentrack -# don't remove without being sure as hell -sh 20140922 -add_definitions(-DOPENTRACK_API) - -if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - set(CMAKE_COMPILER_IS_GNUCC TRUE) - set(CMAKE_COMPILER_IS_GNUCXX TRUE) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) - if(MINGW) - set(version-script mingw) - else() - set(version-script posix) - endif() -endif() - -if(APPLE) - set(CMAKE_MACOSX_RPATH OFF) - set(apple-frameworks "-stdlib=libc++ -framework Cocoa -framework CoreFoundation -lobjc -lz -framework Carbon") - set(CMAKE_SHARED_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_SHARED_LINKER_FLAGS}") - #set(CMAKE_STATIC_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_STATIC_LINKER_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_EXE_LINKER_FLAGS}") - set(CMAKE_MODULE_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_MODULE_LINKER_FLAGS}") - set(CMAKE_CXX_FLAGS " -stdlib=libc++ ${CMAKE_CXX_FLAGS}") -endif() - -if(CMAKE_COMPILER_IS_GNUCXX OR APPLE) - set(CMAKE_CXX_FLAGS " -std=c++11 ${CMAKE_CXX_FLAGS} ") -endif() - -set_property(GLOBAL PROPERTY USE_FOLDERS OFF) - -macro(opentrack_module n dir) - file(GLOB ${n}-c ${dir}/*.cpp ${dir}/*.c ${dir}/*.h ${dir}/*.hpp) - file(GLOB ${n}-res ${dir}/*.rc) - foreach(f ${n}-res) - set_source_files_properties(${f} PROPERTIES LANGUAGE RC) - endforeach() - file(GLOB ${n}-ui ${dir}/*.ui) - file(GLOB ${n}-rc ${dir}/*.qrc) -endmacro() - -macro(opentrack_qt n) - qt5_wrap_cpp(${n}-moc ${${n}-c} OPTIONS --no-notes) - QT5_WRAP_UI(${n}-uih ${${n}-ui}) - QT5_ADD_RESOURCES(${n}-rcc ${${n}-rc}) - set(${n}-all ${${n}-c} ${${n}-rc} ${${n}-rcc} ${${n}-uih} ${${n}-moc} ${${n}-res}) -endmacro() - -set(msvc-subsystem "/VERSION:5.1 /SUBSYSTEM:WINDOWS,5.01") -function(opentrack_compat target) - if(MSVC) - set_target_properties(${target} PROPERTIES LINK_FLAGS "${msvc-subsystem} /DEBUG /OPT:ICF") - endif() -endfunction() - -macro(opentrack_library n dir) - cmake_parse_arguments(foolib "" "LINK;COMPILE;GNU-LINK;GNU-COMPILE;STATIC" "" ${ARGN}) - if(NOT " ${foolib_UNPARSED_ARGUMENTS}" STREQUAL " ") - message(FATAL_ERROR "opentrack_library bad formals") - endif() - opentrack_module(${n} ${dir}) - opentrack_qt(${n}) - set(link-mode SHARED) - if (foolib_STATIC) - set(link-mode STATIC) - endif() - add_library(${n} ${link-mode} ${${n}-all}) - target_link_libraries(${n} opentrack-api ${MY_QT_LIBS} opentrack-compat) - if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) - SET_TARGET_PROPERTIES(${n} PROPERTIES - LINK_FLAGS "${foolib_LINK} ${foolib_GNU-LINK} -Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"" - COMPILE_FLAGS "${foolib_COMPILE} ${foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden" - ) - else() - set(link-flags) - if(MSVC) - set(link-flags "${msvc-subsystem} /DEBUG /OPT:ICF") - endif() - set_target_properties(${n} PROPERTIES LINK_FLAGS "${link-flags} ${foolib_LINK}" COMPILE_FLAGS "${foolib_COMPILE}") - endif() - if(NOT foolib_STATIC) - install(TARGETS ${n} RUNTIME DESTINATION . LIBRARY DESTINATION .) - endif() - opentrack_compat(${n}) -endmacro() - -function(link_with_dinput8 n) - if(WIN32) - target_link_libraries(${n} dinput8 dxguid strmiids) - endif() -endfunction() - -# ---- - -# cache variables - -# ---- - -IF(WIN32) - SET(SDK_VJOY "" CACHE PATH "VJoy SDK path") - SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console window visible at runtime") -ENDIF() - -IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(LINUX TRUE) -endif() - -if(LINUX OR APPLE) - set(SDK_XPLANE "" CACHE PATH "Path to X-Plane SDK") - set(SDK_ENABLE_LIBEVDEV FALSE CACHE BOOL "libevdev virtual joystick protocol support") -endif() - -SET(SDK_HYDRA "" CACHE PATH "libSixense path for Razer Hydra") -SET(SDK_HYDRA_AMD64 FALSE CACHE BOOL "whether libSixense is amd64 (else ia-32)") -SET(SDK_RIFT_080 "" CACHE PATH "libOVR path for Oculus Rift") -SET(SDK_RIFT_042 "" CACHE PATH "libOVR path for Oculus Rift") -SET(SDK_RIFT_025 "" CACHE PATH "libOVR 0.2.5 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_FSUIPC "" CACHE PATH "FSUIPC for older MS FSX path") -endif() - -if(NOT WIN32) - set(SDK_WINE_PREFIX "" CACHE PATH "Wine install prefix") - set(SDK_WINE_NO_WRAPPER FALSE CACHE BOOL "disable Wine wrapper -- use Wine only for X-Plane") -endif() - -# --- tarball - -string(TIMESTAMP filename-date "%Y%m%d") -set(filename-ostype ${CMAKE_SYSTEM_NAME}) -get_git_head_revision(filename-branch_0 filename-hash_0) -if(filename-hash_0) - string(SUBSTRING "${filename-hash_0}" 0 7 filename-hash) -endif() -string(REPLACE "refs/heads/" "" filename-branch_1 "${filename-branch_0}") -string(REPLACE "/" "-" filename-branch "${filename-branch_1}") -set(filename_0 "${OPENTRACK_COMMIT}") -set(filename_1) -if (NOT OPENTRACK_TAG_EXACT STREQUAL OPENTRACK_COMMIT) - string(TIMESTAMP filename_1 "-%Y%m%d%H%M%S") -endif() -set(filename "${CMAKE_BINARY_DIR}/${filename_0}${filename_1}.zip") - -add_custom_target(tarball-real) -add_custom_target(tarball-real2) -add_custom_command(TARGET tarball-real COMMAND cmake -P ${CMAKE_SOURCE_DIR}/cmake/tarball.cmake) - -add_custom_command(TARGET tarball-real2 COMMAND /usr/bin/env sh - "${CMAKE_SOURCE_DIR}/make-tar.sh" "${CMAKE_INSTALL_PREFIX}" - "${filename}" "${CMAKE_BINARY_DIR}") -add_custom_target(tarball DEPENDS tarball-real) - -# -- end tarball - -opentrack_module(opentrack-api opentrack) -opentrack_qt(opentrack-api) -add_library(opentrack-api STATIC ${opentrack-api-all}) -opentrack_compat(opentrack-api) -target_link_libraries(opentrack-api ${MY_QT_LIBS}) -if(NOT WIN32) - target_link_libraries(opentrack-api dl) -else() - target_link_libraries(opentrack-api winmm) -endif() - -opentrack_module(opentrack-compat opentrack-compat) -add_library(opentrack-compat STATIC ${opentrack-compat-c}) -opentrack_compat(opentrack-compat) # uh... -if(NOT WIN32 AND NOT APPLE) - target_link_libraries(opentrack-compat rt) -endif() - -# ---- - -# conditional targets - -# ---- - -set(opentrack-perms PERMISSIONS WORLD_READ WORLD_EXECUTE OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) - -if(WIN32) - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_RC_COMPILER_INIT i686-w64-mingw32-windres) - SET(CMAKE_RC_COMPILE_OBJECT " --use-temp-file -O coff -i -o ") - endif() - ENABLE_LANGUAGE(RC) -endif(WIN32) - -opentrack_module(opentrack-xplane-plugin x-plane-plugin) - -if(SDK_XPLANE) - # probably librt already included - add_library(opentrack-xplane-plugin SHARED ${opentrack-xplane-plugin-c}) - target_include_directories(opentrack-xplane-plugin SYSTEM PUBLIC ${SDK_XPLANE}/CHeaders ${SDK_XPLANE}/CHeaders/XPLM) - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC AND NOT APPLE) - SET_TARGET_PROPERTIES(opentrack-xplane-plugin - PROPERTIES LINK_FLAGS - "-Wl,--version-script=${CMAKE_SOURCE_DIR}/x-plane-plugin/version-script.txt -shared -rdynamic -nodefaultlibs -undefined_warning -fPIC" - COMPILE_FLAGS "-Wall -O2 -pipe -fPIC -DLIN -DXPLM200 -DXPLM210" - LIBRARY_OUTPUT_NAME "opentrack.xpl" - PREFIX "" SUFFIX "") - endif() - if(APPLE) - SET_TARGET_PROPERTIES(opentrack-xplane-plugin PROPERTIES - COMPILE_FLAGS "-iframework ${SDK_XPLANE}/Libraries/Mac/ -DAPL -DXPLM200 -DXPLM210 -framework XPLM -framework XPWidgets" - LINK_FLAGS "-F${SDK_XPLANE}/Libraries/Mac/ -framework XPLM -framework XPWidgets" - LIBRARY_OUTPUT_NAME "opentrack.xpl" - PREFIX "" SUFFIX "") - endif() - if(UNIX AND NOT APPLE) - target_link_libraries(opentrack-xplane-plugin rt) - endif() -endif() - -opentrack_module(opentrack-csv csv) -add_library(opentrack-csv STATIC ${opentrack-csv-c}) -opentrack_compat(opentrack-csv) -target_link_libraries(opentrack-csv ${MY_QT_LIBS}) - -opentrack_module(opentrack-pose-widget pose-widget) -opentrack_qt(opentrack-pose-widget) - -add_library(opentrack-pose-widget STATIC ${opentrack-pose-widget-all}) -opentrack_compat(opentrack-pose-widget) -target_include_directories(opentrack-pose-widget PUBLIC pose-widget/) # else Qt moc breaks -target_link_libraries(opentrack-pose-widget ${MY_QT_LIBS}) - -opentrack_module(opentrack-spline-widget qfunctionconfigurator) -opentrack_qt(opentrack-spline-widget) -add_library(opentrack-spline-widget STATIC ${opentrack-spline-widget-all}) -opentrack_compat(opentrack-spline-widget) -target_include_directories(opentrack-spline-widget PUBLIC qfunctionconfigurator/) -target_link_libraries(opentrack-spline-widget ${MY_QT_LIBS}) - -add_library(opentrack-version STATIC ${CMAKE_BINARY_DIR}/version.cc) -opentrack_compat(opentrack-version) - -opentrack_library(opentrack-filter-accela ftnoir_filter_accela) -target_link_libraries(opentrack-filter-accela opentrack-spline-widget) -opentrack_library(opentrack-filter-ewma ftnoir_filter_ewma2) - -opentrack_library(opentrack-proto-fgfs ftnoir_protocol_fg) - -if(SDK_VJOY) - opentrack_library(opentrack-proto-vjoy ftnoir_protocol_vjoy GNU-LINK "-Wl,--enable-stdcall-fixup") - if(MSVC) - set(ext .lib) - else() - set(ext .dll) - endif() - target_link_libraries(opentrack-proto-vjoy ${MY_QT_LIBS} ${SDK_VJOY}/VJoy${ext}) - target_include_directories(opentrack-proto-vjoy SYSTEM PUBLIC ${SDK_VJOY}) -endif() - -if(SDK_ENABLE_LIBEVDEV) - include(FindPkgConfig) - opentrack_library(opentrack-proto-libevdev ftnoir_protocol_libevdev) - pkg_check_modules(libevdev REQUIRED QUIET libevdev) - target_link_libraries(opentrack-proto-libevdev ${libevdev_LIBRARIES}) - include_directories(opentrack-proto-libevdev SYSTEM PUBLIC ${libevdev_INCLUDE_DIRS}) -endif() - -if(SDK_FSUIPC) - opentrack_library(opentrack-proto-fsuipc ftnoir_protocol_fsuipc) - target_link_libraries(opentrack-proto-fsuipc ${SDK_FSUIPC}/FSUIPC_User.lib) - target_include_directories(opentrack-proto-fsuipc SYSTEM PUBLIC ${SDK_FSUIPC}) - if(MSVC) - set_target_properties(opentrack-proto-fsuipc PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBC.lib") - endif() - #target_link_directories(${SDK_FSUIPC}) -endif() - -if(WIN32) - opentrack_library(opentrack-proto-simconnect ftnoir_protocol_sc) -endif() - -if(WIN32) - opentrack_library(opentrack-proto-freetrack ftnoir_protocol_ft) - target_link_libraries(opentrack-proto-freetrack opentrack-csv opentrack-compat) - opentrack_library(opentrack-proto-win32-mouse ftnoir_protocol_mouse) -endif() - -opentrack_library(opentrack-proto-udp ftnoir_protocol_ftn) - -if(WIN32) - opentrack_library(opentrack-tracker-joystick ftnoir_tracker_joystick) -endif() - -if(Qt5SerialPort_FOUND) - opentrack_library(opentrack-tracker-hatire ftnoir_tracker_hatire) - target_link_libraries(opentrack-tracker-hatire ${Qt5SerialPort_LIBRARIES}) - target_include_directories(opentrack-tracker-hatire SYSTEM PUBLIC ${Qt5SerialPort_INCLUDE_DIRS}) -endif() - -if(SDK_WINE_PREFIX) - opentrack_library(opentrack-proto-wine ftnoir_protocol_wine) - target_link_libraries(opentrack-proto-wine opentrack-compat opentrack-csv) - if(NOT SDK_WINE_NO_WRAPPER) - set(my-rt -lrt) - if(APPLE) - set(my-rt) - endif() - file(GLOB wine-deps ${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/*.cxx) - add_custom_command( - OUTPUT opentrack-wrapper-wine.exe.so - DEPENDS ${wine-deps} - COMMAND ${SDK_WINE_PREFIX}/bin/wineg++ -g -DNOMINMAX -O2 -m32 -std=c++11 -o - opentrack-wrapper-wine.exe -I "${CMAKE_SOURCE_DIR}" - ${wine-deps} - ${my-rt}) - add_custom_target(wine-wrapper ALL DEPENDS opentrack-wrapper-wine.exe.so) - add_dependencies(opentrack-proto-wine wine-wrapper) - add_dependencies(wine-wrapper opentrack-compat) - endif() -endif() - -opentrack_library(opentrack-tracker-udp ftnoir_tracker_udp) -opentrack_library(opentrack-tracker-freepie-udp ftnoir_tracker_freepie-udp) - -if(WIN32) - opentrack_library(opentrack-tracker-rs ftnoir_tracker_rs) -endif() - -if(OpenCV_FOUND) - opentrack_library(opentrack-tracker-pt ftnoir_tracker_pt) - target_link_libraries(opentrack-tracker-pt ${OpenCV_LIBS}) - target_include_directories(opentrack-tracker-pt SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) - link_with_dinput8(opentrack-tracker-pt) - - if(SDK_ARUCO_LIBPATH) - opentrack_library(opentrack-tracker-aruco ftnoir_tracker_aruco) - target_link_libraries(opentrack-tracker-aruco ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS}) - target_include_directories(opentrack-tracker-aruco SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) - link_with_dinput8(opentrack-tracker-aruco) - endif() - - opentrack_library(opentrack-filter-kalman ftnoir_filter_kalman) - target_link_libraries(opentrack-filter-kalman ${OpenCV_LIBS}) - target_include_directories(opentrack-filter-kalman 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 ${SDK_HT} ${SDK_HT_FLANDMARK} ${OpenCV_LIBS}) - link_with_dinput8(opentrack-tracker-ht) - target_include_directories(opentrack-tracker-ht SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) - endif() -endif() - -link_with_dinput8(opentrack-tracker-joystick) - -foreach(ver 025 042 080) - if(SDK_RIFT_${ver}) - set(link-flags) - set(c-flags) - if(APPLE) - set(link-flags "-framework CoreFoundation -framework CoreGraphics -framework IOKit -framework Quartz") - set(c-flags "-fno-strict-aliasing") - else() - if(NOT MSVC) - set(c-flags "-fno-strict-aliasing") - endif() - endif() - opentrack_library(opentrack-tracker-rift-${ver} ftnoir_tracker_rift_${ver} LINK ${link-flags} COMPILE ${c-flags}) - target_include_directories(opentrack-tracker-rift-${ver} SYSTEM PUBLIC - ${SDK_RIFT_${ver}}/Include ${SDK_RIFT_${ver}}/Src - ) - if(WIN32) - if(MSVC) - set(ext lib) - set(p) - else() - set(ext a) - set(p lib) - endif() - target_link_libraries(opentrack-tracker-rift-${ver} ${SDK_RIFT_${ver}}/${p}LibOVR.${ext} winmm setupapi ws2_32 imagehlp wbemuuid) - else() - if(NOT APPLE) - target_link_libraries(opentrack-tracker-rift-${ver} ${SDK_RIFT_${ver}}/libLibOVR.a udev Xinerama) - else() - target_link_libraries(opentrack-tracker-rift-${ver} ${SDK_RIFT_${ver}}/libLibOVR.a) - endif() - endif() - endif() +include(CMakeParseArguments) +include(opentrack-policy) +include(opentrack-platform) +include(opentrack-macros) +include(opentrack-qt) +include(opentrack-version) +include(opentrack-tarball) +include(opentrack-install) + +set(C CMakeLists.txt) +file(GLOB opentrack-subprojects + "tracker-*/${C}" + "protocol-*/${C}" + "filter-*/${C}" + "opentrack*/${C}" + "facetracknoir/${C}" + "x-plane-plugin/${C}" + "csv/${C}" + "pose-widget/${C}" + "spline-widget/${C}" +) +foreach(i ${opentrack-subprojects}) + get_filename_component(i ${i} DIRECTORY) + get_filename_component(j ${i} NAME) + message(STATUS "project ${j}") + add_subdirectory(${i}) endforeach() - -if(SDK_HYDRA) - opentrack_library(opentrack-tracker-hydra ftnoir_tracker_hydra) - target_include_directories(opentrack-tracker-hydra SYSTEM PUBLIC ${SDK_HYDRA}/include ${SDK_HYDRA}/include/sixense_utils) - if(WIN32) - if(MSVC) - set(dir lib) - set(ext lib) - else() - set(dir bin) - set(ext dll) - endif() - target_link_libraries(opentrack-tracker-hydra - "${SDK_HYDRA}/${dir}/win32/release_dll/sixense.${ext}" - #"${SDK_HYDRA}/${dir}/win32/release_dll/sixense_utils.${ext}" - ) - install(FILES "${SDK_HYDRA}/bin/win32/release_dll/sixense.dll" - #"${SDK_HYDRA}/bin/win32/release_dll/sixense_utils.dll" - DESTINATION . ${opentrack-perms}) - else() - if(SDK_HYDRA_AMD64) - set(underscore-sixtyfour _x64) - else() - set(underscore-sixtyfour) - endif() - if(APPLE) - set(underscore-dll _dll) - set(soext dylib) - set(sixense-plat osx) - else() - set(underscore-dll) - set(soext so) - set(sixense-plat linux) - endif() - install(FILES - "${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense${underscore-sixtyfour}.${soext}" - #"${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense_utils${underscore-sixtyfour}.${soext}" - DESTINATION . - ) - target_link_libraries(opentrack-tracker-hydra - "${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense${underscore-sixtyfour}.${soext}" - #"${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense_utils${underscore-sixtyfour}.${soext}" - ) - endif() -endif() - -if(UNIX OR APPLE) - # Qxt bundled :: sorry for this, but gentoo ebuild is broken - include_directories("qxt-mini/") - if(APPLE) - set(qxt-plat mac) - else() - set(qxt-plat x11) - endif() - file(GLOB qxt-mini-c qxt-mini/*.h qxt-mini/qxtglobalshortcut.cpp qxt-mini/plat/qxtglobalshortcut_${qxt-plat}.cpp) - opentrack_qt(qxt-mini) - add_library(opentrack-qxt-mini STATIC ${qxt-mini-all}) - target_link_libraries(opentrack-qxt-mini ${MY_QT_LIBS}) - if(NOT APPLE) - target_link_libraries(opentrack-qxt-mini X11) - endif() -endif() - -if(WIN32 AND NOT SDK_CONSOLE_DEBUG) - set(opentrack-win32-executable WIN32) -else() - set(opentrack-win32-executable "") -endif() - -opentrack_module(opentrack facetracknoir) -if(UNIX OR APPLE) - list(APPEND opentrack-c qxt-mini/qxtglobalshortcut.h) -endif() -opentrack_qt(opentrack) -add_executable(opentrack ${opentrack-win32-executable} ${opentrack-all}) -opentrack_compat(opentrack) -if(NOT WIN32) - set_target_properties(opentrack PROPERTIES SUFFIX ".bin") -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() - -if(UNIX OR APPLE) - target_link_libraries(opentrack opentrack-qxt-mini) -endif() - -link_with_dinput8(opentrack) -target_link_libraries(opentrack ${MY_QT_LIBS}) - -if(APPLE) - # for process detector - target_link_libraries(opentrack proc) -endif() - -if(LINUX) - # for process detector - target_link_libraries(opentrack procps) -endif() - -# ---- - -# make install - -# ---- - -install(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION .) - -if(SDK_XPLANE) - install(TARGETS opentrack-xplane-plugin RUNTIME DESTINATION . LIBRARY DESTINATION . ) -endif() - -install(DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty-notices DESTINATION .) - -install(FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll" DESTINATION . ${opentrack-perms}) -install(FILES "${CMAKE_SOURCE_DIR}/bin/NPClient.dll" "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe" DESTINATION . - ${opentrack-perms}) -install(DIRECTORY "${CMAKE_SOURCE_DIR}/bin/settings" "${CMAKE_SOURCE_DIR}/contrib" DESTINATION .) - -if(NOT WIN32 AND SDK_WINE_PREFIX AND NOT SDK_WINE_NO_WRAPPER) - install(FILES "${CMAKE_BINARY_DIR}/opentrack-wrapper-wine.exe.so" - DESTINATION .) -endif() - -install(TARGETS opentrack DESTINATION .) - -if(SDK_VJOY) - install(FILES "${SDK_VJOY}/VJoy.dll" DESTINATION . ${opentrack-perms}) -endif() - -if(WIN32) - install(FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config" DESTINATION .) -endif() - -if(WIN32) - install(FILES "${CMAKE_SOURCE_DIR}/ftnoir_tracker_rs/rs_impl/bin/opentrack-tracker-rs-impl.exe" DESTINATION . ${opentrack-perms}) - install(FILES - "${CMAKE_SOURCE_DIR}/ftnoir_tracker_rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe" DESTINATION ./contrib/ ${opentrack-perms}) -endif() - -if(APPLE) - install(CODE " - execute_process(COMMAND /bin/sh \"${CMAKE_SOURCE_DIR}/macosx/make-app-bundle.sh\" - \"${CMAKE_SOURCE_DIR}/macosx\" - \"${CMAKE_INSTALL_PREFIX}\" - \"${CMAKE_BINARY_DIR}\" - \"${OPENTRACK_COMMIT}\") - ") -endif() diff --git a/bin/settings/facetracknoir supported games.csv b/bin/settings/facetracknoir supported games.csv deleted file mode 100644 index cf43d7f6..00000000 --- a/bin/settings/facetracknoir supported games.csv +++ /dev/null @@ -1,576 +0,0 @@ -No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID -1;18 Wheels of Steel: Haulin';FreeTrack20;V160;V;doc-uk;13601;000121F172F35116A02100 -2;1944 D-Day;FreeTrack20;V160;;;15701;00022E542A6A0575F05200 -497;2KMarinNEXT;FreeTrack20;V170;;;3425;0D614F6A0820D1EA8EE800 -3;3D Instructor;FreeTrack20;V160;;;20490;00034B0FC367116611B100 -4;3D Interactive;FreeTrack20;V160;;;20425;0004C6371D77135815A600 -505;3D Interieur Visualisation;FreeTrack20;V160;;;20815;01F9EDEE75DAC2968D9A00 -5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00 -6;3D-Fahrschule Driving Simulator;FreeTrack20;V160;;;20020;000601075146E0E9625B00 -7;3ds Max;FreeTrack20;V160;;;8601;00077A32A1A7523A4DE700 -8;Aaaaa!;FreeTrack20;V160;;;1775;00085485D831DA62CA7E00 -9;Accessible Computer Games;FreeTrack20;V160;;;4301;000916BC07A2F9B35B6300 -10;Aces High II;FreeTrack20;V160;V;bash1;2701;000A4B798B7221A72E5800 -11;ADS;FreeTrack20;V160;;;20690;000BB25377780C8A894400 -12;Aerofly FS;FreeTrack20;V160;V;V4Friend;2025;000C3797169752CAB39A00 -13;Affineon;FreeTrack20;V160;;;20405;000D662B0374339635A000 -14;Air Battles: Sky Defender;FreeTrack20;V160;;;7003;000E7C822098630A2ED700 -15;Air Phobia;FreeTrack20;V160;;;20100;000F0108339B3E78525B00 -16;Air Traffic Control Tower;FreeTrack20;V160;;;3601;0010432C28637A8EF97400 -17;AirBook;FreeTrack20;V160;;;15201;0011D615A9C8430A201A00 -18;America's Army;FreeTrack20;V160;;;4101;00120BCF5753D98399E200 -19;America's Army 3;FreeTrack20;V170;;;14203;00133F3206BCEA252BB700 -20;ANAG 3D;FreeTrack20;V160;;;20250;0014E2D1D7780A72166300 -21;Apache: Air Assault;FreeTrack20;V160;V;paleta77;1875;001591D997A2D912AAA200 -519;Apex Motorsports;FreeTrack20;V160;;;3675;02078F3159271BBE676800 -22;Aprisoft Gartenplaner;FreeTrack20;V160;;;20014;0016F2F27A5762FA937A00 -23;Aprisoft Traumhaus Designer;FreeTrack20;V160;;;20013;00174655E792BB825B9300 -498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200 -24;ArmA;FreeTrack20;V160;V;EmBeES;10601;0018F2F27A57631A40F200 -25;ArmA 2;FreeTrack20;V170;V;V4Friend Ronski;7502;0019EB3616B3A44F05B900 -26;ArmA 2 Operation Arrowhead;FreeTrack20;V160;V;vn88holden;0;001ABC224B7783DAF0D500 -27;ArmA 3;FreeTrack20;V170;;;7503;001BB69411ABD4E2B39900 -28;Armored Assault - Gold Edition;FreeTrack20;V170;;;1303;001CA7F7CAA00814ECA700 -559;Artificial Head;FreeTrack20;V160;;;20380;022F3A9DCD1F7E0D62C000 -29;Arvoch Alliance;FreeTrack20;V160;;;14908;001D318F8773BAE29A9300 -30;Arvoch Conflict;FreeTrack20;V160;;;14901;001E5C1FDE722DAE2BA900 -31;Auditory Displays for the blind;FreeTrack20;V160;;;20035;001F0FC9FF862F9D34BA00 -486;Autodesk;FreeTrack20;V160;;;20755;01E6953FA7F759AF33AC00 -32;AV Core Technology;FreeTrack20;V160;;;20016;00204655E791166FEB5300 -33;AVRS;FreeTrack20;V160;;;20340;0021231517525830F41D00 -482;B.O.M.B.;FreeTrack20;V160;;;3325;01E248ECCB81191AD49F00 -34;BAE Systems HILAS cockpit;FreeTrack20;V160;;;20019;00220D9C887FD88E98B300 -35;Battle of Britain (iENT);FreeTrack20;V170;;;1305;00230BA119195B701AED00 -36;Battle of Britain II - Wings of Victory;FreeTrack20;V160;V;Normalguy;7001;002452135882CA6419E200 -37;Battlecruiser;FreeTrack20;V160;;;6101;00257C822098728A442900 -38;Battlefield 2;FreeTrack20;V170;;;9601;0026B1560A2A7327659200 -39;Battlefield 2 Trauma Studios;FreeTrack20;V160;;;6501;002720C7529B733AE2EA00 -40;Battlefield 2142;FreeTrack20;V170;;;9602;00281C739AD3817FD43300 -41;Battleground Europe : World War II Online;FreeTrack20;V160;;;3301;0029F07957792CAD3DAF00 -42;Battleground Europe : WWII Online;FreeTrack20;V160;;;11201;002A985017330A844A1200 -573;Beamng.drive;FreeTrack20;V160;;;4525;023D0291C9C05323AC9500 -43;Beckman Institute UIUC;FreeTrack20;V160;;;20012;002BB59DEFA8322A926A00 -44;Beyond The Red Line;FreeTrack20;V160;;;13301;002CE7A7FAA27424BA2A00 -45;BF2 (Unsupported Demo);FreeTrack20;V160;;;9651;002DC6371D86156AEB6000 -46;Big Scale Racing;FreeTrack20;V160;;;8301;002E4655E7A24ADDB99200 -47;Birds of Prey;FreeTrack20;V160;;;1601;002FBF8C4EAA57730B3200 -48;Birds of Steel;FreeTrack20;V160;;;1878;0030D7690F607233A21E00 -49;Boeing;FreeTrack20;V160;;;20351;0031044872BA630A033E00 -50;Boeing Demo;FreeTrack20;V160;;;20350;003228C57B369A37B13600 -51;Bomber Squadron;FreeTrack20;V160;;;1850;00338481733B9E32A83A00 -52;Brain-IT Group;FreeTrack20;V160;;;20050;0034E482F5772C9330B100 -53;Brothers In Arms;FreeTrack20;V160;;;13501;003503FB872CA8439D1F00 -82;C-Spine;FreeTrack20;V160;;;4901;00525FD692C188FB8B2D00 -54;C.A.R.S.;FreeTrack20;V170;;;2825;003698EFE2EB6EE8E11300 -55;C.U.B.;FreeTrack20;V160;;;20505;0037848174F986FD85F500 -56;CameraGripTools;FreeTrack20;V160;;;20150;003870A8B761FA524A4200 -57;Caterpillar Simulators;FreeTrack20;V160;;;23080;0039F52E4221742FA63100 -58;CCG Metamedia;FreeTrack20;V160;;;20009;003A6FA8A8DD86FE8BDB00 -547;CDF Ghostship;FreeTrack20;V160;;;4150;02230A04C45292CC5DA400 -568;CDF Starfighter;FreeTrack20;V160;;;4153;0238E7D9A14B2A1AE98900 -59;CEWIT Immersive Cabin;FreeTrack20;V160;;;20370;003B90B5780C90078DEE00 -60;Chopper;FreeTrack20;V160;;;3150;003CC166C8632A32EA2300 -61;Clearbox;FreeTrack20;V160;;;20565;003D5C1FDE74279D1DB800 -62;CNKFsoft;FreeTrack20;V160;;;20495;003ED7690F6073187B0000 -558;Code 10;FreeTrack20;V160;;;2975;022E45423D22193FF81900 -487;Cognitics;FreeTrack20;V160;;;20760;01E715A96D19515BFC1500 -63;Colin McRae DiRT 2;FreeTrack20;V170;V;V4Friend;8107;003F7815C5379491C73300 -64;Colin McRae Rally 04;FreeTrack20;V160;;;8103;0040D13C2A843DA526A610 -65;Comanche;FreeTrack20;V160;;;2275;00414097C36A12BA32BA00 -569;Combat Air Patrol 2;FreeTrack20;V160;;;4425;02399AAA88F5062AB14500 -66;Combat Flight Simulator 3;FreeTrack20;V160;V;V4Friend;2304;00420EC5F763AB21CA7310 -67;Combat Helo;FreeTrack20;V160;;;2001;004329DFA863FAE1EA7300 -515;Combined Arms;FreeTrack20;V160;;;1309;0203387EDB1A5AFEADB600 -68;Commandos Strike Force;FreeTrack20;V160;;;8801;0044C1BBF892DB037A7200 -555;COMPUTERGRAFIK;FreeTrack20;V160;;;20900;022B5BB1CE1DAA0B1DEB00 -69;Concept RS;FreeTrack20;V160;;;10701;004537971697736A72DA00 -70;Condor: The Competitive Soaring Simulator;FreeTrack20;V160;V;MicheleF;5901;004670A8B762DA623A1300 -71;Conflict Taiwan;FreeTrack20;V160;;;1950;0047D7690F6073399E2000 -72;Corys;FreeTrack20;V160;;;20550;0048157D78738A342A8D00 -73;Counter Strike;FreeTrack20;V160;;;12501;004953FE1E862AB73DA600 -74;Crane Simulator;FreeTrack20;V160;;;20048;004A6B62C6A7931972DA00 -567;Cranfield University;FreeTrack20;V160;;;20905;0237A8C5B26E7A38A66500 -75;Crashday;FreeTrack20;V160;;;5601;004BD6E585F893D933BA00 -76;Creanex Training Simulator;FreeTrack20;V160;;;20205;004CF478D277A40A929A00 -77;Creative Labs headset;FreeTrack20;V160;;;20018;004D348B1743E961FA6300 -78;Cross Racing Championship;FreeTrack20;V160;;;4801;004E20C763AB232B5E8900 -79;Crysis Mod;FreeTrack20;V160;;;1625;004F90B57839B231A24200 -80;Crystal Growth Simulation;FreeTrack20;V160;;;20029;005026F79742FB241A6200 -81;Crytek;FreeTrack20;V170;;;2775;0051D5F1EBBAD81C714600 -571;CS GO MOD;FreeTrack20;V160;;;12504;023BCA154A55F9587FC500 -562;Cypher City;FreeTrack20;V160;;;4250;023259070AE238A9E78100 -83;D2x-XL;FreeTrack20;V160;;;16001;00532E20237BEDABEB8A00 -84;Dark Horizons Lore;FreeTrack20;V160;;;7901;005487801A852AA7385200 -85;Dawn of Aces - Gold Edition;FreeTrack20;V170;;;1304;0055A9ED7700814190DE00 -86;Dawn of Aces II;FreeTrack20;V160;;;1302;00566925967C2BB0285500 -513;Dawn of Aces/Red Baron;FreeTrack20;V160;;;1307;0201916C14F32918D9B800 -87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200 -88;DCS: Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00 -89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91 Shadow;1003;0059B6DCD15F5A572F6500 -90;Dead Reckoning;FreeTrack20;V160;;;10401;005A4C2F6752F912D66200 -91;Delivery;FreeTrack20;V160;;;15901;005BF3E85B1A8534AE3400 -471;Demon Core;FreeTrack20;V160;;;3225;01D7D1DC6052A165A7AC00 -563;Descent: Underground;FreeTrack20;V160;;;4275;023355381D3CCBD801D700 -92;DiRT;FreeTrack20;V160;;;8104;005C72456F7523881F1800 -93;DiRT 3;FreeTrack20;V170;;;8108;005DABA016ED2DFBDF6F00 -94;Door3;FreeTrack20;V160;;;20665;005ED13C2A853DA82F6B00 -528;Dovetail Games;FreeTrack20;V160;;;3850;0210EE3E0DA9BC1B888100 -534;Dovetail Train Simulator 2015;FreeTrack20;V160;;;3851;02160B238D555F3D389E00 -95;Down In Flames;FreeTrack20;V160;;;1025;005F29DFA873FB82A66000 -96;Driver Test;FreeTrack20;V160;;;20265;00609343487C3FAA429D00 -97;Driver's Republic;FreeTrack20;V160;;;14001;0061D24C3F8A3F9C33AB00 -98;DriveSim;FreeTrack20;V160;;;5001;0062DD7CC2B47830A14400 -99;Driving Simulator;FreeTrack20;V160;;;13001;00630AC67539AC3F9F3A00 -100;dSphere TBA;FreeTrack20;V160;;;2425;0064A2AE4981FB5389A300 -101;DTS;FreeTrack20;V160;;;20625;006505B37C12868B3E8500 -102;Dungeons and Dragons Online;FreeTrack20;V170;;;1575;0066BD4D4DDC6BB6818800 -103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00 -104;EADS Testing;FreeTrack20;V160;;;20303;00680288709760D5512900 -504;EAFIT;FreeTrack20;V160;;;20810;01F8D2675ABC163E99B000 -105;Eagle Lander 3D;FreeTrack20;V160;;;11901;00697686E5A7B209C27900 -106;EasyVR;FreeTrack20;V160;;;20220;006A68292872FAC4588100 -107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500 -508;Elite: Dangerous;FreeTrack20;V170;;;3475;0D93A9485EECA12E18BE00 -481;Embers of Caerus;FreeTrack20;V170;;;3275;0CCB4134258D7E10119E00 -108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500 -109;Enemy Engaged 2;FreeTrack20;V160;;;2102;006D010873EA635AEDC800 -110;Enemy Engaged: Commanche vs Hokum;FreeTrack20;V160;;;2101;006E157D789379636AED00 -524;Enemy Starfighter;FreeTrack20;V160;;;3725;020C7EF3AC4F08C8787600 -111;Envision TE;FreeTrack20;V160;;;20320;006FD13C2A863CAF26AB00 -112;EON Reality;FreeTrack20;V160;;;20410;0070B6C6142771F82EE900 -113;eSigma;FreeTrack20;V160;;;20700;0071950F9AA60DAD2E9F00 -114;Euro Truck Simulator;FreeTrack20;V160;V;mamsa;13602;00721B4BFF8B3EA3296600 -115;EVE Online;FreeTrack20;V160;;;11801;0073F47CC377C2388DC900 -550;EVE Valkyrie;FreeTrack20;V170;;;4175;104F28E121C07E6D84C200 -116;Eventology;FreeTrack20;V160;;;12201;0074849F8B469C2BAC3600 -117;EVOC-101 Training;FreeTrack20;V160;;;20038;00756925967D2088FC6200 -118;Evochron Alliance 2.0;FreeTrack20;V160;;;14904;00767A32A1A8735A022900 -557;Evochron Legacy;FreeTrack20;V160;;;14909;022D84A6946770E4EFD800 -119;Evochron Legends;FreeTrack20;V160;;;14906;0077D6E585F8B41A12BA00 -120;Evochron Mercenary;FreeTrack20;V160;V;Scavenger4711 ;14907;00783752FBC7B42B221A00 -121;Evochron Renegades;FreeTrack20;V160;;;14905;0079621E7763FB421A1300 -122;EZCA;FreeTrack20;V160;V;dennison ;2475;007A6DBB52F7B147510601 -572;EZCamViews;FreeTrack20;V160;;;4475;023CF141A5E222B5ACE000 -125;F-22 Total Air War;FreeTrack20;V160;;;1750;007D20C79F475F0621DB00 -126;F-35 PTA;FreeTrack20;V160;;;20185;007E26F7977E96C0352100 -148;F-Trainer;FreeTrack20;V160;;;20615;0094C6371D8AFB8C3E9900 -123;F1 2011/2012;FreeTrack20;V170;;;8109;007B265ECD74893EA12900 -531;F1 2015;FreeTrack20;V170;;;8110;1FAE39C238A4D2D6541200 -124;F1 Challenge 99-02;FreeTrack20;V160;;;4401;007CA15F278FB660C9D210 -127;FAAC;FreeTrack20;V160;;;20500;007F0F00F489118300C000 -128;Farmer Simulator 2009;FreeTrack20;V160;;;1725;0080926ED8A1EB628AB300 -129;Faros Driving Simulator;FreeTrack20;V160;;;8001;0081B1C6647A1EA839A800 -130;Faubert Lab Car Simulator;FreeTrack20;V160;;;20480;00822E542A7F2DB61F9700 -131;Ferrari Virtual Academy;FreeTrack20;V160;V;sosna1983 ;0;0083C0AF8C24B62D974000 -132;FIFA 09;FreeTrack20;V170;;;9002;0084288979C65B0DAA0D00 -133;Fighter Ace;FreeTrack20;V160;;;8401;0085E2D1D77D259837B700 -134;Fighter Ops;FreeTrack20;V160;;;9301;00860FC9FF8B23A033BA00 -135;Fighter Squadron: Screamin Demons Over Europe;FreeTrack20;V160;;;1675;00872E20237D259A27A600 -136;First Eagles Wings Over Europe Strike Fighters;FreeTrack20;V160;;;1101;0088311857638A73BB7E00 -469;Flight Gear;FreeTrack20;V160;;;12901;01D5D896C66B030606E000 -466;Flight Simulator 2002;FreeTrack20;V160;;;2302;01D21F7650E254B4514B00 -467;Flight Simulator 2004;FreeTrack20;V160;;;2303;01D3E91BAAB385B2362E00 -468;Flight Simulator X;FreeTrack20;V160;;;2305;01D41C31F42FAF32603600 -137;FlightGear;FlightGear;V110;V;V4Friend;0;0089054E8839A02FAB2F00 -138;Flyboys / Warbirds;FreeTrack20;V160;;;1301;008ABB5BF72C8934AB2B00 -139;Flyer;FreeTrack20;V160;;;1650;008BD1C9F27826AE2CA500 -140;Flying Tigers;FreeTrack20;V160;;;7002;008C91D997F29A930B0200 -141;FlyingGuns;FreeTrack20;V160;;;14801;008D7A32A1A882BAA28A00 -142;Ford Racing 3;FreeTrack20;V160;;;6901;008E27D5047C2BA62F5800 -561;Forklift Simulator;FreeTrack20;V160;;;20885;02314A30F16DAF63EABB00 -542;Fractured Space;FreeTrack20;V170;;;3976;0F88A4D88906429E684E00 -143;Free Falcon 4.0;FreeTrack20;V160;;;1901;008F157D78A3B962E55000 -144;Free Falcon 4.0: Allied Force;FreeTrack20;V160;;;8901;0090656DD6793CA9325900 -145;Free Falcon 5;FreeTrack20;V160;V;V4Friend;1902;00911038C3AAB32590E900 -146;FreeSpace2;FreeTrack20;V160;;;13302;0092C8CDF8C2EA63496300 -552;FSX Steam Edition;FreeTrack20;V160;;;3852;02287F45F0FFBEF6102900 -147;FTAlpha;FreeTrack20;V160;;;20270;00936C69677F1D772AA900 -149;Full Out;FreeTrack20;V160;;;1701;009527D5047C31A0375800 -150;Future Pinball;FreeTrack20;V160;V;V4Friend;13101;00969343487E42B541AA00 -151;Game VR;FreeTrack20;V160;;;20325;009756BA018030B0355500 -152;GameLab;FreeTrack20;V160;;;20555;00985485D891DB23092200 -472;Games Farm;FreeTrack20;V160;;;3250;01D875C0981E627E5C7600 -153;Gamma;FreeTrack20;V160;;;1050;009921007D1B9D38A76F00 -503;Garry's Mod;FreeTrack20;V160;;;12503;01F74EEB71FA7F37856900 -532;Gavap Simulator;FreeTrack20;V160;;;20850;0214C254E2B970AA7A6200 -483;Generic Robotics;FreeTrack20;V160;;;20750;01E3FE7B4F05872A415400 -548;Ghostship Aftermath;FreeTrack20;V160;;;4151;02243F473BAD82FFD14A00 -475;Glider Sim;FreeTrack20;V160;;;20720;01DB42130C4B0620871C00 -154;Global Ground Support Deicing Simulation;FreeTrack20;V160;;;20330;009ACFE709237A3AA11F00 -546;GoD Factory: Wingmen;FreeTrack20;V160;;;4125;0222C0ECA71AD9C75AD100 -155;GosNIIAS Sim Trainer;FreeTrack20;V160;;;20355;009BB78B06EC8A2DB81800 -156;Gothic 3;FreeTrack20;V160;;;14401;009C37971697B36AD32A00 -157;Grand Prix Legends;FreeTrack20;V160;;;6701;009D521358D3D933B96E01 -158;Grand Theft Auto: San Andreas;FreeTrack20;V160;;;7808;009E5F3D95777D3BA23700 -159;GRID;FreeTrack20;V160;V;LeapoEclipse ;8105;009FD8175F8D1D7C0D3800 -160;GSE Power Plant Simulation;FreeTrack20;V160;;;20044;00A0432C28C217BEF93300 -161;GT Legends;FreeTrack20;V160;V;TrickyDee ;3902;00A116BC08020581CA8200 -162;GTR;FreeTrack20;V160;;;3901;00A2FD6BFE39A881B85B00 -163;GTR2 EVO;FreeTrack20;V160;V;zild1221 ;0;00A34B0FC37B2198F96300 -164;Gun Commander;FreeTrack20;V160;;;2675;00A4E2D1D77E319FEE8600 -520;H1Z1;FreeTrack20;V170;;;6004;1774F090B1BA9E782D0800 -165;Half Life 2;FreeTrack20;V160;;;7806;00A556BA018130AF365500 -166;Halo;FreeTrack20;V160;;;3801;00A656BA018130AF3F9C00 -502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00 -167;Hardware Control Simulator Railway Electronics;FreeTrack20;V160;;;20705;00A7F3E85B1A8930B42F00 -168;Harrier Attack II;FreeTrack20;V160;;;1175;00A8F2F27A57D20A940900 -499;Harry's Hard Choices Interactive;FreeTrack20;V160;;;20800;01F33A21BAE3DB6D48A000 -169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000 -170;Herissons (Paris France);FreeTrack20;V160;;;20001;00AAEA1CBED8C20B430B00 -523;hiCRANE2;FreeTrack20;V160;;;20835;020BA8FC8C7DFFA1381A00 -171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900 -172;HoverAssault;FreeTrack20;V160;;;5303;00AC521358E3AA832A4000 -173;HPC;FreeTrack20;V160;;;20600;00AD0FC9FF8D0A7CEF9500 -174;HPG Tracking;FreeTrack20;V160;;;20255;00AE0288A1879D98930900 -175;HTW;FreeTrack20;V160;;;20630;00AF26F797911901C22C00 -176;Huawei Software;FreeTrack20;V160;;;20660;00B04655E8030A733AB300 -177;HueSpace;FreeTrack20;V160;;;20510;00B1231517C44960FB6300 -178;Hyper Vision;FreeTrack20;V160;;;15101;00B2DB242B657D43B32300 -179;iAmFootball;FreeTrack20;V160;;;1250;00B3B59DEFAAAFDB301A00 -180;id Research;FreeTrack20;V170;;;2950;00B4E723B873D7FC87D700 -181;IESA;FreeTrack20;V160;;;20037;00B5157D78D0E840AD7100 -182;IL-2 Cliffs of Dover;FreeTrack20;V160;V;V4Friend;0;00B6282282095F00521000 -183;IL-2 Forgotten Battles ACE Pacific Fighters;FreeTrack20;V160;V;Glenn;1001;00B722FD79137100621100 -484;IL-2 Sturmovik: Battle of Stalingrad;FreeTrack20;V170;;;1008;03F04D5368D1FD2DF2AE00 -184;Illumina;FreeTrack20;V160;;;1350;00B8054E8B39A33DB02400 -185;ILP;FreeTrack20;V160;;;20310;00B9F07957801789C9A600 -186;Imagine 3D ATC Tower Simulation;FreeTrack20;V160;;;20032;00BAEF7A8F4B8812B95300 -187;In Touch Technologies Inc.;FreeTrack20;V160;;;20006;00BB84817A3A5124B23D00 -188;Inglobe;FreeTrack20;V160;;;20360;00BCE7A7FAA27B2DA82700 -189;Innovatec Simulator;FreeTrack20;V160;;;20036;00BD22FD7935B23DB82C00 -190;Insurgency;FreeTrack20;V160;;;9401;00BEB6C61427B3EA744B00 -575;Interstellar Rift;FreeTrack20;V160;;;4550;023FF83230A370CBC6AC00 -191;Intific;FreeTrack20;V160;;;20655;00BF2BCA747F2AA8309D00 -566;Into the Dungeon;FreeTrack20;V160;;;4375;0236B346990ACCFC047A00 -192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900 -193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00 -536;ISAMM;FreeTrack20;V160;;;20860;0218303730165E681DB000 -194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00 -506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100 -195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00 -196;J.J. Keller and Associates;FreeTrack20;V160;;;20002;00C4E482F57FE77CF46300 -197;Janes F18;FreeTrack20;V160;;;9001;00C55F3D9577802AAF2E00 -198;Javal Ent.;FreeTrack20;V160;;;2650;00C622FD7A28BA2FAEEA00 -199;JC Demo;FreeTrack20;V160;;;20470;00C70AC67B0A630D9B3900 -200;Jet Thunder;FreeTrack20;V160;;;4501;00C82100801FA4EA9A3500 -201;Jetfighter V;FreeTrack20;V160;;;2501;00C9F52E42217B33A63200 -202;JFIST;FreeTrack20;V160;;;20560;00CAC932727C0F8D208600 -203;John Deere Vehicle Simulator;FreeTrack20;V160;;;20175;00CB29DFA8D3FA92A66000 -204;Jump to Lightspeed;FreeTrack20;V160;;;6001;00CCC166C8D3FA12E52400 -205;Jumpgate;FreeTrack20;V160;;;15001;00CD26F797B32A63E99200 -206;Jumpgate Evolution;FreeTrack20;V170;;;15002;00CE5936D4F93DCE0CE700 -207;KAF Keymapper;FreeTrack20;V160;;;3101;00CF934348830E87EB8300 -476;KAI FLight Simulator;FreeTrack20;V160;;;20725;01DCC522132A5C01EDE500 -560;Keita Head Tracking;FreeTrack20;V160;;;20385;02307E33478667072B0800 -208;Key Macro View;FreeTrack20;V160;;;12001;00D016BC08431B1EF90100 -209;kiwi.vg;FreeTrack20;V160;;;20395;00D1409A430AB33633E900 -521;Kongsberg GlobalSim;FreeTrack20;V160;;;20825;0209B2C573D990BF764700 -210;L-3;FreeTrack20;V160;;;20465;00D2F885EFA8DE67878B00 -211;L-3 Communications;FreeTrack20;V160;;;20051;00D3D6E585F92F765E7800 -522;LG Electronics;FreeTrack20;V160;;;20830;020A3678F5833D513DCA00 -212;Lionhead MGS Game Research;FreeTrack20;V160;;;15301;00D4C1BBF9227B238AE200 -213;Live For Speed;FreeTrack20;V160;V;zild1221 ;7101;00D528228526A833521300 -214;Live for Speed S2;FreeTrack20;V160;;;11601;00D63752FBC8235B923500 -218;Lock-On: Modern Air Combat;FreeTrack20;V160;;;1002;00DAAC156D903C993B6200 -215;Lockheed Martin Littoral Combat Ship simulator;FreeTrack20;V160;;;20025;00D771ED5E802A9827A000 -216;Lockheed Martin Prepar3D;SimConnect;V130;V;elelbe ;0;00D8D615A9C8F36932AA00 -217;LockOn: Flaming Cliffs 2;FreeTrack20;V170;V;EmBeES ;1005;00D9AFB0D279F3A6F72200 -219;London NHS;FreeTrack20;V160;;;20640;00DB2E2023832BA123A100 -220;Lore (Dark Horizons);FreeTrack20;V160;;;5302;00DCF478D27833DB62D500 -221;Love;FreeTrack20;V160;;;3125;00DD71ED5E802AAB214800 -222;Lucid Engine;FreeTrack20;V160;;;10501;00DE71ED5E803098259C00 -514;M4 Tank Brigade;FreeTrack20;V160;;;1308;02024ED5A3A26741604300 -223;M4 Tank Platoon;FreeTrack20;V160;;;1306;00DFDCC441A8E036320900 -224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000 -549;MAG WIP;FreeTrack20;V160;;;4152;02252A1C82FD29D9FFB900 -225;ManuVAR;FreeTrack20;V160;;;20455;00E153FE1E901CB0448800 -226;MaqSIM4;FreeTrack20;V160;;;20026;00E28F54A207D29B611700 -227;Mech Tactical Sim;FreeTrack20;V160;;;9501;00E3F3E85B1A8E34A53300 -228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200 -516;MechWarrior Online;FreeTrack20;V170;;;3026;0BD2E0DCBC723836CD2400 -229;Medical Image Visualization;FreeTrack20;V160;;;20295;00E59343488532A5359B00 -230;Meggitt Defense Systems;FreeTrack20;V160;;;20045;00E6926ED9122AB22AF300 -231;MetaVR;FreeTrack20;V160;;;20545;00E7C5BEE48120A8308800 -232;Meteoroid Maze;FreeTrack20;V160;;;13003;00E8F079578430AD2EB200 -233;MeVEA;FreeTrack20;V160;;;2250;00E9D24C3F933289028700 -234;Micro Flight;FreeTrack20;V160;V;V4Friend;5101;00EABA89D078439932EA00 -235;Microsoft ESP;FreeTrack20;V160;;;2306;00EB0AC67E30A63BA53F00 -236;Microsoft Flight;FreeTrack20;V170;V;V4Friend;2307;00ECAFBC54959539C51500 -237;Microsoft Flight Simulator 3;FreeTrack20;V160;V;V4Friend;0;00ED5909437D36963EA810 -238;Microsoft FS2002/2004;FSUIPC;V130;V;V4Friend;0;00EE44958F34992CB43A00 -239;Microsoft FSX;SimConnect;V130;V;V4Friend;0;00EFF478D278437A73AA00 -240;Microsoft Train Simulator;FreeTrack20;V160;;;7805;00F00449225A439A13FB00 -494;MiddleVR;FreeTrack20;V160;;;20785;01EE1227DF43CA90C26100 -241;Mig Alley;FreeTrack20;V160;;;1501;00F17686E5A83289CDA700 -242;Mimik Vehicle Simulator;FreeTrack20;V160;;;20585;00F2AB1D58A8E35A531A00 -243;Miner Wars;FreeTrack20;V160;;;2550;00F3C5BEE48124A234A400 -244;MKMapper Keymapper;FreeTrack20;V160;;;2201;00F487801A8E14822EA200 -245;ModelSim;FreeTrack20;V160;;;20540;00F544958F3A9A1FB11A00 -246;Morgan State University;FreeTrack20;V160;;;20010;00F65909437D3CA5339A00 -247;Motor Company;FreeTrack20;V160;;;11501;00F70288F37A629A7DD700 -248;Motorsport Simulators;FreeTrack20;V160;;;4201;00F8F52E42217E3DA63B00 -249;Mouse Emulation;FreeTrack20;V160;;;8501;00F9950F9A8E29B93A9700 -250;MS World Tour Kart 2004;FreeTrack20;V160;;;6601;00FA9F819CA27F10591600 -251;MSN Virtual Earth;FreeTrack20;V160;;;2309;00FBF47CC37842091DC900 -252;mTBI Balance;FreeTrack20;V160;;;20420;00FC72456F9E0E78145800 -253;NASA Crew Exploration Vehicle;FreeTrack20;V160;;;20017;00FD028900985FA5501A00 -254;NASCAR Heat;FreeTrack20;V160;;;2602;00FE311857E10880B84100 -255;NASCAR Racing 2003 season;FreeTrack20;V160;;;7804;00FFDE661F6D920B87FC10 -256;NASCAR SimRacing;FreeTrack20;V160;;;6201;01004098708870D761A500 -535;Navi Trainer Professional;FreeTrack20;V160;;;20855;0217C0E0793305EE8D5200 -257;NecroVisioN;FreeTrack20;V160;;;15601;0101621E77F2EA830A8100 -258;NetKar Pro;FreeTrack20;V160;V;sosna1983 ;10901;01028C3958334A5169A300 -259;Nitro Stunt Racing;FreeTrack20;V160;;;13901;0103C0AF9428B82DA5ED00 -260;North Eastern University;FreeTrack20;V160;;;20003;0104A2AE4823BB7449DE00 -261;Novint;FreeTrack20;V160;;;2725;01051C76F8137B823A4300 -262;NVH Sound Simulator;FreeTrack20;V160;;;20695;010655A2AA93158DDE9500 -479;OHJCH;FreeTrack20;V160;;;20740;01DF992E6C0DA43A703600 -551;Omni-Directional Movement;FreeTrack20;V160;;;20870;0227088B794053785DBE00 -263;OMSI Bus Simulator;FreeTrack20;V160;V;Thiago ;2225;0107F47CC37861A9606600 -264;Onadime - Realtime Animation;FreeTrack20;V160;;;20049;010853FE1E9229A3339B00 -265;Open Falcon 4.5;FreeTrack20;V160;V;muplex ;0;0109B1C664832D9B385500 -266;Operation Air Assault 2;FreeTrack20;V160;;;5401;010ABB5BF72C9238973B00 -267;Operation Flashpoint 2 (inactive);FreeTrack20;V160;;;7601;010BD1C9F2812A9A399400 -268;Operation Flashpoint(r): Dragon Rising(tm);FreeTrack20;V170;;;8106;010C3328780E1322676100 -269;OptiMetrics;FreeTrack20;V160;;;20011;010D55A2AA942FB9288F00 -270;OpusFSX;FreeTrack20;V160;;;3175;010E1C76F8238B72D7C100 -271;Orbiter 2005 Plug-In;FreeTrack20;V160;;;10301;010F87801A903B9736A600 -272;Orbiter 2006;FreeTrack20;V160;V;Ripley;10303;0110D24C3F953F9526BA00 -273;Orbiter 2006 Plug-In;FreeTrack20;V160;;;10302;0111054E913F9931B72000 -274;Oryx Vehicle Simulators;FreeTrack20;V160;;;20028;0112C8CDF952EBA4763100 -275;Outer Conflict: Frontiers;FreeTrack20;V160;;;1900;01136C6967883EAA23AB00 -276;Over Flanders Fields;FreeTrack20;V160;V;Summelar ;2325;0114A59E68873E9B315210 -277;PanoPro;FreeTrack20;V160;;;20525;0115B6C61428231A23E900 -278;Paraworld;FreeTrack20;V160;;;14501;0116656DD6832BB62EB000 -279;Phoenix R/C;FreeTrack20;V160;;;3075;0117B6C61428238A334B00 -280;Pivot Maritime;FreeTrack20;V160;;;20365;01187686E5A8628AB2AA00 -281;PlanetSide 2;FreeTrack20;V170;;;6002;0119BB34B53FDC5C5AAF00 -474;PlanetSide 2 M.E.;FreeTrack20;V160;;;6003;01DA321EF31DA48C159A00 -282;Pointman;FreeTrack20;V160;;;7525;011ACFE70923833D9B2B00 -538;Police 1013;FreeTrack20;V160;;;3925;021ABAE5040512FE42CA00 -283;Power Driving Simulator;FreeTrack20;V160;;;20675;011BB78B06EC932DBC2F00 -470;Prepar3D;FreeTrack20;V160;;;20440;01D6DA768CE8AA43D8DC00 -284;Priston Tale;FreeTrack20;V160;;;9701;011C849F9642A030AC3600 -285;Project Reality (BF2 Mod);FreeTrack20;V160;;;9201;011D3C2C1C922CB239A800 -286;Project Torque (Invictus);FreeTrack20;V160;;;4802;011E612F28540B52797100 -287;Project X;FreeTrack20;V160;;;20022;011FE9D85E4842DA439900 -529;Puegeot PSA Simulator;FreeTrack20;V160;;;20840;021127A7344E7C044E9500 -545;PULSAR: Lost Colony;FreeTrack20;V160;;;4075;02214BC732C034C3620400 -553;QSTP;FreeTrack20;V160;;;20875;0229A3C108BE55FFF2BC00 -288;Quanser;FreeTrack20;V160;;;20435;0120950F9A922FA535A500 -289;QuantaDyn;FreeTrack20;V160;;;20575;012199BB5C9433A739B600 -290;Quest 3D Xframe Plugin;FreeTrack20;V160;;;20043;0122FD6BFE39A923C98200 -291;Quest3D;FreeTrack20;V160;;;1425;01234B0FC38542AB3BB700 -292;Quest3D - CINEACT integration;FreeTrack20;V160;;;20040;0124A15F28340AB3CA9000 -303;R-concept X (AdrenalinStorm);FreeTrack20;V160;;;9101;012F72456F83E6993AA600 -293;R.U.D.O. Tools;FreeTrack20;V160;;;20039;0125612F287FB9BEA76E00 -294;RACE (the WTCC game);FreeTrack20;V160;;;3904;01263C2C1C94FA86146300 -295;RACE 07 RACE GTR 2;FreeTrack20;V160;V;zild1221 TrickyDee ;3903;0127C0AF9800870056FD00 -296;RaceOn;FreeTrack20;V160;V;zild1221 ;0;0128621E7832AA82388200 -297;Racer;FreeTrack20;V160;;;2401;01296D2D103862E932EA00 -298;Racer S;FreeTrack20;V160;;;20030;012AEA1CBED961CA52CB00 -490;RaceRoom Racing Experience;FreeTrack20;V160;;;3905;01EA9124F663AF03BBC500 -299;Rail Simulator 1;FreeTrack20;V160;;;1550;012BB253778929A0395900 -300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100 -301;RailWorks 2;FreeTrack20;V160;;;2750;012D3919C4972D9D299000 -507;RailWorks 5 (TS2014);FreeTrack20;V160;;;1551;01FB8B5232CB1502C95A00 -302;Raydon Driving Simulator;FreeTrack20;V160;;;3701;012E5485D941DBE2FB5300 -574;RCPlugin;FreeTrack20;V160;;;23090;023E0448BCFD48E0149D00 -304;Real Time Visual;FreeTrack20;V160;;;9901;0130B1C664862297365500 -305;RealFlight;FreeTrack20;V160;;;4001;0131AC6E87892E993A8B00 -306;Reality Manager;FreeTrack20;V160;;;20046;0132DB242B65872FA42A00 -307;RealWorld;FreeTrack20;V160;;;20215;0133B59DEFA9322A727800 -308;Red Baron 3D;FreeTrack20;V160;;;1125;0134C6371D96349CEB7A00 -309;Red Orchestra: Heroes of Stalingrad;FreeTrack20;V170;;;12602;013521F9121056CD997300 -310;Red Orchestra: Ostfront;FreeTrack20;V170;;;12601;01369A9A2BE97252BB9000 -311;Redline Monitor;FreeTrack20;V160;;;20210;01373752FBC8831A72AA00 -312;REFLEX XTR;FreeTrack20;V160;;;2150;0138054E94127D14881300 -313;Remote Presence;FreeTrack20;V160;;;20710;01399BC3BDA93229D2BB00 -314;rFactor;FreeTrack20;V160;V;V4Friend;7401;013AEF7A8F4B8AA0495200 -315;rFactor Pro;FreeTrack20;V170;;;7403;013B175198D74BE8E89600 -316;rFactor2;FreeTrack20;V170;;;7402;013CBFF3A86D34DA24C000 -533;rFPro;FreeTrack20;V170;;;7404;1CEC6BE26009B31DE7BC00 -317;Richard Burns Rally;FreeTrack20;V160;V;zild1221;3401;013D42868B339A31A73C10 -318;RidingStar;FreeTrack20;V160;;;1475;013E3919C497359826A700 -544;Rift's Cave;FreeTrack20;V160;;;4050;02209C681EAD3B06D15A00 -319;Rig N Roll;FreeTrack20;V160;;;9801;013FD1C9F284239CE68100 -320;Rio Tinto Resource Development;FreeTrack20;V160;;;20033;01401039831B5EC8D31900 -321;Rise of Flight;FreeTrack20;V160;V;Seborgarsen ;11401;0141AA71218335A51F5100 -322;Rise: The Vieneo Province;FreeTrack20;V160;;;6301;0142DEE3582F9837A82D00 -323;Rising Conflicts;FreeTrack20;V160;;;12101;014384818335A439B12F00 -492;RITS;FreeTrack20;V160;;;20775;01ECEE745B83DD3A0DBE00 -324;Road Legends;FreeTrack20;V160;;;1876;0144379716986369A2E600 -325;Rogue Space;FreeTrack20;V160;;;3050;014588F5872C9C30ABE900 -326;Rogue Warrior;FreeTrack20;V160;;;14202;0146432C2973D9D45A8E00 -530;RoRo Simulator;FreeTrack20;V160;;;20845;02123A5F2F98EF4D0F0700 -327;ROV Sim;FreeTrack20;V160;;;20530;0147FA04BD27891D9ADD00 -328;Rowan's Battle Of Britain;FreeTrack20;V160;;;1502;014821008829A72CB4F300 -329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00 -330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200 -331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400 -540;Rust;FreeTrack20;V170;;;3950;0F6EF7CEF7DFA93405D700 -511;Sail;FreeTrack20;V160;;;3575;01FF2916D764159099F800 -332;Sail Simulator 5;FreeTrack20;V160;;;1975;014CE2D1D78A1D9A3B6300 -333;Sailors of the Sky;FreeTrack20;V160;;;10201;014D17BE02961FAF3AB100 -334;Santa Cruz Watermill;FreeTrack20;V160;;;20290;014E88F5881EA32FA7E900 -335;SCANeR Studio Plugin;FreeTrack20;V160;;;20445;014FA2AE4870F861E9A100 -336;SEGA Demo;FreeTrack20;V160;;;2075;015016BC08C117F1163000 -337;Seven-G;FreeTrack20;V160;;;2350;01510F00F49635B822A200 -338;SFSPC;FreeTrack20;V160;;;2801;0152F885EFA9400981B700 -339;Ship Simulator 2006;FreeTrack20;V160;;;5002;015329DFA9638AA2C66100 -340;Ship Simulator 2008;FreeTrack20;V160;V;djj3ff ;5003;01545213599339B3D52100 -341;Shiphandling Simulator;FreeTrack20;V160;;;20570;01553FD0FC9D8B37AD3700 -554;ShiVa;FreeTrack20;V160;;;4225;022AA2A7DC2F7222696C00 -342;Shooting Simulator;FreeTrack20;V160;;;20047;0156F2F27A58827A63DA00 -343;SIA Games;FreeTrack20;V160;;;20015;0157926ED970685DA8D200 -344;Silent Wings;FreeTrack20;V160;;;8701;0158D615A9C96309C24A00 -345;SilverHat;FreeTrack20;V160;;;12401;0159D8175F99349F3F9600 -346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00 -347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00 -348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00 -518;SimCraft;FreeTrack20;V160;;;3650;02065BA013963203CB1900 -349;SimCreator;FreeTrack20;V160;;;20520;015D3752FBC8935B001A00 -350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100 -351;SimQuest immersion system;FreeTrack20;V160;;;20023;015F6C69678C32A30FAE00 -352;SimSol;FreeTrack20;V160;;;20034;01602315187389E0FB5300 -491;Simumak;FreeTrack20;V160;;;20770;01EB119629980784DCE600 -510;Sir You Are Being Hunted;FreeTrack20;V160;;;3550;01FEDAB345FA104ED4A100 -353;Sirocco Racing;FreeTrack20;V160;;;5801;01612BCA748925A6369A00 -354;Sky God: Military Freefall;FreeTrack20;V170;;;1526;01622C0104385FD1C44400 -355;Soft fx Demo;FreeTrack20;V160;;;2125;01632E20238A2B99335200 -537;Solitude;FreeTrack20;V160;;;3875;02199BA2A9B217BB4B7200 -356;Source Engine (Half-Life 2);FreeTrack20;V160;;;12502;0164E482F58829A739A600 -357;Space Shuttle Mission 2007;FreeTrack20;V160;V;purewhitewings ;1225;0165662B03863D912F9700 -517;Spaze;FreeTrack20;V160;;;3625;020573F9D3ED8C43B8DC00 -358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100 -359;Stanford University;FreeTrack20;V160;;;20004;0167CE35BAF9933A62AA00 -500;Star Citizen;FreeTrack20;V170;;;3450;0D7AF4CE4E343EC6B4A200 -360;Starshatter;FreeTrack20;V160;;;6401;0168F079578A3F9A3BB600 -361;Steel Beasts 2;FreeTrack20;V160;;;11703;0169DCC441A9443A831A00 -362;Steel Beasts Pro;FreeTrack20;V160;;;11701;016A8F54A20833CAA23900 -363;Steel Beasts Pro Personal;FreeTrack20;V160;;;11702;016BF3E85B1A9443A73000 -565;Steel Beasts Professional;FreeTrack20;V160;;;4350;02356C64A9AFBB37E56E00 -364;Stoked Rider;FreeTrack20;V160;;;14701;016CC166C963EA32997300 -365;Storm of War: the Battle of Britain;FreeTrack20;V170;;;11001;016D8F54A68B71F25D0200 -495;STRAFT;FreeTrack20;V160;;;3375;01EF1329E014ADF98D6B00 -366;Stride;FreeTrack20;V170;;;2310;016EC784B21E4B21984400 -541;Strike Suit Zero;FreeTrack20;V170;;;3975;0F87E77F3BD3DB8821A200 -367;STS Driving Simulator;FreeTrack20;V160;;;20300;016FA59E688B1C89DE7600 -368;Sunaerosys;FreeTrack20;V160;;;20475;01700449831AF28973EB00 -369;Superkarting;FreeTrack20;V160;;;14903;0171DE661F6D973FA41F00 -370;SuperX Research;FreeTrack20;V160;;;15401;0172BA89D078A45A021A00 -371;SWRI Demo;FreeTrack20;V160;;;20230;01730AC6841E9512561000 -372;Syncon Robot Control;FreeTrack20;V160;;;20415;0174C1BBF9937B12DB5200 -373;Synergy Simulation;FreeTrack20;V160;;;20595;0175926ED9736B220B8200 -374;T and TS Corp.;FreeTrack20;V160;;;20005;017617BE0297DDA73CA600 -539;Tacview;FreeTrack20;V160;;;20865;021B1F0CFB651B91405C00 -375;Take On Helicopters;FreeTrack20;V170;;;7504;0177513CB40C0623B96A00 -376;Target: Korea;FreeTrack20;V160;;;1201;0178F52E4221852FA43300 -377;Target: Rabaul;FreeTrack20;V160;;;1202;0179E9D85E4881CA736900 -378;Targeting Demo;FreeTrack20;V160;;;13002;017AAB1D58A952DAA2F900 -379;TD Demo;FreeTrack20;V160;;;1925;017BC5BEE488FE54139700 -489;TeachLive;FreeTrack20;V160;;;20765;01E905245B5AC5484FC100 -380;Telepresence;FreeTrack20;V160;;;20450;017CF478D278B33B02DA00 -381;Tenstar Simulator;FreeTrack20;V160;;;20605;017D318F88A2EA62DBA200 -382;Test Drive Unlimited;FreeTrack20;V160;;;13201;017E6F2699559730A84000 -509;Tetrahedral;FreeTrack20;V160;;;3525;01FDCFF1C56D6F757E8200 -501;The Crew;FreeTrack20;V170;;;1009;03F1F534E94F4834D9B100 -488;The Gallery;FreeTrack20;V160;;;3350;01E8CE152EDE5FFD267700 -383;The Sky Gods;FreeTrack20;V170;;;1525;017FDFF782DCCEEA27C200 -384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000 -385;thriXXX HII 3D;FreeTrack20;V160;;;13403;0181FA04BD27AB36B62700 -386;thriXXX Jenna;FreeTrack20;V160;;;13401;01829F819CA2A625AB2800 -387;ThriXXX Technology;FreeTrack20;V160;;;13402;0183F47CC378B35B526900 -388;tir2joy;FreeTrack20;V160;;;2202;018487801AB532A7FE9C00 -389;TIRF4;FreeTrack20;V160;;;2203;0185311858418870E77000 -390;TNO;FreeTrack20;V160;;;20285;01861AAF6870A853D64900 -391;ToCA Race Driver 2;FreeTrack20;V160;;;8102;0187FFE9E886F286297910 -392;Toca Race Driver 3;FreeTrack20;V160;;;8101;01884098D36972B551A900 -393;Tom Clancy's H.A.W.X.;FreeTrack20;V170;V;EmBeES ;1004;0189AA4D48E85966FBAA00 -394;Tom Clancy's H.A.W.X. 2;FreeTrack20;V170;;;1007;018A1B7583521C12406F00 -395;Torque Game Engine;FreeTrack20;V160;;;5301;018BC0AF9A2EB62CAB3300 -396;Total War;FreeTrack20;V160;;;1375;018C72456F8529AA2CA400 -397;Tower Crane Simulator;FreeTrack20;V160;;;20670;018D03FB9929B034A7D900 -398;Tower I;FreeTrack20;V160;;;1325;018E662B03873CA731A400 -399;TPL Testing;FreeTrack20;V160;;;20260;018F849F9A2083DC8C2C00 -400;trackd;FreeTrack20;V160;;;20580;019053FE1EB72DA3329D00 -401;TrackMapper2;FreeTrack20;V160;;;2175;0191CE35BAF9A31A61FA00 -402;TrainMaster;FreeTrack20;V160;;;20042;01925C1FDE852D9925B400 -403;Trainz;FreeTrack20;V160;;;4701;0193D1C9F2862C9630A100 -404;TraumTek;FreeTrack20;V160;;;20650;0194A2AE4883EA645A2100 -405;Turismo Carretera;FreeTrack20;V160;;;15801;01956F2699559740A73500 -406;UK Rally Champion;FreeTrack20;V160;;;5701;019679EC0E28B196522A00 -407;ULAN;FreeTrack20;V160;;;20645;01974ADE68E16780D97A00 -473;Underwater Navigation;FreeTrack20;V160;;;20715;01D9FE2B94FB03772DE200 -408;Unity 3D Plugin;FreeTrack20;V160;;;20430;0198D24C3F9B3B9C31BF00 -525;Unity 64-bit;FreeTrack20;V160;;;3750;020DC8AB18AF3539FA5200 -556;Unity Plugin (64-bit);FreeTrack20;V160;;;20880;022C55B8AAD3A670670100 -409;Untitled 10tacle;FreeTrack20;V160;;;13701;0199FFE9E886F28728AA00 -410;Untitled 3D People;FreeTrack20;V160;;;15501;019A6925968D38AD23A900 -411;Untitled Apportmedia;FreeTrack20;V160;;;6801;019B3C2C1C9728B738B700 -412;Untitled Combat Flight Sim;FreeTrack20;V160;;;13801;019CA59E688D36AA28A600 -413;Untitled Deep Silver;FreeTrack20;V160;;;14601;019D656DD68838B836AD00 -414;Untitled G5 Software;FreeTrack20;V160;;;7301;019E318F88B37AC23BA300 -415;Untitled Microsoft;FreeTrack20;V160;;;2308;019FA15F28739BA32A9300 -416;Untitled Research;FreeTrack20;V160;;;1075;01A07686E5A8B2DA924A00 -417;Untitled Ron E;FreeTrack20;V160;;;14902;01A14ADE68E38AB28B9300 -418;Untitled Sega of America;FreeTrack20;V160;;;12801;01A27A32A1A972DA528A00 -419;Untitled Simbin;FreeTrack20;V160;;;3902;01A36C69678E37AA27AD00 -420;Untitled WorkShield;FreeTrack20;V160;;;4601;01A442868E38AB32BA3600 -421;Untitled ZootFly;FreeTrack20;V160;;;12701;01A5348B1863AA527A6300 -422;UQO;FreeTrack20;V160;;;23085;01A67C822099A187FE3600 -423;UVEG Machinery Simulator;FreeTrack20;V160;;;20024;01A73118585257A0F63100 -424;VAR;FreeTrack20;V160;;;20460;01A8950F9A97FA96FD2E00 -425;VBS2;FreeTrack20;V160;;;7501;01A999BB5C990099FCBF00 -485;VBS2 2.0;FreeTrack20;V170;;;7505;1D51EB3616B3A44F05B900 -527;VCORP RBR2 MOD;FreeTrack20;V160;;;3825;020FEE9EA847F2ADB45800 -426;Vehicle Simulator (Quality Simulations);FreeTrack20;V160;;;5102;01AA0FC9FF9B1FA134A900 -478;Vehicle Simulator Direction;FreeTrack20;V160;;;20735;01DEB88CF58E570F1CEF00 -427;Vestibular Ocular Reflex;FreeTrack20;V160;;;20008;01AB3919C49B31A731A200 -428;Viper Arena;FreeTrack20;V160;;;3501;01AC6F2699559934A53100 -429;VIRTools Engine;FreeTrack20;V160;;;10801;01AD1AAF68905881EB5300 -430;Virtools Plugin;FreeTrack20;V160;;;20200;01AE03FB9B23AB43A42900 -431;Virtual Driving;FreeTrack20;V160;;;20245;01AF99BB5C9927B83FB700 -432;Virtual Heroes;FreeTrack20;V160;;;20375;01B0621E78732B732AE200 -433;Virtual RC Racing;FreeTrack20;V160;;;8201;01B16D2D1038A36A23DA00 -434;Virtual Sailor;FreeTrack20;V160;;;5201;01B25F3D95778C32B33D00 -435;Virtual Shopper;FreeTrack20;V160;;;20610;01B3B78B06EC9927B73E00 -436;Virtual Supermarket;FreeTrack20;V160;;;20280;01B4849F9C39A931AD2800 -496;VirtualiTeach;FreeTrack20;V160;;;20790;01F062AE1CAB33B52D0700 -480;Vizard;FreeTrack20;V160;;;20745;01E0C1F20A79D7C0561300 -437;VizRD;FreeTrack20;V160;;;20031;01B55485D9825BF1D8AB00 -438;Void War;FreeTrack20;V160;;;10001;01B65C1FDE872AA1206600 -564;VR Truck Simulator;FreeTrack20;V160;;;4325;02344CAEE1BC9E243D9F00 -477;VRPlayer;FreeTrack20;V160;;;20730;01DD6787E57245201D5000 -439;VT08;FreeTrack20;V160;;;1275;01B7B78B06EC9912750200 -440;VVVV Plugin;FreeTrack20;V160;;;20075;01B8B1C6648A138C205500 -441;VW Testing;FreeTrack20;V160;;;20275;01B9AC6E878D205822AA00 -442;Walkabout3d;FreeTrack20;V160;;;20125;01BA2822901E9E39932F00 -443;Wallbusters;FreeTrack20;V160;;;1450;01BB88F58C1EA127A83F00 -444;War Thunder;FreeTrack20;V160;;;0;01BC17BE029A1FB8ED9600 -445;WAVES;FreeTrack20;V160;;;20515;01BD05B38FFE89008B8B00 -446;Welding Simulator;FreeTrack20;V160;;;2625;01BE348B188319D229B300 -447;West Racing;FreeTrack20;V160;;;1801;01BF91D999022A33B62000 -448;Whirlwind of Vietnam;FreeTrack20;V160;;;11101;01C0054E9935A03AAF3200 -449;Wikid FJ;FreeTrack20;V160;;;20685;01C19BC3BDA98269B25A00 -450;Wings of Prey;FreeTrack20;V160;V;V4Friend;1877;01C25909438736A133AC00 -451;Wings of War;FreeTrack20;V160;;;7807;01C34B0FC38B36B42FB610 -512;Wings: Over Flanders Fields;FreeTrack20;V160;;;2326;02008AE39AAA4624B33C00 -570;Wingsuit Simulator;FreeTrack20;V160;;;4450;023A472FA37FCD7427D900 -543;World of Diving;FreeTrack20;V160;;;4025;021F27B7B28D5012E1B300 -452;World Racing 2;FreeTrack20;V160;;;7201;01C41AAF68A2BA836AAE00 -453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100 -454;X Motor Racing;FreeTrack20;V160;;;1150;01C669259690E98629A900 -526;X-Camera;FreeTrack20;V160;;;3775;020E1C4055DE39CBC03D00 -458;X-Cockpit for X-Plane;FreeTrack20;V160;;;2901;01CA1C76F8BF4852999300 -459;X-Plane (32 and 64 bit);FreeTrack20;V160;V;EmBeES ;7701;01CB3FD0FC9D90FB943300 -460;X-Plane 6DOF Plugin;FreeTrack20;V160;;;10101;01CCA15F28AF7963596300 -461;X-Plane Pilot View (32 and 64 bit);FreeTrack20;V160;V;V4Friend;11301;01CD79EC0E28EFA953CA00 -462;X-Tower for X-Plane;FreeTrack20;V160;;;3001;01CE05B390EA872AAF3200 -455;X1Alpha;FreeTrack20;V160;;;1825;01C76D2D1038CFD7135A00 -456;X2: The Threat;FreeTrack20;V160;;;5501;01C81039EF980EC8D30900 -457;X3: Albion Prelude and Reunion;FreeTrack20;V170;V;V4Friend;5502;01C97E101A708F8524E300 -463;Xyphoid;FreeTrack20;V160;;;14301;01CF656DD68B43B435A800 -464;zedasoft F-35 Demo;FreeTrack20;V160;;;20041;01D02100B01F942CB93C00 -493;ZKT;FreeTrack20;V160;;;20780;01ED2BAA723F3C097EE800 -465;Zombie AA Research;FreeTrack20;V160;;;14201;01D1AA71218B3B9F1C9A00 diff --git a/cmake/opentrack-install.cmake b/cmake/opentrack-install.cmake new file mode 100644 index 00000000..8e3d0420 --- /dev/null +++ b/cmake/opentrack-install.cmake @@ -0,0 +1,27 @@ +set(opentrack-perms PERMISSIONS WORLD_READ WORLD_EXECUTE OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) + +if(WIN32) + install(FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config" DESTINATION .) +endif() + +install(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION .) + +install(DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty-notices DESTINATION .) +install(DIRECTORY "${CMAKE_SOURCE_DIR}/settings" "${CMAKE_SOURCE_DIR}/contrib" DESTINATION .) + +install(FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll" DESTINATION . ${opentrack-perms}) +install(FILES + "${CMAKE_SOURCE_DIR}/bin/NPClient.dll" + "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" + "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe" + DESTINATION . ${opentrack-perms}) + +if(APPLE) + install(CODE " + execute_process(COMMAND /bin/sh \"${CMAKE_SOURCE_DIR}/macosx/make-app-bundle.sh\" + \"${CMAKE_SOURCE_DIR}/macosx\" + \"${CMAKE_INSTALL_PREFIX}\" + \"${CMAKE_BINARY_DIR}\" + \"${OPENTRACK_COMMIT}\") + ") +endif() diff --git a/cmake/opentrack-macros.cmake b/cmake/opentrack-macros.cmake new file mode 100644 index 00000000..a9fa5bc7 --- /dev/null +++ b/cmake/opentrack-macros.cmake @@ -0,0 +1,79 @@ +macro(opentrack_module n dir) + file(GLOB ${n}-c ${dir}/*.cpp ${dir}/*.c ${dir}/*.h ${dir}/*.hpp) + file(GLOB ${n}-res ${dir}/*.rc) + foreach(f ${n}-res) + set_source_files_properties(${f} PROPERTIES LANGUAGE RC) + endforeach() + file(GLOB ${n}-ui ${dir}/*.ui) + file(GLOB ${n}-rc ${dir}/*.qrc) +endmacro() + +macro(opentrack_boilerplate opentrack-project-name) + set(extra_macro_args ${ARGN}) + set(spliced ${extra_macro_args}) + project(${opentrack-project-name}) + opentrack_library(${opentrack-project-name} ${PROJECT_SOURCE_DIR} ${spliced}) + set(spliced) +endmacro() + +macro(opentrack_qt n) + qt5_wrap_cpp(${n}-moc ${${n}-c} OPTIONS --no-notes) + QT5_WRAP_UI(${n}-uih ${${n}-ui}) + QT5_ADD_RESOURCES(${n}-rcc ${${n}-rc}) + set(${n}-all ${${n}-c} ${${n}-rc} ${${n}-rcc} ${${n}-uih} ${${n}-moc} ${${n}-res}) +endmacro() + +set(msvc-subsystem "/VERSION:5.1 /SUBSYSTEM:WINDOWS,5.01") +function(opentrack_compat target) + if(MSVC) + set_target_properties(${target} PROPERTIES LINK_FLAGS "${msvc-subsystem} /DEBUG /OPT:ICF") + endif() +endfunction() + +macro(opentrack_library n dir) + cmake_parse_arguments(opentrack-foolib + "NO-LIBRARY;STATIC;NO-COMPAT" + "LINK;COMPILE;GNU-LINK;GNU-COMPILE" + "" + ${ARGN} + ) + if(NOT " ${opentrack-foolib_UNPARSED_ARGUMENTS}" STREQUAL " ") + message(FATAL_ERROR "opentrack_library bad formals ${opentrack-foolib_UNPARSED_ARGUMENTS}") + endif() + opentrack_module(${n} ${dir}) + opentrack_qt(${n}) + set(link-mode SHARED) + if(NOT opentrack-foolib_NO-LIBRARY) + if (opentrack-foolib_STATIC) + set(link-mode STATIC) + endif() + add_library(${n} ${link-mode} ${${n}-all}) + set(link-mode) + if(NOT opentrack-foolib_NO-COMPAT) + target_link_libraries(${n} opentrack-api ${MY_QT_LIBS} opentrack-compat) + endif() + if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) + SET_TARGET_PROPERTIES(${n} PROPERTIES + LINK_FLAGS "${opentrack-foolib_LINK} ${opentrack-foolib_GNU-LINK} -Wl,--as-needed -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack-compat/${version-script}-version-script.txt\"" + COMPILE_FLAGS "${opentrack-foolib_COMPILE} ${opentrack-foolib_GNU-COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden" + ) + else() + set(link-flags) + if(MSVC) + set(link-flags "${msvc-subsystem} /DEBUG /OPT:ICF") + endif() + set_target_properties(${n} PROPERTIES LINK_FLAGS "${link-flags} ${opentrack-foolib_LINK}" COMPILE_FLAGS "${opentrack-foolib_COMPILE}") + set(link-flags) + endif() + if(NOT opentrack-foolib_STATIC) + install(TARGETS ${n} RUNTIME DESTINATION . LIBRARY DESTINATION .) + endif() + opentrack_compat(${n}) + endif() +endmacro() + +function(link_with_dinput8 n) + if(WIN32) + target_link_libraries(${n} dinput8 dxguid strmiids) + endif() +endfunction() diff --git a/cmake/opentrack-platform.cmake b/cmake/opentrack-platform.cmake new file mode 100644 index 00000000..aac3a2b8 --- /dev/null +++ b/cmake/opentrack-platform.cmake @@ -0,0 +1,60 @@ +IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(LINUX TRUE) +endif() + +if(MSVC) + add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS) +endif() + +if(WIN32) + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_RC_COMPILER_INIT i686-w64-mingw32-windres) + SET(CMAKE_RC_COMPILE_OBJECT " --use-temp-file -O coff -i -o ") + endif() + ENABLE_LANGUAGE(RC) +endif(WIN32) + +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +set(CMAKE_SKIP_INSTALL_RPATH FALSE) +set(CMAKE_SKIP_RPATH FALSE) +set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC OFF) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +include_directories(${CMAKE_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +# note, hatire supports both ftnoir and opentrack +# don't remove without being sure as hell -sh 20140922 +add_definitions(-DOPENTRACK_API) + +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_COMPILER_IS_GNUCC TRUE) + set(CMAKE_COMPILER_IS_GNUCXX TRUE) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) + if(MINGW) + set(version-script mingw) + else() + set(version-script posix) + endif() +endif() + +if(APPLE) + set(CMAKE_MACOSX_RPATH OFF) + set(apple-frameworks "-stdlib=libc++ -framework Cocoa -framework CoreFoundation -lobjc -lz -framework Carbon") + set(CMAKE_SHARED_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_SHARED_LINKER_FLAGS}") + #set(CMAKE_STATIC_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_STATIC_LINKER_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_EXE_LINKER_FLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_MODULE_LINKER_FLAGS}") + set(CMAKE_CXX_FLAGS " -stdlib=libc++ ${CMAKE_CXX_FLAGS}") +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR APPLE) + set(CMAKE_CXX_FLAGS " -std=c++11 ${CMAKE_CXX_FLAGS} ") +endif() + +set_property(GLOBAL PROPERTY USE_FOLDERS OFF) diff --git a/cmake/opentrack-policy.cmake b/cmake/opentrack-policy.cmake new file mode 100644 index 00000000..48aba3cc --- /dev/null +++ b/cmake/opentrack-policy.cmake @@ -0,0 +1,10 @@ +cmake_policy(SET CMP0020 NEW) +if(POLICY CMP0058) + cmake_policy(SET CMP0058 OLD) +endif() +if(POLICY CMP0028) + cmake_policy(SET CMP0028 OLD) +endif() +if(POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) +endif() diff --git a/cmake/opentrack-qt.cmake b/cmake/opentrack-qt.cmake new file mode 100644 index 00000000..12966827 --- /dev/null +++ b/cmake/opentrack-qt.cmake @@ -0,0 +1,5 @@ +find_package(Qt5 REQUIRED COMPONENTS Core Xml Network Widgets Gui QUIET) +find_package(Qt5 COMPONENTS SerialPort QUIET) +include_directories(SYSTEM ${Qt5Core_INCLUDE_DIRS} ${Qt5Xml_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}) +add_definitions(${Qt5Core_DEFINITIONS} ${Qt5Xml_DEFINITIONS} ${Qt5Gui_DEFINITIONS} ${Qt5Widgets_DEFINITIONS} ${Qt5Network_DEFINITIONS}) +set(MY_QT_LIBS ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Xml_LIBRARIES}) diff --git a/cmake/opentrack-rift.cmake b/cmake/opentrack-rift.cmake new file mode 100644 index 00000000..86396637 --- /dev/null +++ b/cmake/opentrack-rift.cmake @@ -0,0 +1,37 @@ +macro(opentrack_rift_boilerplate proj opt) + if(${opt}) + set(link-flags) + set(c-flags) + if(APPLE) + set(link-flags "-framework CoreFoundation -framework CoreGraphics -framework IOKit -framework Quartz") + set(c-flags "-fno-strict-aliasing") + else() + if(NOT MSVC) + set(c-flags "-fno-strict-aliasing") + endif() + endif() + opentrack_boilerplate("${proj}" LINK ${link-flags} COMPILE ${c-flags}) + set(proj ${opentrack-project-name}) + target_include_directories(${proj} SYSTEM PUBLIC ${${opt}}/Include ${${opt}}/Src) + set(c-flags) + set(link-flags) + if(WIN32) + if(MSVC) + set(ext lib) + set(p) + else() + set(ext a) + set(p lib) + endif() + target_link_libraries(${proj} ${${opt}}/${p}LibOVR.${ext} winmm setupapi ws2_32 imagehlp wbemuuid) + set(ext) + set(p) + else() + if(NOT APPLE) + target_link_libraries(${proj} ${${opt}}/libLibOVR.a udev Xinerama) + else() + target_link_libraries(${proj} ${${opt}}/libLibOVR.a) + endif() + endif() + endif() +endmacro() diff --git a/cmake/opentrack-tarball.cmake b/cmake/opentrack-tarball.cmake new file mode 100644 index 00000000..6b40081b --- /dev/null +++ b/cmake/opentrack-tarball.cmake @@ -0,0 +1,23 @@ +string(TIMESTAMP filename-date "%Y%m%d") +set(filename-ostype ${CMAKE_SYSTEM_NAME}) +get_git_head_revision(filename-branch_0 filename-hash_0) +if(filename-hash_0) + string(SUBSTRING "${filename-hash_0}" 0 7 filename-hash) +endif() +string(REPLACE "refs/heads/" "" filename-branch_1 "${filename-branch_0}") +string(REPLACE "/" "-" filename-branch "${filename-branch_1}") +set(filename_0 "${OPENTRACK_COMMIT}") +set(filename_1) +if (NOT OPENTRACK_TAG_EXACT STREQUAL OPENTRACK_COMMIT) + string(TIMESTAMP filename_1 "-%Y%m%d%H%M%S") +endif() +set(filename "${CMAKE_BINARY_DIR}/${filename_0}${filename_1}.zip") + +add_custom_target(tarball-real) +add_custom_target(tarball-real2) +add_custom_command(TARGET tarball-real COMMAND cmake -P ${CMAKE_SOURCE_DIR}/cmake/tarball.cmake) + +add_custom_command(TARGET tarball-real2 COMMAND /usr/bin/env sh + "${CMAKE_SOURCE_DIR}/make-tar.sh" "${CMAKE_INSTALL_PREFIX}" + "${filename}" "${CMAKE_BINARY_DIR}") +add_custom_target(tarball DEPENDS tarball-real) diff --git a/cmake/opentrack-version.cmake b/cmake/opentrack-version.cmake new file mode 100644 index 00000000..64072e1c --- /dev/null +++ b/cmake/opentrack-version.cmake @@ -0,0 +1,33 @@ +include(GetGitRevisionDescription) + +find_package(Git QUIET) +if(GIT_FOUND) + git_describe(OPENTRACK_COMMIT --tags --always --dirty) + git_describe(OPENTRACK_TAG_EXACT --tag --exact) +endif() + +file(WRITE ${CMAKE_BINARY_DIR}/opentrack-version.h "#define OPENTRACK_VERSION \"${OPENTRACK_COMMIT}\"") + +add_library(opentrack-version STATIC ${CMAKE_BINARY_DIR}/version.cc) +opentrack_compat(opentrack-version) + +set(version-string " +#include \"opentrack-compat/export.hpp\" + +#ifdef __cplusplus +extern \"C\" +#endif +OPENTRACK_EXPORT +const char* opentrack_version; + +const char* opentrack_version = \"${OPENTRACK_COMMIT}\"; +") + +set(crapola-ver) +if(EXISTS ${CMAKE_BINARY_DIR}/version.cc) + file(READ ${CMAKE_BINARY_DIR}/version.cc crapola-ver) +endif() + +if(NOT (crapola-ver STREQUAL version-string)) + file(WRITE ${CMAKE_BINARY_DIR}/version.cc "${version-string}") +endif() diff --git a/csv/CMakeLists.txt b/csv/CMakeLists.txt new file mode 100644 index 00000000..07dae55c --- /dev/null +++ b/csv/CMakeLists.txt @@ -0,0 +1,4 @@ +opentrack_boilerplate(opentrack-csv NO-LIBRARY) +add_library(opentrack-csv STATIC ${opentrack-csv-c}) +opentrack_compat(opentrack-csv) +target_link_libraries(opentrack-csv ${MY_QT_LIBS}) diff --git a/facetracknoir/CMakeLists.txt b/facetracknoir/CMakeLists.txt new file mode 100644 index 00000000..51d0cea3 --- /dev/null +++ b/facetracknoir/CMakeLists.txt @@ -0,0 +1,62 @@ +opentrack_boilerplate(opentrack NO-LIBRARY) + +if(UNIX OR APPLE) + target_include_directories(opentrack "${CMAKE_SOURCE_DIR}/qxt-mini") + if(APPLE) + set(qxt-plat mac) + else() + set(qxt-plat x11) + endif() + file(GLOB qxt-mini-c + ${CMAKE_SOURCE_DIR}/qxt-mini/*.h + ${CMAKE_SOURCE_DIR}/qxt-mini/qxtglobalshortcut.cpp + ${CMAKE_SOURCE_DIR}/qxt-mini/plat/qxtglobalshortcut_${qxt-plat}.cpp + ) + opentrack_qt(qxt-mini) + add_library(opentrack-qxt-mini STATIC ${qxt-mini-all}) + target_link_libraries(opentrack-qxt-mini ${MY_QT_LIBS}) + if(NOT APPLE) + target_link_libraries(opentrack-qxt-mini X11) + endif() +endif() + +if(WIN32) + SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console window visible at runtime") +endif() + +if(WIN32 AND NOT SDK_CONSOLE_DEBUG) + set(opentrack-win32-executable WIN32) +else() + set(opentrack-win32-executable "") +endif() + +if(UNIX OR APPLE) + list(APPEND opentrack-c ${CMAKE_SOURCE_DIR}/qxt-mini/qxtglobalshortcut.h) +endif() +opentrack_qt(opentrack) +add_executable(opentrack ${opentrack-win32-executable} ${opentrack-all}) +opentrack_compat(opentrack) +if(NOT WIN32) + set_target_properties(opentrack PROPERTIES SUFFIX ".bin") +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() +if(UNIX OR APPLE) + target_link_libraries(opentrack opentrack-qxt-mini) +endif() +link_with_dinput8(opentrack) +target_link_libraries(opentrack ${MY_QT_LIBS}) + +if(APPLE) + # for process detector + target_link_libraries(opentrack proc) +endif() + +if(LINUX) + # for process detector + target_link_libraries(opentrack procps) +endif() + +install(TARGETS opentrack DESTINATION .) diff --git a/facetracknoir/main.ui b/facetracknoir/main.ui index 24c3d38c..ab63e832 100644 --- a/facetracknoir/main.ui +++ b/facetracknoir/main.ui @@ -1231,7 +1231,7 @@ GLWidget QWidget -
glwidget.h
+
pose-widget/glwidget.h
diff --git a/facetracknoir/mapping.ui b/facetracknoir/mapping.ui index 379bbe08..75c32e27 100644 --- a/facetracknoir/mapping.ui +++ b/facetracknoir/mapping.ui @@ -368,7 +368,7 @@ QFunctionConfigurator QWidget -
qfunctionconfigurator.h
+
spline-widget/qfunctionconfigurator.h
diff --git a/filter-accela/CMakeLists.txt b/filter-accela/CMakeLists.txt new file mode 100644 index 00000000..5bfa8128 --- /dev/null +++ b/filter-accela/CMakeLists.txt @@ -0,0 +1,2 @@ +opentrack_boilerplate(opentrack-filter-accela) +target_link_libraries(opentrack-filter-accela opentrack-spline-widget) diff --git a/filter-accela/ftnoir_accela_filtercontrols.ui b/filter-accela/ftnoir_accela_filtercontrols.ui new file mode 100644 index 00000000..3ab9a78e --- /dev/null +++ b/filter-accela/ftnoir_accela_filtercontrols.ui @@ -0,0 +1,300 @@ + + + AccelaUICFilterControls + + + Qt::NonModal + + + + 0 + 0 + 501 + 359 + + + + Accela filter settings + + + + :/images/filter-16.png:/images/filter-16.png + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + 99 + + + 5 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 25 + + + + + + + + 0 + 0 + + + + Rotation sensitivity + + + + + + + Smoothing + + + + + + + + 48 + 0 + + + + 0 ms + + + + + + + 0° + + + + + + + 100 + + + 10 + + + 25 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 25 + + + + + + + Translation deadzone + + + + + + + Rotation deadzone + + + + + + + 100 + + + Qt::Horizontal + + + + + + + 0° + + + + + + + 100 + + + Qt::Horizontal + + + + + + + 0mm + + + + + + + + 0 + 0 + + + + Translation sensitivity + + + + + + + 0mm + + + + + + + 99 + + + 5 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 25 + + + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + + 0 + 0 + + + + + 7 + + + + QFrame::NoFrame + + + <html><head/><body><p align="justify"><br/><span style=" font-size:10pt;">Accela by </span><a href="https://github.com/sthalik"><span style=" font-size:10pt; text-decoration: underline; color:#0057ae;">StanisÅ‚aw Halik</span></a><span style=" font-size:10pt;"><br/>Thanks to </span><a href="https://github.com/dbaarda"><span style=" font-size:10pt; text-decoration: underline; color:#0057ae;">Donovan Baarda</span></a></p><p align="right"><span style=" font-size:10pt;">2012-2015</span></p><p align="right"><br/></p></body></html> + + + Qt::RichText + + + false + + + Qt::AlignCenter + + + true + + + 0 + + + 0 + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 10 + + + + <html><head/><body><p>Visit <a href="https://github.com/opentrack/opentrack/wiki/Accela-in-opentrack-2.3"><span style=" text-decoration: underline; color:#0000ff;">our wiki</span></a> for description of the settings.</p></body></html> + + + true + + + + + + + + + + buttonBox + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/filter-accela/ftnoir_filter_accela.cpp b/filter-accela/ftnoir_filter_accela.cpp new file mode 100644 index 00000000..62d1598d --- /dev/null +++ b/filter-accela/ftnoir_filter_accela.cpp @@ -0,0 +1,108 @@ +/* Copyright (c) 2012-2015 Stanislaw Halik + * + * 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_filter_accela.h" +#include +#include +#include +#include +#include "opentrack/plugin-api.hpp" + +static constexpr double rot_gains[][2] = { + { 2.66, 110 }, + { 2.33, 80 }, + { 2, 50 }, + { 1.66, 30 }, + { 1.33, 15 }, + { 1, 5 }, + { .66, 1.4 }, + { .33, .4 }, + { 0, 0 }, + { -1, 0 } +}; + +static constexpr double trans_gains[][2] = { + { 2, 400 }, + { 1.66, 120 }, + { 1.33, 40 }, + { 1, 10 }, + { .66, 2 }, + { .33, .6 }, + { 0, 0 }, + { -1, 0 } +}; + +constexpr double settings_accela::mult_rot; +constexpr double settings_accela::mult_trans; +constexpr double settings_accela::mult_rot_dz; +constexpr double settings_accela::mult_trans_dz; +constexpr double settings_accela::mult_ewma; + +FTNoIR_Filter::FTNoIR_Filter() : first_run(true) +{ + rot.setMaxInput(rot_gains[0][0]); + trans.setMaxInput(trans_gains[0][0]); + rot.setMaxOutput(rot_gains[0][1]); + trans.setMaxOutput(trans_gains[0][1]); + + for (int i = 0; rot_gains[i][0] >= 0; i++) + { + rot.addPoint(QPointF(rot_gains[i][0], rot_gains[i][1])); + } + for (int i = 0; trans_gains[i][0] >= 0; i++) + { + trans.addPoint(QPointF(trans_gains[i][0], trans_gains[i][1])); + } +} + +void FTNoIR_Filter::filter(const double* input, double *output) +{ + if (first_run) + { + for (int i = 0; i < 6; i++) + { + const double f = input[i]; + output[i] = f; + last_output[i] = f; + smoothed_input[i] = f; + } + first_run = false; + t.start(); + return; + } + + const double rot_t = (1+s.rot_threshold) * s.mult_rot; + const double trans_t = (1+s.trans_threshold) * s.mult_trans; + + const double dt = t.elapsed() * 1e-9; + t.start(); + + const double RC = s.mult_ewma * s.ewma / 1000.; // seconds + const double alpha = dt/(dt+RC); + const double rot_dz = s.rot_deadzone * s.mult_rot_dz; + const double trans_dz = s.trans_deadzone * s.mult_trans_dz; + + for (int i = 0; i < 6; i++) + { + Map& m = i >= 3 ? rot : trans; + + smoothed_input[i] = smoothed_input[i] * (1.-alpha) + input[i] * alpha; + + const double in = smoothed_input[i]; + + const double vec = in - last_output[i]; + const double dz = i >= 3 ? rot_dz : trans_dz; + const double vec_ = std::max(0., fabs(vec) - dz); + const double thres = i >= 3 ? rot_t : trans_t; + const double val = m.getValue(vec_ / thres); + const double result = last_output[i] + (vec < 0 ? -1 : 1) * dt * val; + + last_output[i] = output[i] = result; + } +} + +OPENTRACK_DECLARE_FILTER(FTNoIR_Filter, FilterControls, FTNoIR_FilterDll) + diff --git a/filter-accela/ftnoir_filter_accela.h b/filter-accela/ftnoir_filter_accela.h new file mode 100644 index 00000000..b15e0cea --- /dev/null +++ b/filter-accela/ftnoir_filter_accela.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2012-2015 Stanislaw Halik + * + * 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 "ui_ftnoir_accela_filtercontrols.h" +#include "opentrack/plugin-api.hpp" +#include "spline-widget/functionconfig.h" +#include +#include +#include + +#include "opentrack/options.hpp" +using namespace options; +#include "opentrack-compat/timer.hpp" + +struct settings_accela : opts { + value rot_threshold, trans_threshold, ewma, rot_deadzone, trans_deadzone; + static constexpr double mult_rot = 4. / 100.; + static constexpr double mult_trans = 4. / 100.; + static constexpr double mult_rot_dz = 2. / 100.; + static constexpr double mult_trans_dz = 2. / 100.; + static constexpr double mult_ewma = 1.25; + settings_accela() : + opts("Accela"), + rot_threshold(b, "rotation-threshold", 30), + trans_threshold(b, "translation-threshold", 50), + ewma(b, "ewma", 2), + rot_deadzone(b, "rotation-deadzone", 0), + trans_deadzone(b, "translation-deadzone", 0) + {} +}; + +class FTNoIR_Filter : public IFilter +{ +public: + FTNoIR_Filter(); + void filter(const double* input, double *output) override; + void center() override { first_run = true; } + Map rot, trans; +private: + settings_accela s; + bool first_run; + double last_output[6]; + double smoothed_input[6]; + Timer t; +}; + +class FilterControls: public IFilterDialog +{ + Q_OBJECT +public: + FilterControls(); + void register_filter(IFilter* filter); + void unregister_filter(); +private: + Ui::AccelaUICFilterControls ui; + void discard(); + void save(); + FTNoIR_Filter* accela_filter; + settings_accela s; +private slots: + void doOK(); + void doCancel(); + void update_ewma_display(int value); + void update_rot_display(int value); + void update_trans_display(int value); + void update_rot_dz_display(int value); + void update_trans_dz_display(int value); +}; + +class FTNoIR_FilterDll : public Metadata +{ +public: + QString name() { return QString("Accela"); } + QIcon icon() { return QIcon(":/images/filter-16.png"); } +}; diff --git a/filter-accela/ftnoir_filter_accela_dialog.cpp b/filter-accela/ftnoir_filter_accela_dialog.cpp new file mode 100644 index 00000000..599cb716 --- /dev/null +++ b/filter-accela/ftnoir_filter_accela_dialog.cpp @@ -0,0 +1,105 @@ +/* Copyright (c) 2012-2015 Stanislaw Halik + * + * 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_filter_accela.h" +#include +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "spline-widget/qfunctionconfigurator.h" +#include + +FilterControls::FilterControls() : + accela_filter(nullptr) +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + connect(ui.rotation_slider, SIGNAL(valueChanged(int)), this, SLOT(update_rot_display(int))); + connect(ui.translation_slider, SIGNAL(valueChanged(int)), this, SLOT(update_trans_display(int))); + connect(ui.ewma_slider, SIGNAL(valueChanged(int)), this, SLOT(update_ewma_display(int))); + connect(ui.rot_dz_slider, SIGNAL(valueChanged(int)), this, SLOT(update_rot_dz_display(int))); + connect(ui.trans_dz_slider, SIGNAL(valueChanged(int)), this, SLOT(update_trans_dz_display(int))); + + tie_setting(s.rot_threshold, ui.rotation_slider); + tie_setting(s.trans_threshold, ui.translation_slider); + tie_setting(s.ewma, ui.ewma_slider); + tie_setting(s.rot_deadzone, ui.rot_dz_slider); + tie_setting(s.trans_deadzone, ui.trans_dz_slider); + + update_rot_display(ui.rotation_slider->value()); + update_trans_display(ui.translation_slider->value()); + update_ewma_display(ui.ewma_slider->value()); + update_rot_dz_display(ui.rot_dz_slider->value()); + update_trans_dz_display(ui.trans_dz_slider->value()); +} + +void FilterControls::register_filter(IFilter* filter) +{ + accela_filter = static_cast(filter); +//#define LEAKING_DEBUG +#ifdef LEAKING_DEBUG + auto d = new QDialog(); + auto r = new QFunctionConfigurator(d); + r->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + r->setConfig(&accela_filter->rot, ""); + r->setFixedSize(800, 300); + d->show(); +#endif +} + +void FilterControls::unregister_filter() +{ + accela_filter = nullptr; +} + +void FilterControls::doOK() { + save(); + this->close(); +} + +void FilterControls::doCancel() { + discard(); + close(); +} + +void FilterControls::discard() +{ + s.b->reload(); +} + +void FilterControls::save() { + s.b->save(); +} + +void FilterControls::update_rot_display(int value) +{ + ui.rot_gain->setText(QString::number((value + 1) * s.mult_rot) + "°"); +} + +void FilterControls::update_trans_display(int value) +{ + ui.trans_gain->setText(QString::number((value + 1) * s.mult_trans) + "mm"); +} + +void FilterControls::update_ewma_display(int value) +{ + ui.ewma_label->setText(QString::number(value * s.mult_ewma) + "ms"); +} + +void FilterControls::update_rot_dz_display(int value) +{ + ui.rot_dz->setText(QString::number(value * s.mult_rot_dz) + "°"); +} + +void FilterControls::update_trans_dz_display(int value) +{ + ui.trans_dz->setText(QString::number(value * s.mult_trans_dz) + "mm"); +} + diff --git a/filter-ewma2/CMakeLists.txt b/filter-ewma2/CMakeLists.txt new file mode 100644 index 00000000..af786487 --- /dev/null +++ b/filter-ewma2/CMakeLists.txt @@ -0,0 +1 @@ +opentrack_boilerplate(opentrack-filter-ewma) diff --git a/filter-ewma2/ftnoir_ewma_filtercontrols.ui b/filter-ewma2/ftnoir_ewma_filtercontrols.ui new file mode 100644 index 00000000..9387f0d5 --- /dev/null +++ b/filter-ewma2/ftnoir_ewma_filtercontrols.ui @@ -0,0 +1,372 @@ + + + UICFilterControls + + + Qt::NonModal + + + + 0 + 0 + 448 + 380 + + + + EWMA2 filter settings + + + + :/images/filter-16.png:/images/filter-16.png + + + Qt::LeftToRight + + + false + + + + + + + + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + Min + + + + + + + + 0 + 0 + + + + 1 + + + 100 + + + 5 + + + 2 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 0 + 0 + + + + background:none; + + + true + + + QAbstractSpinBox::PlusMinus + + + 1 + + + 120 + + + 5 + + + 2 + + + + + + + + 0 + 0 + + + + + + + Max + + + + + + + + 0 + 0 + + + + 1 + + + 100 + + + 5 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 0 + 0 + + + + background:none; + + + true + + + QAbstractSpinBox::PlusMinus + + + 1 + + + 120 + + + 5 + + + 10 + + + + + + + + 0 + 0 + + + + + + + Curve + + + + + + + + 0 + 0 + + + + 1 + + + 100 + + + 5 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + + 0 + 0 + + + + background:none; + + + true + + + QAbstractSpinBox::PlusMinus + + + 100 + + + 5 + + + 10 + + + + + + + + + + background-color: rgb(214, 214, 214); +border-color: rgb(0, 0, 0); + + + QFrame::Box + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Min:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Defines the way the filter responds to fast movements;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Higher value: slower response;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Max:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Defines the way the filter responds to slow movements;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Higher value: slower response;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Pow:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Defines the filters 'readiness' to respond to speed changes;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Higher value = </span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">faster</span><span style=" font-family:'MS Shell Dlg 2';"> response;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> + + + 5 + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + minSmooth + valueChanged(int) + spinMinSmooth + setValue(int) + + + 303 + 33 + + + 391 + 36 + + + + + maxSmooth + valueChanged(int) + spinMaxSmooth + setValue(int) + + + 281 + 61 + + + 390 + 74 + + + + + powCurve + valueChanged(int) + spinPowCurve + setValue(int) + + + 236 + 101 + + + 391 + 98 + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/filter-ewma2/ftnoir_filter_ewma2.cpp b/filter-ewma2/ftnoir_filter_ewma2.cpp new file mode 100644 index 00000000..c09fb912 --- /dev/null +++ b/filter-ewma2/ftnoir_filter_ewma2.cpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2014 Donovan Baarda + * + * 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_filter_ewma2.h" +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include +#include + +// Exponentially Weighted Moving Average (EWMA) Filter with dynamic smoothing. +// +// This filter tries to adjust the amount of filtering to minimize lag when +// moving, and minimize noise when still. It uses the delta filtered over the +// last 1/60sec (16ms) compared to the delta's average noise variance over +// the last 60sec to try and detect movement vs noise. As the delta increases +// from 0 to 3 stdevs of the noise, the filtering scales down from maxSmooth +// to minSmooth at a rate controlled by the powCurve setting. + + +FTNoIR_Filter::FTNoIR_Filter() +{ + reset(); +} + +void FTNoIR_Filter::receiveSettings() +{ + s.b->reload(); +} + +void FTNoIR_Filter::reset() +{ + timer.invalidate(); +} + +void FTNoIR_Filter::filter(const double *input, double *output) +{ + // Start the timer and initialise filter state if it's not running. + if (!timer.isValid()) { + timer.start(); + for (int i=0;i<6;i++) { + last_output[i] = input[i]; + last_delta[i] = 0.0; + last_noise[i] = 0.0; + } + } + // Get the time in seconds since last run and restart the timer. + auto dt = timer.restart() / 1000.0f; + // Calculate delta_alpha and noise_alpha from dt. + double delta_alpha = dt/(dt + delta_RC); + double noise_alpha = dt/(dt + noise_RC); + // Calculate the new camera position. + for (int i=0;i<6;i++) { + // Calculate the current and smoothed delta. + double delta = input[i] - last_output[i]; + last_delta[i] = delta_alpha*delta + (1.0-delta_alpha)*last_delta[i]; + // Calculate the current and smoothed noise variance. + double noise = last_delta[i]*last_delta[i]; + last_noise[i] = noise_alpha*noise + (1.0-noise_alpha)*last_noise[i]; + // Normalise the noise between 0->1 for 0->9 variances (0->3 stddevs). + double norm_noise = std::min(noise/(9.0*last_noise[i]), 1.0); + if (std::isnan(norm_noise)) + norm_noise = 0; + // Calculate the smoothing 0.0->1.0 from the normalized noise. + // TODO(abo): change kSmoothingScaleCurve to a float where 1.0 is sqrt(norm_noise). + double smoothing = 1.0 - pow(norm_noise, s.kSmoothingScaleCurve/20.0); + // Currently min/max smoothing are ints 0->100. We want 0.0->3.0 seconds. + // TODO(abo): Change kMinSmoothing, kMaxSmoothing to floats 0.0->3.0 seconds RC. + double RC = 3.0*(s.kMinSmoothing + smoothing*(s.kMaxSmoothing - s.kMinSmoothing))/100.0; + // Calculate the dynamic alpha. + double alpha = dt/(dt + RC); + // Calculate the new output position. + output[i] = last_output[i] = alpha*input[i] + (1.0-alpha)*last_output[i]; + } +} + +OPENTRACK_DECLARE_FILTER(FTNoIR_Filter, FilterControls, FTNoIR_FilterDll) diff --git a/filter-ewma2/ftnoir_filter_ewma2.h b/filter-ewma2/ftnoir_filter_ewma2.h new file mode 100644 index 00000000..bf4e83ad --- /dev/null +++ b/filter-ewma2/ftnoir_filter_ewma2.h @@ -0,0 +1,66 @@ +#pragma once + +#include "opentrack/plugin-api.hpp" +#include "ui_ftnoir_ewma_filtercontrols.h" +#include +#include +#include +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + // these are sadly sliders for now due to int/double mismatch -sh + value kMinSmoothing, kMaxSmoothing, kSmoothingScaleCurve; + settings() : + opts("ewma-filter"), + kMinSmoothing(b, "min-smoothing", 15), + kMaxSmoothing(b, "max-smoothing", 50), + kSmoothingScaleCurve(b, "smoothing-scale-curve", 10) + {} +}; + + +class FTNoIR_Filter : public IFilter +{ +public: + FTNoIR_Filter(); + void reset(); + void filter(const double *input, double *output); + void receiveSettings(); +private: + // Deltas are smoothed over the last 1/60sec (16ms). + const double delta_RC = 0.016; + // Noise is smoothed over the last 60sec. + const double noise_RC = 60.0; + double last_delta[6]; + double last_noise[6]; + double last_output[6]; + QElapsedTimer timer; + settings s; +}; + +class FilterControls: public IFilterDialog +{ + Q_OBJECT +public: + FilterControls(); + void register_filter(IFilter* flt); + void unregister_filter(); + +private: + Ui::UICFilterControls ui; + void save(); + settings s; + FTNoIR_Filter* pFilter; + +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_FilterDll : public Metadata +{ +public: + QString name() { return QString("EWMA"); } + QIcon icon() { return QIcon(":/images/filter-16.png"); } +}; diff --git a/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp b/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp new file mode 100644 index 00000000..30fb6003 --- /dev/null +++ b/filter-ewma2/ftnoir_filter_ewma2_dialog.cpp @@ -0,0 +1,43 @@ +#include "ftnoir_filter_ewma2.h" +#include +#include +#include "opentrack/plugin-api.hpp" +#include "ui_ftnoir_ewma_filtercontrols.h" + +FilterControls::FilterControls() : pFilter(NULL) +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.kMaxSmoothing, ui.maxSmooth); + tie_setting(s.kMinSmoothing, ui.minSmooth); + tie_setting(s.kSmoothingScaleCurve, ui.powCurve); +} + +void FilterControls::register_filter(IFilter* flt) +{ + pFilter = (FTNoIR_Filter*) flt; +} + +void FilterControls::unregister_filter() +{ + pFilter = NULL; +} + +void FilterControls::doOK() { + save(); + this->close(); +} + +void FilterControls::doCancel() { + s.b->reload(); + this->close(); +} + +void FilterControls::save() { + s.b->save(); + if (pFilter) + pFilter->receiveSettings(); +} diff --git a/filter-kalman/CMakeLists.txt b/filter-kalman/CMakeLists.txt new file mode 100644 index 00000000..666a35db --- /dev/null +++ b/filter-kalman/CMakeLists.txt @@ -0,0 +1,4 @@ +find_package(OpenCV 3.0) +opentrack_boilerplate(opentrack-filter-kalman) +target_link_libraries(opentrack-filter-kalman ${OpenCV_LIBS}) +target_include_directories(opentrack-filter-kalman SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) diff --git a/filter-kalman/ftnoir_filter_kalman.h b/filter-kalman/ftnoir_filter_kalman.h new file mode 100644 index 00000000..a6f40bb7 --- /dev/null +++ b/filter-kalman/ftnoir_filter_kalman.h @@ -0,0 +1,73 @@ +#pragma once +/* Copyright (c) 2013 StanisÅ‚aw Halik + * + * 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. + */ +#ifndef INCLUDED_FTN_FILTER_H +#define INCLUDED_FTN_FILTER_H + +#include "ui_ftnoir_kalman_filtercontrols.h" +#include "opentrack/plugin-api.hpp" +#include +#include +#include +#include +#include +#include +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value noise_stddev_slider; + // slider for noise_stddev goes 0->(mult_noise_stddev * 100) + static constexpr double mult_noise_stddev = .5; + settings() : opts("kalman-filter"), noise_stddev_slider(b, "noise-stddev", 40) + {} +}; + +class FTNoIR_Filter : public IFilter +{ +public: + FTNoIR_Filter(); + void reset(); + void filter(const double *input, double *output); + // Set accel_stddev assuming moving 0.0->accel in dt_ is 3 stddevs: (accel*4/dt_^2)/3. + static constexpr double dt_ = .4; + static constexpr double accel = 60.; + static constexpr double accel_stddev = (accel*4/(dt_*dt_))/3.0; + cv::KalmanFilter kalman; + double last_input[6]; + QElapsedTimer timer; + settings s; + int prev_slider_pos; +}; + +class FTNoIR_FilterDll : public Metadata +{ +public: + QString name() { return QString("Kalman"); } + QIcon icon() { return QIcon(":/images/filter-16.png"); } +}; + +class FilterControls: public IFilterDialog +{ + Q_OBJECT +public: + FilterControls() { + ui.setupUi(this); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + tie_setting(s.noise_stddev_slider, ui.noise_slider); + } + Ui::KalmanUICFilterControls ui; + void register_filter(IFilter*) override {} + void unregister_filter() override {} + settings s; +public slots: + void doOK(); + void doCancel(); +}; + +#endif diff --git a/filter-kalman/ftnoir_kalman_filtercontrols.ui b/filter-kalman/ftnoir_kalman_filtercontrols.ui new file mode 100644 index 00000000..69297102 --- /dev/null +++ b/filter-kalman/ftnoir_kalman_filtercontrols.ui @@ -0,0 +1,116 @@ + + + KalmanUICFilterControls + + + Qt::NonModal + + + + 0 + 0 + 288 + 132 + + + + + 0 + 0 + + + + Kalman settings + + + + :/images/filter-16.png:/images/filter-16.png + + + Qt::LeftToRight + + + false + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Noise standard deviation + + + + + + + 1 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 10 + + + + + + + + + + Written by Donovan Baarda, 2014 + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + 10 + + + 10 + + + false + + + false + + + true + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/filter-kalman/kalman.cpp b/filter-kalman/kalman.cpp new file mode 100644 index 00000000..39a08703 --- /dev/null +++ b/filter-kalman/kalman.cpp @@ -0,0 +1,129 @@ +/* Copyright (c) 2013 StanisÅ‚aw Halik + * + * 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_filter_kalman.h" +#include "opentrack/plugin-api.hpp" +#include +#include + +constexpr double settings::mult_noise_stddev; + +FTNoIR_Filter::FTNoIR_Filter() { + reset(); + prev_slider_pos = s.noise_stddev_slider; +} + +// the following was written by Donovan Baarda +// https://sourceforge.net/p/facetracknoir/discussion/1150909/thread/418615e1/?limit=25#af75/084b +void FTNoIR_Filter::reset() { + // Setup kalman with state (x) is the 6 tracker outputs then + // their 6 corresponding velocities, and the measurement (z) is + // the 6 tracker outputs. + kalman.init(12, 6, 0, CV_64F); + // Initialize the transitionMatrix and processNoiseCov for + // dt=0.1. This needs to be updated each frame for the real dt + // value, but this hows you what they should look like. See + // http://en.wikipedia.org/wiki/Kalman_filter#Example_application.2C_technical + double dt = 0.1; + kalman.transitionMatrix = (cv::Mat_(12, 12) << + 1, 0, 0, 0, 0, 0, dt, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, dt, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, dt, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, dt, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, dt, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, dt, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + double accel_variance = accel_stddev * accel_stddev; + double a = dt * dt * accel_variance; // dt^2 * accel_variance. + double b = 0.5 * a * dt; // (dt^3)/2 * accel_variance. + double c = 0.5 * b * dt; // (dt^4)/4 * accel_variance. + kalman.processNoiseCov = (cv::Mat_(12, 12) << + c, 0, 0, 0, 0, 0, b, 0, 0, 0, 0, 0, + 0, c, 0, 0, 0, 0, 0, b, 0, 0, 0, 0, + 0, 0, c, 0, 0, 0, 0, 0, b, 0, 0, 0, + 0, 0, 0, c, 0, 0, 0, 0, 0, b, 0, 0, + 0, 0, 0, 0, c, 0, 0, 0, 0, 0, b, 0, + 0, 0, 0, 0, 0, c, 0, 0, 0, 0, 0, b, + b, 0, 0, 0, 0, 0, a, 0, 0, 0, 0, 0, + 0, b, 0, 0, 0, 0, 0, a, 0, 0, 0, 0, + 0, 0, b, 0, 0, 0, 0, 0, a, 0, 0, 0, + 0, 0, 0, b, 0, 0, 0, 0, 0, a, 0, 0, + 0, 0, 0, 0, b, 0, 0, 0, 0, 0, a, 0, + 0, 0, 0, 0, 0, b, 0, 0, 0, 0, 0, a); + cv::setIdentity(kalman.measurementMatrix); + const double noise_stddev = (1+s.noise_stddev_slider) * s.mult_noise_stddev; + const double noise_variance = noise_stddev * noise_stddev; + cv::setIdentity(kalman.measurementNoiseCov, cv::Scalar::all(noise_variance)); + cv::setIdentity(kalman.errorCovPost, cv::Scalar::all(accel_variance * 1e4)); + for (int i = 0; i < 6; i++) { + last_input[i] = 0; + } + timer.invalidate(); +} + +void FTNoIR_Filter::filter(const double* input, double *output) +{ + if (prev_slider_pos != s.noise_stddev_slider) + { + reset(); + prev_slider_pos = s.noise_stddev_slider; + } + // Start the timer if it's not running. + if (!timer.isValid()) + timer.start(); + // Get the time in seconds since last run and restart the timer. + auto dt = timer.restart() / 1000.0f; + // Note this is a terrible way to detect when there is a new + // frame of tracker input, but it is the best we have. + bool new_input = false; + for (int i = 0; i < 6 && !new_input; i++) + new_input = (input[i] != last_input[i]); + // Update the transitionMatrix and processNoiseCov for dt. + double accel_variance = accel_stddev * accel_stddev; + double a = dt * dt * accel_variance; // dt^2 * accel_variance. + double b = 0.5 * a * dt; // (dt^3)/2 * accel_variance. + double c = 0.5 * b * dt; // (dt^4)/4 * accel_variance. + for (int i = 0; i < 6; i++) { + kalman.transitionMatrix.at(i,i+6) = dt; + kalman.processNoiseCov.at(i,i) = c; + kalman.processNoiseCov.at(i+6,i+6) = a; + kalman.processNoiseCov.at(i,i+6) = b; + kalman.processNoiseCov.at(i+6,i) = b; + } + // Get the updated predicted position. + cv::Mat next_output = kalman.predict(); + // If we have new tracker input, get the corrected position. + if (new_input) { + cv::Mat measurement(6, 1, CV_64F); + for (int i = 0; i < 6; i++) { + measurement.at(i) = input[i]; + // Save last_input for detecting new tracker input. + last_input[i] = input[i]; + } + next_output = kalman.correct(measurement); + } + // Set output to the next_output. + for (int i = 0; i < 6; i++) { + output[i] = next_output.at(i); + } +} + +void FilterControls::doOK() { + s.b->save(); + close(); +} + +void FilterControls::doCancel() { + s.b->reload(); + close(); +} + +OPENTRACK_DECLARE_FILTER(FTNoIR_Filter, FilterControls, FTNoIR_FilterDll) diff --git a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui deleted file mode 100644 index 3ab9a78e..00000000 --- a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui +++ /dev/null @@ -1,300 +0,0 @@ - - - AccelaUICFilterControls - - - Qt::NonModal - - - - 0 - 0 - 501 - 359 - - - - Accela filter settings - - - - :/images/filter-16.png:/images/filter-16.png - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - 99 - - - 5 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 25 - - - - - - - - 0 - 0 - - - - Rotation sensitivity - - - - - - - Smoothing - - - - - - - - 48 - 0 - - - - 0 ms - - - - - - - 0° - - - - - - - 100 - - - 10 - - - 25 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 25 - - - - - - - Translation deadzone - - - - - - - Rotation deadzone - - - - - - - 100 - - - Qt::Horizontal - - - - - - - 0° - - - - - - - 100 - - - Qt::Horizontal - - - - - - - 0mm - - - - - - - - 0 - 0 - - - - Translation sensitivity - - - - - - - 0mm - - - - - - - 99 - - - 5 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 25 - - - - - - - - - - - 0 - 0 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - - - 0 - 0 - - - - - 7 - - - - QFrame::NoFrame - - - <html><head/><body><p align="justify"><br/><span style=" font-size:10pt;">Accela by </span><a href="https://github.com/sthalik"><span style=" font-size:10pt; text-decoration: underline; color:#0057ae;">StanisÅ‚aw Halik</span></a><span style=" font-size:10pt;"><br/>Thanks to </span><a href="https://github.com/dbaarda"><span style=" font-size:10pt; text-decoration: underline; color:#0057ae;">Donovan Baarda</span></a></p><p align="right"><span style=" font-size:10pt;">2012-2015</span></p><p align="right"><br/></p></body></html> - - - Qt::RichText - - - false - - - Qt::AlignCenter - - - true - - - 0 - - - 0 - - - true - - - Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - 10 - - - - <html><head/><body><p>Visit <a href="https://github.com/opentrack/opentrack/wiki/Accela-in-opentrack-2.3"><span style=" text-decoration: underline; color:#0000ff;">our wiki</span></a> for description of the settings.</p></body></html> - - - true - - - - - - - - - - buttonBox - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.cpp b/ftnoir_filter_accela/ftnoir_filter_accela.cpp deleted file mode 100644 index 0158f27e..00000000 --- a/ftnoir_filter_accela/ftnoir_filter_accela.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2012-2015 Stanislaw Halik - * - * 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_filter_accela/ftnoir_filter_accela.h" -#include -#include -#include -#include -#include "opentrack/plugin-api.hpp" - -static constexpr double rot_gains[][2] = { - { 2.66, 110 }, - { 2.33, 80 }, - { 2, 50 }, - { 1.66, 30 }, - { 1.33, 15 }, - { 1, 5 }, - { .66, 1.4 }, - { .33, .4 }, - { 0, 0 }, - { -1, 0 } -}; - -static constexpr double trans_gains[][2] = { - { 2, 400 }, - { 1.66, 120 }, - { 1.33, 40 }, - { 1, 10 }, - { .66, 2 }, - { .33, .6 }, - { 0, 0 }, - { -1, 0 } -}; - -constexpr double settings_accela::mult_rot; -constexpr double settings_accela::mult_trans; -constexpr double settings_accela::mult_rot_dz; -constexpr double settings_accela::mult_trans_dz; -constexpr double settings_accela::mult_ewma; - -FTNoIR_Filter::FTNoIR_Filter() : first_run(true) -{ - rot.setMaxInput(rot_gains[0][0]); - trans.setMaxInput(trans_gains[0][0]); - rot.setMaxOutput(rot_gains[0][1]); - trans.setMaxOutput(trans_gains[0][1]); - - for (int i = 0; rot_gains[i][0] >= 0; i++) - { - rot.addPoint(QPointF(rot_gains[i][0], rot_gains[i][1])); - } - for (int i = 0; trans_gains[i][0] >= 0; i++) - { - trans.addPoint(QPointF(trans_gains[i][0], trans_gains[i][1])); - } -} - -void FTNoIR_Filter::filter(const double* input, double *output) -{ - if (first_run) - { - for (int i = 0; i < 6; i++) - { - const double f = input[i]; - output[i] = f; - last_output[i] = f; - smoothed_input[i] = f; - } - first_run = false; - t.start(); - return; - } - - const double rot_t = (1+s.rot_threshold) * s.mult_rot; - const double trans_t = (1+s.trans_threshold) * s.mult_trans; - - const double dt = t.elapsed() * 1e-9; - t.start(); - - const double RC = s.mult_ewma * s.ewma / 1000.; // seconds - const double alpha = dt/(dt+RC); - const double rot_dz = s.rot_deadzone * s.mult_rot_dz; - const double trans_dz = s.trans_deadzone * s.mult_trans_dz; - - for (int i = 0; i < 6; i++) - { - Map& m = i >= 3 ? rot : trans; - - smoothed_input[i] = smoothed_input[i] * (1.-alpha) + input[i] * alpha; - - const double in = smoothed_input[i]; - - const double vec = in - last_output[i]; - const double dz = i >= 3 ? rot_dz : trans_dz; - const double vec_ = std::max(0., fabs(vec) - dz); - const double thres = i >= 3 ? rot_t : trans_t; - const double val = m.getValue(vec_ / thres); - const double result = last_output[i] + (vec < 0 ? -1 : 1) * dt * val; - - last_output[i] = output[i] = result; - } -} - -OPENTRACK_DECLARE_FILTER(FTNoIR_Filter, FilterControls, FTNoIR_FilterDll) - diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.h b/ftnoir_filter_accela/ftnoir_filter_accela.h deleted file mode 100644 index a6f04dfa..00000000 --- a/ftnoir_filter_accela/ftnoir_filter_accela.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (c) 2012-2015 Stanislaw Halik - * - * 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 "ui_ftnoir_accela_filtercontrols.h" -#include "opentrack/plugin-api.hpp" -#include "qfunctionconfigurator/functionconfig.h" -#include -#include -#include - -#include "opentrack/options.hpp" -using namespace options; -#include "opentrack-compat/timer.hpp" - -struct settings_accela : opts { - value rot_threshold, trans_threshold, ewma, rot_deadzone, trans_deadzone; - static constexpr double mult_rot = 4. / 100.; - static constexpr double mult_trans = 4. / 100.; - static constexpr double mult_rot_dz = 2. / 100.; - static constexpr double mult_trans_dz = 2. / 100.; - static constexpr double mult_ewma = 1.25; - settings_accela() : - opts("Accela"), - rot_threshold(b, "rotation-threshold", 30), - trans_threshold(b, "translation-threshold", 50), - ewma(b, "ewma", 2), - rot_deadzone(b, "rotation-deadzone", 0), - trans_deadzone(b, "translation-deadzone", 0) - {} -}; - -class FTNoIR_Filter : public IFilter -{ -public: - FTNoIR_Filter(); - void filter(const double* input, double *output) override; - void center() override { first_run = true; } - Map rot, trans; -private: - settings_accela s; - bool first_run; - double last_output[6]; - double smoothed_input[6]; - Timer t; -}; - -class FilterControls: public IFilterDialog -{ - Q_OBJECT -public: - FilterControls(); - void register_filter(IFilter* filter); - void unregister_filter(); -private: - Ui::AccelaUICFilterControls ui; - void discard(); - void save(); - FTNoIR_Filter* accela_filter; - settings_accela s; -private slots: - void doOK(); - void doCancel(); - void update_ewma_display(int value); - void update_rot_display(int value); - void update_trans_display(int value); - void update_rot_dz_display(int value); - void update_trans_dz_display(int value); -}; - -class FTNoIR_FilterDll : public Metadata -{ -public: - QString name() { return QString("Accela"); } - QIcon icon() { return QIcon(":/images/filter-16.png"); } -}; diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp deleted file mode 100644 index 3400ac92..00000000 --- a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (c) 2012-2015 Stanislaw Halik - * - * 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_filter_accela/ftnoir_filter_accela.h" -#include -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "qfunctionconfigurator/qfunctionconfigurator.h" -#include - -FilterControls::FilterControls() : - accela_filter(nullptr) -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - connect(ui.rotation_slider, SIGNAL(valueChanged(int)), this, SLOT(update_rot_display(int))); - connect(ui.translation_slider, SIGNAL(valueChanged(int)), this, SLOT(update_trans_display(int))); - connect(ui.ewma_slider, SIGNAL(valueChanged(int)), this, SLOT(update_ewma_display(int))); - connect(ui.rot_dz_slider, SIGNAL(valueChanged(int)), this, SLOT(update_rot_dz_display(int))); - connect(ui.trans_dz_slider, SIGNAL(valueChanged(int)), this, SLOT(update_trans_dz_display(int))); - - tie_setting(s.rot_threshold, ui.rotation_slider); - tie_setting(s.trans_threshold, ui.translation_slider); - tie_setting(s.ewma, ui.ewma_slider); - tie_setting(s.rot_deadzone, ui.rot_dz_slider); - tie_setting(s.trans_deadzone, ui.trans_dz_slider); - - update_rot_display(ui.rotation_slider->value()); - update_trans_display(ui.translation_slider->value()); - update_ewma_display(ui.ewma_slider->value()); - update_rot_dz_display(ui.rot_dz_slider->value()); - update_trans_dz_display(ui.trans_dz_slider->value()); -} - -void FilterControls::register_filter(IFilter* filter) -{ - accela_filter = static_cast(filter); -//#define LEAKING_DEBUG -#ifdef LEAKING_DEBUG - auto d = new QDialog(); - auto r = new QFunctionConfigurator(d); - r->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - r->setConfig(&accela_filter->rot, ""); - r->setFixedSize(800, 300); - d->show(); -#endif -} - -void FilterControls::unregister_filter() -{ - accela_filter = nullptr; -} - -void FilterControls::doOK() { - save(); - this->close(); -} - -void FilterControls::doCancel() { - discard(); - close(); -} - -void FilterControls::discard() -{ - s.b->reload(); -} - -void FilterControls::save() { - s.b->save(); -} - -void FilterControls::update_rot_display(int value) -{ - ui.rot_gain->setText(QString::number((value + 1) * s.mult_rot) + "°"); -} - -void FilterControls::update_trans_display(int value) -{ - ui.trans_gain->setText(QString::number((value + 1) * s.mult_trans) + "mm"); -} - -void FilterControls::update_ewma_display(int value) -{ - ui.ewma_label->setText(QString::number(value * s.mult_ewma) + "ms"); -} - -void FilterControls::update_rot_dz_display(int value) -{ - ui.rot_dz->setText(QString::number(value * s.mult_rot_dz) + "°"); -} - -void FilterControls::update_trans_dz_display(int value) -{ - ui.trans_dz->setText(QString::number(value * s.mult_trans_dz) + "mm"); -} - diff --git a/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui b/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui deleted file mode 100644 index 9387f0d5..00000000 --- a/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui +++ /dev/null @@ -1,372 +0,0 @@ - - - UICFilterControls - - - Qt::NonModal - - - - 0 - 0 - 448 - 380 - - - - EWMA2 filter settings - - - - :/images/filter-16.png:/images/filter-16.png - - - Qt::LeftToRight - - - false - - - - - - - - - - 2 - - - 2 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - - - Min - - - - - - - - 0 - 0 - - - - 1 - - - 100 - - - 5 - - - 2 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - 0 - 0 - - - - background:none; - - - true - - - QAbstractSpinBox::PlusMinus - - - 1 - - - 120 - - - 5 - - - 2 - - - - - - - - 0 - 0 - - - - - - - Max - - - - - - - - 0 - 0 - - - - 1 - - - 100 - - - 5 - - - 10 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - 0 - 0 - - - - background:none; - - - true - - - QAbstractSpinBox::PlusMinus - - - 1 - - - 120 - - - 5 - - - 10 - - - - - - - - 0 - 0 - - - - - - - Curve - - - - - - - - 0 - 0 - - - - 1 - - - 100 - - - 5 - - - 10 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - - - - 0 - 0 - - - - background:none; - - - true - - - QAbstractSpinBox::PlusMinus - - - 100 - - - 5 - - - 10 - - - - - - - - - - background-color: rgb(214, 214, 214); -border-color: rgb(0, 0, 0); - - - QFrame::Box - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Min:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Defines the way the filter responds to fast movements;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Higher value: slower response;</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Max:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Defines the way the filter responds to slow movements;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Higher value: slower response;</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Pow:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Defines the filters 'readiness' to respond to speed changes;</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2';">Higher value = </span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">faster</span><span style=" font-family:'MS Shell Dlg 2';"> response;</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html> - - - 5 - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - minSmooth - valueChanged(int) - spinMinSmooth - setValue(int) - - - 303 - 33 - - - 391 - 36 - - - - - maxSmooth - valueChanged(int) - spinMaxSmooth - setValue(int) - - - 281 - 61 - - - 390 - 74 - - - - - powCurve - valueChanged(int) - spinPowCurve - setValue(int) - - - 236 - 101 - - - 391 - 98 - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp deleted file mode 100644 index c09fb912..00000000 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2014 Donovan Baarda - * - * 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_filter_ewma2.h" -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include -#include - -// Exponentially Weighted Moving Average (EWMA) Filter with dynamic smoothing. -// -// This filter tries to adjust the amount of filtering to minimize lag when -// moving, and minimize noise when still. It uses the delta filtered over the -// last 1/60sec (16ms) compared to the delta's average noise variance over -// the last 60sec to try and detect movement vs noise. As the delta increases -// from 0 to 3 stdevs of the noise, the filtering scales down from maxSmooth -// to minSmooth at a rate controlled by the powCurve setting. - - -FTNoIR_Filter::FTNoIR_Filter() -{ - reset(); -} - -void FTNoIR_Filter::receiveSettings() -{ - s.b->reload(); -} - -void FTNoIR_Filter::reset() -{ - timer.invalidate(); -} - -void FTNoIR_Filter::filter(const double *input, double *output) -{ - // Start the timer and initialise filter state if it's not running. - if (!timer.isValid()) { - timer.start(); - for (int i=0;i<6;i++) { - last_output[i] = input[i]; - last_delta[i] = 0.0; - last_noise[i] = 0.0; - } - } - // Get the time in seconds since last run and restart the timer. - auto dt = timer.restart() / 1000.0f; - // Calculate delta_alpha and noise_alpha from dt. - double delta_alpha = dt/(dt + delta_RC); - double noise_alpha = dt/(dt + noise_RC); - // Calculate the new camera position. - for (int i=0;i<6;i++) { - // Calculate the current and smoothed delta. - double delta = input[i] - last_output[i]; - last_delta[i] = delta_alpha*delta + (1.0-delta_alpha)*last_delta[i]; - // Calculate the current and smoothed noise variance. - double noise = last_delta[i]*last_delta[i]; - last_noise[i] = noise_alpha*noise + (1.0-noise_alpha)*last_noise[i]; - // Normalise the noise between 0->1 for 0->9 variances (0->3 stddevs). - double norm_noise = std::min(noise/(9.0*last_noise[i]), 1.0); - if (std::isnan(norm_noise)) - norm_noise = 0; - // Calculate the smoothing 0.0->1.0 from the normalized noise. - // TODO(abo): change kSmoothingScaleCurve to a float where 1.0 is sqrt(norm_noise). - double smoothing = 1.0 - pow(norm_noise, s.kSmoothingScaleCurve/20.0); - // Currently min/max smoothing are ints 0->100. We want 0.0->3.0 seconds. - // TODO(abo): Change kMinSmoothing, kMaxSmoothing to floats 0.0->3.0 seconds RC. - double RC = 3.0*(s.kMinSmoothing + smoothing*(s.kMaxSmoothing - s.kMinSmoothing))/100.0; - // Calculate the dynamic alpha. - double alpha = dt/(dt + RC); - // Calculate the new output position. - output[i] = last_output[i] = alpha*input[i] + (1.0-alpha)*last_output[i]; - } -} - -OPENTRACK_DECLARE_FILTER(FTNoIR_Filter, FilterControls, FTNoIR_FilterDll) diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h deleted file mode 100644 index bf4e83ad..00000000 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "opentrack/plugin-api.hpp" -#include "ui_ftnoir_ewma_filtercontrols.h" -#include -#include -#include -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - // these are sadly sliders for now due to int/double mismatch -sh - value kMinSmoothing, kMaxSmoothing, kSmoothingScaleCurve; - settings() : - opts("ewma-filter"), - kMinSmoothing(b, "min-smoothing", 15), - kMaxSmoothing(b, "max-smoothing", 50), - kSmoothingScaleCurve(b, "smoothing-scale-curve", 10) - {} -}; - - -class FTNoIR_Filter : public IFilter -{ -public: - FTNoIR_Filter(); - void reset(); - void filter(const double *input, double *output); - void receiveSettings(); -private: - // Deltas are smoothed over the last 1/60sec (16ms). - const double delta_RC = 0.016; - // Noise is smoothed over the last 60sec. - const double noise_RC = 60.0; - double last_delta[6]; - double last_noise[6]; - double last_output[6]; - QElapsedTimer timer; - settings s; -}; - -class FilterControls: public IFilterDialog -{ - Q_OBJECT -public: - FilterControls(); - void register_filter(IFilter* flt); - void unregister_filter(); - -private: - Ui::UICFilterControls ui; - void save(); - settings s; - FTNoIR_Filter* pFilter; - -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_FilterDll : public Metadata -{ -public: - QString name() { return QString("EWMA"); } - QIcon icon() { return QIcon(":/images/filter-16.png"); } -}; diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp deleted file mode 100644 index 30fb6003..00000000 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "ftnoir_filter_ewma2.h" -#include -#include -#include "opentrack/plugin-api.hpp" -#include "ui_ftnoir_ewma_filtercontrols.h" - -FilterControls::FilterControls() : pFilter(NULL) -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.kMaxSmoothing, ui.maxSmooth); - tie_setting(s.kMinSmoothing, ui.minSmooth); - tie_setting(s.kSmoothingScaleCurve, ui.powCurve); -} - -void FilterControls::register_filter(IFilter* flt) -{ - pFilter = (FTNoIR_Filter*) flt; -} - -void FilterControls::unregister_filter() -{ - pFilter = NULL; -} - -void FilterControls::doOK() { - save(); - this->close(); -} - -void FilterControls::doCancel() { - s.b->reload(); - this->close(); -} - -void FilterControls::save() { - s.b->save(); - if (pFilter) - pFilter->receiveSettings(); -} diff --git a/ftnoir_filter_kalman/ftnoir_filter_kalman.h b/ftnoir_filter_kalman/ftnoir_filter_kalman.h deleted file mode 100644 index a6f40bb7..00000000 --- a/ftnoir_filter_kalman/ftnoir_filter_kalman.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -/* Copyright (c) 2013 StanisÅ‚aw Halik - * - * 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. - */ -#ifndef INCLUDED_FTN_FILTER_H -#define INCLUDED_FTN_FILTER_H - -#include "ui_ftnoir_kalman_filtercontrols.h" -#include "opentrack/plugin-api.hpp" -#include -#include -#include -#include -#include -#include -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value noise_stddev_slider; - // slider for noise_stddev goes 0->(mult_noise_stddev * 100) - static constexpr double mult_noise_stddev = .5; - settings() : opts("kalman-filter"), noise_stddev_slider(b, "noise-stddev", 40) - {} -}; - -class FTNoIR_Filter : public IFilter -{ -public: - FTNoIR_Filter(); - void reset(); - void filter(const double *input, double *output); - // Set accel_stddev assuming moving 0.0->accel in dt_ is 3 stddevs: (accel*4/dt_^2)/3. - static constexpr double dt_ = .4; - static constexpr double accel = 60.; - static constexpr double accel_stddev = (accel*4/(dt_*dt_))/3.0; - cv::KalmanFilter kalman; - double last_input[6]; - QElapsedTimer timer; - settings s; - int prev_slider_pos; -}; - -class FTNoIR_FilterDll : public Metadata -{ -public: - QString name() { return QString("Kalman"); } - QIcon icon() { return QIcon(":/images/filter-16.png"); } -}; - -class FilterControls: public IFilterDialog -{ - Q_OBJECT -public: - FilterControls() { - ui.setupUi(this); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - tie_setting(s.noise_stddev_slider, ui.noise_slider); - } - Ui::KalmanUICFilterControls ui; - void register_filter(IFilter*) override {} - void unregister_filter() override {} - settings s; -public slots: - void doOK(); - void doCancel(); -}; - -#endif diff --git a/ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui b/ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui deleted file mode 100644 index 69297102..00000000 --- a/ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui +++ /dev/null @@ -1,116 +0,0 @@ - - - KalmanUICFilterControls - - - Qt::NonModal - - - - 0 - 0 - 288 - 132 - - - - - 0 - 0 - - - - Kalman settings - - - - :/images/filter-16.png:/images/filter-16.png - - - Qt::LeftToRight - - - false - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - Noise standard deviation - - - - - - - 1 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 10 - - - - - - - - - - Written by Donovan Baarda, 2014 - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - 10 - - - 10 - - - false - - - false - - - true - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_filter_kalman/kalman.cpp b/ftnoir_filter_kalman/kalman.cpp deleted file mode 100644 index 39a08703..00000000 --- a/ftnoir_filter_kalman/kalman.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2013 StanisÅ‚aw Halik - * - * 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_filter_kalman.h" -#include "opentrack/plugin-api.hpp" -#include -#include - -constexpr double settings::mult_noise_stddev; - -FTNoIR_Filter::FTNoIR_Filter() { - reset(); - prev_slider_pos = s.noise_stddev_slider; -} - -// the following was written by Donovan Baarda -// https://sourceforge.net/p/facetracknoir/discussion/1150909/thread/418615e1/?limit=25#af75/084b -void FTNoIR_Filter::reset() { - // Setup kalman with state (x) is the 6 tracker outputs then - // their 6 corresponding velocities, and the measurement (z) is - // the 6 tracker outputs. - kalman.init(12, 6, 0, CV_64F); - // Initialize the transitionMatrix and processNoiseCov for - // dt=0.1. This needs to be updated each frame for the real dt - // value, but this hows you what they should look like. See - // http://en.wikipedia.org/wiki/Kalman_filter#Example_application.2C_technical - double dt = 0.1; - kalman.transitionMatrix = (cv::Mat_(12, 12) << - 1, 0, 0, 0, 0, 0, dt, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, dt, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, dt, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, dt, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, dt, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, dt, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); - double accel_variance = accel_stddev * accel_stddev; - double a = dt * dt * accel_variance; // dt^2 * accel_variance. - double b = 0.5 * a * dt; // (dt^3)/2 * accel_variance. - double c = 0.5 * b * dt; // (dt^4)/4 * accel_variance. - kalman.processNoiseCov = (cv::Mat_(12, 12) << - c, 0, 0, 0, 0, 0, b, 0, 0, 0, 0, 0, - 0, c, 0, 0, 0, 0, 0, b, 0, 0, 0, 0, - 0, 0, c, 0, 0, 0, 0, 0, b, 0, 0, 0, - 0, 0, 0, c, 0, 0, 0, 0, 0, b, 0, 0, - 0, 0, 0, 0, c, 0, 0, 0, 0, 0, b, 0, - 0, 0, 0, 0, 0, c, 0, 0, 0, 0, 0, b, - b, 0, 0, 0, 0, 0, a, 0, 0, 0, 0, 0, - 0, b, 0, 0, 0, 0, 0, a, 0, 0, 0, 0, - 0, 0, b, 0, 0, 0, 0, 0, a, 0, 0, 0, - 0, 0, 0, b, 0, 0, 0, 0, 0, a, 0, 0, - 0, 0, 0, 0, b, 0, 0, 0, 0, 0, a, 0, - 0, 0, 0, 0, 0, b, 0, 0, 0, 0, 0, a); - cv::setIdentity(kalman.measurementMatrix); - const double noise_stddev = (1+s.noise_stddev_slider) * s.mult_noise_stddev; - const double noise_variance = noise_stddev * noise_stddev; - cv::setIdentity(kalman.measurementNoiseCov, cv::Scalar::all(noise_variance)); - cv::setIdentity(kalman.errorCovPost, cv::Scalar::all(accel_variance * 1e4)); - for (int i = 0; i < 6; i++) { - last_input[i] = 0; - } - timer.invalidate(); -} - -void FTNoIR_Filter::filter(const double* input, double *output) -{ - if (prev_slider_pos != s.noise_stddev_slider) - { - reset(); - prev_slider_pos = s.noise_stddev_slider; - } - // Start the timer if it's not running. - if (!timer.isValid()) - timer.start(); - // Get the time in seconds since last run and restart the timer. - auto dt = timer.restart() / 1000.0f; - // Note this is a terrible way to detect when there is a new - // frame of tracker input, but it is the best we have. - bool new_input = false; - for (int i = 0; i < 6 && !new_input; i++) - new_input = (input[i] != last_input[i]); - // Update the transitionMatrix and processNoiseCov for dt. - double accel_variance = accel_stddev * accel_stddev; - double a = dt * dt * accel_variance; // dt^2 * accel_variance. - double b = 0.5 * a * dt; // (dt^3)/2 * accel_variance. - double c = 0.5 * b * dt; // (dt^4)/4 * accel_variance. - for (int i = 0; i < 6; i++) { - kalman.transitionMatrix.at(i,i+6) = dt; - kalman.processNoiseCov.at(i,i) = c; - kalman.processNoiseCov.at(i+6,i+6) = a; - kalman.processNoiseCov.at(i,i+6) = b; - kalman.processNoiseCov.at(i+6,i) = b; - } - // Get the updated predicted position. - cv::Mat next_output = kalman.predict(); - // If we have new tracker input, get the corrected position. - if (new_input) { - cv::Mat measurement(6, 1, CV_64F); - for (int i = 0; i < 6; i++) { - measurement.at(i) = input[i]; - // Save last_input for detecting new tracker input. - last_input[i] = input[i]; - } - next_output = kalman.correct(measurement); - } - // Set output to the next_output. - for (int i = 0; i < 6; i++) { - output[i] = next_output.at(i); - } -} - -void FilterControls::doOK() { - s.b->save(); - close(); -} - -void FilterControls::doCancel() { - s.b->reload(); - close(); -} - -OPENTRACK_DECLARE_FILTER(FTNoIR_Filter, FilterControls, FTNoIR_FilterDll) diff --git a/ftnoir_protocol_fg/fg-protocol.qrc b/ftnoir_protocol_fg/fg-protocol.qrc deleted file mode 100644 index 1c685437..00000000 --- a/ftnoir_protocol_fg/fg-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/flightgear.png - - diff --git a/ftnoir_protocol_fg/fgtypes.h b/ftnoir_protocol_fg/fgtypes.h deleted file mode 100644 index 2e493f46..00000000 --- a/ftnoir_protocol_fg/fgtypes.h +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************************** -* FaceTrackNoIR This program is a private project of the some enthusiastic * -* gamers from Holland, who don't like to pay much for * -* head-tracking. * -* * -* Copyright (C) 2010 Wim Vriend (Developing) * -* Ron Hendriks (Researching and Testing) * -* * -* Homepage * -* * -* Type definitions for the FlightGear server. * -********************************************************************************/ -#pragma once -#ifndef INCLUDED_FGTYPES_H -#define INCLUDED_FGTYPES_H - -// -// x,y,z position in metres, heading, pitch and roll in degrees... -// -#pragma pack(push, 2) -struct TFlightGearData { - double x, y, z, h, p, r; - int status; -}; -#pragma pack(pop) - -#endif//INCLUDED_FGTYPES_H diff --git a/ftnoir_protocol_fg/ftnoir_fgcontrols.ui b/ftnoir_protocol_fg/ftnoir_fgcontrols.ui deleted file mode 100644 index 575549d6..00000000 --- a/ftnoir_protocol_fg/ftnoir_fgcontrols.ui +++ /dev/null @@ -1,143 +0,0 @@ - - - UICFGControls - - - Qt::NonModal - - - - 0 - 0 - 415 - 112 - - - - FlightGear protocol settings - - - - :/images/filter-16.png:/images/filter-16.png - - - Qt::LeftToRight - - - false - - - - - - IP-address remote PC - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - Port-number - - - - - - - 1000 - - - 10000 - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - spinIPFirstNibble - spinIPSecondNibble - spinIPThirdNibble - spinIPFourthNibble - spinPortNumber - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp deleted file mode 100644 index 660a7352..00000000 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* 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_fg.h" -#include "opentrack/plugin-api.hpp" - -// For Todd and Arda Kutlu - -void FTNoIR_Protocol::pose(const double* headpose) { - FlightData.x = headpose[TX] * 1e-2; - FlightData.y = headpose[TY] * 1e-2; - FlightData.z = headpose[TZ] * 1e-2; - FlightData.p = headpose[Pitch]; - FlightData.h = headpose[Yaw]; - FlightData.r = headpose[Roll]; - FlightData.status = 1; - QHostAddress destIP(QString("%1.%2.%3.%4").arg( - QString::number(static_cast(s.ip1)), - QString::number(static_cast(s.ip2)), - QString::number(static_cast(s.ip3)), - QString::number(static_cast(s.ip4)))); - int destPort = s.port; - (void) outSocket.writeDatagram(reinterpret_cast(&FlightData), sizeof(FlightData), destIP, static_cast(destPort)); -} - -bool FTNoIR_Protocol::correct() -{ - return outSocket.bind(QHostAddress::Any, 0, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FGControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.h b/ftnoir_protocol_fg/ftnoir_protocol_fg.h deleted file mode 100644 index de528270..00000000 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg.h +++ /dev/null @@ -1,69 +0,0 @@ -/* 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. * - */ -#pragma once -#include "ui_ftnoir_fgcontrols.h" -#include "fgtypes.h" -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value ip1, ip2, ip3, ip4; - value port; - settings() : - opts("flightgear-proto"), - ip1(b, "ip1", 192), - ip2(b, "ip2", 168), - ip3(b, "ip3", 0), - ip4(b, "ip4", 2), - port(b, "port", 5542) - {} -}; - -class FTNoIR_Protocol : public IProtocol -{ -public: - bool correct(); - void pose(const double *headpose); - QString game_name() { - return "FlightGear"; - } -private: - settings s; - TFlightGearData FlightData; - QUdpSocket outSocket; -}; - -// Widget that has controls for FTNoIR protocol client-settings. -class FGControls: public IProtocolDialog -{ - Q_OBJECT -public: - FGControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} -private: - Ui::UICFGControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("FlightGear"); } - QIcon icon() { return QIcon(":/images/flightgear.png"); } -}; diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp deleted file mode 100644 index 1d583115..00000000 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* 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_fg.h" -#include -#include -#include "opentrack/plugin-api.hpp" - -//******************************************************************************************************* -// FaceTrackNoIR Client Settings-dialog. -//******************************************************************************************************* - -// -// Constructor for server-settings-dialog -// -FGControls::FGControls() -{ - ui.setupUi( this ); - - tie_setting(s.ip1, ui.spinIPFirstNibble); - tie_setting(s.ip2, ui.spinIPSecondNibble); - tie_setting(s.ip3, ui.spinIPThirdNibble); - tie_setting(s.ip4, ui.spinIPFourthNibble); - tie_setting(s.port, ui.spinPortNumber); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); -} - -void FGControls::doOK() { - s.b->save(); - this->close(); -} - -void FGControls::doCancel() { - s.b->reload(); - this->close(); -} - diff --git a/ftnoir_protocol_fg/images/flightgear.png b/ftnoir_protocol_fg/images/flightgear.png deleted file mode 100644 index 2a546642..00000000 Binary files a/ftnoir_protocol_fg/images/flightgear.png and /dev/null differ diff --git a/ftnoir_protocol_fsuipc/fsuipc-protocol.qrc b/ftnoir_protocol_fsuipc/fsuipc-protocol.qrc deleted file mode 100644 index 34756f84..00000000 --- a/ftnoir_protocol_fsuipc/fsuipc-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/fs9.png - - diff --git a/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui b/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui deleted file mode 100644 index 637e4dba..00000000 --- a/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui +++ /dev/null @@ -1,134 +0,0 @@ - - - UICFSUIPCControls - - - Qt::NonModal - - - - 0 - 0 - 512 - 100 - - - - FSUIPC settings FaceTrackNoIR - - - - images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png - - - Qt::LeftToRight - - - false - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - Cancel - - - - - - - - 230 - 0 - - - - Location of FSUIPC.dll - - - QFrame::Box - - - QFrame::Sunken - - - 1 - - - Location of FSUIPC.dll - - - - - - - The DLL should be located in the Modules/ directory of MS FS 2004 - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - OK - - - - - - - - 35 - 16777215 - - - - ... - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp deleted file mode 100644 index 702a92d4..00000000 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* 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 "opentrack/plugin-api.hpp" - -FTNoIR_Protocol::FTNoIR_Protocol() -{ - prevPosX = 0.0f; - prevPosY = 0.0f; - prevPosZ = 0.0f; - prevRotX = 0.0f; - prevRotY = 0.0f; - prevRotZ = 0.0f; -} - -FTNoIR_Protocol::~FTNoIR_Protocol() -{ - FSUIPC_Close(); - FSUIPCLib.unload(); -} - -int FTNoIR_Protocol::scale2AnalogLimits( float x, float min_x, float max_x ) { -double y; -double local_x; - - local_x = x; - if (local_x > max_x) { - local_x = max_x; - } - if (local_x < min_x) { - local_x = min_x; - } - y = ( 16383 * local_x ) / max_x; - - return (int) y; -} - -void FTNoIR_Protocol::pose(const double *headpose ) { - DWORD result; - TFSState pitch; - TFSState yaw; - TFSState roll; - WORD FSZoom; - - float virtPosX; - float virtPosY; - float virtPosZ; - - float virtRotX; - float virtRotY; - float virtRotZ; - -// qDebug() << "FSUIPCServer::run() says: started!"; - - virtRotX = -headpose[Pitch]; // degrees - virtRotY = headpose[Yaw]; - virtRotZ = headpose[Roll]; - - virtPosX = 0.0f; // cm, X and Y are not working for FS2002/2004! - virtPosY = 0.0f; - virtPosZ = headpose[TZ]; - - // - // Init. the FSUIPC offsets (derived from Free-track...) - // - pitch.Control = 66503; - yaw.Control = 66504; - roll.Control = 66505; - - // - // Only do this when the data has changed. This way, the HAT-switch can be used when tracking is OFF. - // - if ((prevPosX != virtPosX) || (prevPosY != virtPosY) || (prevPosZ != virtPosZ) || - (prevRotX != virtRotX) || (prevRotY != virtRotY) || (prevRotZ != virtRotZ)) { - // - // Open the connection - // - 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))) { -// qDebug() << "FSUIPCServer::run() says: FSUIPC opened succesfully"; - // - // Write the 4! DOF-data to FS. Only rotations and zoom are possible. - // - pitch.Value = scale2AnalogLimits(virtRotX, -180, 180); - FSUIPC_Write(0x3110, 8, &pitch, &result); - - yaw.Value = scale2AnalogLimits(virtRotY, -180, 180); - FSUIPC_Write(0x3110, 8, &yaw, &result); - - roll.Value = scale2AnalogLimits(virtRotZ, -180, 180); - FSUIPC_Write(0x3110, 8, &roll, &result); - - FSZoom = (WORD) (64/50) * virtPosZ + 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(); - } - } - } - - prevPosX = virtPosX; - prevPosY = virtPosY; - prevPosZ = virtPosZ; - prevRotX = virtRotX; - prevRotY = virtRotY; - prevRotZ = virtRotZ; -} - -bool FTNoIR_Protocol::correct() -{ - qDebug() << "correct says: Starting Function"; - - // - // Load the DLL. - // - FSUIPCLib.setFileName( s.LocationOfDLL ); - if (FSUIPCLib.load() != true) { - qDebug() << "correct says: Error loading FSUIPC DLL"; - return false; - } - else { - qDebug() << "correct says: FSUIPC DLL loaded."; - } - - return true; -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FSUIPCControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h deleted file mode 100644 index c8e91a42..00000000 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h +++ /dev/null @@ -1,90 +0,0 @@ -/* 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. * - */ -#pragma once -#ifndef INCLUDED_FSUIPCSERVER_H -#define INCLUDED_FSUIPCSERVER_H - -#include -#include -#include "FSUIPC_User.h" -#include "opentrack/plugin-api.hpp" -#include "ui_ftnoir_fsuipccontrols.h" -#include -#include -#include -#include -#include -#include -#include -#include "opentrack/options.hpp" -using namespace options; - -#define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll" - -struct settings : opts { - value LocationOfDLL; - settings() : - opts("proto-fsuipc"), - LocationOfDLL(b, "dll-location", FSUIPC_FILENAME) - {} -}; - -#pragma pack(push,1) // All fields in structure must be byte aligned. -typedef struct -{ - int Control; // Control identifier - int Value; // Value of DOF -} TFSState; -#pragma pack(pop) - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol(); - ~FTNoIR_Protocol() override; - bool correct(); - void pose(const double* headpose); - QString game_name() { - return "Microsoft Flight Simulator X"; - } -private: - QLibrary FSUIPCLib; - double prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ; - static int scale2AnalogLimits( float x, float min_x, float max_x ); - settings s; -}; - -class FSUIPCControls: public IProtocolDialog -{ - Q_OBJECT -public: - FSUIPCControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} -private: - Ui::UICFSUIPCControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); - void getLocationOfDLL(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("FSUIPC -- Microsoft FS2002/FS2004"); } - QIcon icon() { return QIcon(":/images/fs9.png"); } -}; - - -#endif//INCLUDED_FSUIPCSERVER_H -//END diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp deleted file mode 100644 index d573420a..00000000 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 "opentrack/plugin-api.hpp" - -FSUIPCControls::FSUIPCControls() -{ - ui.setupUi( this ); - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); - connect(ui.btnFindDLL, SIGNAL(clicked()), this, SLOT(getLocationOfDLL())); - - tie_setting(s.LocationOfDLL, ui.txtLocationOfDLL); -} - -void FSUIPCControls::doOK() { - s.b->save(); - this->close(); -} - -void FSUIPCControls::doCancel() { - s.b->reload(); - close(); -} - -void FSUIPCControls::getLocationOfDLL() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Locate file"), - ui.txtLocationOfDLL->text(), - tr("FSUIPC DLL file (FSUIPC*.dll);;All Files (*)")); - if (!fileName.isEmpty()) { - s.LocationOfDLL = fileName; - } -} - diff --git a/ftnoir_protocol_fsuipc/images/fs9.png b/ftnoir_protocol_fsuipc/images/fs9.png deleted file mode 100644 index 914c9dcb..00000000 Binary files a/ftnoir_protocol_fsuipc/images/fs9.png and /dev/null differ diff --git a/ftnoir_protocol_fsuipc/images/fs91.png b/ftnoir_protocol_fsuipc/images/fs91.png deleted file mode 100644 index f9540d1d..00000000 Binary files a/ftnoir_protocol_fsuipc/images/fs91.png and /dev/null differ diff --git a/ftnoir_protocol_ft/ft-protocol.qrc b/ftnoir_protocol_ft/ft-protocol.qrc deleted file mode 100644 index c04959f0..00000000 --- a/ftnoir_protocol_ft/ft-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/freetrack.png - - diff --git a/ftnoir_protocol_ft/ftnoir_ftcontrols.ui b/ftnoir_protocol_ft/ftnoir_ftcontrols.ui deleted file mode 100644 index 5356d2e5..00000000 --- a/ftnoir_protocol_ft/ftnoir_ftcontrols.ui +++ /dev/null @@ -1,182 +0,0 @@ - - - UICFTControls - - - Qt::NonModal - - - true - - - - 0 - 0 - 422 - 305 - - - - - 0 - 0 - - - - - 0 - 0 - - - - freetrack protocol settings - - - - :/images/freetrack.png:/images/freetrack.png - - - Qt::LeftToRight - - - false - - - - - - - 0 - 0 - - - - TIRViews - - - Qt::AlignJustify|Qt::AlignTop - - - false - - - - - - Qt::RightToLeft - - - Memory hacks - - - - - - - Only for very old and buggy old games such as CFS3. - - - false - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - - - - 0 - 0 - - - - Repair NPClient location - - - Qt::AlignJustify|Qt::AlignTop - - - false - - - - - - Locate DLL - - - - - - - Replace the registry entry if you want to use other software with the NPClient protocol and it doesn't work automatically. - - - true - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - 0 - 0 - - - - Select interface - - - Qt::AlignJustify|Qt::AlignTop - - - false - - - - - - - - - Disable one of the protocols if game is confused by presence of both at the same time. - - - true - - - - - - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp deleted file mode 100644 index 05253174..00000000 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (c) 2013-2015 Stanislaw Halik - * 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_ft.h" -#include "csv/csv.h" - -FTNoIR_Protocol::FTNoIR_Protocol() : - shm(FREETRACK_HEAP, FREETRACK_MUTEX, sizeof(FTHeap)), - pMemData((FTHeap*) shm.ptr()), - viewsStart(nullptr), - viewsStop(nullptr), - intGameID(0) -{ -} - -FTNoIR_Protocol::~FTNoIR_Protocol() -{ - if (viewsStop != NULL) { - viewsStop(); - FTIRViewsLib.unload(); - } - dummyTrackIR.terminate(); - dummyTrackIR.kill(); - dummyTrackIR.waitForFinished(50); -} - -void FTNoIR_Protocol::pose(const double* headpose) { - float yaw = -getRadsFromDegrees(headpose[Yaw]); - float pitch = -getRadsFromDegrees(headpose[Pitch]); - float roll = getRadsFromDegrees(headpose[Roll]); - float tx = headpose[TX] * 10.f; - float ty = headpose[TY] * 10.f; - float tz = headpose[TZ] * 10.f; - - FTHeap* ft = pMemData; - FTData* data = &ft->data; - - data->RawX = 0; - data->RawY = 0; - data->RawZ = 0; - data->RawPitch = 0; - data->RawYaw = 0; - data->RawRoll = 0; - - data->X = tx; - data->Y = ty; - data->Z = tz; - data->Yaw = yaw; - data->Pitch = pitch; - data->Roll = roll; - - data->X1 = data->DataID; - data->X2 = 0; - data->X3 = 0; - data->X4 = 0; - data->Y1 = 0; - data->Y2 = 0; - data->Y3 = 0; - data->Y4 = 0; - - int32_t id = ft->GameID; - - if (intGameID != id) - { - QString gamename; - { - unsigned char table[8]; - if (CSV::getGameData(id, table, gamename)) - for (int i = 0; i < 8; i++) pMemData->table[i] = table[i]; - } - ft->GameID2 = id; - intGameID = id; - QMutexLocker foo(&this->game_name_mutex); - connected_game = gamename; - } - - data->DataID += 1; -} - -void FTNoIR_Protocol::start_tirviews() { - QString aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll"; - if ( QFile::exists( aFileName )) { - FTIRViewsLib.setFileName(aFileName); - FTIRViewsLib.load(); - - viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart"); - if (viewsStart == NULL) { - qDebug() << "FTServer::run() says: TIRViewsStart function not found in DLL!"; - } - else { - qDebug() << "FTServer::run() says: TIRViewsStart executed!"; - viewsStart(); - } - - // - // Load the Stop function from TIRViews.dll. Call it when terminating the thread. - // - viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop"); - if (viewsStop == NULL) { - qDebug() << "FTServer::run() says: TIRViewsStop function not found in DLL!"; - } - } -} - -void FTNoIR_Protocol::start_dummy() { - - - QString program = QCoreApplication::applicationDirPath() + "/TrackIR.exe"; - dummyTrackIR.setProgram("\"" + program + "\""); - dummyTrackIR.start(); -} - -bool FTNoIR_Protocol::correct() -{ - // Registry settings (in HK_USER) - QSettings settings("Freetrack", "FreetrackClient"); - QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); - - if (!shm.success()) - return false; - - QString aLocation = QCoreApplication::applicationDirPath() + "/"; - - switch (s.intUsedInterface) { - case 0: - // Use both interfaces - settings.setValue( "Path" , aLocation ); - settingsTIR.setValue( "Path" , aLocation ); - break; - case 1: - // Use FreeTrack, disable TrackIR - settings.setValue( "Path" , aLocation ); - settingsTIR.setValue( "Path" , "" ); - break; - case 2: - // Use TrackIR, disable FreeTrack - settings.setValue( "Path" , "" ); - settingsTIR.setValue( "Path" , aLocation ); - break; - default: - break; - } - - if (s.useTIRViews) { - start_tirviews(); - } - - // more games need the dummy executable than previously thought - start_dummy(); - - pMemData->data.DataID = 1; - pMemData->data.CamWidth = 100; - pMemData->data.CamHeight = 250; - pMemData->GameID2 = 0; - for (int i = 0; i < 8; i++) - pMemData->table[i] = 0; - - return true; -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FTControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.h b/ftnoir_protocol_ft/ftnoir_protocol_ft.h deleted file mode 100644 index 8e50f1cb..00000000 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2013-2015 Stanislaw Halik - * 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. - */ - -#pragma once -#include "ui_ftnoir_ftcontrols.h" -#include "opentrack/plugin-api.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "opentrack-compat/shm.h" -#include "opentrack/options.hpp" -#include "freetrackclient/fttypes.h" -using namespace options; - -struct settings : opts { - value intUsedInterface; - value useTIRViews; - settings() : - opts("proto-freetrack"), - intUsedInterface(b, "used-interfaces", 0), - useTIRViews(b, "use-memory-hacks", false) - {} -}; - -typedef void (__stdcall *importTIRViewsStart)(void); -typedef void (__stdcall *importTIRViewsStop)(void); - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol(); - ~FTNoIR_Protocol() override; - bool correct(); - void pose( const double *headpose ); - QString game_name() override { - QMutexLocker foo(&game_name_mutex); - return connected_game; - } -private: - settings s; - PortableLockedShm shm; - FTHeap *pMemData; - - QLibrary FTIRViewsLib; - QProcess dummyTrackIR; - importTIRViewsStart viewsStart; - importTIRViewsStop viewsStop; - - int intGameID; - QString connected_game; - QMutex game_name_mutex; - - static inline double getRadsFromDegrees(double degrees) { return degrees * 0.017453; } - void start_tirviews(); - void start_dummy(); -}; - -class FTControls: public IProtocolDialog -{ - Q_OBJECT -public: - FTControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} -private: - Ui::UICFTControls ui; - settings s; -private slots: - void selectDLL(); - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("freetrack 2.0 Enhanced"); } - QIcon icon() { return QIcon(":/images/freetrack.png"); } -}; diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp deleted file mode 100644 index 25f3a4cb..00000000 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* 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_ft.h" -#include -#include - -FTControls::FTControls() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - connect(ui.bntLocateNPClient, SIGNAL(clicked()), this, SLOT(selectDLL())); - - tie_setting(s.useTIRViews, ui.chkTIRViews); - - ui.cbxSelectInterface->addItem("Enable both"); - ui.cbxSelectInterface->addItem("Use FreeTrack, hide TrackIR"); - ui.cbxSelectInterface->addItem("Use TrackIR, hide FreeTrack"); - - tie_setting(s.intUsedInterface, ui.cbxSelectInterface); - - QFile memhacks_pathname(QCoreApplication::applicationDirPath() + "/TIRViews.dll"); - if (!memhacks_pathname.exists()) { - ui.chkTIRViews->setChecked( false ); - ui.chkTIRViews->setEnabled ( false ); - } - else { - ui.chkTIRViews->setEnabled ( true ); - } -} - -void FTControls::doOK() { - s.b->save(); - this->close(); -} - -void FTControls::doCancel() { - s.b->reload(); - this->close(); -} - -void FTControls::selectDLL() { - QString filename = QFileDialog::getOpenFileName( this, tr("Select the desired NPClient DLL"), QCoreApplication::applicationDirPath() + "/NPClient.dll", tr("Dll file (*.dll);;All Files (*)")); - - if (! filename.isEmpty() ) { - QSettings node("NaturalPoint", "NATURALPOINT\\NPClient Location"); - QFileInfo dllname(filename); - node.setValue( "Path" , dllname.dir().path() ); - } -} - diff --git a/ftnoir_protocol_ft/images/freetrack.png b/ftnoir_protocol_ft/images/freetrack.png deleted file mode 100644 index c184dc88..00000000 Binary files a/ftnoir_protocol_ft/images/freetrack.png and /dev/null differ diff --git a/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui b/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui deleted file mode 100644 index ca811e99..00000000 --- a/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui +++ /dev/null @@ -1,266 +0,0 @@ - - - UICFTNControls - - - Qt::NonModal - - - - 0 - 0 - 411 - 169 - - - - UDP protocol settings - - - - :/images/facetracknoir.png:/images/facetracknoir.png - - - Qt::LeftToRight - - - false - - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - - 60 - 16777215 - - - - 255 - - - 1 - - - - - - - IP-address remote PC - - - - - - - Port-number - - - - - - - 1000 - - - 10000 - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Enter IP-address and port-number for the remote PC. - - - true - - - - - - - Remember: you may have to change firewall-settings too! - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - OK - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - Cancel - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - - - spinIPFirstNibble - spinIPSecondNibble - spinIPThirdNibble - spinIPFourthNibble - spinPortNumber - btnOK - btnCancel - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp deleted file mode 100644 index db852f55..00000000 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* 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_ftn.h" -#include -#include "opentrack/plugin-api.hpp" - -FTNoIR_Protocol::FTNoIR_Protocol() -{ -} - -void FTNoIR_Protocol::pose(const double *headpose) { - int destPort = s.port; - QHostAddress destIP(QString("%1.%2.%3.%4").arg( - QString::number(static_cast(s.ip1)), - QString::number(static_cast(s.ip2)), - QString::number(static_cast(s.ip3)), - QString::number(static_cast(s.ip4)))); - outSocket.writeDatagram((const char *) headpose, sizeof( double[6] ), destIP, destPort); -} - -bool FTNoIR_Protocol::correct() -{ - return outSocket.bind(QHostAddress::Any, 0, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FTNControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h deleted file mode 100644 index 7fe6c225..00000000 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h +++ /dev/null @@ -1,69 +0,0 @@ -/* 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. * - */ -#pragma once - -#include "ui_ftnoir_ftncontrols.h" -#include -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value ip1, ip2, ip3, ip4, port; - settings() : - opts("udp-proto"), - ip1(b, "ip1", 192), - ip2(b, "ip2", 168), - ip3(b, "ip3", 0), - ip4(b, "ip4", 2), - port(b, "port", 4242) - {} -}; - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol(); - bool correct(); - void pose(const double *headpose); - QString game_name() { - return "UDP Tracker"; - } -private: - QUdpSocket outSocket; - settings s; -}; - -// Widget that has controls for FTNoIR protocol client-settings. -class FTNControls: public IProtocolDialog -{ - Q_OBJECT -public: - FTNControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} -private: - Ui::UICFTNControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("UDP receiver"); } - QIcon icon() { return QIcon(":/images/facetracknoir.png"); } -}; diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp deleted file mode 100644 index 77a1508a..00000000 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* 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_ftn.h" -#include "opentrack/plugin-api.hpp" - -FTNControls::FTNControls() -{ - ui.setupUi( this ); - - tie_setting(s.ip1, ui.spinIPFirstNibble); - tie_setting(s.ip2, ui.spinIPSecondNibble); - tie_setting(s.ip3, ui.spinIPThirdNibble); - tie_setting(s.ip4, ui.spinIPFourthNibble); - tie_setting(s.port, ui.spinPortNumber); - - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); -} - -// -// OK clicked on server-dialog -// -void FTNControls::doOK() { - s.b->save(); - this->close(); -} - -// -// Cancel clicked on server-dialog -// -void FTNControls::doCancel() { - s.b->reload(); - this->close(); -} diff --git a/ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui b/ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui deleted file mode 100644 index d2b86445..00000000 --- a/ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui +++ /dev/null @@ -1,111 +0,0 @@ - - - UICLibevdevControls - - - Qt::NonModal - - - - 0 - 0 - 228 - 69 - - - - VJoy - - - - :/images/vjoy.png:/images/vjoy.png - - - Qt::LeftToRight - - - false - - - - - - Make sure rw for /dev/input/uinput! - - - - - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - OK - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - Cancel - - - - - - - - - - - btnOK - btnCancel - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp deleted file mode 100644 index 96805b39..00000000 --- a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "ftnoir_protocol_libevdev.h" -#include "opentrack/plugin-api.hpp" -#include -#include - -#include -#include - -#define CHECK_LIBEVDEV(expr) if ((error = (expr)) != 0) goto error; - -static const int max_input = 65535; -static const int mid_input = 32767; -static const int min_input = 0; - -FTNoIR_Protocol::FTNoIR_Protocol() : dev(NULL), uidev(NULL) -{ - int error = 0; - - dev = libevdev_new(); - - if (!dev) - goto error; - - CHECK_LIBEVDEV(libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD)); - - libevdev_set_name(dev, "opentrack headpose"); - - struct input_absinfo absinfo; - - absinfo.minimum = min_input; - absinfo.maximum = max_input; - absinfo.resolution = 1; - absinfo.value = mid_input; - absinfo.flat = 1; - absinfo.fuzz = 0; - - CHECK_LIBEVDEV(libevdev_enable_event_type(dev, EV_ABS)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_X, &absinfo)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_Y, &absinfo)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_Z, &absinfo)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RX, &absinfo)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RY, &absinfo)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RZ, &absinfo)); - - /* do not remove next 3 lines or udev scripts won't assign 0664 permissions -sh */ - CHECK_LIBEVDEV(libevdev_enable_event_type(dev, EV_KEY)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_KEY, BTN_JOYSTICK, NULL)); - CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_KEY, BTN_TRIGGER, NULL)); - - CHECK_LIBEVDEV(libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev)); - - return; -error: - if (uidev) - libevdev_uinput_destroy(uidev); - if (dev) - libevdev_free(dev); - if (error) - fprintf(stderr, "libevdev error: %d\n", error); - uidev = NULL; - dev = NULL; -} - -FTNoIR_Protocol::~FTNoIR_Protocol() -{ - if (uidev) - libevdev_uinput_destroy(uidev); - if (dev) - libevdev_free(dev); -} - -void FTNoIR_Protocol::pose(const double* headpose) { - static const int axes[] = { - /* translation goes first */ - ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ - }; - - static const int max_value[] = { - 100, - 100, - 100, - 180, - 90, - 180 - }; - - for (int i = 0; i < 6; i++) - { - int value = headpose[i] * mid_input / max_value[i] + mid_input; - int normalized = std::max(std::min(max_input, value), min_input); - (void) libevdev_uinput_write_event(uidev, EV_ABS, axes[i], normalized); - } - - (void) libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, LibevdevControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h deleted file mode 100644 index ecb3b201..00000000 --- a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2013 Stanislaw Halik - * - * 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 "ui_ftnoir_libevdev_controls.h" - -#include -#include "opentrack/plugin-api.hpp" - -extern "C" { -# include -# include -} - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol(); - ~FTNoIR_Protocol() override; - bool correct() { - return dev != NULL; - } - void pose(const double *headpose); - QString game_name() { - return "Virtual joystick for Linux"; - } -private: - struct libevdev* dev; - struct libevdev_uinput* uidev; -}; - -class LibevdevControls: public IProtocolDialog -{ - Q_OBJECT -public: - LibevdevControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} - -private: - Ui::UICLibevdevControls ui; - void save(); - -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("libevdev joystick receiver"); } - QIcon icon() { return QIcon(":/images/linux.png"); } -}; diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp deleted file mode 100644 index 70495a8f..00000000 --- a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "ftnoir_protocol_libevdev.h" -#include "opentrack/plugin-api.hpp" - -LibevdevControls::LibevdevControls() -{ - ui.setupUi( this ); - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); -} - -void LibevdevControls::doOK() { - save(); - this->close(); -} - -void LibevdevControls::doCancel() { - this->close(); -} - -void LibevdevControls::save() { -} diff --git a/ftnoir_protocol_libevdev/images/linux.png b/ftnoir_protocol_libevdev/images/linux.png deleted file mode 100644 index 8836c0e2..00000000 Binary files a/ftnoir_protocol_libevdev/images/linux.png and /dev/null differ diff --git a/ftnoir_protocol_libevdev/libevdev-protocol.qrc b/ftnoir_protocol_libevdev/libevdev-protocol.qrc deleted file mode 100644 index 70bb415f..00000000 --- a/ftnoir_protocol_libevdev/libevdev-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/linux.png - - diff --git a/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui b/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui deleted file mode 100644 index b1f4bcf8..00000000 --- a/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui +++ /dev/null @@ -1,188 +0,0 @@ - - - UICMOUSEControls - - - Qt::NonModal - - - - 0 - 0 - 280 - 106 - - - - Mouse protocol settings - - - - :/images/mouse.png:/images/mouse.png - - - Qt::LeftToRight - - - false - - - - - - - 0 - 0 - - - - Map mouse X to: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - false - - - - - - - - 80 - 16777215 - - - - Select Number - - - QComboBox::InsertAlphabetically - - - - None - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - - - - - 80 - 16777215 - - - - Select Number - - - QComboBox::InsertAlphabetically - - - - None - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - - - - - 0 - 0 - - - - Map mouse Y to: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - false - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp deleted file mode 100644 index c0a0a868..00000000 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2015 Stanislaw Halik - * - * 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_mouse.h" -#include "opentrack/plugin-api.hpp" -#include - -#ifndef MOUSEEVENTF_MOVE_NOCOALESCE -# define MOUSEEVENTF_MOVE_NOCOALESCE 0x2000 -#endif - -void FTNoIR_Protocol::pose(const double *headpose ) { - RECT desktop; - const HWND hDesktop = GetDesktopWindow(); - if (hDesktop != NULL && GetWindowRect(hDesktop, &desktop)) { - // XXX TODO remove axis selector, use mapping window's - // axis selection. Mention in UI axis used. -sh 20140920 - int axis_x = s.Mouse_X; - int axis_y = s.Mouse_Y; - - int mouse_x = 0, mouse_y = 0; - - if (axis_x > 0 && axis_x <= 6) - mouse_x = headpose[axis_x-1] / (axis_x <= 3 ? 100 : 180) * 10 * desktop.right/2; - - if (axis_y > 0 && axis_y <= 6) - mouse_y = headpose[axis_y-1] / (axis_y <= 3 ? 100 : 180) * 10 * desktop.bottom/2; - - MOUSEINPUT mi; - mi.dx = mouse_x - last_x; - mi.dy = mouse_y - last_y; - mi.mouseData = 0; - mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_MOVE_NOCOALESCE; - mi.time = 0; - mi.dwExtraInfo = 0; - INPUT input; - input.type = INPUT_MOUSE; - input.mi = mi; - (void) SendInput(1, &input, sizeof(INPUT)); - - last_x = mouse_x; - last_y = mouse_y; - } -} - -bool FTNoIR_Protocol::correct() -{ - return true; -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, MOUSEControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h deleted file mode 100644 index 595be393..00000000 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (c) 2015 Stanislaw Halik - * - * 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 "ui_ftnoir_mousecontrols.h" -#include -#include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value Mouse_X, Mouse_Y; - settings() : - opts("mouse-proto"), - Mouse_X(b, "mouse-x", 0), - Mouse_Y(b, "mouse-y", 0) - {} -}; - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol() : last_x(0), last_y(0) {} - bool correct(); - void pose( const double *headpose); - QString game_name() { - return "Mouse tracker"; - } - int last_x, last_y; -private: - struct settings s; -}; - -class MOUSEControls: public IProtocolDialog -{ - Q_OBJECT -public: - MOUSEControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} -private: - Ui::UICMOUSEControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("mouse emulation"); } - QIcon icon() { return QIcon(":/images/mouse.png"); } -}; diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp deleted file mode 100644 index bb5fe3b8..00000000 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "ftnoir_protocol_mouse.h" -#include "opentrack/plugin-api.hpp" - -MOUSEControls::MOUSEControls() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.Mouse_X, ui.cbxSelectMouse_X); - tie_setting(s.Mouse_Y, ui.cbxSelectMouse_Y); -} - -void MOUSEControls::doOK() { - s.b->save(); - this->close(); -} - -void MOUSEControls::doCancel() { - s.b->reload(); - this->close(); -} - diff --git a/ftnoir_protocol_mouse/images/mouse.png b/ftnoir_protocol_mouse/images/mouse.png deleted file mode 100644 index c6f9ea26..00000000 Binary files a/ftnoir_protocol_mouse/images/mouse.png and /dev/null differ diff --git a/ftnoir_protocol_mouse/win32-mouse-protocol.qrc b/ftnoir_protocol_mouse/win32-mouse-protocol.qrc deleted file mode 100644 index ed6a71be..00000000 --- a/ftnoir_protocol_mouse/win32-mouse-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/mouse.png - - diff --git a/ftnoir_protocol_sc/ftnoir-protocol-sc.rc b/ftnoir_protocol_sc/ftnoir-protocol-sc.rc deleted file mode 100644 index c89eb9a7..00000000 --- a/ftnoir_protocol_sc/ftnoir-protocol-sc.rc +++ /dev/null @@ -1,4 +0,0 @@ -#include -142 RT_MANIFEST scserver.manifest -143 RT_MANIFEST scserver_sp2.manifest -144 RT_MANIFEST scserver_acceleration.manifest \ No newline at end of file diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp deleted file mode 100644 index 0c6cb486..00000000 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* Homepage http://facetracknoir.sourceforge.net/home/default.htm * - * * - * ISC License (ISC) * - * * - * Copyright (c) 2015, Wim Vriend - * Copyright (c) 2014, Stanislaw Halik - * * - * 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_sc.h" -#include "opentrack/plugin-api.hpp" - -FTNoIR_Protocol::FTNoIR_Protocol() : should_stop(false), hSimConnect(nullptr) -{ -} - -FTNoIR_Protocol::~FTNoIR_Protocol() -{ - should_stop = true; - wait(); -} - -void FTNoIR_Protocol::run() -{ - HANDLE event = CreateEvent(NULL, FALSE, FALSE, nullptr); - - if (event == nullptr) - { - qDebug() << "simconnect: event create" << GetLastError(); - return; - } - - while (!should_stop) - { - if (SUCCEEDED(simconnect_open(&hSimConnect, "opentrack", NULL, 0, event, 0))) - { - simconnect_subscribetosystemevent(hSimConnect, 0, "Frame"); - - while (!should_stop) - { - if (WaitForSingleObject(event, 10) == WAIT_OBJECT_0) - { - if (FAILED(simconnect_calldispatch(hSimConnect, processNextSimconnectEvent, reinterpret_cast(this)))) - break; - } - } - - (void) simconnect_close(hSimConnect); - } - - if (!should_stop) - Sleep(100); - } - - CloseHandle(event); -} - -void FTNoIR_Protocol::pose( const double *headpose ) { - virtSCRotX = -headpose[Pitch]; // degrees - virtSCRotY = headpose[Yaw]; - virtSCRotZ = headpose[Roll]; - - virtSCPosX = headpose[TX]/100.f; // cm to meters - virtSCPosY = headpose[TY]/100.f; - virtSCPosZ = -headpose[TZ]/100.f; -} - -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -class ActivationContext { -public: - ActivationContext(const int resid) : ok(false) { - hactctx = INVALID_HANDLE_VALUE; - actctx_cookie = 0; - ACTCTXA actx = {0}; - actx.cbSize = sizeof(ACTCTXA); - actx.lpResourceName = MAKEINTRESOURCEA(resid); - actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; -#ifdef _MSC_VER -# define PREFIX "" -#else -# define PREFIX "lib" -#endif - QString path = QCoreApplication::applicationDirPath() + "/" PREFIX "opentrack-proto-simconnect.dll"; - QByteArray name = QFile::encodeName(path); - actx.lpSource = name.constData(); - hactctx = CreateActCtxA(&actx); - actctx_cookie = 0; - if (hactctx != INVALID_HANDLE_VALUE) { - if (!ActivateActCtx(hactctx, &actctx_cookie)) { - qDebug() << "SC: can't set win32 activation context" << GetLastError(); - ReleaseActCtx(hactctx); - hactctx = INVALID_HANDLE_VALUE; - } - else - ok = true; - } else { - qDebug() << "SC: can't create win32 activation context" << GetLastError(); - } - } - ~ActivationContext() { - if (hactctx != INVALID_HANDLE_VALUE) - { - DeactivateActCtx(0, actctx_cookie); - ReleaseActCtx(hactctx); - } - } - bool is_ok() { return ok; } -private: - ULONG_PTR actctx_cookie; - HANDLE hactctx; - bool ok; -}; - -bool FTNoIR_Protocol::correct() -{ - if (!SCClientLib.isLoaded()) - { - ActivationContext ctx(142 + static_cast(s.sxs_manifest)); - - if (ctx.is_ok()) - { - SCClientLib.setFileName("SimConnect.dll"); - if (!SCClientLib.load()) { - qDebug() << "SC load" << SCClientLib.errorString(); - return false; - } - } - else - return false; - } - - simconnect_open = (importSimConnect_Open) SCClientLib.resolve("SimConnect_Open"); - if (simconnect_open == NULL) { - qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_Open function not found in DLL!"; - return false; - } - simconnect_set6DOF = (importSimConnect_CameraSetRelative6DOF) SCClientLib.resolve("SimConnect_CameraSetRelative6DOF"); - if (simconnect_set6DOF == NULL) { - qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_CameraSetRelative6DOF function not found in DLL!"; - return false; - } - simconnect_close = (importSimConnect_Close) SCClientLib.resolve("SimConnect_Close"); - if (simconnect_close == NULL) { - qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_Close function not found in DLL!"; - return false; - } - - simconnect_calldispatch = (importSimConnect_CallDispatch) SCClientLib.resolve("SimConnect_CallDispatch"); - if (simconnect_calldispatch == NULL) { - qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_CallDispatch function not found in DLL!"; - return false; - } - - simconnect_subscribetosystemevent = (importSimConnect_SubscribeToSystemEvent) SCClientLib.resolve("SimConnect_SubscribeToSystemEvent"); - if (simconnect_subscribetosystemevent == NULL) { - qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_SubscribeToSystemEvent function not found in DLL!"; - return false; - } - - start(); - - return true; -} - -void FTNoIR_Protocol::handle() -{ - (void) simconnect_set6DOF(hSimConnect, virtSCPosX, virtSCPosY, virtSCPosZ, virtSCRotX, virtSCRotZ, virtSCRotY); -} - -void CALLBACK FTNoIR_Protocol::processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD, void *self_) -{ - FTNoIR_Protocol& self = *reinterpret_cast(self_); - - switch(pData->dwID) - { - default: - break; - case SIMCONNECT_RECV_ID_EVENT_FRAME: - self.handle(); - break; - } -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, SCControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.h b/ftnoir_protocol_sc/ftnoir_protocol_sc.h deleted file mode 100644 index 671a3500..00000000 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Homepage http://facetracknoir.sourceforge.net/home/default.htm * - * * - * ISC License (ISC) * - * * - * Copyright (c) 2015, Wim Vriend * - * Copyright (c) 2014, Stanislaw Halik * - * * - * 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 "opentrack/plugin-api.hpp" - -#include "ui_ftnoir_sccontrols.h" -#include -#include -#include -#include -#include -#include -#include -#include "opentrack/options.hpp" -using namespace options; -#include - -struct settings : opts { - value sxs_manifest; - settings() : - opts("proto-simconnect"), - sxs_manifest(b, "sxs-manifest-version", 0) - {} -}; - -class FTNoIR_Protocol : public IProtocol, private QThread -{ -public: - FTNoIR_Protocol(); - ~FTNoIR_Protocol() override; - bool correct(); - void pose(const double* headpose); - void handle(); - QString game_name() { - 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; - - volatile float virtSCPosX; - volatile float virtSCPosY; - volatile float virtSCPosZ; - volatile float virtSCRotX; - volatile float virtSCRotY; - volatile float virtSCRotZ; - - importSimConnect_Open simconnect_open; - importSimConnect_Close simconnect_close; - importSimConnect_CameraSetRelative6DOF simconnect_set6DOF; - importSimConnect_CallDispatch simconnect_calldispatch; - importSimConnect_SubscribeToSystemEvent simconnect_subscribetosystemevent; - - HANDLE hSimConnect; - static void CALLBACK processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext); - settings s; - QLibrary SCClientLib; -}; - -class SCControls: public IProtocolDialog -{ - Q_OBJECT -public: - SCControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} -private: - Ui::UICSCControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("Microsoft FSX SimConnect"); } - QIcon icon() { return QIcon(":/images/fsx.png"); } -}; diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp deleted file mode 100644 index 7c2ecfd4..00000000 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* 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_sc.h" -#include -#include "opentrack/plugin-api.hpp" - -SCControls::SCControls() -{ - ui.setupUi( this ); - - // Connect Qt signals to member-functions - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.sxs_manifest, ui.comboBox); -} - -void SCControls::doOK() { - s.b->save(); - this->close(); -} - -void SCControls::doCancel() { - s.b->reload(); - close(); -} - diff --git a/ftnoir_protocol_sc/ftnoir_sccontrols.ui b/ftnoir_protocol_sc/ftnoir_sccontrols.ui deleted file mode 100644 index 5b2fd291..00000000 --- a/ftnoir_protocol_sc/ftnoir_sccontrols.ui +++ /dev/null @@ -1,72 +0,0 @@ - - - UICSCControls - - - Qt::NonModal - - - - 0 - 0 - 290 - 79 - - - - SimConnect settings FaceTrackNoIR - - - - images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png - - - Qt::LeftToRight - - - false - - - - - - FSX version - - - - - - - - SP1 - - - - - SP2 - - - - - Acceleration - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_sc/images/fsx.png b/ftnoir_protocol_sc/images/fsx.png deleted file mode 100644 index 16b072a1..00000000 Binary files a/ftnoir_protocol_sc/images/fsx.png and /dev/null differ diff --git a/ftnoir_protocol_sc/images/fsx1.png b/ftnoir_protocol_sc/images/fsx1.png deleted file mode 100644 index a1f0f188..00000000 Binary files a/ftnoir_protocol_sc/images/fsx1.png and /dev/null differ diff --git a/ftnoir_protocol_sc/sc-protocol.qrc b/ftnoir_protocol_sc/sc-protocol.qrc deleted file mode 100644 index 127d5180..00000000 --- a/ftnoir_protocol_sc/sc-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/fsx.png - - diff --git a/ftnoir_protocol_sc/scserver.manifest b/ftnoir_protocol_sc/scserver.manifest deleted file mode 100644 index d342cfda..00000000 --- a/ftnoir_protocol_sc/scserver.manifest +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/ftnoir_protocol_sc/scserver_acceleration.manifest b/ftnoir_protocol_sc/scserver_acceleration.manifest deleted file mode 100644 index 06459587..00000000 --- a/ftnoir_protocol_sc/scserver_acceleration.manifest +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/ftnoir_protocol_sc/scserver_sp2.manifest b/ftnoir_protocol_sc/scserver_sp2.manifest deleted file mode 100644 index 3020d16c..00000000 --- a/ftnoir_protocol_sc/scserver_sp2.manifest +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp deleted file mode 100644 index 24148c63..00000000 --- a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "ftnoir_protocol_vjoy.h" -#include "opentrack/plugin-api.hpp" - -FTNoIR_Protocol::FTNoIR_Protocol() -{ - static char meh[1] = {0}; - VJoy_Initialize(meh, meh); -} - -FTNoIR_Protocol::~FTNoIR_Protocol() -{ - VJoy_Shutdown(); -} - -void FTNoIR_Protocol::pose( const double *headpose ) { -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - JOYSTICK_STATE state[2] = { 0 }; - - state[0].POV = (4 << 12) | (4 << 8) | (4 << 4) | 4; - - state[0].XAxis = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[Yaw] * VJOY_AXIS_MAX / 180.0)); - state[0].YAxis = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[Pitch] * VJOY_AXIS_MAX / 180.0)); - state[0].ZAxis = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[Roll] * VJOY_AXIS_MAX / 180.0)); - state[0].XRotation = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[TX] * VJOY_AXIS_MAX / 100.0)); - state[0].YRotation = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[TY] * VJOY_AXIS_MAX / 100.0)); - state[0].ZRotation = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[TZ] * VJOY_AXIS_MAX / 100.0)); - - VJoy_UpdateJoyState(0, state); -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, VJoyControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h deleted file mode 100644 index 118306b5..00000000 --- a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h +++ /dev/null @@ -1,91 +0,0 @@ -/* 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. * - */ -#pragma once -#include "ui_ftnoir_vjoy_controls.h" -#include -#include "opentrack/plugin-api.hpp" - -#define FT_PROGRAMID "FT_ProgramID" - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol(); - ~FTNoIR_Protocol() override; - bool correct() { - return true; - } - void pose( const double *headpose ); - QString game_name() { - return "Virtual joystick"; - } -private: -}; - -// Widget that has controls for FTNoIR protocol client-settings. -class VJoyControls: public IProtocolDialog -{ - Q_OBJECT -public: - - explicit VJoyControls(); - void register_protocol(IProtocol *) {} - void unregister_protocol() {} - -private: - Ui::UICVJoyControls ui; - void save(); - -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() { return QString("Joystick emulation -- VJoy"); } - QIcon icon() { return QIcon(":/images/vjoy.png"); } -}; - -#define VJOY_AXIS_MIN -32768 -#define VJOY_AXIS_NIL 0 -#define VJOY_AXIS_MAX 32767 - -#include - -#include - -typedef struct _JOYSTICK_STATE -{ - UCHAR ReportId; // Report Id - SHORT XAxis; // X Axis - SHORT YAxis; // Y Axis - SHORT ZAxis; // Z Axis - SHORT XRotation; // X Rotation - SHORT YRotation; // Y Rotation - SHORT ZRotation; // Z Rotation - SHORT Slider; // Slider - SHORT Dial; // Dial - USHORT POV; // POV - UINT32 Buttons; // 32 Buttons -} JOYSTICK_STATE, * PJOYSTICK_STATE; - -#ifndef _MSC_VER -EXTERN_C BOOL __stdcall VJoy_Initialize(PCHAR name, PCHAR serial); -EXTERN_C VOID __stdcall VJoy_Shutdown(); -EXTERN_C BOOL __stdcall VJoy_UpdateJoyState(int id, PJOYSTICK_STATE pJoyState); -#else -#define VJOY_API __declspec(dllimport) -VJOY_API BOOL __stdcall VJoy_Initialize(PCHAR name, PCHAR serial); -VJOY_API VOID __stdcall VJoy_Shutdown(); -VJOY_API BOOL __stdcall VJoy_UpdateJoyState(int id, PJOYSTICK_STATE pJoyState); -#endif diff --git a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp deleted file mode 100644 index 08c65558..00000000 --- a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "ftnoir_protocol_vjoy.h" -#include "opentrack/plugin-api.hpp" - -VJoyControls::VJoyControls() -{ - ui.setupUi( this ); - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); -} - -void VJoyControls::doOK() { - save(); - this->close(); -} - -void VJoyControls::doCancel() { - this->close(); -} - -void VJoyControls::save() { -} - diff --git a/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui b/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui deleted file mode 100644 index 2214b887..00000000 --- a/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui +++ /dev/null @@ -1,113 +0,0 @@ - - - UICVJoyControls - - - Qt::NonModal - - - - 0 - 0 - 228 - 69 - - - - VJoy - - - - :/images/vjoy.png:/images/vjoy.png - - - Qt::LeftToRight - - - false - - - - - - No settings necessary - - - - - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - OK - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - Cancel - - - - - - - - - - - btnOK - btnCancel - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_vjoy/images/vjoy.png b/ftnoir_protocol_vjoy/images/vjoy.png deleted file mode 100644 index 8eb14be8..00000000 Binary files a/ftnoir_protocol_vjoy/images/vjoy.png and /dev/null differ diff --git a/ftnoir_protocol_vjoy/vjoy-protocol.qrc b/ftnoir_protocol_vjoy/vjoy-protocol.qrc deleted file mode 100644 index 7b3741f1..00000000 --- a/ftnoir_protocol_vjoy/vjoy-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/vjoy.png - - diff --git a/ftnoir_protocol_vjoy/vjoy.def b/ftnoir_protocol_vjoy/vjoy.def deleted file mode 100644 index aea590a4..00000000 --- a/ftnoir_protocol_vjoy/vjoy.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY vjoy.dll -IMPORTS -VJoy_Initialize = _VJoy_Initialize -VJoy_Shutdown = _VJoy_Shutdown -VJoy_UpdateJoyState = _VJoy_UpdateJoyState diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp b/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp deleted file mode 100644 index 99ad30a2..00000000 --- a/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "ftnoir_protocol_wine.h" -#include -#include -#include /* For mode constants */ -#include /* For O_* constants */ -#include "csv/csv.h" - -FTNoIR_Protocol::FTNoIR_Protocol() : lck_shm(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)), shm(NULL), gameid(0) -{ - if (lck_shm.success()) { - shm = (WineSHM*) lck_shm.ptr(); - memset(shm, 0, sizeof(*shm)); - } - wrapper.start("wine", QStringList() << (QCoreApplication::applicationDirPath() + "/opentrack-wrapper-wine.exe.so")); -} - -FTNoIR_Protocol::~FTNoIR_Protocol() -{ - if (shm) { - shm->stop = true; - wrapper.waitForFinished(100); - } - wrapper.terminate(); - if (!wrapper.waitForFinished(100)) - { - wrapper.kill(); - wrapper.waitForFinished(42); - } - //shm_unlink("/" WINE_SHM_NAME); -} - -void FTNoIR_Protocol::pose( const double *headpose ) { - if (shm) - { - lck_shm.lock(); - for (int i = 3; i < 6; i++) - shm->data[i] = headpose[i] / 57.295781; - for (int i = 0; i < 3; i++) - shm->data[i] = headpose[i] * 10; - if (shm->gameid != gameid) - { - QString gamename; - QMutexLocker foo(&game_name_mutex); - /* only EZCA for FSX requires dummy process, and FSX doesn't work on Linux */ - /* memory-hacks DLL can't be loaded into a Linux process, either */ - CSV::getGameData(shm->gameid, shm->table, gamename); - gameid = shm->gameid2 = shm->gameid; - connected_game = gamename; - } - lck_shm.unlock(); - } -} - -bool FTNoIR_Protocol::correct() -{ - return lck_shm.success(); -} - -OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FTControls, FTNoIR_ProtocolDll) diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine.h b/ftnoir_protocol_wine/ftnoir_protocol_wine.h deleted file mode 100644 index 2aeb4608..00000000 --- a/ftnoir_protocol_wine/ftnoir_protocol_wine.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "ui_ftnoir_winecontrols.h" -#include -#include -#include -#include -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "opentrack-compat/shm.h" -#include "ftnoir_protocol_wine/wine-shm.h" - -class FTNoIR_Protocol : public IProtocol -{ -public: - FTNoIR_Protocol(); - ~FTNoIR_Protocol() override; - - bool correct() override; - void pose(const double* headpose) override; - QString game_name() override { - QMutexLocker foo(&game_name_mutex); - return connected_game; - } -private: - PortableLockedShm lck_shm; - WineSHM* shm; - QProcess wrapper; - int gameid; - QString connected_game; - QMutex game_name_mutex; -}; - -class FTControls: public IProtocolDialog -{ - Q_OBJECT -public: - FTControls(); - void register_protocol(IProtocol *) override {} - void unregister_protocol() override {} - -private: - Ui::UICFTControls ui; - -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_ProtocolDll : public Metadata -{ -public: - QString name() override { return QString("Wine -- Windows layer for Unix"); } - QIcon icon() override { return QIcon(":/images/wine.png"); } -}; diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp b/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp deleted file mode 100644 index e4027c73..00000000 --- a/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "ftnoir_protocol_wine.h" -#include -#include "opentrack/plugin-api.hpp" - -FTControls::FTControls() -{ - ui.setupUi( this ); - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); -} - -void FTControls::doOK() { - this->close(); -} - -void FTControls::doCancel() { - this->close(); -} - diff --git a/ftnoir_protocol_wine/ftnoir_winecontrols.ui b/ftnoir_protocol_wine/ftnoir_winecontrols.ui deleted file mode 100644 index 9356c448..00000000 --- a/ftnoir_protocol_wine/ftnoir_winecontrols.ui +++ /dev/null @@ -1,170 +0,0 @@ - - - UICFTControls - - - Qt::NonModal - - - - 0 - 0 - 409 - 110 - - - - FreeTrack settings FaceTrackNoIR - - - - images/freetrack.pngimages/freetrack.png - - - Qt::LeftToRight - - - false - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - There are no settings necessary for the Wine protocol. - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - OK - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100 - 16777215 - - - - Cancel - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_protocol_wine/images/wine.png b/ftnoir_protocol_wine/images/wine.png deleted file mode 100644 index bcf3a012..00000000 Binary files a/ftnoir_protocol_wine/images/wine.png and /dev/null differ diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx deleted file mode 100644 index ffe8938d..00000000 --- a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx +++ /dev/null @@ -1,80 +0,0 @@ -#include -// OSX sdk 10.8 build error otherwise -#ifdef _LIBCPP_MSVCRT -# undef _LIBCPP_MSVCRT -#endif -#include -#include "freetrackclient/fttypes.h" -#include "ftnoir_protocol_wine/wine-shm.h" -#include "opentrack-compat/export.hpp" - -enum Axis { - TX = 0, TY, TZ, Yaw, Pitch, Roll -}; - -#include "opentrack-compat/shm.h" - -void create_registry_key(void); - -class ShmPosix { -public: - ShmPosix(const char *shmName, const char *mutexName, int mapSize); - ~ShmPosix(); - void lock(); - void unlock(); - bool success(); - inline void* ptr() { return mem; } -private: - void* mem; - int fd, size; -}; - -class ShmWine { -public: - ShmWine(const char *shmName, const char *mutexName, int mapSize); - ~ShmWine(); - void lock(); - void unlock(); - bool success(); - inline void* ptr() { return mem; } -private: - void* mem; - void *hMutex, *hMapFile; -}; -#include - -int main(void) -{ - ShmPosix lck_posix(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)); - ShmWine lck_wine("FT_SharedMem", "FT_Mutext", sizeof(FTHeap)); - if(!lck_posix.success()) { - printf("Can't open posix map: %d\n", errno); - return 1; - } - if(!lck_wine.success()) { - printf("Can't open Wine map\n"); - return 1; - } - WineSHM* shm_posix = (WineSHM*) lck_posix.ptr(); - FTHeap* shm_wine = (FTHeap*) lck_wine.ptr(); - FTData* data = &shm_wine->data; - create_registry_key(); - while (1) { - if (shm_posix->stop) - break; - data->Yaw = -shm_posix->data[Yaw]; - data->Pitch = -shm_posix->data[Pitch]; - data->Roll = shm_posix->data[Roll]; - data->X = shm_posix->data[TX]; - data->Y = shm_posix->data[TY]; - data->Z = shm_posix->data[TZ]; - data->DataID++; - data->CamWidth = 250; - data->CamHeight = 100; - shm_wine->GameID2 = shm_posix->gameid2; - shm_posix->gameid = shm_wine->GameID; - for (int i = 0; i < 8; i++) - shm_wine->table[i] = shm_posix->table[i]; - (void) Sleep(4); - } -} diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx deleted file mode 100644 index 50cce728..00000000 --- a/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef _WIN32 -# undef _WIN32 -#endif - -#define PortableLockedShm ShmPosix -#include "opentrack-compat/shm.h" -#include "opentrack-compat/shm.cpp" diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx deleted file mode 100644 index 19ee8ffd..00000000 --- a/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __WIN32 -# error "bad cross" -#endif - -#define PortableLockedShm ShmWine -#include "opentrack-compat/shm.h" -#include "opentrack-compat/shm.cpp" -#include "wine-shm.h" - -static void write_path(const char* key, const char* subkey) -{ - char dir[8192]; - - if (GetCurrentDirectoryA(8192, dir) < 8190) - { - HKEY hkpath; - if (RegCreateKeyExA(HKEY_CURRENT_USER, - key, - 0, - NULL, - 0, - KEY_ALL_ACCESS, - NULL, - &hkpath, - NULL) == ERROR_SUCCESS) - { - for (int i = 0; dir[i]; i++) - if (dir[i] == '\\') - dir[i] = '/'; - strcat(dir, "/"); - (void) RegSetValueExA(hkpath, subkey, 0, REG_SZ, (BYTE*) dir, strlen(dir) + 1); - RegCloseKey(hkpath); - } - } -} - -void create_registry_key(void) { - write_path("Software\\NaturalPoint\\NATURALPOINT\\NPClient Location", "Path"); - write_path("Software\\Freetrack\\FreeTrackClient", "Path"); -} diff --git a/ftnoir_protocol_wine/wine-protocol.qrc b/ftnoir_protocol_wine/wine-protocol.qrc deleted file mode 100644 index af81caea..00000000 --- a/ftnoir_protocol_wine/wine-protocol.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/wine.png - - diff --git a/ftnoir_protocol_wine/wine-shm.h b/ftnoir_protocol_wine/wine-shm.h deleted file mode 100644 index c7e29abb..00000000 --- a/ftnoir_protocol_wine/wine-shm.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#define WINE_SHM_NAME "facetracknoir-wine-shm" -#define WINE_MTX_NAME "facetracknoir-wine-mtx" - -// OSX sdk 10.8 build error otherwise -#ifdef _LIBCPP_MSVCRT -# undef _LIBCPP_MSVCRT -#endif - -#include - -template using ptr = std::shared_ptr; - -struct WineSHM { - double data[6]; - int gameid, gameid2; - unsigned char table[8]; - bool stop; -}; diff --git a/ftnoir_tracker_aruco/ar_video_widget.cpp b/ftnoir_tracker_aruco/ar_video_widget.cpp deleted file mode 100644 index 1c3af262..00000000 --- a/ftnoir_tracker_aruco/ar_video_widget.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2014 Stanislaw Halik - * - * 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 "ar_video_widget.h" - -void ArucoVideoWidget::update_image(const cv::Mat& frame) -{ - QMutexLocker foo(&mtx); - if (!fresh) - { - _frame = frame.clone(); - fresh = true; - } -} - -void ArucoVideoWidget::update_and_repaint() -{ - QImage qframe; - - { - QMutexLocker foo(&mtx); - if (_frame.cols*_frame.rows <= 0 || !fresh) - return; - fresh = false; - qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); - uchar* data = qframe.bits(); - const int pitch = qframe.bytesPerLine(); - unsigned char *input = (unsigned char*)(_frame.data); - const int chans = _frame.channels(); - for (int y = 0; y < _frame.rows; y++) - { - const int step = y * _frame.step; - const int pitch_ = y * pitch; - for (int x = 0; x < _frame.cols; x++) - { - data[pitch_ + x * 3 + 0] = input[step + x * chans + 2]; - data[pitch_ + x * 3 + 1] = input[step + x * chans + 1]; - data[pitch_ + x * 3 + 2] = input[step + x * chans + 0]; - } - } - } - - qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); - - { - QMutexLocker foo(&mtx); - texture = qframe; - } - - update(); -} - -void ArucoVideoWidget::paintEvent(QPaintEvent* e) -{ - QMutexLocker foo(&mtx); - QPainter(this).drawImage(e->rect(), texture); -} - -ArucoVideoWidget::ArucoVideoWidget(QWidget* parent): QWidget(parent), fresh(false) -{ - connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); - timer.start(60); -} diff --git a/ftnoir_tracker_aruco/ar_video_widget.h b/ftnoir_tracker_aruco/ar_video_widget.h deleted file mode 100644 index 6df2d626..00000000 --- a/ftnoir_tracker_aruco/ar_video_widget.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (c) 2014 Stanislaw Halik - * - * 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 -#include -#include -#include -#include -#include -#include - -class ArucoVideoWidget : public QWidget -{ - Q_OBJECT -private: - QMutex mtx; - QImage texture; - QTimer timer; - cv::Mat _frame; - bool fresh; -private slots: - void update_and_repaint(); -public: - ArucoVideoWidget(QWidget *parent); - void update_image(const cv::Mat& frame); - void paintEvent( QPaintEvent*) override; -}; diff --git a/ftnoir_tracker_aruco/aruco-tracker.qrc b/ftnoir_tracker_aruco/aruco-tracker.qrc deleted file mode 100644 index 70859876..00000000 --- a/ftnoir_tracker_aruco/aruco-tracker.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/aruco.png - - diff --git a/ftnoir_tracker_aruco/aruco-trackercontrols.ui b/ftnoir_tracker_aruco/aruco-trackercontrols.ui deleted file mode 100644 index 7e32936c..00000000 --- a/ftnoir_tracker_aruco/aruco-trackercontrols.ui +++ /dev/null @@ -1,281 +0,0 @@ - - - Form - - - Qt::NonModal - - - - 0 - 0 - 485 - 202 - - - - - 0 - 0 - - - - Tracker settings - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - Frames per second - - - - - - - - 0 - 0 - - - - - 640x480 - - - - - 320x240 - - - - - 320x200 - - - - - Default (not recommended!) - - - - - - - - Camera name - - - - - - - Resolution - - - - - - - Diagonal FOV - - - - - - - - 0 - 0 - - - - - Default - - - - - 30 - - - - - 60 - - - - - 125 - - - - - 200 - - - - - - - - - 0 - 0 - - - - - - - - Camera settings - - - - - - - Open - - - - - - - - 0 - 0 - - - - - - - 10 - - - 180 - - - - - - - - - - - - - Head X - - - - - - - - 0 - 0 - - - - -10000.000000000000000 - - - 10000.000000000000000 - - - - - - - - 0 - 0 - - - - -10000.000000000000000 - - - 10000.000000000000000 - - - - - - - - 0 - 0 - - - - -10000.000000000000000 - - - 10000.000000000000000 - - - - - - - Head Z - - - - - - - Head Y - - - - - - - Toggle calibration - - - true - - - - - - - - - - - - - 10 - - - 10 - - - false - - - false - - - true - - - diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp deleted file mode 100644 index 570c2e0d..00000000 --- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/* Copyright (c) 2013-2015 Stanislaw Halik - * - * 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 -#include -#include -#include -#include -#include "./include/markerdetector.h" -#include "ftnoir_tracker_aruco.h" -#include "opentrack/plugin-api.hpp" -#include -#include -#include -#include "opentrack/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" - -typedef struct { - int width; - int height; -} resolution_tuple; - -static resolution_tuple resolution_choices[] = { - { 640, 480 }, - { 320, 240 }, - { 320, 200 }, - { 0, 0 } -}; - -Tracker::Tracker() : stop(false), layout(nullptr), videoWidget(nullptr) -{ -} - -Tracker::~Tracker() -{ - stop = true; - wait(); - if (videoWidget) - delete videoWidget; - if(layout) - delete layout; - camera.release(); -} - -void Tracker::start_tracker(QFrame* videoframe) -{ - videoframe->show(); - videoWidget = new ArucoVideoWidget(videoframe); - QHBoxLayout* layout = new QHBoxLayout(); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(videoWidget); - if (videoframe->layout()) - delete videoframe->layout(); - videoframe->setLayout(layout); - videoWidget->show(); - start(); - for (int i = 0; i < 6; i++) - pose[i] = 0; - this->layout = layout; -} - -#define HT_PI 3.1415926535 - -void Tracker::getRT(cv::Matx33d& r_, cv::Vec3d& t_) -{ - QMutexLocker l(&mtx); - - r_ = r; - t_ = t; -} - -void Tracker::run() -{ - int rint = s.resolution; - if (rint < 0 || rint >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple))) - rint = 0; - resolution_tuple res = resolution_choices[rint]; - int fps; - switch (static_cast(s.force_fps)) - { - default: - case 0: - fps = 0; - break; - case 1: - fps = 30; - break; - case 2: - fps = 60; - break; - case 3: - fps = 125; - break; - case 4: - fps = 200; - break; - } - - { - QMutexLocker l(&camera_mtx); - - camera = cv::VideoCapture(camera_name_to_index(s.camera_name)); - if (res.width) - { - camera.set(cv::CAP_PROP_FRAME_WIDTH, res.width); - camera.set(cv::CAP_PROP_FRAME_HEIGHT, res.height); - } - if (fps) - camera.set(cv::CAP_PROP_FPS, fps); - - if (!camera.isOpened()) - { - qDebug() << "aruco tracker: can't open camera"; - return; - } - } - - aruco::MarkerDetector detector; - detector.setDesiredSpeed(3); - - cv::Rect last_roi(65535, 65535, 0, 0); - - auto freq = cv::getTickFrequency(); - auto last_time = cv::getTickCount(); - double cur_fps = 0; - std::vector box_sizes { 5, 7, 9, 11 }; - int box_idx = 0; - double failed = 0; - const double max_failed = 1.25; - cv::Vec3d rvec, tvec; - cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); - cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); - bool otsu = false; - - while (!stop) - { - cv::Mat color; - { - QMutexLocker l(&camera_mtx); - - if (!camera.read(color)) - continue; - } - static constexpr int thres_param2 = 5; - cv::Mat grayscale; - cv::cvtColor(color, grayscale, cv::COLOR_RGB2GRAY); - - const int scale = grayscale.cols > 480 ? 2 : 1; - detector.setThresholdParams(box_sizes[box_idx], thres_param2); - - static constexpr double pi = 3.1415926f; - const int w = grayscale.cols, h = grayscale.rows; - const double diag_fov = static_cast(s.fov) * pi / 180.; - const double fov_w = 2.*atan(tan(diag_fov/2.)/sqrt(1. + h/(double)w * h/(double)w)); - const double fov_h = 2.*atan(tan(diag_fov/2.)/sqrt(1. + w/(double)h * w/(double)h)); - const float focal_length_w = .5 * w / tan(.5 * fov_w); - const float focal_length_h = .5 * h / tan(.5 * fov_h); - - intrinsics.at (0, 0) = focal_length_w; - intrinsics.at (1, 1) = focal_length_h; - intrinsics.at (0, 2) = grayscale.cols/2; - intrinsics.at (1, 2) = grayscale.rows/2; - - std::vector< aruco::Marker > markers; - - const double size_min = 0.05; - const double size_max = 0.3; - - bool roi_valid = false; - - auto time = cv::getTickCount(); - - const double dt = (time - last_time) / freq; - last_time = time; - cur_fps = cur_fps * 0.97 + 0.03 * (dt == 0 ? 0 : 1./dt); - - if (last_roi.width > 0 && last_roi.height) - { - detector.setThresholdParams(box_sizes[box_idx], thres_param2); - detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width), - std::min(1.0, size_max * grayscale.cols / last_roi.width)); - - cv::Mat grayscale_ = grayscale(last_roi).clone(); - if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), - markers.size() == 1 && markers[0].size() == 4) - { - failed = std::max(0., failed - dt); - auto& m = markers.at(0); - for (int i = 0; i < 4; i++) - { - auto& p = m.at(i); - p.x += last_roi.x; - p.y += last_roi.y; - } - roi_valid = true; - } - } - - if (!roi_valid) - { - otsu = !otsu; - detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; - failed += dt; - if (failed > max_failed) - { - box_idx++; - box_idx %= box_sizes.size(); - qDebug() << "aruco: box size now" << box_sizes[box_idx]; - failed = 0; - } - detector.setThresholdParams(box_sizes[box_idx], thres_param2); - detector.setMinMaxSize(size_min, size_max); - detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false); - } - - if (markers.size() == 1 && markers[0].size() == 4) { - const auto& m = markers.at(0); - for (int i = 0; i < 4; i++) - cv::line(color, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), scale, 8); - } - - char buf[128]; - - frame = color.clone(); - - ::sprintf(buf, "Hz: %d", (int)cur_fps); - cv::putText(frame, buf, cv::Point(10, 32), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(0, 255, 0), scale*2); - - if (markers.size() == 1 && markers[0].size() == 4) { - const auto& m = markers.at(0); - const float size = 40; - - cv::Mat obj_points(4,3,CV_32FC1); - const int x1=1, x2=2, x3=3, x4=0; - obj_points.at(x1,0)=-size + s.headpos_x; - obj_points.at(x1,1)=-size + s.headpos_y; - obj_points.at(x1,2)= 0 + s.headpos_z; - - obj_points.at(x2,0)=size + s.headpos_x; - obj_points.at(x2,1)=-size + s.headpos_y; - obj_points.at(x2,2)= 0 + s.headpos_z; - - obj_points.at(x3,0)=size + s.headpos_x; - obj_points.at(x3,1)=size + s.headpos_y; - obj_points.at(x3,2)= 0 + s.headpos_z; - - obj_points.at(x4,0)= -size + s.headpos_x; - obj_points.at(x4,1)= size + s.headpos_y; - obj_points.at(x4,2)= 0 + s.headpos_z; - - std::vector img_points = m; - if (!cv::solvePnP(obj_points, img_points, intrinsics, dist_coeffs, rvec, tvec, false, cv::SOLVEPNP_ITERATIVE)) - goto fail; - - { - std::vector repr2; - std::vector centroid; - centroid.push_back(cv::Point3f(0, 0, 0)); - cv::projectPoints(centroid, rvec, tvec, intrinsics, dist_coeffs, repr2); - - { - auto s = cv::Scalar(255, 0, 255); - cv::circle(frame, repr2.at(0), 4, s, -1); - } - } - - for (int i = 0; i < 4; i++) - { - obj_points.at(i, 0) -= s.headpos_x; - obj_points.at(i, 1) -= s.headpos_y; - obj_points.at(i, 2) -= s.headpos_z; - } - - cv::Mat rvec_, tvec_; - cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec_, tvec_, false, cv::SOLVEPNP_ITERATIVE); - - cv::Mat roi_points = obj_points * c_search_window; - std::vector roi_projection(4); - cv::projectPoints(roi_points, rvec_, tvec_, intrinsics, dist_coeffs, roi_projection); - - last_roi = cv::Rect(color.cols-1, color.rows-1, 0, 0); - - for (int i = 0; i < 4; i++) - { - auto proj = roi_projection[i]; - int min_x = std::min(proj.x, last_roi.x), - min_y = std::min(proj.y, last_roi.y); - - int max_x = std::max(proj.x, last_roi.width), - max_y = std::max(proj.y, last_roi.height); - - last_roi.x = min_x; - last_roi.y = min_y; - - last_roi.width = max_x; - last_roi.height = max_y; - } - - if (last_roi.x < 0) - last_roi.x = 0; - if (last_roi.y < 0) - last_roi.y = 0; - if (last_roi.width < 0) - last_roi.width = 0; - if (last_roi.height < 0) - last_roi.height = 0; - if (last_roi.x >= color.cols-1) - last_roi.x = color.cols-1; - if (last_roi.width >= color.cols-1) - last_roi.width = color.cols-1; - if (last_roi.y >= color.rows-1) - last_roi.y= color.rows-1; - if (last_roi.height >= color.rows-1) - last_roi.height = color.rows-1; - - last_roi.width -= last_roi.x; - last_roi.height -= last_roi.y; - - auto rmat = cv::Matx33d::zeros(); - cv::Matx33d m_r(3, 3, CV_64FC1), m_q(3, 3, CV_64FC1); - cv::Rodrigues(rvec, rmat); - - { - cv::Vec3d euler = cv::RQDecomp3x3(rmat, m_r, m_q); - - QMutexLocker lck(&mtx); - - for (int i = 0; i < 3; i++) - pose[i] = tvec(i); - pose[Yaw] = euler[1]; - pose[Pitch] = -euler[0]; - pose[Roll] = euler[2]; - - r = rmat; - t = cv::Vec3d(tvec[0], -tvec[1], tvec[2]); - } - - if (roi_valid) - cv::rectangle(frame, last_roi, cv::Scalar(255, 0, 255), 1); - } - else -fail: - last_roi = cv::Rect(65535, 65535, 0, 0); - - if (frame.rows > 0) - videoWidget->update_image(frame); - } - - // give opencv time to exit camera threads, etc. - portable::sleep(500); -} - -void Tracker::data(double *data) -{ - QMutexLocker lck(&mtx); - - data[Yaw] = pose[Yaw]; - data[Pitch] = pose[Pitch]; - data[Roll] = pose[Roll]; - data[TX] = pose[TX] * .1; - data[TY] = pose[TY] * .1; - data[TZ] = pose[TZ] * .1; -} - -TrackerControls::TrackerControls() -{ - tracker = nullptr; - calib_timer.setInterval(200); - ui.setupUi(this); - setAttribute(Qt::WA_NativeWindow, true); - ui.cameraName->addItems(get_camera_names()); - tie_setting(s.camera_name, ui.cameraName); - tie_setting(s.resolution, ui.resolution); - tie_setting(s.force_fps, ui.cameraFPS); - tie_setting(s.fov, ui.cameraFOV); - tie_setting(s.headpos_x, ui.cx); - tie_setting(s.headpos_y, ui.cy); - tie_setting(s.headpos_z, ui.cz); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - connect(ui.btn_calibrate, SIGNAL(clicked()), this, SLOT(toggleCalibrate())); - connect(this, SIGNAL(destroyed()), this, SLOT(cleanupCalib())); - connect(&calib_timer, SIGNAL(timeout()), this, SLOT(update_tracker_calibration())); - connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings())); -} - -void TrackerControls::toggleCalibrate() -{ - if (!calib_timer.isActive()) - { - s.headpos_x = 0; - s.headpos_y = 0; - s.headpos_z = 0; - calibrator.reset(); - calib_timer.start(); - } else { - cleanupCalib(); - - auto pos = calibrator.get_estimate(); - s.headpos_x = pos(0); - s.headpos_y = pos(1); - s.headpos_z = pos(2); - } -} - -void TrackerControls::cleanupCalib() -{ - if (calib_timer.isActive()) - calib_timer.stop(); -} - -void TrackerControls::update_tracker_calibration() -{ - if (calib_timer.isActive() && tracker) - { - cv::Matx33d r; - cv::Vec3d t; - tracker->getRT(r, t); - calibrator.update(r, t); - } -} - -void TrackerControls::doOK() -{ - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() -{ - s.b->reload(); - this->close(); -} - -void TrackerControls::camera_settings() -{ - open_camera_settings(tracker ? &tracker->camera : nullptr, s.camera_name, tracker ? &tracker->camera_mtx : nullptr); -} - -OPENTRACK_DECLARE_TRACKER(Tracker, TrackerControls, TrackerDll) diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h deleted file mode 100644 index 436602a1..00000000 --- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (c) 2013-2015 Stanislaw Halik - * - * 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 "ui_aruco-trackercontrols.h" -#include "ar_video_widget.h" -#include -#include -#include -#include -#include -#include -#include "opentrack/options.hpp" -#include "ftnoir_tracker_aruco/trans_calib.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack/opencv-camera-dialog.hpp" - -#include -#include - -using namespace options; - -struct settings : opts { - value fov; - value headpos_x, headpos_y, headpos_z; - value camera_name; - value force_fps, resolution; - settings() : - opts("aruco-tracker"), - fov(b, "field-of-view", 56), - headpos_x(b, "headpos-x", 0), - headpos_y(b, "headpos-y", 0), - headpos_z(b, "headpos-z", 0), - camera_name(b, "camera-name", ""), - force_fps(b, "force-fps", 0), - resolution(b, "force-resolution", 0) - {} -}; - -class TrackerControls; - -class Tracker : protected QThread, public ITracker -{ - Q_OBJECT - friend class TrackerControls; - static constexpr double c_search_window = 2.65; -public: - Tracker(); - ~Tracker() override; - void start_tracker(QFrame* frame) override; - void data(double *data) override; - void run() override; - void getRT(cv::Matx33d &r, cv::Vec3d &t); -private: - cv::VideoCapture camera; - QMutex camera_mtx; - QMutex mtx; - volatile bool stop; - QHBoxLayout* layout; - ArucoVideoWidget* videoWidget; - settings s; - double pose[6]; - cv::Mat frame; - cv::Matx33d r; - cv::Vec3d t; -}; - -class TrackerControls : public ITrackerDialog, protected camera_dialog -{ - Q_OBJECT -public: - TrackerControls(); - void register_tracker(ITracker * x) override { tracker = static_cast(x); } - void unregister_tracker() override { tracker = nullptr; } -private: - Ui::Form ui; - Tracker* tracker; - settings s; - TranslationCalibrator calibrator; - QTimer calib_timer; -private slots: - void doOK(); - void doCancel(); - void toggleCalibrate(); - void cleanupCalib(); - void update_tracker_calibration(); - void camera_settings(); -}; - -class TrackerDll : public Metadata -{ - QString name() { return QString("aruco -- paper marker tracker"); } - QIcon icon() { return QIcon(":/images/aruco.png"); } -}; diff --git a/ftnoir_tracker_aruco/images/aruco.png b/ftnoir_tracker_aruco/images/aruco.png deleted file mode 100644 index 491c39e6..00000000 Binary files a/ftnoir_tracker_aruco/images/aruco.png and /dev/null differ diff --git a/ftnoir_tracker_aruco/include/aruco.h b/ftnoir_tracker_aruco/include/aruco.h deleted file mode 100644 index 569b95fb..00000000 --- a/ftnoir_tracker_aruco/include/aruco.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. - - - - \mainpage ArUco: Augmented Reality library from the University of Cordoba - - -ArUco is a minimal C++ library for detection of Augmented Reality markers based on OpenCv exclusively. - -It is an educational project to show student how to detect augmented reality markers and it is provided under BSD license. - - -\section INTRODUCTION INTRODUCTION - -The library relies on the use of coded markers. Each marker has an unique code indicated by the black and white colors in it. The libary detect borders, and analyzes into the rectangular regions which of them are likely to be markers. Then, a decoding is performed and if the code is valid, it is considered that the rectangle is a marker. - -The codification included into the marker is a slighly modified version of the Hamming Code. It has a total a 25 bits didived in 5 rows of 5 bits each. So, we have 5 words of 5 bits. Each word, contains only 2 bits of real information, the rest is for and error detection/correction (error correction is yet to be done). As a conclusion, a marker contains 10 bits of real information wich allows 1024 different markers. - - -\section BOARDS BOARDS - -Aruco allows the possibility to employ board. Boards are markers composed by an array of markers arranged in a known order. The advantages of using boards instead of simple markers are: - - More robusteness. The misdetection of several markers of the board is not a problem as long as a minimum set of them are detected. - - More precision. Since there are a larger number of corners, camera pose estimation becomes more precise. - - -\section APPLICATIONS APPLICATIONS - -The library comes with five applications that will help you to learn how to use the library: - - aruco_create_marker: which creates marker and saves it in a jpg file you can print. - - aruco_simple : simple test aplication that detects the markers in a image - - aruco_test: this is the main application for detection. It reads images either from the camera of from a video and detect markers. Additionally, if you provide the intrinsics of the camera(obtained by OpenCv calibration) and the size of the marker in meters, the library calculates the marker intrinsics so that you can easily create your AR applications. - - aruco_test_gl: shows how to use the library AR applications using OpenGL for rendering - - aruco_create_board: application that helps you to create a board - - aruco_simple_board: simple test aplication that detects a board of markers in a image - - aruco_test_board: application that detects boards - - aruco_test_board_gl: application that detects boards and uses OpenGL to draw - -\section LIBRARY LIBRARY DESCRIPTION: - -The ArUco library contents are divided in two main directories. The src directory, which contains the library itself. And the utils directory which contains the applications. - -The library main classes are: - - aruco::CameraParameters: represent the information of the camera that captures the images. Here you must set the calibration info. - - aruco::Marker: which represent a marker detected in the image - - aruco::MarkerDetector: that is in charge of deteting the markers in a image Detection is done by simple calling the member funcion ArMarkerDetector::detect(). Additionally, the classes contain members to create the required matrices for rendering using OpenGL. See aruco_test_gl for details - - aruco::BoardConfiguration: A board is an array of markers in a known order. BoardConfiguracion is the class that defines a board by indicating the id of its markers. In addition, it has informacion about the distance between the markers so that extrinsica camera computations can be done. - - aruco::Board: This class defines a board detected in a image. The board has the extrinsic camera parameters as public atributes. In addition, it has a method that allows obtain the matrix for getting its position in OpenGL (see aruco_test_board_gl for details). - - aruco::BoardDetector : This is the class in charge of detecting a board in a image. You must pass to it the set of markers detected by ArMarkerDetector and the BoardConfiguracion of the board you want to detect. This class will do the rest for you, even calculating the camera extrinsics. - - -\section COMPILING COMPILING THE LIBRARY: -\subsection Linux -Go to the aruco library and do -\verbatim ->mkdir build ->cd build ->cmake .. ->make ->make install (optional) -\endverbatim - -NOTE ON OPENGL: The library supports eaily the integration with OpenGL. In order to compile with support for OpenGL, you just have installed in your system the develop packages for GL and glut (or freeglut). - -\subsection WINDOWS - -The library has been compiled using MinGW and codeblocks. Below I describe the best way to compile it that I know. If you know better, please let me know. - - step 1) codeblocks - -# Download codeblocks. I recommend to download the version 10.5 with mingw included (codeblocks-10.05mingw-setup.exe) - -# Install and set the PATH variable so that the codeblock/mingw/bin directory is included. In my case c:/codeblocks/mingw/bin. This will allow cmake to find the compiler. - -# The codeblock program will not find the mingw path by deafult. So, run codeblocks and go to setting->Compuiler debugger and set the correct path to the MinGW dir. - - step 2) cmake - -# Download and install the last version of cmake. - - step 3) OpenCv - -# Download the source code and compile it using cmake and codeblocks. Note: install the library in C:\ if you want it to be easily detected by cmake afterwards - - step 4) aruco - -# Download and decompress. - -# Open cmake gui application and set the path to the main library directory and also set a path where the project is going to be built. - -# Generate the codeblock project. - -# Open the project with codeblock and compile then, install. The programs will be probably generated into the bin directory - -OpenGL: by default, the mingw version installed has not the glut library. So, the opengl programs are not compiled. If you want to compile with OpenGL support, you must install glut, or prefereably freeglut. -Thus, - - Download the library (http://www.martinpayne.me.uk/software/development/GLUT/freeglut-MinGW.zip) for mingw. - - Decompress in a directory X. - - Then, rerun cmake setting the variable GLU_PATH to that directory (>cmake .. -DGLUT_PATH="C:\X") - - Finally, recompile and test. Indeed, you should move the freeglut.dll to the directory with the binaries or to any other place in the PATH. - - -CONCLUSION: Move to Linux, things are simpler :P - - -\section Testing - -For testing the applications, the library provides videos and the corresponding camera parameters of these videos. Into the directories you will find information on how to run the examples. - -\section Final Notes - - - REQUIREMENTS: OpenCv >= 2.1.0. and OpenGL for (aruco_test_gl and aruco_test_board_gl) - - CONTACT: Rafael Munoz-Salinas: rmsalinas@uco.es - - This libary is free software and come with no guaratee! - -*/ - -#include "markerdetector.h" -#include "boarddetector.h" -#include "cvdrawingutils.h" - diff --git a/ftnoir_tracker_aruco/include/arucofidmarkers.h b/ftnoir_tracker_aruco/include/arucofidmarkers.h deleted file mode 100644 index 7dad4672..00000000 --- a/ftnoir_tracker_aruco/include/arucofidmarkers.h +++ /dev/null @@ -1,119 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ - -#ifndef ArucoFiducicalMarkerDetector_H -#define ArucoFiducicalMarkerDetector_H -#include -#include "exports.h" -#include "marker.h" -#include "board.h" -namespace aruco { - -class ARUCO_EXPORTS FiducidalMarkers { -public: - /** - * \brief Creates an ar marker with the id specified using a modified version of the hamming code. - * There are two type of markers: a) These of 10 bits b) these of 3 bits. The latter are employed for applications - * that need few marker but they must be small. The two type of markers are distinguished by their ids. While the first type - * of markers have ids in the interval [0-1023], the second type ids in the interval [2000-2006]. - * - * - * 10 bits markers - * ----------------------- - * There are a total of 5 rows of 5 cols. Each row encodes a total of 2 bits, so there are 2^10 bits:(0-1023). - * - * The least significative bytes are first (from left-up to to right-bottom) - * - * Example: the id = 110 (decimal) is be represented in binary as : 00 01 10 11 10. - * - * Then, it will generate the following marker: - * - * -# 1st row encodes 00: 1 0 0 0 0 : hex 0x10 - * -# 2nd row encodes 01: 1 0 1 1 1 : hex 0x17 - * -# 3nd row encodes 10: 0 1 0 0 1 : hex 0x09 - * -# 4th row encodes 11: 0 1 1 1 0 : hex 0x0e - * -# 5th row encodes 10: 0 1 0 0 1 : hex 0x09 - * - * Note that : The first bit, is the inverse of the hamming parity. This avoids the 0 0 0 0 0 to be valid - * These marker are detected by the function getFiduciadlMarker_Aruco_Type1 - */ - static cv::Mat createMarkerImage(int id,int size) throw (cv::Exception); - - /** Detection of fiducidal aruco markers (10 bits) - * @param in input image with the patch that contains the possible marker - * @param nRotations number of 90deg rotations in clockwise direction needed to set the marker in correct position - * @return -1 if the image passed is a not a valid marker, and its id in case it really is a marker - */ - static int detect(const cv::Mat &in,int &nRotations); - - /**Similar to createMarkerImage. Instead of returning a visible image, returns a 8UC1 matrix of 0s and 1s with the marker info - */ - static cv::Mat getMarkerMat(int id) throw (cv::Exception); - - - /**Creates a printable image of a board - * @param gridSize grid layout (numer of sqaures in x and Y) - * @param MarkerSize size of markers sides in pixels - * @param MarkerDistance distance between the markers - * @param TInfo output - * @param excludedIds set of ids excluded from the board - */ - static cv::Mat createBoardImage( cv::Size gridSize,int MarkerSize,int MarkerDistance, BoardConfiguration& TInfo ,vector *excludedIds=NULL ) throw (cv::Exception); - - - /**Creates a printable image of a board in chessboard_like manner - * @param gridSize grid layout (numer of sqaures in x and Y) - * @param MarkerSize size of markers sides in pixels - * @param TInfo output - * @param setDataCentered indicates if the center is set at the center of the board. Otherwise it is the left-upper corner - * - */ - static cv::Mat createBoardImage_ChessBoard( cv::Size gridSize,int MarkerSize, BoardConfiguration& TInfo ,bool setDataCentered=true ,vector *excludedIds=NULL) throw (cv::Exception); - - /**Creates a printable image of a board in a frame fashion - * @param gridSize grid layout (numer of sqaures in x and Y) - * @param MarkerSize size of markers sides in pixels - * @param MarkerDistance distance between the markers - * @param TInfo output - * @param setDataCentered indicates if the center is set at the center of the board. Otherwise it is the left-upper corner - * - */ - static cv::Mat createBoardImage_Frame( cv::Size gridSize,int MarkerSize,int MarkerDistance, BoardConfiguration& TInfo ,bool setDataCentered=true,vector *excludedIds=NULL ) throw (cv::Exception); - -private: - - static vector getListOfValidMarkersIds_random(int nMarkers,vector *excluded) throw (cv::Exception); - static cv::Mat rotate(const cv::Mat & in); - static int hammDistMarker(cv::Mat bits); - static int analyzeMarkerImage(cv::Mat &grey,int &nRotations); - static bool correctHammMarker(cv::Mat &bits); -}; - -} - -#endif diff --git a/ftnoir_tracker_aruco/include/board.h b/ftnoir_tracker_aruco/include/board.h deleted file mode 100644 index ec7dd43f..00000000 --- a/ftnoir_tracker_aruco/include/board.h +++ /dev/null @@ -1,168 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ -#ifndef _Aruco_board_h -#define _Aruco_board_h -#include -#include -#include -#include "exports.h" -#include "marker.h" -namespace aruco { -using namespace std; -/** - * 3d representation of a marker - */ -struct ARUCO_EXPORTS MarkerInfo:public vector { - MarkerInfo() {} - MarkerInfo(int _id) {id=_id; } - MarkerInfo(const MarkerInfo&MI): vector(MI){id=MI.id; } - MarkerInfo & operator=(const MarkerInfo&MI){ - vector ::operator=(MI); - id=MI.id; - return *this; - } - int id;//maker id -}; - -/**\brief This class defines a board with several markers. - * A Board contains several markers so that they are more robustly detected. - * - * In general, a board is a set of markers. So BoardConfiguration is only a list - * of the id of the markers along with the position of their corners. - * - * The position of the corners can be specified either in pixels (in a non-specific size) or in meters. - * The first is the typical case in which you generate the image of board and the print it. Since you do not know in advance the real - * size of the markers, their corners are specified in pixels, and then, the translation to meters can be made once you know the real size. - * - * On the other hand, you may want to have the information of your boards in meters. The BoardConfiguration allows you to do so. - * - * The point is in the mInfoType variable. It can be either PIX or METERS according to your needs. - * -*/ - - -class ARUCO_EXPORTS BoardConfiguration: public vector -{ - friend class Board; -public: - enum MarkerInfoType {NONE=-1,PIX=0,METERS=1};//indicates if the data in MakersInfo is expressed in meters or in pixels so as to do conversion internally - //variable indicates if the data in MakersInfo is expressed in meters or in pixels so as to do conversion internally - int mInfoType; - /** - */ - BoardConfiguration(); - - /** - */ - BoardConfiguration(const BoardConfiguration &T); - - /** - */ - BoardConfiguration & operator=(const BoardConfiguration &T); - /**Saves the board info to a file - */ - void saveToFile(string sfile)throw (cv::Exception); - /**Reads board info from a file - */ - void readFromFile(string sfile)throw (cv::Exception); - /**Indicates if the corners are expressed in meters - */ - bool isExpressedInMeters()const { - return mInfoType==METERS; - } - /**Indicates if the corners are expressed in meters - */ - bool isExpressedInPixels()const { - return mInfoType==PIX; - } - /**Returns the index of the marker with id indicated, if is in the list - */ - int getIndexOfMarkerId(int id)const; - /**Returns the Info of the marker with id specified. If not in the set, throws exception - */ - const MarkerInfo& getMarkerInfo(int id)const throw (cv::Exception); - /**Set in the list passed the set of the ids - */ - void getIdList(vector &ids,bool append=true)const; -private: - /**Saves the board info to a file - */ - void saveToFile(cv::FileStorage &fs)throw (cv::Exception); - /**Reads board info from a file - */ - void readFromFile(cv::FileStorage &fs)throw (cv::Exception); -}; - -/** -*/ -class ARUCO_EXPORTS Board:public vector -{ - -public: - BoardConfiguration conf; - //matrices of rotation and translation respect to the camera - cv::Mat Rvec,Tvec; - /** - */ - Board() - { - Rvec.create(3,1,CV_32FC1); - Tvec.create(3,1,CV_32FC1); - for (int i=0;i<3;i++) - Tvec.at(i,0)=Rvec.at(i,0)=-999999; - } - - /**Given the extrinsic camera parameters returns the GL_MODELVIEW matrix for opengl. - * Setting this matrix, the reference corrdinate system will be set in this board - */ - void glGetModelViewMatrix(double modelview_matrix[16])throw(cv::Exception); - - /** - * Returns position vector and orientation quaternion for an Ogre scene node or entity. - * Use: - * ... - * Ogre::Vector3 ogrePos (position[0], position[1], position[2]); - * Ogre::Quaternion ogreOrient (orientation[0], orientation[1], orientation[2], orientation[3]); - * mySceneNode->setPosition( ogrePos ); - * mySceneNode->setOrientation( ogreOrient ); - * ... - */ - void OgreGetPoseParameters( double position[3], double orientation[4] )throw(cv::Exception); - - - /**Save this from a file - */ - void saveToFile(string filePath)throw(cv::Exception); - /**Read this from a file - */ - void readFromFile(string filePath)throw(cv::Exception); - -}; -} - -#endif diff --git a/ftnoir_tracker_aruco/include/boarddetector.h b/ftnoir_tracker_aruco/include/boarddetector.h deleted file mode 100644 index 619b4798..00000000 --- a/ftnoir_tracker_aruco/include/boarddetector.h +++ /dev/null @@ -1,138 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ -#ifndef _Aruco_BoardDetector_H -#define _Aruco_BoardDetector_H -#include -#include "exports.h" -#include "board.h" -#include "cameraparameters.h" -#include "markerdetector.h" - -namespace aruco -{ -using namespace std; -/**\brief This class detects AR boards - * Version 1.2 - * There are two modes for board detection. - * First, the old way. (You first detect markers with MarkerDetector and then call to detect in this class. - * - * Second: New mode, marker detection is included in the class - * \code - - CameraParameters CP; - CP.readFromFile(path_cp) - BoardConfiguration BC; - BC.readFromFile(path_bc); - BoardDetector BD; - BD.setParams(BC,CP); //or only BD.setParams(BC) - //capture image - cv::Mat im; - capture_image(im); - - float prob=BD.detect(im); - if (prob>0.3) - CvDrawingUtils::draw3DAxis(im,BD.getDetectedBoard(),CP); - - \endcode - * -*/ -class ARUCO_EXPORTS BoardDetector -{ -public: - /** See discussion in @see enableRotateXAxis. - * Do not change unless you know what you are doing - */ - BoardDetector(bool setYPerperdicular=true); - - - /** - * Use if you plan to let this class to perform marker detection too - */ - void setParams(const BoardConfiguration &bc,const CameraParameters &cp, float markerSizeMeters=-1); - void setParams(const BoardConfiguration &bc); - /** - * Detect markers, and then, look for the board indicated in setParams() - * @return value indicating the likelihood of having found the marker - */ - float detect(const cv::Mat &im)throw (cv::Exception); - /**Returns a reference to the board detected - */ - Board & getDetectedBoard(){return _boardDetected;} - /**Returns a reference to the internal marker detector - */ - MarkerDetector &getMarkerDetector(){return _mdetector;} - /**Returns the vector of markers detected - */ - vector &getDetectedMarkers(){return _vmarkers;} - - - //ALTERNATIVE DETECTION METHOD, BASED ON MARKERS PREVIOUSLY DETECTED - - /** Given the markers detected, determines if there is the board passed - * @param detectedMarkers result provided by aruco::ArMarkerDetector - * @param BConf the board you want to see if is present - * @param Bdetected output information of the detected board - * @param camMatrix camera matrix with intrinsics - * @param distCoeff camera distorsion coeff - * @param camMatrix intrinsic camera information. - * @param distCoeff camera distorsion coefficient. If set Mat() if is assumed no camera distorion - * @param markerSizeMeters size of the marker sides expressed in meters - * @return value indicating the likelihood of having found the marker - */ - float detect(const vector &detectedMarkers,const BoardConfiguration &BConf, Board &Bdetected, cv::Mat camMatrix=cv::Mat(),cv::Mat distCoeff=cv::Mat(), float markerSizeMeters=-1 )throw (cv::Exception); - float detect(const vector &detectedMarkers,const BoardConfiguration &BConf, Board &Bdetected,const CameraParameters &cp, float markerSizeMeters=-1 )throw (cv::Exception); - - - /** - * By default, the Y axis is set to point up. However this is not the default - * operation mode of opencv, which produces the Z axis pointing up instead. - * So, to achieve this change, we have to rotate the X axis. - */ - void setYPerperdicular(bool enable){_setYPerperdicular=enable;} - - - - -private: - void rotateXAxis(cv::Mat &rotation); - bool _setYPerperdicular; - - //-- Functionality to detect markers inside - bool _areParamsSet; - BoardConfiguration _bconf; - Board _boardDetected; - float _markerSize; - CameraParameters _camParams; - MarkerDetector _mdetector;//internal markerdetector - vector _vmarkers;//markers detected in the call to : float detect(const cv::Mat &im); - -}; - -}; -#endif - diff --git a/ftnoir_tracker_aruco/include/cameraparameters.h b/ftnoir_tracker_aruco/include/cameraparameters.h deleted file mode 100644 index 083d5f96..00000000 --- a/ftnoir_tracker_aruco/include/cameraparameters.h +++ /dev/null @@ -1,138 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ -#ifndef _Aruco_CameraParameters_H -#define _Aruco_CameraParameters_H -#include "exports.h" -#include -#include - -namespace aruco -{ -using namespace std; -/**\brief Parameters of the camera - */ - -class ARUCO_EXPORTS CameraParameters -{ -public: - - // 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1) - cv::Mat CameraMatrix; - //4x1 matrix (k1,k2,p1,p2) - cv::Mat Distorsion; - //size of the image - cv::Size CamSize; - - /**Empty constructor - */ - CameraParameters() ; - /**Creates the object from the info passed - * @param cameraMatrix 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1) - * @param distorsionCoeff 4x1 matrix (k1,k2,p1,p2) - * @param size image size - */ - CameraParameters(cv::Mat cameraMatrix,cv::Mat distorsionCoeff,cv::Size size) throw(cv::Exception); - /**Sets the parameters - * @param cameraMatrix 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1) - * @param distorsionCoeff 4x1 matrix (k1,k2,p1,p2) - * @param size image size - */ - void setParams(cv::Mat cameraMatrix,cv::Mat distorsionCoeff,cv::Size size) throw(cv::Exception); - /**Copy constructor - */ - CameraParameters(const CameraParameters &CI) ; - - /**Indicates whether this object is valid - */ - bool isValid()const { - return CameraMatrix.rows!=0 && CameraMatrix.cols!=0 && Distorsion.rows!=0 && Distorsion.cols!=0 && CamSize.width!=-1 && CamSize.height!=-1; - } - /**Assign operator - */ - CameraParameters & operator=(const CameraParameters &CI); - /**Reads the camera parameters from a file generated using saveToFile. - */ - void readFromFile(string path)throw(cv::Exception); - /**Saves this to a file - */ - void saveToFile(string path,bool inXML=true)throw(cv::Exception); - - /**Reads from a YAML file generated with the opencv2.2 calibration utility - */ - void readFromXMLFile(string filePath)throw(cv::Exception); - - /**Adjust the parameters to the size of the image indicated - */ - void resize(cv::Size size)throw(cv::Exception); - - /**Returns the location of the camera in the reference system given by the rotation and translation vectors passed - * NOT TESTED - */ - static cv::Point3f getCameraLocation(cv::Mat Rvec,cv::Mat Tvec); - - /**Given the intrinsic camera parameters returns the GL_PROJECTION matrix for opengl. - * PLease NOTE that when using OpenGL, it is assumed no camera distorsion! So, if it is not true, you should have - * undistor image - * - * @param orgImgSize size of the original image - * @param size of the image/window where to render (can be different from the real camera image). Please not that it must be related to CamMatrix - * @param proj_matrix output projection matrix to give to opengl - * @param gnear,gfar: visible rendering range - * @param invert: indicates if the output projection matrix has to yield a horizontally inverted image because image data has not been stored in the order of glDrawPixels: bottom-to-top. - */ - void glGetProjectionMatrix( cv::Size orgImgSize, cv::Size size,double proj_matrix[16],double gnear,double gfar,bool invert=false )throw(cv::Exception); - - /** - * setup camera for an Ogre project. - * Use: - * ... - * Ogre::Matrix4 PM(proj_matrix[0], proj_matrix[1], ... , proj_matrix[15]); - * yourCamera->setCustomProjectionMatrix(true, PM); - * yourCamera->setCustomViewMatrix(true, Ogre::Matrix4::IDENTITY); - * ... - * As in OpenGL, it assumes no camera distorsion - */ - void OgreGetProjectionMatrix( cv::Size orgImgSize, cv::Size size,double proj_matrix[16],double gnear,double gfar,bool invert=false )throw(cv::Exception); - - -private: - //GL routines - - static void argConvGLcpara2( double cparam[3][4], int width, int height, double gnear, double gfar, double m[16], bool invert )throw(cv::Exception); - static int arParamDecompMat( double source[3][4], double cpara[3][4], double trans[3][4] )throw(cv::Exception); - static double norm( double a, double b, double c ); - static double dot( double a1, double a2, double a3, - double b1, double b2, double b3 ); - - -}; - -} -#endif - - diff --git a/ftnoir_tracker_aruco/include/cvdrawingutils.h b/ftnoir_tracker_aruco/include/cvdrawingutils.h deleted file mode 100644 index ff67242f..00000000 --- a/ftnoir_tracker_aruco/include/cvdrawingutils.h +++ /dev/null @@ -1,52 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ -#ifndef _ArUco_DrawUtils_H_ -#define _ArUco_DrawUtils_H_ -#include "exports.h" -#include "aruco.h" -namespace aruco -{ - /**\brief A set of functions to draw in opencv images - */ - class ARUCO_EXPORTS CvDrawingUtils - { - public: - - static void draw3dAxis(cv::Mat &Image,Marker &m,const CameraParameters &CP); - - static void draw3dCube(cv::Mat &Image,Marker &m,const CameraParameters &CP); - - static void draw3dAxis(cv::Mat &Image,Board &m,const CameraParameters &CP); - - static void draw3dCube(cv::Mat &Image,Board &m,const CameraParameters &CP); - - }; -}; - -#endif - diff --git a/ftnoir_tracker_aruco/include/exports.h b/ftnoir_tracker_aruco/include/exports.h deleted file mode 100644 index 8f7dab8c..00000000 --- a/ftnoir_tracker_aruco/include/exports.h +++ /dev/null @@ -1,46 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ - - - -#ifndef __OPENARUCO_CORE_TYPES_H__ -#define __OPENARUCO_CORE_TYPES_H__ - -#if !defined _CRT_SECURE_NO_DEPRECATE && _MSC_VER > 1300 -#define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio 2005 warnings */ -#endif - - -#if ((defined WIN32 || defined _WIN32 || defined WINCE) && defined DSO_EXPORTS) || defined(_MSC_VER) - #define ARUCO_EXPORTS __declspec(dllexport) -#else - #define ARUCO_EXPORTS __attribute__ ((visibility ("default"))) -#endif - - -#endif diff --git a/ftnoir_tracker_aruco/include/marker.h b/ftnoir_tracker_aruco/include/marker.h deleted file mode 100644 index efc3e5fe..00000000 --- a/ftnoir_tracker_aruco/include/marker.h +++ /dev/null @@ -1,143 +0,0 @@ -/***************************** -Copyright 2011 Rafael Muñoz Salinas. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of Rafael Muñoz Salinas. -********************************/ -#ifndef _Aruco_Marker_H -#define _Aruco_Marker_H -#include -#include -#include -#include "exports.h" -#include "cameraparameters.h" -namespace aruco { -using namespace std; -/**\brief This class represents a marker. It is a vector of the fours corners ot the marker - * - */ - -class ARUCO_EXPORTS Marker: public std::vector -{ -public: - //id of the marker - int id; - //size of the markers sides in meters - float ssize; - //matrices of rotation and translation respect to the camera - cv::Mat Rvec,Tvec; - - /** - */ - Marker(); - /** - */ - Marker(const Marker &M); - /** - */ - Marker(const std::vector &corners,int _id=-1); - /** - */ - ~Marker() {} - /**Indicates if this object is valid - */ - bool isValid()const{return id!=-1 && size()==4;} - - /**Draws this marker in the input image - */ - void draw(cv::Mat &in, cv::Scalar color, int lineWidth=1,bool writeId=true)const; - - /**Calculates the extrinsics (Rvec and Tvec) of the marker with respect to the camera - * @param markerSize size of the marker side expressed in meters - * @param CP parmeters of the camera - * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis - */ - void calculateExtrinsics(float markerSize,const CameraParameters &CP,bool setYPerperdicular=true)throw(cv::Exception); - /**Calculates the extrinsics (Rvec and Tvec) of the marker with respect to the camera - * @param markerSize size of the marker side expressed in meters - * @param CameraMatrix matrix with camera parameters (fx,fy,cx,cy) - * @param Distorsion matrix with distorsion parameters (k1,k2,p1,p2) - * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis - */ - void calculateExtrinsics(float markerSize,cv::Mat CameraMatrix,cv::Mat Distorsion=cv::Mat(),bool setYPerperdicular=true)throw(cv::Exception); - - /**Given the extrinsic camera parameters returns the GL_MODELVIEW matrix for opengl. - * Setting this matrix, the reference coordinate system will be set in this marker - */ - void glGetModelViewMatrix( double modelview_matrix[16])throw(cv::Exception); - - /** - * Returns position vector and orientation quaternion for an Ogre scene node or entity. - * Use: - * ... - * Ogre::Vector3 ogrePos (position[0], position[1], position[2]); - * Ogre::Quaternion ogreOrient (orientation[0], orientation[1], orientation[2], orientation[3]); - * mySceneNode->setPosition( ogrePos ); - * mySceneNode->setOrientation( ogreOrient ); - * ... - */ - void OgreGetPoseParameters( double position[3], double orientation[4] )throw(cv::Exception); - - /**Returns the centroid of the marker - */ - cv::Point2f getCenter()const; - /**Returns the perimeter of the marker - */ - float getPerimeter()const; - /**Returns the area - */ - float getArea()const; - /** - */ - /** - */ - friend bool operator<(const Marker &M1,const Marker&M2) - { - return M1.id -#include -#include -#include "cameraparameters.h" -#include "exports.h" -#include "marker.h" - -namespace aruco -{ -using namespace std; -/**\brief Main class for marker detection - * - */ -class ARUCO_EXPORTS MarkerDetector -{ - //Represent a candidate to be a maker - class MarkerCandidate: public Marker{ - public: - MarkerCandidate(){} - MarkerCandidate(const Marker &M): Marker(M){} - MarkerCandidate(const MarkerCandidate &M): Marker(M){ - contour=M.contour; - idx=M.idx; - } - MarkerCandidate & operator=(const MarkerCandidate &M){ - (*(Marker*)this)=(*(Marker*)&M); - contour=M.contour; - idx=M.idx; - return *this; - } - - vector contour;//all the points of its contour - int idx;//index position in the global contour list - }; -public: - - /** - * See - */ - MarkerDetector(); - - /** - */ - ~MarkerDetector(); - - /**Detects the markers in the image passed - * - * If you provide information about the camera parameters and the size of the marker, then, the extrinsics of the markers are detected - * - * @param input input color image - * @param detectedMarkers output vector with the markers detected - * @param camMatrix intrinsic camera information. - * @param distCoeff camera distorsion coefficient. If set Mat() if is assumed no camera distorion - * @param markerSizeMeters size of the marker sides expressed in meters - * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis - */ - void detect(const cv::Mat &input,std::vector &detectedMarkers,cv::Mat camMatrix=cv::Mat(),cv::Mat distCoeff=cv::Mat(),float markerSizeMeters=-1,bool setYPerperdicular=true) throw (cv::Exception); - /**Detects the markers in the image passed - * - * If you provide information about the camera parameters and the size of the marker, then, the extrinsics of the markers are detected - * - * @param input input color image - * @param detectedMarkers output vector with the markers detected - * @param camParams Camera parameters - * @param markerSizeMeters size of the marker sides expressed in meters - * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis - */ - void detect(const cv::Mat &input,std::vector &detectedMarkers, CameraParameters camParams,float markerSizeMeters=-1,bool setYPerperdicular=true) throw (cv::Exception); - - /**This set the type of thresholding methods available - */ - - enum ThresholdMethods {FIXED_THRES,ADPT_THRES,CANNY}; - - - - /**Sets the threshold method - */ - void setThresholdMethod(ThresholdMethods m) { - _thresMethod=m; - } - /**Returns the current threshold method - */ - ThresholdMethods getThresholdMethod()const { - return _thresMethod; - } - /** - * Set the parameters of the threshold method - * We are currently using the Adptive threshold ee opencv doc of adaptiveThreshold for more info - * @param param1: blockSize of the pixel neighborhood that is used to calculate a threshold value for the pixel - * @param param2: The constant subtracted from the mean or weighted mean - */ - void setThresholdParams(double param1,double param2) { - _thresParam1=param1; - _thresParam2=param2; - } - /** - * Set the parameters of the threshold method - * We are currently using the Adptive threshold ee opencv doc of adaptiveThreshold for more info - * param1: blockSize of the pixel neighborhood that is used to calculate a threshold value for the pixel - * param2: The constant subtracted from the mean or weighted mean - */ - void getThresholdParams(double ¶m1,double ¶m2)const { - param1=_thresParam1; - param2=_thresParam2; - } - - - /**Returns a reference to the internal image thresholded. It is for visualization purposes and to adjust manually - * the parameters - */ - const cv::Mat & getThresholdedImage() { - return thres; - } - /**Methods for corner refinement - */ - enum CornerRefinementMethod {NONE,HARRIS,SUBPIX,LINES}; - /** - */ - void setCornerRefinementMethod(CornerRefinementMethod method) { - _cornerMethod=method; - } - /** - */ - CornerRefinementMethod getCornerRefinementMethod()const { - return _cornerMethod; - } - /**Specifies the min and max sizes of the markers as a fraction of the image size. By size we mean the maximum - * of cols and rows. - * @param min size of the contour to consider a possible marker as valid (0,1] - * @param max size of the contour to consider a possible marker as valid [0,1) - * - */ - void setMinMaxSize(float min=0.03,float max=0.5)throw(cv::Exception); - - /**reads the min and max sizes employed - * @param min output size of the contour to consider a possible marker as valid (0,1] - * @param max output size of the contour to consider a possible marker as valid [0,1) - * - */ - void getMinMaxSize(float &min,float &max){min=_minSize;max=_maxSize;} - - /**Enables/Disables erosion process that is REQUIRED for chessboard like boards. - * By default, this property is enabled - */ - void enableErosion(bool enable){_doErosion=enable;} - - /** - * Specifies a value to indicate the required speed for the internal processes. If you need maximum speed (at the cost of a lower detection rate), - * use the value 3, If you rather a more precise and slow detection, set it to 0. - * - * Actually, the main differences are that in highspeed mode, we employ setCornerRefinementMethod(NONE) and internally, we use a small canonical - * image to detect the marker. In low speed mode, we use setCornerRefinementMethod(HARRIS) and a bigger size for the canonical marker image - */ - void setDesiredSpeed(int val); - /** - */ - int getDesiredSpeed()const { - return _speed; - } - - /** - * Allows to specify the function that identifies a marker. Therefore, you can create your own type of markers different from these - * employed by default in the library. - * The marker function must have the following structure: - * - * int myMarkerIdentifier(const cv::Mat &in,int &nRotations); - * - * The marker function receives the image 'in' with the region that migh contain one of your markers. These are the rectangular regions with black - * in the image. - * - * As output your marker function must indicate the following information. First, the output parameter nRotations must indicate how many times the marker - * must be rotated clockwise 90 deg to be in its ideal position. (The way you would see it when you print it). This is employed to know - * always which is the corner that acts as reference system. Second, the function must return -1 if the image does not contains one of your markers, and its id otherwise. - * - */ - void setMakerDetectorFunction(int (* markerdetector_func)(const cv::Mat &in,int &nRotations) ) { - markerIdDetector_ptrfunc=markerdetector_func; - } - - /** Use an smaller version of the input image for marker detection. - * If your marker is small enough, you can employ an smaller image to perform the detection without noticeable reduction in the precision. - * Internally, we are performing a pyrdown operation - * - * @param level number of times the image size is divided by 2. Internally, we are performing a pyrdown. - */ - void pyrDown(unsigned int level){pyrdown_level=level;} - - ///------------------------------------------------- - /// Methods you may not need - /// Thesde methods do the hard work. They have been set public in case you want to do customizations - ///------------------------------------------------- - - /** - * Thesholds the passed image with the specified method. - */ - void thresHold(int method,const cv::Mat &grey,cv::Mat &thresImg,double param1=-1,double param2=-1)throw(cv::Exception); - /** - * Detection of candidates to be markers, i.e., rectangles. - * This function returns in candidates all the rectangles found in a thresolded image - */ - void detectRectangles(const cv::Mat &thresImg,vector > & candidates); - - /**Returns a list candidates to be markers (rectangles), for which no valid id was found after calling detectRectangles - */ - const vector > &getCandidates() { - return _candidates; - } - - /**Given the iput image with markers, creates an output image with it in the canonical position - * @param in input image - * @param out image with the marker - * @param size of out - * @param points 4 corners of the marker in the image in - * @return true if the operation succeed - */ - bool warp(cv::Mat &in,cv::Mat &out,cv::Size size, std::vector points)throw (cv::Exception); - - - - /** Refine MarkerCandidate Corner using LINES method - * @param candidate candidate to refine corners - */ - void refineCandidateLines(MarkerCandidate &candidate); - - - /**DEPRECATED!!! Use the member function in CameraParameters - * - * Given the intrinsic camera parameters returns the GL_PROJECTION matrix for opengl. - * PLease NOTE that when using OpenGL, it is assumed no camera distorsion! So, if it is not true, you should have - * undistor image - * - * @param CamMatrix arameters of the camera specified. - * @param orgImgSize size of the original image - * @param size of the image/window where to render (can be different from the real camera image). Please not that it must be related to CamMatrix - * @param proj_matrix output projection matrix to give to opengl - * @param gnear,gfar: visible rendering range - * @param invert: indicates if the output projection matrix has to yield a horizontally inverted image because image data has not been stored in the order of glDrawPixels: bottom-to-top. - */ - static void glGetProjectionMatrix( CameraParameters & CamMatrix,cv::Size orgImgSize, cv::Size size,double proj_matrix[16],double gnear,double gfar,bool invert=false )throw(cv::Exception); - -private: - - bool _enableCylinderWarp; - bool warp_cylinder ( cv::Mat &in,cv::Mat &out,cv::Size size, MarkerCandidate& mc ) throw ( cv::Exception ); - /** - * Detection of candidates to be markers, i.e., rectangles. - * This function returns in candidates all the rectangles found in a thresolded image - */ - void detectRectangles(const cv::Mat &thresImg,vector & candidates); -public: - //Current threshold method - ThresholdMethods _thresMethod; - //Threshold parameters - double _thresParam1,_thresParam2; - //Current corner method - CornerRefinementMethod _cornerMethod; - //minimum and maximum size of a contour lenght - float _minSize,_maxSize; - //Speed control - int _speed; - int _markerWarpSize; - bool _doErosion; - //vectr of candidates to be markers. This is a vector with a set of rectangles that have no valid id - vector > _candidates; - //level of image reduction - int pyrdown_level; - //Images - cv::Mat grey,thres,thres2,reduced; - //pointer to the function that analizes a rectangular region so as to detect its internal marker - int (* markerIdDetector_ptrfunc)(const cv::Mat &in,int &nRotations); -private: - /** - */ - bool isInto(cv::Mat &contour,std::vector &b); - /** - */ - int perimeter(std::vector &a); - - -// //GL routines -// -// static void argConvGLcpara2( double cparam[3][4], int width, int height, double gnear, double gfar, double m[16], bool invert )throw(cv::Exception); -// static int arParamDecompMat( double source[3][4], double cpara[3][4], double trans[3][4] )throw(cv::Exception); -// static double norm( double a, double b, double c ); -// static double dot( double a1, double a2, double a3, -// double b1, double b2, double b3 ); -// - - //detection of the - void findBestCornerInRegion_harris(const cv::Mat & grey,vector & Corners,int blockSize); - - - // auxiliar functions to perform LINES refinement - void interpolate2Dline( const vector< cv::Point > &inPoints, cv::Point3f &outLine); - cv::Point2f getCrossPoint(const cv::Point3f& line1, const cv::Point3f& line2); - - - /**Given a vector vinout with elements and a boolean vector indicating the lements from it to remove, - * this function remove the elements - * @param vinout - * @param toRemove - */ - template - void removeElements(vector & vinout,const vector &toRemove) - { - //remove the invalid ones by setting the valid in the positions left by the invalids - size_t indexValid=0; - for (size_t i=0;i &approxCurve ,cv::Scalar color); - void drawContour(cv::Mat &in,std::vector &contour,cv::Scalar ); - void drawAllContours(cv::Mat input, std::vector > &contours); - void draw(cv::Mat out,const std::vector &markers ); - -}; - - - - -} -#endif diff --git a/ftnoir_tracker_aruco/trans_calib.cpp b/ftnoir_tracker_aruco/trans_calib.cpp deleted file mode 100644 index b5148efd..00000000 --- a/ftnoir_tracker_aruco/trans_calib.cpp +++ /dev/null @@ -1,41 +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. - */ - -#include "trans_calib.h" - -TranslationCalibrator::TranslationCalibrator() -{ - reset(); -} - -void TranslationCalibrator::reset() -{ - P = cv::Matx66f::zeros(); - y = cv::Vec6f(0,0,0, 0,0,0); -} - -void TranslationCalibrator::update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k) -{ - cv::Matx H_k_T = cv::Matx::zeros(); - for (int i=0; i<3; ++i) { - for (int j=0; j<3; ++j) { - H_k_T(i,j) = R_CM_k(j,i); - } - } - for (int i=0; i<3; ++i) - { - H_k_T(3+i,i) = 1.0; - } - P += H_k_T * H_k_T.t(); - y += H_k_T * t_CM_k; -} - -cv::Vec3f TranslationCalibrator::get_estimate() -{ - cv::Vec6f x = P.inv() * y; - return cv::Vec3f(x[0], x[1], x[2]); -} diff --git a/ftnoir_tracker_aruco/trans_calib.h b/ftnoir_tracker_aruco/trans_calib.h deleted file mode 100644 index 3d1e56fa..00000000 --- a/ftnoir_tracker_aruco/trans_calib.h +++ /dev/null @@ -1,39 +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. - */ - -#ifndef TRANSCALIB_H -#define TRANSCALIB_H - -#include - -//----------------------------------------------------------------------------- -// Calibrates the translation from head to model = t_MH -// by recursive least squares / -// kalman filter in information form with identity noise covariance -// measurement equation when head position = t_CH is fixed: -// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k - -class TranslationCalibrator -{ -public: - TranslationCalibrator(); - - // reset the calibration process - void reset(); - - // update the current estimate - void update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k); - - // get the current estimate for t_MH - cv::Vec3f get_estimate(); - -private: - cv::Matx66f P; // normalized precision matrix = inverse covariance - cv::Vec6f y; // P*(-t_MH, t_CH) -}; - -#endif //TRANSCALIB_H diff --git a/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui b/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui deleted file mode 100644 index 74e5a6f1..00000000 --- a/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui +++ /dev/null @@ -1,285 +0,0 @@ - - - UI_freepie_udp_dialog - - - Qt::NonModal - - - - 0 - 0 - 227 - 372 - - - - Tracker settings - - - - ../facetracknoir/images/facetracknoir.png../facetracknoir/images/facetracknoir.png - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - 0 - 0 - - - - UDP port - - - - - - - 0 - - - 65535 - - - - - - - - - - Axis order - - - - - - output yaw - - - - - - - - input yaw - - - - - input pitch - - - - - input roll - - - - - - - - - input yaw - - - - - input pitch - - - - - input roll - - - - - - - - output pitch - - - - - - - - input yaw - - - - - input pitch - - - - - input roll - - - - - - - - output roll - - - - - - - - - - Add to axis - - - - - - yaw - - - - - - - - 0 - - - - - +90 - - - - - -90 - - - - - +180 - - - - - -180 - - - - - - - - pitch - - - - - - - roll - - - - - - - - 0 - - - - - +90 - - - - - -90 - - - - - +180 - - - - - -180 - - - - - - - - - 0 - - - - - +90 - - - - - -90 - - - - - +180 - - - - - -180 - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_freepie-udp/freepie-udp-res.qrc b/ftnoir_tracker_freepie-udp/freepie-udp-res.qrc deleted file mode 100644 index 3fd3edc4..00000000 --- a/ftnoir_tracker_freepie-udp/freepie-udp-res.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - glovepie.png - - diff --git a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp deleted file mode 100644 index 12cf9bca..00000000 --- a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "ftnoir_tracker_freepie-udp.h" -#include "opentrack/plugin-api.hpp" - -#include -#include - -TrackerImpl::TrackerImpl() : pose { 0,0,0, 0,0,0 }, should_quit(false) -{ -} - -TrackerImpl::~TrackerImpl() -{ - should_quit = true; - wait(); -} - -template -static const t bound(t datum, t least, t max) -{ - if (datum < least) - return least; - if (datum > max) - return max; - return datum; -} - -void TrackerImpl::run() { -#pragma pack(push, 1) - struct { - uint8_t pad1; - uint8_t flags; - float fl[12]; - } data; -#pragma pack(pop) - enum F { - flag_Raw = 1 << 0, - flag_Orient = 1 << 1, - Mask = flag_Raw | flag_Orient - }; - - (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); - - while (!should_quit) { - int order[] = { - bound(s.idx_x, 0, 2), - bound(s.idx_y, 0, 2), - bound(s.idx_z, 0, 2) - }; - float orient[3]; - bool filled = false; - - while (sock.hasPendingDatagrams()) - { - using t = decltype(data); - t tmp {0,0, {0,0,0, 0,0,0, 0,0,0, 0,0,0}}; - (void) sock.readDatagram(reinterpret_cast(&tmp), sizeof(data)); - - int flags = tmp.flags & F::Mask; - - switch (flags) - { - //default: - case flag_Raw: - continue; - case flag_Raw | flag_Orient: - for (int i = 0; i < 3; i++) - orient[i] = tmp.fl[i+9]; - break; - case flag_Orient: - for (int i = 0; i < 3; i++) - orient[i] = tmp.fl[i]; - break; - } - - filled = true; - data = tmp; - } - - if (filled) - { - static const int add_cbx[] = { - 0, - 90, - -90, - 180, - -180, - }; - int indices[] = { s.add_yaw, s.add_pitch, s.add_roll }; - QMutexLocker foo(&mtx); - static constexpr double r2d = 57.295781; - for (int i = 0; i < 3; i++) - { - int val = 0; - int idx = indices[order[i]]; - if (idx >= 0 && idx < (int)(sizeof(add_cbx) / sizeof(*add_cbx))) - val = add_cbx[idx]; - pose[Yaw + i] = r2d * orient[order[i]] + val; - } - } - usleep(4000); - } -} - -void TrackerImpl::start_tracker(QFrame*) -{ - start(); - sock.moveToThread(this); -} - -void TrackerImpl::data(double *data) -{ - QMutexLocker foo(&mtx); - - data[Yaw] = pose[Yaw]; - data[Pitch] = pose[Pitch]; - data[Roll] = pose[Roll]; -} - -OPENTRACK_DECLARE_TRACKER(TrackerImpl, TrackerDialog, TrackerMeta) diff --git a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h deleted file mode 100644 index 7cff2ec9..00000000 --- a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) 2014 Stanislaw Halik - * - * 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 -#include -#include -#include "ui_freepie-udp-controls.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value port, idx_x, idx_y, idx_z; - value add_yaw, add_pitch, add_roll; - settings() : - opts("freepie-udp-tracker"), - port(b, "port", 5555), - idx_x(b, "axis-index-x", 0), - idx_y(b, "axis-index-y", 1), - idx_z(b, "axis-index-z", 2), - add_yaw(b, "add-yaw-degrees", 0), - add_pitch(b, "add-pitch-degrees", 0), - add_roll(b, "add-roll-degrees", 0) - {} -}; - -class TrackerImpl : public ITracker, private QThread -{ -public: - TrackerImpl(); - ~TrackerImpl() override; - void start_tracker(QFrame *) override; - void data(double *data) override; -protected: - void run() override; -private: - double pose[6]; - QUdpSocket sock; - settings s; - QMutex mtx; - volatile bool should_quit; -}; - -class TrackerDialog : public ITrackerDialog -{ - Q_OBJECT -public: - TrackerDialog(); - void register_tracker(ITracker *) override {} - void unregister_tracker() override {} -private: - Ui::UI_freepie_udp_dialog ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class TrackerMeta : public Metadata -{ -public: - QString name() { return QString("FreePIE UDP receiver"); } - QIcon icon() { return QIcon(":/glovepie.png"); } -}; - diff --git a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp deleted file mode 100644 index 55427d35..00000000 --- a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "ftnoir_tracker_freepie-udp.h" -#include "opentrack/plugin-api.hpp" - -TrackerDialog::TrackerDialog() -{ - ui.setupUi(this); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.port, ui.port); - tie_setting(s.idx_x, ui.input_x); - tie_setting(s.idx_y, ui.input_y); - tie_setting(s.idx_z, ui.input_z); - - tie_setting(s.add_yaw, ui.add_yaw); - tie_setting(s.add_pitch, ui.add_pitch); - tie_setting(s.add_roll, ui.add_roll); -} - -void TrackerDialog::doOK() { - s.b->save(); - this->close(); -} - -void TrackerDialog::doCancel() { - s.b->reload(); - this->close(); -} - diff --git a/ftnoir_tracker_freepie-udp/glovepie.png b/ftnoir_tracker_freepie-udp/glovepie.png deleted file mode 100644 index 2156b7af..00000000 Binary files a/ftnoir_tracker_freepie-udp/glovepie.png and /dev/null differ diff --git a/ftnoir_tracker_hatire/ftnoir_arduino_type.h b/ftnoir_tracker_hatire/ftnoir_arduino_type.h deleted file mode 100644 index 57afed63..00000000 --- a/ftnoir_tracker_hatire/ftnoir_arduino_type.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef FTNOIR_TARDUINO_TYPE_H -#define FTNOIR_TARDUINO_TYPE_H - -#include - -// Arduino trame structure -#pragma pack(push,2) -struct TArduinoData -{ - quint16 Begin; // Header trame 0xAAAA; - quint16 Code; // 0->999 Num Trame >=2000 Info >=3000 Init >=5000 Start Command >=9000 Error - float Rot[3]; - float Trans[3]; - quint16 End; // End trame 0x5555; -} ; -#pragma pack(pop) - - -inline QDataStream & operator >> ( QDataStream& in, TArduinoData& out ) -{ - in.setFloatingPointPrecision(QDataStream::SinglePrecision ); - - in >> out.Begin >> out.Code - >> out.Rot[0] >> out.Rot[1] >> out.Rot[2] - >> out.Trans[0] >> out.Trans[1] >> out.Trans[2] - >> out.End; - return in; -} - - - -#endif diff --git a/ftnoir_tracker_hatire/ftnoir_hat.qrc b/ftnoir_tracker_hatire/ftnoir_hat.qrc deleted file mode 100644 index 41d43617..00000000 --- a/ftnoir_tracker_hatire/ftnoir_hat.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - images/hat_logo.png - images/hat.ico - images/hat.png - - diff --git a/ftnoir_tracker_hatire/ftnoir_hatcontrols.ui b/ftnoir_tracker_hatire/ftnoir_hatcontrols.ui deleted file mode 100644 index 2d347f08..00000000 --- a/ftnoir_tracker_hatire/ftnoir_hatcontrols.ui +++ /dev/null @@ -1,1253 +0,0 @@ - - - UIHATControls - - - - 0 - 0 - 370 - 740 - - - - - 0 - 0 - - - - - 65536 - 65536 - - - - Qt::NoContextMenu - - - Head Arduino Tracker settings FaceTrackNoIR - - - - :/images/hat.png:/images/hat.png - - - 1.000000000000000 - - - Qt::LeftToRight - - - false - - - - - - - 0 - 0 - - - - - 80 - 25 - - - - - 80 - 25 - - - - Cancel - - - - - - - - 0 - 0 - - - - - 80 - 25 - - - - - 80 - 25 - - - - OK - - - - - - - - 0 - 0 - - - - - 65535 - 65535 - - - - 0 - - - - General - - - - - - - - - true - - - - 4 - - - - - - 0 - 0 - - - - - 65536 - 16777215 - - - - Serial port - - - - - - - - 0 - 0 - - - - - 65535 - 16777215 - - - - false - - - QComboBox::AdjustToMinimumContentsLength - - - 0 - - - - - - - - - - false - - - - 80 - 20 - - - - Zero - - - - - - - false - - - - 80 - 20 - - - - Center - - - - - - - false - - - - 80 - 20 - - - - Reset - - - - - - - Axis Configuration - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - Associate Axis - - - - RotX - - - - - RotY - - - - - RotZ - - - - - - - - - 20 - 16777215 - - - - Enable Axis - - - Qt::LeftToRight - - - - - - - - - - - 20 - 16777215 - - - - Enable Axis - - - Qt::LeftToRight - - - - - - - - - - Pitch: - - - - - - - Enable - - - - - - - - 20 - 16777215 - - - - Enable Axis - - - Qt::LeftToRight - - - - - - - - - - Yaw: - - - - - - - Invert - - - - - - - Y: - - - - - - - - 20 - 16777215 - - - - Invert Axis - - - Qt::LeftToRight - - - - - - - - - - - - - X: - - - - - - - - 20 - 16777215 - - - - Invert Axis - - - Qt::LeftToRight - - - - - - - - - - - - - - 20 - 16777215 - - - - Invert Axis - - - Qt::LeftToRight - - - - - - - - - - - - - Associate Axis - - - - X - - - - - Y - - - - - Z - - - - - - - - - 20 - 16777215 - - - - Enable Axis - - - Qt::LeftToRight - - - - - - - - - - Associate Axis - - - - X - - - - - Y - - - - - Z - - - - - - - - Roll: - - - - - - - - 20 - 16777215 - - - - Invert Axis - - - Qt::LeftToRight - - - - - - - - - - - - - Associate Axis - - - - X - - - - - Y - - - - - Z - - - - - - - - - 20 - 16777215 - - - - Invert Axis - - - Qt::LeftToRight - - - - - - - - - - - - - Z: - - - - - - - Associate Axis - - - - RotX - - - - - RotY - - - - - RotZ - - - - - - - - - 20 - 16777215 - - - - Enable Axis - - - Qt::LeftToRight - - - - - - - - - - - - - - 20 - 16777215 - - - - Enable Axis - - - Qt::LeftToRight - - - - - - - - - - - 20 - 16777215 - - - - Invert Axis - - - Qt::LeftToRight - - - - - - - - - - - - - Associate Axis - - - - RotX - - - - - RotY - - - - - RotZ - - - - - - - - Axis - - - - - - - - - - - 0 - 0 - - - - Status - - - false - - - - - - - 31 - 20 - - - - - 60 - 20 - - - - Trame per seconde - - - tps : - - - - - - - - 31 - 20 - - - - - 60 - 20 - - - - 0 - - - Qt::PlainText - - - - - - - - 0 - 20 - - - - - 60 - 20 - - - - Info : - - - - - - - - 170 - 20 - - - - - 60 - 20 - - - - HAT STOPPED - - - Qt::PlainText - - - - - - - - - - - Command - - - - - - Serial Parameters - - - - - - - - - - - - Flow control: - - - - - - - - - - - - - Stop bits: - - - - - - - Parity: - - - - - - - BaudRate: - - - - - - - - - - Data bits: - - - - - - - - - - Arduino Commands - - - - - - Delay Init - - - - - - - Init - - - - - - - Command for Initialising Arduino - - - - - - - Delay Start - - - - - - - Start: - - - - - - - Command for Start send sequence - - - - - - - Delay Sequence - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay after Start Command in ms</span></p></body></html> - - - 5000 - - - 50 - - - - - - - Stop: - - - - - - - Command for Stop send sequence - - - - - - - Center: - - - - - - - Command for read Center Gyro arduino - - - - - - - Zero: - - - - - - - Command for reset Center Gyro arduino - - - - - - - Reset: - - - - - - - Command for Reset Arduino - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Little or Big Endian for <span style=" font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;">the serialization of byte order</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;">Arduino is LittleEndian ( unchecked)</span></p></body></html> - - - Endian - - - - - - - - 60 - 16777215 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay before Init command in ms</span></p></body></html> - - - 5000 - - - 50 - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay after Init command in ms</span></p></body></html> - - - 5000 - - - 50 - - - - - - - - 51 - 19 - - - - <html><head/><body><p>Indicate at OpenTrack speed sketch FPS to adjust CPU </p></body></html> - - - 10 - - - 200 - - - - - - - - - - - About - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">FTNoIR HAT Plugin<br />by FuraX49</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://hatire.sourceforge.net/"><span style=" font-size:8pt; font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html> - - - true - - - - - - - false - - - - - - - :/images/hat_logo.png - - - - - 128 - 128 - - - - true - - - - - - - - Arial Black - 10 - 75 - true - true - - - - Version 1.0.0 - - - Qt::PlainText - - - true - - - - - - - - - - - - - - - - - Send - - - - - - - Qt::ActionsContextMenu - - - true - - - - - - Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - 800 - - - false - - - - - - - Disable when not in use, will have a performance impact - - - Enable logging to diagnostic file - - - - - - - - - - - - 80 - 25 - - - - - 80 - 25 - - - - Save - - - - - - - btnOK - btnSave - btnCancel - cbSerialPort - btnZero - btnCenter - btnReset - chkEnableYaw - cb_yaw - chkInvertYaw - chkEnablePitch - cb_pitch - chkInvertPitch - chkEnableRoll - cb_roll - chkInvertRoll - chkEnableX - cb_x - chkInvertX - chkEnableY - cb_y - chkInvertY - chkEnableZ - cb_z - chkInvertZ - spb_BeforeInit - le_cmd_init - spb_BeforeStart - le_cmd_start - spb_AfterStart - le_cmd_stop - le_cmd_center - le_cmd_zero - le_cmd_reset - spb_Fps - cb_Endian - QCB_Serial_baudRate - QCB_Serial_dataBits - QCB_Serial_parity - QCB_Serial_stopBits - QCB_Serial_flowControl - lineSend - btnSend - pteINFO - tabWidget - btn_icone - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp deleted file mode 100644 index eea1cbca..00000000 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp +++ /dev/null @@ -1,597 +0,0 @@ -/* 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 -#include "ftnoir_tracker_hat.h" - -FTNoIR_Tracker::FTNoIR_Tracker() -{ - qDebug()<<"Tracker::HAT"; - - ComPort = NULL; - - HAT.Rot[0]=0; - HAT.Rot[1]=0; - HAT.Rot[2]=0; - HAT.Trans[0]=0; - HAT.Trans[1]=0; - HAT.Trans[2]=0; - - - // prepare & reserve QByteArray - dataRead.resize(4096); - dataRead.clear(); - Begin.append((char) 0xAA); - Begin.append((char) 0xAA); - End.append((char) 0x55); - End.append((char) 0x55); - - flDiagnostics.setFileName(QCoreApplication::applicationDirPath() + "/HATDiagnostics.txt"); - - settings.load_ini(); -} - -FTNoIR_Tracker::~FTNoIR_Tracker() -{ - qDebug()<<"Tracker::~HAT"; - if (ComPort!=NULL) { - if (ComPort->isOpen() ) { - -#ifdef OPENTRACK_API - QByteArray Msg; - Log("Tracker shut down"); - ComPort->write(sCmdStop); - if (!ComPort->waitForBytesWritten(1000)) { - emit sendMsgInfo("TimeOut in writing CMD"); - } else - { - Msg.append("\r\n"); - Msg.append("SEND '"); - Msg.append(sCmdStop); - Msg.append("'\r\n"); - } - emit sendMsgInfo(Msg); -#endif - ComPort->close(); - disconnect(ComPort,SIGNAL(readyRead()),0,0); - - } - delete ComPort; - ComPort=NULL; - } -} - - -//send ZERO to Arduino -bool FTNoIR_Tracker::notifyZeroed() { - qDebug() << " HAT send ZEROed "; - sendcmd(sCmdZero); - return true; -} - - - -//send RESET to Arduino -void FTNoIR_Tracker::reset() { - qDebug() << " HAT send RESET "; - sendcmd(sCmdReset); -} - - -// Info SerialPort -void FTNoIR_Tracker::SerialInfo() { - QByteArray Msg; - if (ComPort!=NULL) { - if (ComPort->isOpen() ) { - Msg.append("\r\n"); - Msg.append(ComPort->portName()); - Msg.append("\r\n"); - Msg.append("BAUDRATE :"); - Msg.append(QString::number(ComPort->baudRate())); - Msg.append("\r\n"); - Msg.append("DataBits :"); - Msg.append(QString::number(ComPort->dataBits())); - Msg.append("\r\n"); - Msg.append("Parity :"); - switch (ComPort->parity()) { - case 0: Msg.append("No parity"); - break; - case 2: Msg.append("Even parity"); - break; - case 3: Msg.append("Odd parity"); - break; - case 4: Msg.append("Space parity"); - break; - case 5: Msg.append("Mark parity"); - break; - default: Msg.append("Unknown parity"); - break; - } - Msg.append("\r\n"); - Msg.append("Stop Bits :"); - switch (ComPort->stopBits()) { - Msg.append(QString::number(ComPort->stopBits())); - case 1: Msg.append("1 stop bit."); - break; - case 2: Msg.append("2 stop bits."); - break; - case 3: Msg.append("1.5 stop bits."); - break; - default: Msg.append("Unknown number of stop bit."); - break; - } - Msg.append("\r\n"); - Msg.append("Flow Control :"); - switch (ComPort->flowControl()) { - case 0: Msg.append("No flow control"); - break; - case 1: Msg.append("Hardware flow control (RTS/CTS)"); - break; - case 2: Msg.append("Software flow control (XON/XOFF)"); - break; - default: Msg.append("Unknown flow control"); - break; - } - emit sendMsgInfo(Msg); - - } - } -} - - -//send command to Arduino -void FTNoIR_Tracker::sendcmd(const QByteArray &cmd) { - QByteArray Msg; - if (cmd.length()>0) { - if (ComPort->isOpen() ) - { - QString logMess; - logMess.append("SEND '"); - logMess.append(cmd); - logMess.append("'"); - Log(logMess); - ComPort->write(cmd); - if (!ComPort->waitForBytesWritten(1000)) { - emit sendMsgInfo("TimeOut in writing CMD"); - } else - { - Msg.append("\r\n"); - Msg.append("SEND '"); - Msg.append(cmd); - Msg.append("'\r\n"); - } - #if 0 // WaitForReadyRead isn't working well and there are some reports of it being a win32 issue. We can live without it anyway - if ( !ComPort->waitForReadyRead(1000)) { - emit sendMsgInfo("TimeOut in response to CMD") ; - } else { - emit sendMsgInfo(Msg); - } - #else - emit sendMsgInfo(Msg); - #endif - } else { - emit sendMsgInfo("ComPort not open") ; - } - } -} - - -// return FPS -void FTNoIR_Tracker::get_info( int *tps ){ - *tps=frame_cnt; - frame_cnt=0; -} - -void FTNoIR_Tracker::SerialRead() -{ - QMutexLocker lck(&mutex); - dataRead+=ComPort->readAll(); -} - -#ifndef OPENTRACK_API -void FTNoIR_Tracker::Initialize( QFrame *videoframe ) -{ - CptError=0; - dataRead.clear(); - frame_cnt=0; - - Log("INITIALISING HATIRE"); - - settings.load_ini(); - applysettings(settings); - ComPort = new QSerialPort(this); - ComPort->setPortName(sSerialPortName); - if (ComPort->open(QIODevice::ReadWrite ) == true) { - connect(ComPort, SIGNAL(readyRead()), this, SLOT(SerialRead())); - if ( - ComPort->setBaudRate((QSerialPort::BaudRate)iBaudRate) - && ComPort->setDataBits((QSerialPort::DataBits)iDataBits) - && ComPort->setParity((QSerialPort::Parity)iParity) - && ComPort->setStopBits((QSerialPort::StopBits)iStopBits) - && ComPort->setFlowControl((QSerialPort::FlowControl)iFlowControl) - && ComPort->clear(QSerialPort::AllDirections) - && ComPort->setDataErrorPolicy(QSerialPort::IgnorePolicy) - ) { - // Wait init arduino sequence - for (int i = 1; i <=iDelayInit; i+=50) { - if (ComPort->waitForReadyRead(50)) break; - } - sendcmd(sCmdInit); - // Wait init MPU sequence - for (int i = 1; i <=iDelayStart; i+=50) { - if (ComPort->waitForReadyRead(50)) break; - } - - } else { - QMessageBox::warning(0,"Error", ComPort->errorString(),QMessageBox::Ok,QMessageBox::NoButton); - } - } - else { - QMessageBox::warning(0,"Error", "Unable to open ComPort",QMessageBox::Ok,QMessageBox::NoButton); - delete ComPort; - ComPort = NULL; - } - return; -} - - - -void FTNoIR_Tracker::StartTracker(HWND parent_window) -{ - // Send START cmd to IMU - sendcmd(sCmdStart); - Log("Starting Tracker"); - // Wait start MPU sequence - for (int i = 1; i <=iDelaySeq; i+=50) { - if (ComPort->waitForReadyRead(50)) break; - } - return; -} - - -void FTNoIR_Tracker::StopTracker( bool exit ) -{ - QByteArray Msg; - - Log("Stopping tracker"); - if (sCmdStop.length()>0) { - if (ComPort->isOpen() ) - { - ComPort->write(sCmdStop); - if (!ComPort->waitForBytesWritten(1000)) { - emit sendMsgInfo("TimeOut in writing CMD"); - } else - { - Msg.append("\r\n"); - Msg.append("SEND '"); - Msg.append(sCmdStop); - Msg.append("'\r\n"); - } - emit sendMsgInfo(Msg); - } - } - // OK, the thread is not stopped, doing this. That might be dangerous anyway... - // - if (exit || !exit) return; - return; -} -//send CENTER to Arduino -void FTNoIR_Tracker::notifyCenter() { - sendcmd(sCmdCenter); -} - - -#else -void FTNoIR_Tracker::start_tracker(QFrame*) -{ - CptError=0; - dataRead.clear(); - frame_cnt=0; - new_frame=false; - settings.load_ini(); - applysettings(settings); - ComPort = new QSerialPort(this); - ComPort->setPortName(sSerialPortName); - Log("Starting Tracker"); - - if (ComPort->open(QIODevice::ReadWrite ) == true) { - connect(ComPort, SIGNAL(readyRead()), this, SLOT(SerialRead())); - Log("Port Open"); - if ( - ComPort->setBaudRate((QSerialPort::BaudRate)iBaudRate) - && ComPort->setDataBits((QSerialPort::DataBits)iDataBits) - && ComPort->setParity((QSerialPort::Parity)iParity) - && ComPort->setStopBits((QSerialPort::StopBits)iStopBits) - && ComPort->setFlowControl((QSerialPort::FlowControl)iFlowControl) - && ComPort->clear(QSerialPort::AllDirections) - && ComPort->setDataErrorPolicy(QSerialPort::IgnorePolicy) - ) { - Log("Port Parameters set"); - qDebug() << QTime::currentTime() << " HAT OPEN on " << ComPort->portName() << ComPort->baudRate() << ComPort->dataBits() << ComPort->parity() << ComPort->stopBits() << ComPort->flowControl(); - - if (ComPort->flowControl() == QSerialPort::HardwareControl) - { - // Raise DTR - Log("Raising DTR"); - if (!ComPort->setDataTerminalReady(true)) - Log("Couldn't set DTR"); - - // Raise RTS/CTS - Log("Raising RTS"); - if (!ComPort->setRequestToSend(true)) - Log("Couldn't set RTS"); - - } - // Wait init arduino sequence - for (int i = 1; i <=iDelayInit; i+=50) { - if (ComPort->waitForReadyRead(50)) break; - } - Log("Waiting on init"); - qDebug() << QTime::currentTime() << " HAT send INIT "; - sendcmd(sCmdInit); - // Wait init MPU sequence - for (int i = 1; i <=iDelayStart; i+=50) { - if (ComPort->waitForReadyRead(50)) break; - } - // Send START cmd to IMU - qDebug() << QTime::currentTime() << " HAT send START "; - sendcmd(sCmdStart); - - // Wait start MPU sequence - for (int i = 1; i <=iDelaySeq; i+=50) { - if (ComPort->waitForReadyRead(50)) break; - } - Log("Port setup, waiting for HAT frames to process"); - qDebug() << QTime::currentTime() << " HAT wait MPU "; - } else { - QMessageBox::warning(0,"Error", ComPort->errorString(),QMessageBox::Ok,QMessageBox::NoButton); - } - } - else { - QMessageBox::warning(0,"Error", "Unable to open ComPort: " + ComPort->errorString(), QMessageBox::Ok,QMessageBox::NoButton); - delete ComPort; - ComPort = NULL; - } - return; - -} - -//send CENTER to Arduino -void FTNoIR_Tracker::center() { - qDebug() << " HAT send CENTER "; - Log("Sending Centre Command"); - - sendcmd(sCmdCenter); -} - -//Return speed FPS sketch Arduino -int FTNoIR_Tracker::preferredHz() { - qDebug() << " HAT return Preferred FPS " << iFpsArduino; - return iFpsArduino; -} - -#endif - - -// -// Return 6DOF info -// -#ifdef OPENTRACK_API -void FTNoIR_Tracker::data(double *data) -#else -bool FTNoIR_Tracker::GiveHeadPoseData(THeadPoseData *data) -#endif -{ - QMutexLocker lck(&mutex); - while (dataRead.length()>=30) { - Log(dataRead.toHex()); - if ((dataRead.startsWith(Begin) && ( dataRead.mid(28,2)==End )) ) { // .Begin==0xAAAA .End==0x5555 - QDataStream datastream(dataRead.left(30)); - if (bBigEndian) datastream.setByteOrder(QDataStream::BigEndian ); - else datastream.setByteOrder(QDataStream::LittleEndian ); - datastream>>ArduinoData; - frame_cnt++; - if (ArduinoData.Code <= 1000) { - HAT=ArduinoData; - new_frame=true; - } else { - emit sendMsgInfo(dataRead.mid(4,24)) ; - } - dataRead.remove(0,30); - } else { - // resynchro trame - int index = dataRead.indexOf(Begin); - if (index==-1) { - index=dataRead.length(); - } - emit sendMsgInfo(dataRead.mid(0,index)) ; - dataRead.remove(0,index); - CptError++; - qDebug() << QTime::currentTime() << " HAT Resync-Frame, counter " << CptError; - } - } - - if (CptError>50) { - emit sendMsgInfo("Can't find HAT frame") ; - CptError=0; -#ifndef OPENTRACK_API - return false; -#endif - } - // Need to handle this differently in opentrack as opposed to tracknoir - //if (new_frame) { -#ifdef OPENTRACK_API - // in open track always populate the data, it seems opentrack always gives us a zeroed data structure to populate with pose data. - // if we have no new data, we don't populate it and so 0 pose gets handed back which is wrong. By always running the code below, if we - // have no new data, we will just give it the previous pose data which is the best thing we can do really. - if(1){ - - if (bEnableYaw) { - if (bInvertYaw ) data[Yaw] = HAT.Rot[iYawAxe] * -1.0f; - else data[Yaw] = HAT.Rot[iYawAxe]; - - } else data[Yaw] =0; - - if (bEnablePitch) { - if (bInvertPitch) data[Pitch] = HAT.Rot[iPitchAxe] * -1.0f; - else data[Pitch] = HAT.Rot[iPitchAxe]; - } else data[Pitch] = 0; - - if (bEnableRoll) { - if (bInvertRoll) data[Roll] = HAT.Rot[iRollAxe] * -1.0f; - else data[Roll] = HAT.Rot[iRollAxe]; - } else data[Roll] =0; - - if (bEnableX) { - if (bInvertX) data[TX] = HAT.Trans[iXAxe]* -1.0f; - else data[TX] = HAT.Trans[iXAxe]; - } else data[TX] =0; - - if (bEnableY) { - if (bInvertY) data[TY] = HAT.Trans[iYAxe]* -1.0f; - else data[TY] = HAT.Trans[iYAxe]; - } else data[TY] =0; - - if (bEnableZ) { - if (bInvertZ) data[TZ] = HAT.Trans[iZAxe]* -1.0f; - else data[TZ] = HAT.Trans[iZAxe]; - } else data[TZ] =0; -#else - if (new_frame) { // treat frame handling as it was for TrackNoIR. - if (bEnableYaw) { - if (bInvertYaw ) data->yaw = (double) HAT.Rot[iYawAxe] * -1.0f; - else data->yaw = (double) HAT.Rot[iYawAxe]; - } - - if (bEnablePitch) { - if (bInvertPitch)data->pitch = (double) HAT.Rot[iPitchAxe] * -1.0f; - else data->pitch = (double) HAT.Rot[iPitchAxe]; - } - - if (bEnableRoll) { - if (bInvertRoll) data->roll = (double) HAT.Rot[iRollAxe] * -1.0f; - else data->roll = (double) HAT.Rot[iRollAxe]; - } - - if (bEnableX) { - if (bInvertX) data->x = (double) HAT.Trans[iXAxe]* -1.0f; - else data->x = (double) HAT.Trans[iXAxe]; - } - - if (bEnableY) { - if (bInvertY) data->y = (double) HAT.Trans[iYAxe]* -1.0f; - else data->y = (double) HAT.Trans[iYAxe]; - } - - if (bEnableZ) { - if (bInvertZ) data->z = (double) HAT.Trans[iZAxe]* -1.0f; - else data->z = (double) HAT.Trans[iZAxe]; - } - return true; -#endif - new_frame=false; - // For debug - //data->x=dataRead.length(); - //data->y=CptError; - } -} - - - -// -// Apply modification Settings -// -void FTNoIR_Tracker::applysettings(const TrackerSettings& settings){ - QMutexLocker lck(&mutex); - sSerialPortName= settings.SerialPortName; - - bEnableRoll = settings.EnableRoll; - bEnablePitch = settings.EnablePitch; - bEnableYaw = settings.EnableYaw; - bEnableX = settings.EnableX; - bEnableY = settings.EnableY; - bEnableZ = settings.EnableZ; - - bInvertRoll = settings.InvertRoll; - bInvertPitch = settings.InvertPitch; - bInvertYaw = settings.InvertYaw; - bInvertX = settings.InvertX; - bInvertY = settings.InvertY; - bInvertZ = settings.InvertZ; - bEnableLogging = settings.EnableLogging; - - iRollAxe= settings.RollAxe; - iPitchAxe= settings.PitchAxe; - iYawAxe= settings.YawAxe; - iXAxe= settings.XAxe; - iYAxe= settings.YAxe; - iZAxe= settings.ZAxe; - - iBaudRate=settings.pBaudRate; - iDataBits=settings.pDataBits; - iParity=settings.pParity; - iStopBits=settings.pStopBits; - iFlowControl=settings.pFlowControl; - - sCmdStart= settings.CmdStart.toLatin1(); - sCmdStop= settings.CmdStop.toLatin1(); - sCmdInit= settings.CmdInit.toLatin1(); - sCmdReset= settings.CmdReset.toLatin1(); - sCmdCenter= settings.CmdCenter.toLatin1(); - sCmdZero= settings.CmdZero.toLatin1(); - - iDelayInit=settings.DelayInit; - iDelayStart=settings.DelayStart; - iDelaySeq=settings.DelaySeq; - - bBigEndian=settings.BigEndian; -#ifdef OPENTRACK_API - iFpsArduino=settings.FPSArduino; -#endif -} - -void FTNoIR_Tracker::Log(QString message) -{ - // Drop out immediately if logging is off. Yes, there is still some overhead because of passing strings around for no reason. - // that's unfortunate and I'll monitor the impact and see if it needs a more involved fix. - if (!bEnableLogging) return; - QString logMessage; - - if (flDiagnostics.open(QIODevice::ReadWrite | QIODevice::Append)) - { - QTextStream out(&flDiagnostics); - QString milliSeconds; - milliSeconds = QString("%1").arg(QTime::currentTime().msec(), 3, 10, QChar('0')); - // We have a file - out << QTime::currentTime().toString() << "." << milliSeconds << ": " << message << "\r\n"; - flDiagnostics.close(); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// Factory function that creates instances if the Tracker object. - -// Export both decorated and undecorated names. -// GetTracker - Undecorated name, which can be easily used with GetProcAddress -// Win32 API function. -// _GetTracker@0 - Common name decoration for __stdcall functions in C language. -//////////////////////////////////////////////////////////////////////////////// -#ifdef OPENTRACK_API -#include "ftnoir_tracker_hat_dialog.h" -OPENTRACK_DECLARE_TRACKER(FTNoIR_Tracker, TrackerControls, TrackerDll) -#else -#pragma comment(linker, "/export:GetTracker=_GetTracker@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker() -{ - return new FTNoIR_Tracker; -} -#endif - diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat.h b/ftnoir_tracker_hatire/ftnoir_tracker_hat.h deleted file mode 100644 index 2472428b..00000000 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef FTNOIR_TRACKER_HAT_H -#define FTNOIR_TRACKER_HAT_H - -#ifdef OPENTRACK_API -# include "opentrack/plugin-support.hpp" -#else -# include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" -#endif -#include "ftnoir_tracker_hat_settings.h" -#include "ftnoir_arduino_type.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VER_FILEVERSION_STR "Version 2.1.1\0" - -class FTNoIR_Tracker : public QObject, public ITracker -{ - Q_OBJECT -public: - FTNoIR_Tracker(); - ~FTNoIR_Tracker(); - -#ifdef OPENTRACK_API - void start_tracker(QFrame*); - void data(double *data); - int preferredHz(); // unused - void center(); // unused -#else - void Initialize( QFrame *videoframe ); - void StartTracker(HWND parent_window); - void StopTracker(bool exit); - bool GiveHeadPoseData(THeadPoseData *data); - void notifyCenter(); -#endif - void applysettings(const TrackerSettings& settings); - bool notifyZeroed(); - void reset(); - void SerialInfo(); - void sendcmd(const QByteArray &cmd); - void get_info( int *tps ); - -private Q_SLOTS: - void SerialRead(); - void Log(QString message); - -signals: - void sendMsgInfo(const QByteArray &MsgInfo); - - -private: - QSerialPort *ComPort; - TArduinoData ArduinoData, HAT ; // Trame from Arduino - QByteArray dataRead; - QByteArray dataToSend; - QByteArray Begin; - QByteArray End; - QMutex mutex; - int frame_cnt; - bool new_frame; - - TrackerSettings settings; - - bool bEnableRoll; - bool bEnablePitch; - bool bEnableYaw; - bool bEnableX; - bool bEnableY; - bool bEnableZ; - - bool bInvertRoll; - bool bInvertPitch; - bool bInvertYaw; - bool bInvertX; - bool bInvertY; - bool bInvertZ; - bool bEnableLogging; - - int iRollAxe; - int iPitchAxe; - int iYawAxe; - int iXAxe; - int iYAxe; - int iZAxe; - - QByteArray sCmdStart; - QByteArray sCmdStop; - QByteArray sCmdInit; - QByteArray sCmdReset; - QByteArray sCmdCenter; - QByteArray sCmdZero; - - int iDelayInit; - int iDelayStart; - int iDelaySeq; - - bool bBigEndian; - - QString sSerialPortName; - QSerialPort::BaudRate iBaudRate; - QSerialPort::DataBits iDataBits; - QSerialPort::Parity iParity; - QSerialPort::StopBits iStopBits; - QSerialPort::FlowControl iFlowControl; - - QFile flDiagnostics; -#ifdef OPENTRACK_API - int iFpsArduino; -#endif - int CptError; - - -}; - - -//******************************************************************************************************* -// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker -//******************************************************************************************************* -#if defined(OPENTRACK_API) -class TrackerDll : public Metadata -{ - QString name() { return QString("Hatire Arduino"); } - QIcon icon() { return QIcon(":/images/hat.png"); } -}; -#else -class TrackerDll : -public Metadata -public ITrackerDll -{ -public: - TrackerDll(); - ~TrackerDll(); - - void Initialize(); - - QString name(); - QIcon icon(); - void getFullName(QString *strToBeFilled); - void getShortName(QString *strToBeFilled); - void getDescription(QString *strToBeFilled); - void getIcon(QIcon *icon); - -private: - QString trackerFullName; // Trackers' name and description - QString trackerShortName; - QString trackerDescription; -}; -#endif - -#endif // FTNOIR_TRACKER_HAT_H diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.cpp deleted file mode 100644 index 3ef1a764..00000000 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/* 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_tracker_hat.h" -#include "ftnoir_tracker_hat_dialog.h" - -#include - -//******************************************************************************************************* -// FaceTrackNoIR Client Settings-dialog. -//******************************************************************************************************* - -// -// Constructor for server-settings-dialog -// -TrackerControls::TrackerControls() : theTracker(NULL), settingsDirty(false), timer(this) -{ - - ui.setupUi( this ); - settings.load_ini(); - - ui.label_version->setText(VER_FILEVERSION_STR); - - // make SerialPort list - ui.cbSerialPort->clear(); - foreach (QSerialPortInfo PortInfo , QSerialPortInfo::availablePorts() ) { - ui.cbSerialPort->addItem(PortInfo.portName()); - } - - - // Stop if no SerialPort dispo - if (ui.cbSerialPort->count()<1) { - QMessageBox::critical(this,"Error", "No SerialPort avaible"); - } else { - - int indxport =ui.cbSerialPort->findText(settings.SerialPortName,Qt::MatchExactly ); - if (indxport!=-1) { - ui.cbSerialPort->setCurrentIndex(indxport); - } else { - if (settings.SerialPortName != "") - QMessageBox::warning(this,"Error", "Selected SerialPort modified"); - ui.cbSerialPort-> setCurrentIndex(indxport); - } - } - // Serial config - ui.QCB_Serial_baudRate->clear(); - ui.QCB_Serial_baudRate->addItem(QLatin1String("9600"),QSerialPort::Baud9600); - ui.QCB_Serial_baudRate->addItem(QLatin1String("19200"),QSerialPort::Baud19200); - ui.QCB_Serial_baudRate->addItem(QLatin1String("38400"),QSerialPort::Baud38400); - ui.QCB_Serial_baudRate->addItem(QLatin1String("57600"),QSerialPort:: Baud57600); - ui.QCB_Serial_baudRate->addItem(QLatin1String("115200"),QSerialPort::Baud115200); - ui.QCB_Serial_baudRate->setCurrentIndex(ui.QCB_Serial_baudRate->findData(settings.pBaudRate)); - - ui.QCB_Serial_dataBits->clear(); - ui.QCB_Serial_dataBits->addItem(QLatin1String("5"), QSerialPort::Data5); - ui.QCB_Serial_dataBits->addItem(QLatin1String("6"), QSerialPort::Data6); - ui.QCB_Serial_dataBits->addItem(QLatin1String("7"), QSerialPort::Data7); - ui.QCB_Serial_dataBits->addItem(QLatin1String("8"), QSerialPort::Data8); - ui.QCB_Serial_dataBits->setCurrentIndex(ui.QCB_Serial_dataBits->findData(settings.pDataBits)); - - ui.QCB_Serial_parity->clear(); - ui.QCB_Serial_parity->addItem(QLatin1String("None"), QSerialPort::NoParity); - ui.QCB_Serial_parity->addItem(QLatin1String("Even"), QSerialPort::EvenParity); - ui.QCB_Serial_parity->addItem(QLatin1String("Odd"), QSerialPort::OddParity); - ui.QCB_Serial_parity->addItem(QLatin1String("Space"), QSerialPort::SpaceParity); - ui.QCB_Serial_parity->addItem(QLatin1String("Mark"), QSerialPort::MarkParity); - ui.QCB_Serial_parity->setCurrentIndex(ui.QCB_Serial_parity->findData(settings.pParity)); - - ui.QCB_Serial_stopBits->clear(); - ui.QCB_Serial_stopBits->addItem(QLatin1String("1"), QSerialPort::OneStop); - ui.QCB_Serial_stopBits->addItem(QLatin1String("1.5"), QSerialPort::OneAndHalfStop); - ui.QCB_Serial_stopBits->addItem(QLatin1String("2"), QSerialPort::TwoStop); - ui.QCB_Serial_stopBits->setCurrentIndex(ui.QCB_Serial_stopBits->findData(settings.pStopBits)); - - - ui.QCB_Serial_flowControl->clear(); - ui.QCB_Serial_flowControl->addItem(QLatin1String("None"), QSerialPort::NoFlowControl); - ui.QCB_Serial_flowControl->addItem(QLatin1String("RTS/CTS"), QSerialPort::HardwareControl); - ui.QCB_Serial_flowControl->addItem(QLatin1String("XON/XOFF"), QSerialPort::SoftwareControl); - ui.QCB_Serial_flowControl->setCurrentIndex(ui.QCB_Serial_flowControl->findData(settings.pFlowControl)); - - - ui.chkEnableRoll->setChecked(settings.EnableRoll); - ui.chkEnablePitch->setChecked(settings.EnablePitch); - ui.chkEnableYaw->setChecked(settings.EnableYaw); - ui.chkEnableX->setChecked(settings.EnableX); - ui.chkEnableY->setChecked(settings.EnableY); - ui.chkEnableZ->setChecked(settings.EnableZ); - - ui.chkInvertRoll->setChecked(settings.InvertRoll); - ui.chkInvertPitch->setChecked(settings.InvertPitch); - ui.chkInvertYaw->setChecked(settings.InvertYaw); - ui.chkInvertX->setChecked(settings.InvertX); - ui.chkInvertY->setChecked(settings.InvertY); - ui.chkInvertZ->setChecked(settings.InvertZ); - - ui.chkEnableLogging->setChecked(settings.EnableLogging); - - - ui.cb_roll->setCurrentIndex(settings.RollAxe); - ui.cb_pitch->setCurrentIndex(settings.PitchAxe); - ui.cb_yaw->setCurrentIndex(settings.YawAxe); - ui.cb_x->setCurrentIndex(settings.XAxe); - ui.cb_y->setCurrentIndex(settings.YAxe); - ui.cb_z->setCurrentIndex(settings.ZAxe); - - ui.le_cmd_start->setText(settings.CmdStart); - ui.le_cmd_stop->setText(settings.CmdStop); - ui.le_cmd_init->setText(settings.CmdInit); - ui.le_cmd_reset->setText(settings.CmdReset); - ui.le_cmd_center->setText(settings.CmdCenter); - ui.le_cmd_zero->setText(settings.CmdZero); - - ui.spb_BeforeInit->setValue(settings.DelayInit); - ui.spb_BeforeStart->setValue(settings.DelayStart); - ui.spb_AfterStart->setValue(settings.DelaySeq); - - ui.cb_Endian->setChecked(settings.BigEndian); - -#ifdef OPENTRACK_API - ui.spb_Fps->setValue(settings.FPSArduino); - connect(ui.spb_Fps, SIGNAL(valueChanged ( int )), this,SLOT(set_Fps(int))); -#endif - - // Connect Qt signals to member-functions - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); - connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(doSave())); - - - connect(ui.cbSerialPort, SIGNAL(currentIndexChanged(QString)), this,SLOT(set_mod_port(QString)) ); - - connect( ui.chkEnableRoll,SIGNAL(toggled(bool)), this,SLOT(set_ena_roll(bool)) ); - connect( ui.chkEnablePitch,SIGNAL(toggled(bool)), this,SLOT(set_ena_pitch(bool)) ); - connect( ui.chkEnableYaw,SIGNAL(toggled(bool)), this,SLOT(set_ena_yaw(bool)) ); - connect( ui.chkEnableX,SIGNAL(toggled(bool)), this,SLOT(set_ena_x(bool)) ); - connect( ui.chkEnableY,SIGNAL(toggled(bool)), this,SLOT(set_ena_y(bool)) ); - connect( ui.chkEnableZ,SIGNAL(toggled(bool)), this,SLOT(set_ena_z(bool)) ); - - connect( ui.chkInvertRoll,SIGNAL(toggled(bool)), this,SLOT(set_inv_roll(bool)) ); - connect( ui.chkInvertPitch,SIGNAL(toggled(bool)), this,SLOT(set_inv_pitch(bool)) ); - connect( ui.chkInvertYaw,SIGNAL(toggled(bool)), this,SLOT(set_inv_yaw(bool)) ); - connect( ui.chkInvertX,SIGNAL(toggled(bool)), this,SLOT(set_inv_x(bool)) ); - connect( ui.chkInvertY,SIGNAL(toggled(bool)), this,SLOT(set_inv_y(bool)) ); - connect( ui.chkInvertZ,SIGNAL(toggled(bool)), this,SLOT(set_inv_z(bool)) ); - connect( ui.chkEnableLogging,SIGNAL(toggled(bool)), this,SLOT(set_diag_logging(bool)) ); - - connect(ui.cb_roll, SIGNAL(currentIndexChanged(int)), this,SLOT(set_rot_roll(int))); - connect(ui.cb_pitch, SIGNAL(currentIndexChanged(int)),this,SLOT(set_rot_pitch(int))); - connect(ui.cb_yaw, SIGNAL(currentIndexChanged(int)), this,SLOT(set_rot_yaw(int))); - connect(ui.cb_x, SIGNAL(currentIndexChanged(int)), this,SLOT(set_acc_x(int))); - connect(ui.cb_y, SIGNAL(currentIndexChanged(int)), this,SLOT(set_acc_y(int))); - connect(ui.cb_z, SIGNAL(currentIndexChanged(int)), this,SLOT(set_acc_z(int))); - - connect(ui.le_cmd_start, SIGNAL(textEdited (QString )), this,SLOT(set_cmd_start(QString))); - connect(ui.le_cmd_stop, SIGNAL(textEdited ( QString )), this,SLOT(set_cmd_stop(QString))); - connect(ui.le_cmd_init, SIGNAL(textChanged ( QString )), this,SLOT(set_cmd_init(QString))); - connect(ui.le_cmd_reset, SIGNAL(textChanged ( QString )), this,SLOT(set_cmd_reset(QString))); - connect(ui.le_cmd_center, SIGNAL(textChanged ( QString )),this,SLOT(set_cmd_center(QString))); - connect(ui.le_cmd_zero, SIGNAL(textChanged ( QString )),this,SLOT(set_cmd_zero(QString))); - - connect(ui.spb_BeforeInit, SIGNAL(valueChanged ( int )), this,SLOT(set_DelayInit(int))); - connect(ui.spb_BeforeStart, SIGNAL(valueChanged ( int )), this,SLOT(set_DelayStart(int))); - connect(ui.spb_AfterStart, SIGNAL(valueChanged ( int )), this,SLOT(set_DelaySeq(int))); - - connect( ui.cb_Endian,SIGNAL(toggled(bool)), this,SLOT(set_endian(bool)) ); - - - connect(ui.QCB_Serial_baudRate, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_baud(int)) ); - connect(ui.QCB_Serial_dataBits, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_dataBits(int)) ); - connect(ui.QCB_Serial_parity, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_parity(int)) ); - connect(ui.QCB_Serial_stopBits, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_stopBits(int)) ); - connect(ui.QCB_Serial_flowControl, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_flowControl(int)) ); - - connect(ui.btnReset, SIGNAL(clicked()), this, SLOT(doReset())); - connect(ui.btnCenter, SIGNAL(clicked()), this, SLOT(doCenter())); - connect(ui.btnZero, SIGNAL(clicked()), this, SLOT(doZero())); - connect(ui.btnSend, SIGNAL(clicked()), this, SLOT(doSend())); - - connect(ui.btn_icone, SIGNAL(clicked()), this, SLOT(doSerialInfo())); - - connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info())); - - // can't connect slot, keyPressEvent takes QKeyPressEvent as argument - //connect(ui.lineSend,SIGNAL(keyPressEvent),this,SLOT(on_lineSend_returnPressed()) ); -} - -// -// Destructor for server-dialog -// -TrackerControls::~TrackerControls() { -} - -// -// Initialize tracker-client-dialog -// -void TrackerControls::Initialize(QWidget *parent) { - QPoint offsetpos(100, 100); - if (parent) { - this->move(parent->pos() + offsetpos); - } - show(); -} - - - -// -// Apply online settings to tracker -// -void TrackerControls::settings_changed() -{ - settingsDirty = true; - if (theTracker) theTracker->applysettings(settings); -} - - -// -// Center asked to ARDUINO -// -void TrackerControls::doCenter() { -#ifdef OPENTRACK_API - if (theTracker) theTracker->center(); -#else - if (theTracker) theTracker->notifyCenter(); -#endif -} - - -// -// Zero asked to ARDUINO -// -void TrackerControls::doZero() { - if (theTracker) theTracker->notifyZeroed(); -} - - -// -// Reset asked to ARDUINO -// -void TrackerControls::doReset() { - if (theTracker) theTracker->reset(); -} - - -// -// Serial Info debug -// -void TrackerControls::doSerialInfo() { - if (theTracker) theTracker->SerialInfo(); -} - - -// -// Send command to ARDUINO -// -void TrackerControls::doSend() { - if (theTracker) { - if (!ui.lineSend->text().isEmpty()) { - theTracker->sendcmd(ui.lineSend->text().toLatin1()); - } - } -} - - -// -// Enter on lineSend for send to ARDUINO -// -void TrackerControls::on_lineSend_returnPressed() -{ - this->doSend(); - -} - - -// -// Display FPS of Arduino. -// -void TrackerControls::poll_tracker_info() -{ - if (theTracker) - { - int nb_trame; - - theTracker->get_info(&nb_trame); - ui.lab_vtps->setText(QString::number(nb_trame*(1000/last_time.elapsed()))); - last_time.restart(); - } - -} - - -void TrackerControls::WriteMsgInfo(const QByteArray &MsgInfo) -{ - QApplication::beep(); - ui.pteINFO->moveCursor(QTextCursor::End); - ui.pteINFO->insertPlainText(QString(MsgInfo)); - QScrollBar *bar = ui.pteINFO->verticalScrollBar(); - bar->setValue(bar->maximum()); -} - - - -void TrackerControls::doSave() { - settingsDirty=false; - settings.save_ini(); -} - - -// -// OK clicked on server-dialog -// -void TrackerControls::doOK() { - settingsDirty=false; - settings.save_ini(); - this->close(); -} - -// -// Cancel clicked on server-dialog -// -void TrackerControls::doCancel() { - // - // Ask if changed Settings should be saved - // - if (settingsDirty) { - int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); - switch (ret) { - case QMessageBox::Save: - settings.save_ini(); - close(); - break; - case QMessageBox::Discard: - close(); - break; - case QMessageBox::Cancel: - // Cancel was clicked - break; - default: - // should never be reached - break; - } - } - else { - close(); - } -} - -#ifdef OPENTRACK_API -void TrackerControls::register_tracker(ITracker *tracker) -#else -void TrackerControls::registerTracker(ITracker *tracker) -#endif -{ - theTracker = static_cast(tracker); - connect(theTracker, SIGNAL(sendMsgInfo(QByteArray)),this , SLOT(WriteMsgInfo(QByteArray))); - - if (isVisible() && settingsDirty) theTracker->applysettings(settings); - - ui.cbSerialPort->setEnabled(false); - ui.btnZero->setEnabled(true); - ui.btnCenter->setEnabled(true); - ui.btnReset->setEnabled(true); - ui.pteINFO->clear(); - ui.lab_vstatus->setText("HAT START"); - last_time.start(); - timer.start(250); - -} - -#ifdef OPENTRACK_API -void TrackerControls::unregister_tracker() -#else -void TrackerControls::unRegisterTracker() -#endif -{ - timer.stop(); - theTracker=NULL; - ui.cbSerialPort->setEnabled(true); - ui.btnZero->setEnabled(false); - ui.btnCenter->setEnabled(false); - ui.btnReset->setEnabled(false); - ui.lab_vstatus->setText("HAT STOPPED"); - ui.lab_vtps->setText(""); -} - - - - -//////////////////////////////////////////////////////////////////////////////// -// Factory function that creates instances if the Tracker-settings dialog object. - -// Export both decorated and undecorated names. -// GetTrackerDialog - Undecorated name, which can be easily used with GetProcAddress -// Win32 API function. -// _GetTrackerDialog@0 - Common name decoration for __stdcall functions in C language. -#ifdef OPENTRACK_API -#else -#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") -FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( ) -{ - return new TrackerControls; -} -#endif - diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h deleted file mode 100644 index ebaffc6d..00000000 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef FTNOIR_TRACKER_HAT_DIALOG_H -#define FTNOIR_TRACKER_HAT_DIALOG_H - -#ifdef OPENTRACK_API -#include "opentrack/plugin-api.hpp" -#else -#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" -#endif -#include "ftnoir_tracker_hat_settings.h" -#include "ftnoir_tracker_hat.h" -#include "ui_ftnoir_hatcontrols.h" -#include -#include -#include -#include -#include -#include - -// Widget that has controls for FTNoIR protocol client-settings. -#ifdef OPENTRACK_API -class TrackerControls: public ITrackerDialog - #else -class TrackerControls: public QWidget, public ITrackerDialog - #endif -{ - Q_OBJECT -public: - explicit TrackerControls(); - ~TrackerControls() override; -#ifdef OPENTRACK_API - void Initialize(QWidget *parent) ; // unused - void register_tracker(ITracker *tracker); - void unregister_tracker(); -#else - void Initialize(QWidget *parent) ; - void registerTracker(ITracker *tracker) ; - void unRegisterTracker() ; -#endif - -private: - Ui::UIHATControls ui; - FTNoIR_Tracker *theTracker; - QTime last_time; - -public slots: - void WriteMsgInfo(const QByteArray &MsgInfo); - -protected slots: - void set_mod_port(const QString & val) { settings.SerialPortName =val; settings_changed(); } - void set_ena_roll(bool val) { settings.EnableRoll = val; settings_changed(); } - void set_ena_pitch(bool val) { settings.EnablePitch = val; settings_changed(); } - void set_ena_yaw(bool val) { settings.EnableYaw = val; settings_changed(); } - void set_ena_x(bool val) { settings.EnableX = val; settings_changed(); } - void set_ena_y(bool val) { settings.EnableY = val; settings_changed(); } - void set_ena_z(bool val) { settings.EnableZ = val; settings_changed(); } - - void set_inv_roll(bool val) { settings.InvertRoll = val; settings_changed(); } - void set_inv_pitch(bool val) { settings.InvertPitch = val; settings_changed(); } - void set_inv_yaw(bool val) { settings.InvertYaw = val; settings_changed(); } - void set_inv_x(bool val) { settings.InvertX = val; settings_changed(); } - void set_inv_y(bool val) { settings.InvertY = val; settings_changed(); } - void set_inv_z(bool val) { settings.InvertZ = val; settings_changed(); } - - void set_diag_logging(bool val) { settings.EnableLogging = val; settings_changed(); } - - - void set_rot_roll(int val) { settings.RollAxe = val; settings_changed(); } - void set_rot_pitch(int val) { settings.PitchAxe = val; settings_changed(); } - void set_rot_yaw(int val) { settings.YawAxe = val; settings_changed(); } - void set_acc_x(int val) { settings.XAxe = val; settings_changed(); } - void set_acc_y(int val) { settings.YAxe = val; settings_changed(); } - void set_acc_z(int val) { settings.ZAxe = val; settings_changed(); } - - void set_cmd_start(const QString &val) { settings.CmdStart = val; settings_changed(); } - void set_cmd_stop(const QString &val) { settings.CmdStop = val; settings_changed(); } - void set_cmd_init(const QString &val) { settings.CmdInit = val; settings_changed(); } - void set_cmd_reset(const QString &val) { settings.CmdReset = val; settings_changed(); } - void set_cmd_center(const QString &val) { settings.CmdCenter = val; settings_changed(); } - void set_cmd_zero(const QString &val) { settings.CmdZero = val; settings_changed(); } - - void set_DelayInit(int val) { settings.DelayInit = val; settings_changed(); } - void set_DelayStart(int val) { settings.DelayStart = val; settings_changed(); } - void set_DelaySeq(int val) { settings.DelaySeq = val; settings_changed(); } - - void set_endian(bool val) { settings.BigEndian = val; settings_changed(); } -#ifdef OPENTRACK_API - void set_Fps(int val) { settings.FPSArduino = val; settings_changed(); } -#endif - - void set_mod_baud(int val) { settings.pBaudRate = static_cast(ui.QCB_Serial_baudRate->itemData(val).toInt()) ; settings_changed(); } - void set_mod_dataBits(int val) { settings.pDataBits = static_cast(ui.QCB_Serial_dataBits->itemData(val).toInt()) ; settings_changed(); } - void set_mod_parity(int val) { settings.pParity = static_cast(ui.QCB_Serial_parity->itemData(val).toInt()) ; settings_changed(); } - void set_mod_stopBits(int val) { settings.pStopBits = static_cast(ui.QCB_Serial_stopBits->itemData(val).toInt()); settings_changed(); } - void set_mod_flowControl(int val) { settings.pFlowControl = static_cast(ui.QCB_Serial_flowControl->itemData(val).toInt()) ; settings_changed(); } - - void doOK(); - void doCancel(); - void doSave(); - void doReset(); - void doCenter(); - void doZero(); - void doSend(); - void poll_tracker_info(); - void doSerialInfo(); - -protected: - bool settingsDirty; - void settings_changed(); - TrackerSettings settings; - QTimer timer; - -private slots: - void on_lineSend_returnPressed(); -}; - -#endif //FTNOIR_TRACKER_HAT_DIALOG_H diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp deleted file mode 100644 index e6b32047..00000000 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* 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 -#include -#include - -#include "ftnoir_tracker_hat_settings.h" -#ifdef OPENTRACK_API -#include "opentrack/options.hpp" -#endif - -void TrackerSettings::load_ini() -{ -#ifndef OPENTRACK_API - QSettings settings(OPENTRACK_ORG); // Registry settings (in HK_USER) - QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); -#else - QString currentFile = options::group::ini_pathname(); -#endif - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup( "HAT" ); - - SerialPortName=iniFile.value ( "PortName" ).toString(); - - EnableRoll = iniFile.value( "EnableRoll", 1 ).toBool(); - EnablePitch = iniFile.value( "EnablePitch", 1 ).toBool(); - EnableYaw = iniFile.value( "EnableYaw", 1 ).toBool(); - EnableX = iniFile.value( "EnableX", 0 ).toBool(); - EnableY = iniFile.value( "EnableY", 0 ).toBool(); - EnableZ = iniFile.value( "EnableZ", 0 ).toBool(); - EnableLogging = iniFile.value( "EnableLogging", 0).toBool(); - - InvertRoll = iniFile.value( "InvertRoll", 1 ).toBool(); - InvertPitch = iniFile.value( "InvertPitch", 1 ).toBool(); - InvertYaw = iniFile.value( "InvertYaw", 1 ).toBool(); - InvertX = iniFile.value( "InvertX", 0 ).toBool(); - InvertY = iniFile.value( "InvertY", 0 ).toBool(); - InvertZ = iniFile.value( "InvertZ", 0 ).toBool(); - - - RollAxe=iniFile.value("RollAxe",1).toInt(); - PitchAxe=iniFile.value("PitchAxe",2).toInt(); - YawAxe=iniFile.value("YawAxe",0).toInt(); - XAxe=iniFile.value("XAxe",1).toInt(); - YAxe=iniFile.value("YAxe",2).toInt(); - ZAxe=iniFile.value("ZAxe",0).toInt(); - - - CmdStart=iniFile.value ( "CmdStart").toString(); - CmdStop=iniFile.value ( "CmdStop" ).toString(); - CmdInit=iniFile.value ( "CmdInit" ).toString(); - CmdReset=iniFile.value ( "CmdReset" ).toString(); - CmdCenter=iniFile.value ( "CmdCenter" ).toString(); - CmdZero=iniFile.value ( "CmdZero" ).toString(); - - DelayInit=iniFile.value("DelayInit",0).toInt(); - DelayStart=iniFile.value("DelayStart",0).toInt(); - DelaySeq=iniFile.value("DelaySeq",0).toInt(); - -#ifdef OPENTRACK_API - FPSArduino=iniFile.value("FPSArduino",30).toInt(); -#endif - BigEndian=iniFile.value("BigEndian",0).toBool(); - - - pBaudRate=static_cast(iniFile.value("BaudRate",QSerialPort::Baud115200).toInt()); - pDataBits=static_cast(iniFile.value("DataBits",QSerialPort::Data8).toInt()); - pParity=static_cast(iniFile.value("Parity",QSerialPort::NoParity).toInt()); - pStopBits=static_cast(iniFile.value("StopBits",QSerialPort::OneStop).toInt()); - pFlowControl=static_cast(iniFile.value("FlowControl",QSerialPort::HardwareControl).toInt()); - - iniFile.endGroup(); -} - -void TrackerSettings::save_ini() const -{ - -#ifndef OPENTRACK_API - QSettings settings(OPENTRACK_ORG); // Registry settings (in HK_USER) - QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); -#else - QString currentFile = options::group::ini_pathname(); -#endif - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup ( "HAT" ); - - iniFile.setValue ( "PortName",SerialPortName ); - - iniFile.setValue( "EnableRoll", EnableRoll ); - iniFile.setValue( "EnablePitch", EnablePitch ); - iniFile.setValue( "EnableYaw", EnableYaw ); - iniFile.setValue( "EnableX", EnableX ); - iniFile.setValue( "EnableY", EnableY ); - iniFile.setValue( "EnableZ", EnableZ ); - iniFile.setValue( "EnableLogging", EnableLogging ); - - iniFile.setValue( "InvertRoll", InvertRoll ); - iniFile.setValue( "InvertPitch", InvertPitch ); - iniFile.setValue( "InvertYaw", InvertYaw ); - iniFile.setValue( "InvertX", InvertX ); - iniFile.setValue( "InvertY", InvertY ); - iniFile.setValue( "InvertZ", InvertZ ); - - iniFile.setValue ( "RollAxe", RollAxe ); - iniFile.setValue ( "PitchAxe", PitchAxe ); - iniFile.setValue ( "YawAxe",YawAxe ); - iniFile.setValue ( "XAxe", XAxe ); - iniFile.setValue ( "YAxe", YAxe ); - iniFile.setValue ( "ZAxe", ZAxe ); - - iniFile.setValue ( "CmdStart",CmdStart.toLatin1()); - iniFile.setValue ( "CmdStop",CmdStop.toLatin1()); - iniFile.setValue ( "CmdInit",CmdInit.toLatin1()); - iniFile.setValue ( "CmdReset",CmdReset.toLatin1()); - iniFile.setValue ( "CmdCenter",CmdCenter.toLatin1() ); - iniFile.setValue ( "CmdZero",CmdZero.toLatin1() ); - - iniFile.setValue ( "DelayInit",DelayInit); - iniFile.setValue ( "DelayStart",DelayStart); - iniFile.setValue ( "DelaySeq",DelaySeq); - -#ifdef OPENTRACK_API - iniFile.setValue ( "FPSArduino", FPSArduino ); -#endif - iniFile.setValue("BigEndian",BigEndian); - - iniFile.setValue("BaudRate",pBaudRate); - iniFile.setValue("DataBits",pDataBits); - iniFile.setValue("Parity",pParity); - iniFile.setValue("StopBits",pStopBits); - iniFile.setValue("FlowControl",pFlowControl); - - - iniFile.endGroup(); -} - diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.h b/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.h deleted file mode 100644 index ade46d54..00000000 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.h +++ /dev/null @@ -1,68 +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. - */ - -#ifndef FTNOIR_TRACKER_HAT_SETTINGS_H -#define FTNOIR_TRACKER_HAT_SETTINGS_H - -#include - -//----------------------------------------------------------------------------- -struct TrackerSettings -{ - void load_ini(); - void save_ini() const; - - bool EnableRoll; - bool EnablePitch; - bool EnableYaw; - bool EnableX; - bool EnableY; - bool EnableZ; - - bool InvertRoll; - bool InvertPitch; - bool InvertYaw; - bool InvertX; - bool InvertY; - bool InvertZ; - - - int RollAxe; - int PitchAxe; - int YawAxe; - int XAxe; - int YAxe; - int ZAxe; - - QString CmdStart; - QString CmdStop; - QString CmdInit; - QString CmdReset; - QString CmdCenter; - QString CmdZero; - - int DelayInit; - int DelayStart; - int DelaySeq; - - bool BigEndian; - bool EnableLogging; - - QString SerialPortName; - QSerialPort::BaudRate pBaudRate; - QSerialPort::DataBits pDataBits; - QSerialPort::Parity pParity; - QSerialPort::StopBits pStopBits; - QSerialPort::FlowControl pFlowControl; - -#ifdef OPENTRACK_API - int FPSArduino; -#endif -}; - - -#endif //FTNOIR_TRACKER_HAT_SETTINGS_H diff --git a/ftnoir_tracker_hatire/images/hat.ico b/ftnoir_tracker_hatire/images/hat.ico deleted file mode 100644 index d8f5aac4..00000000 Binary files a/ftnoir_tracker_hatire/images/hat.ico and /dev/null differ diff --git a/ftnoir_tracker_hatire/images/hat.png b/ftnoir_tracker_hatire/images/hat.png deleted file mode 100644 index a5f7852f..00000000 Binary files a/ftnoir_tracker_hatire/images/hat.png and /dev/null differ diff --git a/ftnoir_tracker_hatire/images/hat_logo.png b/ftnoir_tracker_hatire/images/hat_logo.png deleted file mode 100644 index c3a92b1b..00000000 Binary files a/ftnoir_tracker_hatire/images/hat_logo.png and /dev/null differ diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp deleted file mode 100644 index cc9d2ba1..00000000 --- a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include "headtracker-ftnoir.h" -#include "ftnoir_tracker_ht.h" -#include "ui_ht-trackercontrols.h" -#include "opentrack/plugin-api.hpp" -#include -#include "opentrack/camera-names.hpp" -#include "opentrack-compat/sleep.hpp" - -typedef struct { - int width; - int height; -} resolution_tuple; - -static resolution_tuple resolution_choices[] = { - { 640, 480 }, - { 320, 240 }, - { 320, 200 }, - { 0, 0 } -}; - -void Tracker::load_settings(ht_config_t* config) -{ - int nframes = 0; - switch (static_cast(s.fps)) - { - default: - case 0: - nframes = 0; - break; - case 1: - nframes = 30; - break; - case 2: - nframes = 60; - break; - case 3: - nframes = 120; - break; - case 4: - nframes = 180; - break; - } - - config->classification_delay = 500; - config->field_of_view = s.fov; - config->max_keypoints = 150; - config->keypoint_distance = 3.5; - config->force_fps = nframes; - config->camera_index = camera_name_to_index(s.camera_name); - - config->ransac_max_reprojection_error = 25; - config->ransac_max_inlier_error = config->ransac_max_reprojection_error; - - 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 = 1; - config->ransac_min_features = 0.95; - 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 = 50; - for (int i = 0; i < 5; i++) - config->dist_coeffs[i] = 0; -} - -Tracker::Tracker() : - ht(nullptr), - ypr {0,0,0, 0,0,0}, - videoWidget(nullptr), - layout(nullptr), - should_stop(false) -{ -} - -Tracker::~Tracker() -{ - should_stop = true; - wait(); - ht_free_context(ht); - if (layout) - delete layout; - if (videoWidget) - delete videoWidget; -} - -void Tracker::start_tracker(QFrame* videoframe) -{ - videoframe->show(); - videoWidget = new HTVideoWidget(videoframe); - QHBoxLayout* layout = new QHBoxLayout(); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(videoWidget); - if (videoframe->layout()) - delete videoframe->layout(); - videoframe->setLayout(layout); - videoWidget->show(); - this->layout = layout; - - 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(y, x); - const cv::Scalar elt2 = static_cast(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; - } - } - } - // give opencv time to exit camera threads, etc. - portable::sleep(500); -} - -void Tracker::data(double* data) -{ - { - QMutexLocker l(&frame_mtx); - - if (frame.width > 0) - { - videoWidget->update_image(frame.frame, frame.width, frame.height); - frame.width = 0; - } - } - - { - QMutexLocker l(&ypr_mtx); - - for (int i = 0; i < 6; i++) - data[i] = ypr[i]; - } -} - -TrackerControls::TrackerControls() : tracker(nullptr) -{ - ui.setupUi(this); - ui.cameraName->clear(); - QList names = get_camera_names(); - names.prepend("Any available"); - ui.cameraName->addItems(names); - tie_setting(s.camera_name, ui.cameraName); - tie_setting(s.fps, ui.cameraFPS); - tie_setting(s.fov, ui.cameraFOV); - tie_setting(s.resolution, ui.resolution); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings())); -} - -void TrackerControls::doOK() -{ - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() -{ - s.b->reload(); - this->close(); -} - -void TrackerControls::camera_settings() -{ - 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); -} - -OPENTRACK_DECLARE_TRACKER(Tracker, TrackerControls, TrackerDll) diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.h b/ftnoir_tracker_ht/ftnoir_tracker_ht.h deleted file mode 100644 index 1e364456..00000000 --- a/ftnoir_tracker_ht/ftnoir_tracker_ht.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2013 Stanislaw Halik - * - * 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 "headtracker-ftnoir.h" -#include "ui_ht-trackercontrols.h" -#include "ht_video_widget.h" -#include "opentrack-compat/shm.h" -#include -#include "opentrack/options.hpp" -#include "opentrack/plugin-api.hpp" -#include "opentrack/opencv-camera-dialog.hpp" - -#include -#include -#include -#include -#include - -using namespace options; - -struct settings : opts { - value fov; - value camera_name; - value fps, resolution; - settings() : - opts("HT-Tracker"), - fov(b, "fov", 56), - camera_name(b, "camera-name", ""), - fps(b, "fps", 0), - resolution(b, "resolution", 0) - {} -}; - -class Tracker : public QThread, public ITracker -{ - Q_OBJECT -public: - Tracker(); - ~Tracker() override; - void run() override; - void start_tracker(QFrame* frame) override; - void data(double *data) override; - void load_settings(ht_config_t* config); - headtracker_t* ht; - QMutex camera_mtx; -private: - double ypr[6]; - settings s; - ht_config_t conf; - HTVideoWidget* videoWidget; - QHBoxLayout* layout; - QMutex ypr_mtx, frame_mtx; - ht_video_t frame; - volatile bool should_stop; -}; - -class TrackerControls : public ITrackerDialog, protected camera_dialog -{ - Q_OBJECT -public: - TrackerControls(); - void register_tracker(ITracker * t) override - { - tracker = static_cast(t); - } - void unregister_tracker() override - { - tracker = nullptr; - } -private: - Ui::Form ui; - settings s; - Tracker* tracker; -private slots: - void doOK(); - void doCancel(); - void camera_settings(); -}; - -class TrackerDll : public Metadata -{ - QString name() { return QString("ht -- face tracker"); } - QIcon icon() { return QIcon(":/images/ht.png"); } -}; diff --git a/ftnoir_tracker_ht/headtracker-ftnoir.h b/ftnoir_tracker_ht/headtracker-ftnoir.h deleted file mode 100644 index 9a343bae..00000000 --- a/ftnoir_tracker_ht/headtracker-ftnoir.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include -#include "ht-api.h" - -#define HT_SHM_NAME "ftnoir-tracker-ht-shm" -#define HT_MUTEX_NAME "ftnoir-tracker-ht-mutex" - -#define HT_MAX_VIDEO_WIDTH 640 -#define HT_MAX_VIDEO_HEIGHT 480 -#define HT_MAX_VIDEO_CHANNELS 3 - -typedef struct { - int width, height, channels; - unsigned char frame[HT_MAX_VIDEO_WIDTH * HT_MAX_VIDEO_HEIGHT * HT_MAX_VIDEO_CHANNELS]; -} ht_video_t; - -typedef struct { - ht_video_t frame; - ht_config_t config; - ht_result_t result; - volatile int timer; - volatile bool pause, terminate, running; -} ht_shm_t; diff --git a/ftnoir_tracker_ht/ht-api.h b/ftnoir_tracker_ht/ht-api.h deleted file mode 100644 index 4629a00b..00000000 --- a/ftnoir_tracker_ht/ht-api.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#ifndef HT_API -# if defined(_WIN32) && !defined(MINGW) -# define HT_API(t) __declspec(dllexport) t __stdcall -# else -# define HT_API(t) t -# endif -#endif -#if !defined(_WIN32) && !defined(_isnan) -# define _isnan isnan -#endif -#include -#include -struct ht_context; -typedef struct ht_context headtracker_t; - -typedef struct ht_config { - float field_of_view; - float classification_delay; - int pyrlk_pyramids; - int pyrlk_win_size_w; - int pyrlk_win_size_h; - float ransac_max_inlier_error; - float ransac_max_reprojection_error; - int max_keypoints; - float keypoint_distance; - int force_width; - int force_height; - int force_fps; - int camera_index; - bool debug; - int ransac_num_iters; - float ransac_min_features; - float ransac_max_mean_error; - float ransac_abs_max_mean_error; - float flandmark_delay; - double dist_coeffs[5]; -} ht_config_t; - -typedef struct { - double rotx, roty, rotz; - double tx, ty, tz; - bool filled; -} ht_result_t; - -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(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/ht-tracker.qrc b/ftnoir_tracker_ht/ht-tracker.qrc deleted file mode 100644 index b6af7a18..00000000 --- a/ftnoir_tracker_ht/ht-tracker.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/ht.png - - diff --git a/ftnoir_tracker_ht/ht-trackercontrols.ui b/ftnoir_tracker_ht/ht-trackercontrols.ui deleted file mode 100644 index 29b80c8d..00000000 --- a/ftnoir_tracker_ht/ht-trackercontrols.ui +++ /dev/null @@ -1,157 +0,0 @@ - - - Form - - - Qt::NonModal - - - - 0 - 0 - 354 - 179 - - - - - 0 - 0 - - - - - 750 - 280 - - - - HT tracker settings - - - - - - Frames per second - - - - - - - - - - 35.000000000000000 - - - 180.000000000000000 - - - 52.000000000000000 - - - - - - - Diagonal FOV - - - - - - - - Default - - - - - 30 - - - - - 60 - - - - - 120 - - - - - 180 - - - - - - - - - - - - 640x480 - - - - - 320x240 - - - - - 320x200 - - - - - Default (not recommended!) - - - - - - - - Resolution - - - - - - - Camera name - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Camera settings - - - - - - - Open - - - - - - - - diff --git a/ftnoir_tracker_ht/ht_video_widget.cpp b/ftnoir_tracker_ht/ht_video_widget.cpp deleted file mode 100644 index 02fe71d1..00000000 --- a/ftnoir_tracker_ht/ht_video_widget.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2014 Stanislaw Halik - * - * 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 "ht_video_widget.h" - -void HTVideoWidget::update_image(unsigned char *frame, int width, int height) -{ - QMutexLocker foo(&mtx); - if (!fresh) - { - memcpy(fb, frame, width * height * 3); - this->width = width; - this->height = height; - fresh = true; - } -} - -void HTVideoWidget::update_and_repaint() -{ - QImage qframe; - { - QMutexLocker foo(&mtx); - if (width*height <= 0 || !fresh) - return; - fresh = false; - qframe = QImage(width, height, QImage::Format_RGB888); - uchar* data = qframe.bits(); - const int pitch = qframe.bytesPerLine(); - for (int y = 0; y < height; y++) - { - const int part = y*width; - for (int x = 0; x < width; x++) - { - const int pos = 3 * (part + x); - const int x_ = x * 3; - data[x_ + 0] = fb[pos + 2]; - data[x_ + 1] = fb[pos + 1]; - data[x_ + 2] = fb[pos + 0]; - } - data += pitch; - } - } - qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); - { - QMutexLocker foo(&mtx); - texture = qframe; - } - update(); -} diff --git a/ftnoir_tracker_ht/ht_video_widget.h b/ftnoir_tracker_ht/ht_video_widget.h deleted file mode 100644 index 054b2cf4..00000000 --- a/ftnoir_tracker_ht/ht_video_widget.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2014 Stanislaw Halik - * - * 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 -#include -#include -#include -#include -#include - -class HTVideoWidget : public QWidget -{ - Q_OBJECT -public: - HTVideoWidget(QWidget *parent) : QWidget(parent), fb(), width(0), height(0), fresh(false) { - connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); - timer.start(60); - } - void update_image(unsigned char* frame, int width, int height); -protected slots: - void paintEvent( QPaintEvent* e ) { - QMutexLocker foo(&mtx); - QPainter painter(this); - painter.drawImage(e->rect(), texture); - } - void update_and_repaint(); -private: - QMutex mtx; - QImage texture; - QTimer timer; - unsigned char fb[2048*2048*3]; - int width,height; - bool fresh; -}; diff --git a/ftnoir_tracker_ht/images/ht.png b/ftnoir_tracker_ht/images/ht.png deleted file mode 100644 index 19c73d21..00000000 Binary files a/ftnoir_tracker_ht/images/ht.png and /dev/null differ diff --git a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui deleted file mode 100644 index 7cfac075..00000000 --- a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui +++ /dev/null @@ -1,53 +0,0 @@ - - - UIHydraControls - - - Qt::NonModal - - - - 0 - 0 - 190 - 62 - - - - Sixense Hydra tracker settings FaceTrackNoIR - - - - images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png - - - Qt::LeftToRight - - - false - - - - - - None whatsoever - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp deleted file mode 100644 index 8d0e6832..00000000 --- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ -#include "ftnoir_tracker_hydra.h" -#include "opentrack/plugin-api.hpp" -#include -#ifdef _WIN32 -# define SIXENSE_STATIC_LIB -# define SIXENSE_UTILS_STATIC_LIB -#endif -#include - -Hydra_Tracker::Hydra_Tracker() : should_quit(false) {} - -#include - -Hydra_Tracker::~Hydra_Tracker() -{ - - sixenseExit(); -} - -void Hydra_Tracker::start_tracker(QFrame*) -{ - sixenseInit(); -} - -void Hydra_Tracker::data(double *data) -{ - - sixenseSetActiveBase(0); - sixenseAllControllerData acd; - sixenseGetAllNewestData( &acd ); - sixenseMath::Matrix4 mat = sixenseMath::Matrix4(acd.controllers[0].rot_mat); - - float ypr[3]; - - mat.getEulerAngles().fill(ypr); - data[TX] = acd.controllers[0].pos[0]/50.0; - data[TY] = acd.controllers[0].pos[1]/50.0; - data[TZ] = acd.controllers[0].pos[2]/50.0; - static constexpr double r2d = 57.295781; - data[Yaw] = ypr[0] * r2d; - data[Pitch] = ypr[1] * r2d; - data[Roll] = ypr[2] * r2d; -} - -OPENTRACK_DECLARE_TRACKER(Hydra_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h deleted file mode 100644 index 47a1eb9a..00000000 --- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h +++ /dev/null @@ -1,46 +0,0 @@ -#include "ui_ftnoir_hydra_clientcontrols.h" -#include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - settings() : - opts("tracker-hydra") - {} -}; - -class Hydra_Tracker : public ITracker -{ -public: - Hydra_Tracker(); - ~Hydra_Tracker(); - void start_tracker(QFrame *) override; - void data(double *data) override; - volatile bool should_quit; -private: - settings s; - QMutex mutex; -}; - -class TrackerControls: public ITrackerDialog -{ - Q_OBJECT -public: - TrackerControls(); - void register_tracker(ITracker *) {} - void unregister_tracker() {} -private: - settings s; - Ui::UIHydraControls ui; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_TrackerDll : public Metadata -{ -public: - QString name() { return QString("Razer Hydra -- inertial device"); } - QIcon icon() { return QIcon(":/images/facetracknoir.png"); } -}; - diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp deleted file mode 100644 index 2c23ee46..00000000 --- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "ftnoir_tracker_hydra.h" -#include "opentrack/plugin-api.hpp" - -TrackerControls::TrackerControls() -{ - ui.setupUi( this ); - - // Connect Qt signals to member-functions - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); -} - -void TrackerControls::doOK() { - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() { - s.b->reload(); - close(); -} - diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp deleted file mode 100644 index 77fd7241..00000000 --- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright (c) 2013 Stanislaw Halik - * - * 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_tracker_joystick.h" -#include "opentrack/plugin-api.hpp" -#include - -FTNoIR_Tracker::FTNoIR_Tracker() : - g_pDI(nullptr), - g_pJoystick(nullptr), - mtx(QMutex::Recursive), - iter(-1) -{ -} - -void FTNoIR_Tracker::reload() -{ - s.b->reload(); - QMutexLocker foo(&mtx); - if (g_pJoystick) - { - g_pJoystick->Unacquire(); - g_pJoystick->Release(); - } - if (g_pDI) - g_pDI->Release(); - - g_pJoystick = nullptr; - g_pDI = nullptr; - - start_tracker(frame); -} - -FTNoIR_Tracker::~FTNoIR_Tracker() -{ - if (g_pJoystick) - { - g_pJoystick->Unacquire(); - g_pJoystick->Release(); - } - if (g_pDI) - { - g_pDI->Release(); - } -} - -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, - VOID* pContext ) -{ - auto self = (FTNoIR_Tracker*) pContext; - - if( pdidoi->dwType & DIDFT_AXIS ) - { - DIPROPRANGE diprg = {0}; - diprg.diph.dwSize = sizeof( DIPROPRANGE ); - diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = pdidoi->dwType; - diprg.lMax = FTNoIR_Tracker::AXIS_MAX; - diprg.lMin = -FTNoIR_Tracker::AXIS_MAX; - - if( FAILED( self->g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) - return DIENUM_STOP; - - self->iter++; - } - - return self->iter == 8 ? DIENUM_STOP : DIENUM_CONTINUE; -} - -static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) -{ - auto self = reinterpret_cast(pContext); - bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid; - - if (stop) - { - if (self->guid_to_check.size()) - { - QString guid = guid_to_string(pdidInstance->guidInstance); - if (guid != self->guid_to_check) - { - return DIENUM_CONTINUE; - } - else - qDebug() << "guid ok" << self->guid_to_check; - } - - (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL); - qDebug() << "device" << static_cast(self->s.joyid); - } - - return stop ? DIENUM_STOP : DIENUM_CONTINUE; -} - -void FTNoIR_Tracker::start_tracker(QFrame* frame) -{ - QMutexLocker foo(&mtx); - this->frame = frame; - iter = 0; - auto hr = CoInitialize( nullptr ); - - if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, - IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) - { - qDebug() << "create"; - goto fail; - } - - guid_to_check = s.guid; - - if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "enum1"; - goto fail; - } - - if (!g_pJoystick && guid_to_check.size()) - { - guid_to_check = ""; - - if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "enum2"; - goto fail; - } - } - - if (!g_pJoystick) - { - qDebug() << "ENODEV"; - goto fail; - } - - if (FAILED(g_pJoystick->SetDataFormat(&c_dfDIJoystick))) - { - qDebug() << "format"; - goto fail; - } - - if (FAILED(g_pJoystick->SetCooperativeLevel((HWND) frame->window()->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) - { - qDebug() << "coop"; - goto fail; - } - - iter = 0; - - if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback, - ( VOID* )this, DIDFT_ALL ))) - { - qDebug() << "enum axes"; - goto fail; - } - - return; - -fail: - if (g_pJoystick) - g_pJoystick->Release(); - if (g_pDI) - g_pDI->Release(); - g_pJoystick = nullptr; - g_pDI = nullptr; - - qDebug() << "joy init failure"; -} - -void FTNoIR_Tracker::data(double *data) -{ - QMutexLocker foo(&mtx); - DIJOYSTATE js = {0}; - - if( !g_pDI || !g_pJoystick) - return; - - bool ok = false; - - for (int i = 0; i < 100; i++) - { - if (!FAILED(g_pJoystick->Poll())) - { - ok = true; - break; - } - if (g_pJoystick->Acquire() != DI_OK) - continue; - else - ok = true; - break; - } - - if (!ok) - return; - - HRESULT hr = 0; - - if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof( js ), &js ) ) ) - return; - - const LONG values[] = { - js.lX, - js.lY, - js.lZ, - js.lRx, - js.lRy, - js.lRz, - js.rglSlider[0], - js.rglSlider[1] - }; - - int map[6] = { - s.joy_1 - 1, - s.joy_2 - 1, - s.joy_3 - 1, - s.joy_4 - 1, - s.joy_5 - 1, - s.joy_6 - 1, - }; - - const double limits[] = { - 100, - 100, - 100, - 180, - 180, - 180 - }; - - for (int i = 0; i < 6; i++) - { - int k = map[i] - 1; - if (k < 0 || k >= 8) - data[i] = 0; - else - data[i] = values[k] * limits[i] / AXIS_MAX; - } -} - -OPENTRACK_DECLARE_TRACKER(FTNoIR_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h deleted file mode 100644 index 75305f07..00000000 --- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (c) 2013 Stanislaw Halik - * - * 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 "ui_ftnoir_tracker_joystick_controls.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#ifndef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x800 -#endif -#include -#include -#include -#include -#include -#include - -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value joyid, guid; - value joy_1, joy_2, joy_3, joy_4, joy_5, joy_6; - settings() : - opts("tracker-joystick"), - joyid(b, "joy-id", ""), - guid(b, "joy-guid", ""), - joy_1(b, "axis-map-1", 1), - joy_2(b, "axis-map-2", 2), - joy_3(b, "axis-map-3", 3), - joy_4(b, "axis-map-4", 4), - joy_5(b, "axis-map-5", 5), - joy_6(b, "axis-map-6", 6) - {} -}; - -template -QString guid_to_string(const GUID guid) -{ - char buf[40] = {0}; - wchar_t szGuidW[40] = {0}; - - StringFromGUID2(guid, szGuidW, 40); - WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); - - return QString(buf); -} - -class FTNoIR_Tracker : public ITracker -{ -public: - FTNoIR_Tracker(); - ~FTNoIR_Tracker(); - void start_tracker(QFrame *frame); - void data(double *data); - void reload(); - LPDIRECTINPUT8 g_pDI; - LPDIRECTINPUTDEVICE8 g_pJoystick; - QMutex mtx; - QFrame* frame; - DIDEVICEINSTANCE def; - int iter; // XXX bad style - settings s; - QString guid_to_check; - static constexpr int AXIS_MAX = 65535; -}; - -class TrackerControls: public ITrackerDialog -{ - Q_OBJECT -public: - TrackerControls(); - void register_tracker(ITracker *) {} - void unregister_tracker() {} - Ui::UIJoystickControls ui; - FTNoIR_Tracker* tracker; - settings s; - struct joys { - QString name; - QString guid; - }; - QList _joys; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_TrackerDll : public Metadata -{ -public: - QString name() { return QString("Joystick input"); } - QIcon icon() { return QIcon(":/images/facetracknoir.png"); } -}; - diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui deleted file mode 100644 index 88737023..00000000 --- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui +++ /dev/null @@ -1,492 +0,0 @@ - - - UIJoystickControls - - - Qt::NonModal - - - - 0 - 0 - 498 - 303 - - - - Tracker settings - - - - ../facetracknoir/images/facetracknoir.png../facetracknoir/images/facetracknoir.png - - - - 12 - - - 6 - - - 12 - - - 6 - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - - - - - 0 - 0 - - - - Device - - - - - - - - 0 - 0 - - - - - - - - - - - Mapping - - - - - - - 0 - 0 - - - - 1 - - - - Disabled - - - - - Joystick axis #1 - - - - - Joystick axis #2 - - - - - Joystick axis #3 - - - - - Joystick axis #4 - - - - - Joystick axis #5 - - - - - Joystick axis #6 - - - - - Joystick axis #7 - - - - - Joystick axis #8 - - - - - - - - - 0 - 0 - - - - 2 - - - - Disabled - - - - - Joystick axis #1 - - - - - Joystick axis #2 - - - - - Joystick axis #3 - - - - - Joystick axis #4 - - - - - Joystick axis #5 - - - - - Joystick axis #6 - - - - - Joystick axis #7 - - - - - Joystick axis #8 - - - - - - - - - 0 - 0 - - - - 3 - - - - Disabled - - - - - Joystick axis #1 - - - - - Joystick axis #2 - - - - - Joystick axis #3 - - - - - Joystick axis #4 - - - - - Joystick axis #5 - - - - - Joystick axis #6 - - - - - Joystick axis #7 - - - - - Joystick axis #8 - - - - - - - - - 0 - 0 - - - - 4 - - - - Disabled - - - - - Joystick axis #1 - - - - - Joystick axis #2 - - - - - Joystick axis #3 - - - - - Joystick axis #4 - - - - - Joystick axis #5 - - - - - Joystick axis #6 - - - - - Joystick axis #7 - - - - - Joystick axis #8 - - - - - - - - - 0 - 0 - - - - 5 - - - - Disabled - - - - - Joystick axis #1 - - - - - Joystick axis #2 - - - - - Joystick axis #3 - - - - - Joystick axis #4 - - - - - Joystick axis #5 - - - - - Joystick axis #6 - - - - - Joystick axis #7 - - - - - Joystick axis #8 - - - - - - - - - 0 - 0 - - - - 6 - - - - Disabled - - - - - Joystick axis #1 - - - - - Joystick axis #2 - - - - - Joystick axis #3 - - - - - Joystick axis #4 - - - - - Joystick axis #5 - - - - - Joystick axis #6 - - - - - Joystick axis #7 - - - - - Joystick axis #8 - - - - - - - - X - - - - - - - Y - - - - - - - Z - - - - - - - Yaw - - - - - - - Pitch - - - - - - - Roll - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - buttonBox - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp deleted file mode 100644 index 0463933f..00000000 --- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "ftnoir_tracker_joystick.h" -#include "opentrack/plugin-api.hpp" - -static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) -{ - auto self = ( TrackerControls* )pContext; - auto name = QString(pdidInstance->tszInstanceName); - auto guid = guid_to_string(pdidInstance->guidInstance); - TrackerControls::joys cur { name, guid }; - self->_joys.append(cur); - - self->ui.joylist->addItem(name + " " + guid); - - return DIENUM_CONTINUE; -} - -TrackerControls::TrackerControls() : tracker(nullptr) -{ - ui.setupUi( this ); - - // Connect Qt signals to member-functions - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - { - auto hr = CoInitialize( nullptr ); - LPDIRECTINPUT8 g_pDI = nullptr; - - if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, - IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) - goto fin; - - if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY ))) - goto fin; - -fin: - if (g_pDI) - g_pDI->Release(); - } - - tie_setting(s.joy_1, ui.joy_1); - tie_setting(s.joy_2, ui.joy_2); - tie_setting(s.joy_3, ui.joy_3); - tie_setting(s.joy_4, ui.joy_4); - tie_setting(s.joy_5, ui.joy_5); - tie_setting(s.joy_6, ui.joy_6); -} - -void TrackerControls::doOK() { - int idx = ui.joylist->currentIndex(); - joys def { "", "" }; - auto val = _joys.value(idx, def); - s.guid = val.guid; - s.joyid = val.name; - s.b->save(); - if (tracker) - tracker->reload(); - this->close(); -} - -void TrackerControls::doCancel() { - s.b->reload(); - this->close(); -} - - diff --git a/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui b/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui deleted file mode 100644 index 88575644..00000000 --- a/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui +++ /dev/null @@ -1,1220 +0,0 @@ - - - UICPTClientControls - - - Qt::NonModal - - - - 0 - 0 - 424 - 579 - - - - - 0 - 0 - - - - PointTracker Settings - - - - :/Resources/Logo_IR.png:/Resources/Logo_IR.png - - - Qt::LeftToRight - - - false - - - - QLayout::SetFixedSize - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - - - 0 - - - - Camera - - - - - - Camera settings - - - - - - - 0 - 0 - - - - FPS - - - fps_spin - - - - - - - - 0 - 0 - - - - Desired capture height - - - px - - - 2000 - - - 10 - - - - - - - - 0 - 0 - - - - Diagonal field of view - - - - - - - - 0 - 0 - - - - Width - - - - - - - ° - - - - - - 10 - - - 90 - - - - - - - - - - - - - - - 0 - 0 - - - - Dynamic pose resolution - - - - - - - Dynamic pose timeout - - - - - - - - 0 - 0 - - - - Desired capture framerate - - - Hz - - - 2000 - - - - - - - ms - - - 1 - - - 10000 - - - - - - - - 0 - 0 - - - - Height - - - - - - - - 0 - 0 - - - - Desired capture width - - - px - - - 2000 - - - 10 - - - - - - - - 0 - 0 - - - - 10 - - - - - - - - 0 - 0 - - - - Device - - - camdevice_combo - - - - - - - Camera settings dialog - - - - - - - - 0 - 0 - - - - Open - - - - - - - - - - Point extraction - - - - - - Max size - - - maxdiam_spin - - - - - - - Threshold - - - threshold_slider - - - - - - - Min size - - - mindiam_spin - - - - - - - Intensity threshold for point extraction - - - 255 - - - 1 - - - 127 - - - Qt::Horizontal - - - QSlider::TicksBothSides - - - 25 - - - - - - - Automatic threshold - - - - - - - Enable, slider sets point size - - - - - - - Maximum point diameter - - - px - - - 1 - - - 0.100000000000000 - - - - - - - Minimum point diameter - - - px - - - 1 - - - 0.100000000000000 - - - - - - - - - - - Model - - - - - - - 0 - 0 - - - - QTabWidget::Rounded - - - 0 - - - false - - - false - - - false - - - - Clip - - - - - - - 0 - 0 - - - - - 331 - 208 - - - - Model Dimensions - - - - - 70 - 35 - 100 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - 150 - 130 - 100 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - 65 - 55 - 71 - 111 - - - - - - - :/Resources/clip_side.png - - - - - - 20 - 40 - 46 - 13 - - - - Side - - - - - - 50 - 160 - 100 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - 150 - 70 - 100 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - 290 - 40 - 46 - 13 - - - - Front - - - - - - 300 - 70 - 21 - 111 - - - - - - - :/Resources/clip_front.png - - - - - - - - - Cap - - - - - - - 331 - 208 - - - - Model Dimensions - - - - - 100 - 60 - 111 - 81 - - - - - - - :/Resources/cap_side.png - - - - - - 20 - 40 - 46 - 13 - - - - Side - - - - - - 90 - 40 - 101 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - 220 - 100 - 81 - 81 - - - - - - - :/Resources/cap_front.png - - - - - - 240 - 70 - 81 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - 240 - 40 - 46 - 13 - - - - Front - - - - - - 20 - 90 - 81 - 22 - - - - mm - - - -65535 - - - 65535 - - - - - - - - - Custom - - - - - - Model Dimensions - - - - - - - 0 - 0 - - - - z: - - - - - - - mm - - - -65535 - - - 65535 - - - - - - - - 0 - 0 - - - - x: - - - - - - - mm - - - -65535 - - - 65535 - - - - - - - mm - - - -65535 - - - 65535 - - - - - - - mm - - - -65535 - - - 65535 - - - - - - - mm - - - -65535 - - - 65535 - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html> - - - - - - - mm - - - -65535 - - - 65535 - - - - - - - - 0 - 0 - - - - y: - - - - - - - - 0 - 0 - - - - x: - - - - - - - - 0 - 0 - - - - <html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html> - - - - - - - - 0 - 0 - - - - <html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html> - - - - - - - - 0 - 0 - - - - z: - - - - - - - - 0 - 0 - - - - y: - - - - - - - - - - - - - - - 0 - 0 - - - - Model position - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - 0 - 0 - - - - x: - - - - - - - mm - - - -65535 - - - 65536 - - - - - - - - 0 - 0 - - - - y: - - - - - - - mm - - - -65535 - - - 65536 - - - - - - - - 0 - 0 - - - - z: - - - - - - - mm - - - -65535 - - - 65536 - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - <html><head/><body><p><a href="https://github.com/opentrack/opentrack/wiki/model-calibration-for-PT-and-Aruco-trackers"><span style=" text-decoration: underline; color:#0000ff;">Instructions on the opentrack wiki</span></a></p></body></html> - - - true - - - - - - - false - - - Toggle calibration - - - true - - - - - - - - - - - - - - About - - - - - - <html><head/><body><p><span style=" font-weight:600;">FTNoIR PointTracker Plugin<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Patrick Ruoff</span></p><p><a href="http://ftnoirpt.sourceforge.net/"><span style=" font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - - - - :/Resources/Logo_IR.png - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - - - Status - - - - - - Extracted Points: - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Camera Info: - - - - - - - - 50 - 0 - - - - - - - - - - - - 0 - 0 - - - - - 120 - 0 - - - - - - - - - - - - - - tabWidget - camdevice_combo - res_x_spin - res_y_spin - fps_spin - fov - threshold_slider - model_tabs - clip_tlength_spin - clip_theight_spin - clip_bheight_spin - clip_blength_spin - cap_length_spin - cap_width_spin - cap_height_spin - m1x_spin - m1y_spin - m1z_spin - m2x_spin - m2y_spin - m2z_spin - tx_spin - ty_spin - tz_spin - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_pt/Resources/Logo_IR.png b/ftnoir_tracker_pt/Resources/Logo_IR.png deleted file mode 100644 index 95032a25..00000000 Binary files a/ftnoir_tracker_pt/Resources/Logo_IR.png and /dev/null differ diff --git a/ftnoir_tracker_pt/Resources/cap_front.png b/ftnoir_tracker_pt/Resources/cap_front.png deleted file mode 100644 index 14207a67..00000000 Binary files a/ftnoir_tracker_pt/Resources/cap_front.png and /dev/null differ diff --git a/ftnoir_tracker_pt/Resources/cap_side.png b/ftnoir_tracker_pt/Resources/cap_side.png deleted file mode 100644 index 5ad4ee65..00000000 Binary files a/ftnoir_tracker_pt/Resources/cap_side.png and /dev/null differ diff --git a/ftnoir_tracker_pt/Resources/clip_front.png b/ftnoir_tracker_pt/Resources/clip_front.png deleted file mode 100644 index 04880138..00000000 Binary files a/ftnoir_tracker_pt/Resources/clip_front.png and /dev/null differ diff --git a/ftnoir_tracker_pt/Resources/clip_side.png b/ftnoir_tracker_pt/Resources/clip_side.png deleted file mode 100644 index 72667ac7..00000000 Binary files a/ftnoir_tracker_pt/Resources/clip_side.png and /dev/null differ diff --git a/ftnoir_tracker_pt/camera.cpp b/ftnoir_tracker_pt/camera.cpp deleted file mode 100644 index 63b401a8..00000000 --- a/ftnoir_tracker_pt/camera.cpp +++ /dev/null @@ -1,145 +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. - */ - -#include "camera.h" -#include -#include -#include "opentrack-compat/sleep.hpp" - -void Camera::set_device_index(int index) -{ - if (desired_index != index) - { - desired_index = index; - _set_device_index(); - - // reset fps - dt_valid = 0; - dt_mean = 0; - active_index = index; - } -} - -void Camera::set_fps(int fps) -{ - if (cam_desired.fps != fps) - { - cam_desired.fps = fps; - _set_fps(); - } -} - -void Camera::set_res(int x_res, int y_res) -{ - if (cam_desired.res_x != x_res || cam_desired.res_y != y_res) - { - cam_desired.res_x = x_res; - cam_desired.res_y = y_res; - _set_res(); - } -} - -bool Camera::get_info(CamInfo& ret) -{ - if (cam_info.res_x == 0 || cam_info.res_y == 0) - { - return false; - } - ret = cam_info; - return true; -} - -bool Camera::get_frame(float dt, cv::Mat* frame) -{ - bool new_frame = _get_frame(frame); - // measure fps of valid frames - const float dt_smoothing_const = 0.95; - dt_valid += dt; - if (new_frame) - { - dt_mean = dt_smoothing_const * dt_mean + (1.0 - dt_smoothing_const) * dt_valid; - cam_info.fps = dt_mean > 1e-3 ? 1.0 / dt_mean : 0; - dt_valid = 0; - } - else - qDebug() << "pt camera: can't get frame"; - return new_frame; -} - -void CVCamera::start() -{ - stop(); - cap = new cv::VideoCapture(desired_index); - _set_res(); - _set_fps(); - // extract camera info - if (cap->isOpened()) - { - active_index = desired_index; - cam_info.res_x = 0; - cam_info.res_y = 0; - } else { - stop(); - } -} - -void CVCamera::stop() -{ - if (cap) - { - const bool opened = cap->isOpened(); - if (opened) - { - qDebug() << "pt: freeing camera"; - cap->release(); - } - delete cap; - cap = nullptr; - // give opencv time to exit camera threads, etc. - if (opened) - portable::sleep(500); - qDebug() << "pt camera: assuming stopped"; - } -} - -bool CVCamera::_get_frame(cv::Mat* frame) -{ - if (cap && cap->isOpened()) - { - cv::Mat img; - for (int i = 0; i < 100 && !cap->read(img); i++) - ;; - - if (img.empty()) - return false; - - *frame = img; - cam_info.res_x = img.cols; - cam_info.res_y = img.rows; - return true; - } - return false; -} - -void CVCamera::_set_fps() -{ - if (cap) cap->set(CV_CAP_PROP_FPS, cam_desired.fps); -} - -void CVCamera::_set_res() -{ - if (cap) - { - cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x); - cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); - } -} -void CVCamera::_set_device_index() -{ - if (desired_index != active_index) - stop(); -} diff --git a/ftnoir_tracker_pt/camera.h b/ftnoir_tracker_pt/camera.h deleted file mode 100644 index e73d9dff..00000000 --- a/ftnoir_tracker_pt/camera.h +++ /dev/null @@ -1,95 +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 -#include -#include -#include - -struct CamInfo -{ - CamInfo() : res_x(0), res_y(0), fps(0) {} - - int res_x; - int res_y; - int fps; -}; - -// ---------------------------------------------------------------------------- -// Base class for cameras, calculates the frame rate -class Camera -{ -public: - Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1) {} - virtual ~Camera() = 0; - - // start/stop capturing - virtual void start() = 0; - virtual void stop() = 0; - void restart() { stop(); start(); } - - // calls corresponding template methods and reinitializes frame rate calculation - void set_device_index(int index); - void set_fps(int fps); - void set_res(int x_res, int y_res); - - // gets a frame from the camera, dt: time since last call in seconds - bool get_frame(float dt, cv::Mat* frame); - - // WARNING: returned references are valid as long as object - bool get_info(CamInfo &ret); - CamInfo get_desired() const { return cam_desired; } - -protected: - // get a frame from the camera - virtual bool _get_frame(cv::Mat* frame) = 0; - - // update the camera using cam_desired, write res and f to cam_info if successful - virtual void _set_device_index() = 0; - virtual void _set_fps() = 0; - virtual void _set_res() = 0; -private: - float dt_valid; - float dt_mean; -protected: - int desired_index; - int active_index; - CamInfo cam_info; - CamInfo cam_desired; -}; -inline Camera::~Camera() {} - -// ---------------------------------------------------------------------------- -// camera based on OpenCV's videoCapture -class CVCamera : public Camera -{ -public: - CVCamera() : cap(NULL) {} - ~CVCamera() { stop(); } - - void start() override; - void stop() override; - - operator cv::VideoCapture*() { return cap; } - -protected: - bool _get_frame(cv::Mat* frame) override; - void _set_fps() override; - void _set_res() override; - void _set_device_index() override; -private: - cv::VideoCapture* cap; -}; - -enum RotationType -{ - CLOCKWISE = 0, - ZERO = 1, - COUNTER_CLOCKWISE = 2 -}; diff --git a/ftnoir_tracker_pt/doc/index.htm b/ftnoir_tracker_pt/doc/index.htm deleted file mode 100644 index 87b7356f..00000000 --- a/ftnoir_tracker_pt/doc/index.htm +++ /dev/null @@ -1,262 +0,0 @@ - - - - - FTNoIR PointTracker Help - - - - - - - - - - - - - - -
-

FaceTrackNoIR PointTracker Plugin

PointTracker Plugin Logo
- - -

About

-
-

-PointTracker is a plugin for the free head tracking software FaceTrackNoIR -which introduces the capability to track a (typically IR-) point model comprising 3 bright points to FaceTrackNoIR, -much like the popular free tracking software Freetrack does.
-It was created as a stable modular alternative to Freetrack, which has some stability issues with newer systems and seems to be no longer actively developped. -

-
- - -

Settings

-
-

-This section desribes the various settings of the PointTracker plugin in detail. -

- -Settings Pane 1 -
-
Show VideoWidget
Whether the video widget is updated or not. It may save some performance to turn this off when not needed
-
Sleep time
Time the tracking thread sleeps after each processed image. It's inverse should be below the framefrate you want to achieve. -(check the framerate in the status region when tracker is active, in case the sleep time is too high, the framerate will decrease). -Low values will result in more CPU-load.
-
Dynamic Pose Resolution
Whether the point correspondence and pose ambiquity is resolved using a more sophisticated dynamic algorithm (constant velocity prediction) or a simple static resolution. -Dynamic pose resolution can capture more extreme poses but may occasionally get stuck in a wrong pose estimates so that a reset of the internal state becomes neccessary.
-
Auto-reset time
If no valid tracking result can be found when using dynamic pose resolution, the tracker will automatically reset its internal state (used for resolving the pose ambiguity and point correspondence) -and return to a fail-safe initialization phase that assumes a neutral pose after this time. -Decrease this time, if you get stuck in a wrong pose too often.
-
Reset
Manually reset the trackers internal state used for dynamic pose resolution and return to a fail-safe initialization phase that assumes a neutral pose. -You may use this in case you get stuck in a wrong pose.
-
Enable Axis ...
Which axis to use for FTNoIR.
-
- -Settings Pane 2 -
-
Device
The camera used for tracking.
-
Resolution
The desired capture resolution. If your camera does not support the entered resolution the true output resolution may be different or even invalid. -You may check the true capture resolution in the status area while the tracker is running. A higher resolution results in more accurate point positions and will increase the -stability of the tracking result, as long as the signal/noise ratio is sufficiently high.
-
FPS
The desired capture framerate. Again, if your camera does not support the entered framerate, the true caputre framerate may be different or invalid. -You may check the true processing framerate in the status area while the tracker is running.
-
F/W
The focal length of the camera divided by the sensor width (of course in the same units). -In case you don't have access to your camera's specifications, you can measure this yourself by placing a plane object of known width (for example a piece of cardboard) in front of the camera until it fills the whole image width. -Then measure the distance between the object and the camera and divide by the object width.
-
VideoWidget
Shows a resizable stand-alone video widget that shows the same content as the integrated video widget in FTNoIR. -Update rate is only 10 fps and may lag behind a bit. Mainly useful during calibration of the point extraction. Same as for the integrated wiget, to save resources, this widget should only be shown when needed.
-
Roll Pitch Yaw...
The orientation of the camera relative to the reference frame. -If these angles are setup properly, the direction of translations may not be correct. -Roll is treated in a special way since it is implemented as a frame rotation by +/- 90 deg that is transparent to the rest of the processing pipeline. -
-
Threshold
The threshold for point recognition. Areas above the threshold are shown in blue in the VideoWidget. -Since point accuracy is best if the points are as big as possible in pixels, the theshold should be chosen as low as possible (stop before the contour of the points becomes "noisy"). -If small reflections are being falsely classified as points, increasing the minimum point diameter (see below) may help.
-
Min Diameter
Minimum diameter of blobs to be classified as a pointmodel-point.
-
Max Diameter
Maximum diameter of blobs to be classified as a pointmodel-point.
-
Status
The tracker's status is shown in this area while the tracker is running. -The FPS shown here correspond to the framerate of the whole tracker processing chain and may be lower than what your camera is able to provide, when
-1. The processing gets not enough CPU time
-2. The sleep time of the tracking thread is set too high
-
- -Settings Pane 3 -
-
Model Selection and Dimensions ...
-First select your model type (point, clip, custom), then enter the dimensions of your model in milimeters here.
-For the custom setting, the coordinates of the two remaining model points have to be entered (reference point M0 is at (0,0,0)) in a pose where the model roughly faces the camera. -For orientation, the coordinates for the standard Freetrack clip are (0,40,-30), (0,-70,-80) and the ones for the cap (40,-60,-100), (-40,-60,-100).
-When using a custom point-model configuration, the following restrictions should be observed:
-The plane in which the 3 points lie should never be parallel to the image plane, M0-M1 and M0-M2 should be roughly perpendicular.
- -
Model Position
The vector from the model to the center of the head in the model frame. Can be calibrated automatically.
-
Calibrate
In order to automatically calibrate the model-head offset, do the following:
Press the Calibrate button, then look around while not moving your shoulder. (i.e. only rotation, no translation). -Do not stay in one pose for too long. The current translation estimate will be updated in real time. As soon as the values stabilized sufficiently, press the Calibrate button again to stop the calibration process.
-
-
- - -

Filter Setup

-
-

-This section desribes how the FTNoIR filter work and what the recommended settings for PointTracker are. -

-

-Filtering is always a tradeoff between stability, accuracy and responsiveness. -

-

-The Smoothing filter in FTNoIR is just a simple average over the last n samples. -Since this filter produces input lag no matter how fast the head-movements are, it is recommended to turn it off by setting samples to 1. -

-

-In the filter tab, it is recommended to select Accela Filter Mk2. -Accela is a non-linear filter that works as follows:
-It looks at the difference between the new raw values new_val from the tracker and the last filtered value old_val -and maps this difference via the customizable response function f via:
-

-

-new_val = old_val + f(new_val - old_val) / reduction_factor -

-

-So by setting f(x) = reduction_factor * x, one will get no filtering at all.
-If you set lower values for small x, small deviations (usually noise) will get dampened. -This results in a dynamic dead-zone around the current position. -

-

-The last two points are used by accela to extrapolate for large deviations. -So in order to get a fast unfiltered response for large deviations, the line connecting the last two points should have a slope >= reduction_factor. -

-

-More aggressive accela settings than the default FTNoIR accela settings are recommended in order to decrease the filtering lag and fully use the potential of point tracking.
-My current settings are: -

-

-[Accela]
-Reduction=20
-
-[Curves-Accela-Scaling-Rotation]
-point-count=4
-point-0-x=0.1
-point-0-y=0
-point-1-x=1.43
-point-1-y=2.45
-point-2-x=2.0
-point-2-y=5.44
-point-3-x=2.06
-point-3-y=6
-
-

-The curve is not too different from the standard one (except that I like a small dynamic dead zone for steady aiming, that's why the curve has a slope of 0 at the beginning).
-However, the reduction factor is decreased to a value of 20 (compared to the standard value of 100). This implies that each value of the curve is effectively 5 times higher than in standard FTNoIR (see formula above), which means higher responsiveness but can also lead to jitter/shaking.
-Keep in mind that there are no best filter settings. Since filtering is always a compromise it's a matter of personal taste and -playing around with the filter settings is highly recommended. -

-
- - -

Support

-
-

-For questions/feedback about the plugin, post to the FTNoIR-Forum.
-In case you like this plugin and would like to support the author, you may consider making a donation. -

-
-
-
- - - - -
-
-
-
- - -

ChangeLog

-
-

1.1

-
    -
  • Added camera yaw and roll correction (intended for vertically mounted cameras)
  • -
  • Improved point extraction algorithm, thanks to Michael Welter
  • -
  • UI improvements: Select camera by device name, different VideoWidget architecture
  • -
  • Bugfixes: Removed 99 FPS limitation
  • -
- -

1.0

-
    -
  • Added camera pitch correction
  • -
  • Better communication with FTNoIR: output axis configuration, status report
  • -
- -

1.0 beta

-
    -
  • Switchted to videoInput library for capture. Desired capture resolution and fps can now be customized
  • -
  • Introduced dynamic point-correspondence and POSIT-ambiguity resolution, which allows for the reconstruction of more extreme poses
  • -
  • More convenient freetrack-like model dimension GUI
  • -
  • Bugfixes: VideoWidget skipping frames, Timer resolution too low for accurate FPS measurement
  • -
-
- - -

Build Instructions

-
-

-This section describes what you need to do in order to build PointTracker yourself.
-You can find the sources at the project site -or as part of the FTNoIR sources. -

-

The project was created with Visual Studio.

- -

Dependencies

-
    -
  • Qt 4.8.2 library
  • -
  • Qt plugin for Visual studio
  • -
  • OpenCV 2.4 prebuilt for Windows
  • -
  • Boost 1.47
  • -
- -

Details

-
-

Common

-
    -
  • setup environment variable "QTDIR" (example value "D:\Devel\Libs\Qt\4.8.2")
  • -
  • add "%QTDIR%\bin" to PATH
  • -
  • setup environment variable "BOOST_DIR" (example value "D:\Devel\Libs\boost_1_47_0")
  • -
  • setup environment variable "OPENCV_DIR" (example value "D:\Devel\Libs\opencv\build")
  • -
-

Debug

-

opencv linked dynamically:

-
    -
  • add "%OPENCV_DIR%\x86\vc9\bin" to PATH
  • -
-

(in case of different Visual studio, change PATH and linker dependencies accordingly)

-

Release

-

opencv linked statically:

-
    -
  • custom build a statically linked version of opencv with the buil-option BUILD_WITH_STATIC_CRT set to OFF!
  • -
  • copy resulting libaries to "%OPENCV_DIR%\x86\vc9\static_lib"
  • -
-

(in case of different Visual studio, change PATH and linker dependencies accordingly)

-
-
- -
- - - \ No newline at end of file diff --git a/ftnoir_tracker_pt/doc/logo.png b/ftnoir_tracker_pt/doc/logo.png deleted file mode 100644 index 95032a25..00000000 Binary files a/ftnoir_tracker_pt/doc/logo.png and /dev/null differ diff --git a/ftnoir_tracker_pt/doc/ptrack.ico b/ftnoir_tracker_pt/doc/ptrack.ico deleted file mode 100644 index c4b2aedc..00000000 Binary files a/ftnoir_tracker_pt/doc/ptrack.ico and /dev/null differ diff --git a/ftnoir_tracker_pt/doc/settings1.png b/ftnoir_tracker_pt/doc/settings1.png deleted file mode 100644 index 35b84c5c..00000000 Binary files a/ftnoir_tracker_pt/doc/settings1.png and /dev/null differ diff --git a/ftnoir_tracker_pt/doc/settings2.png b/ftnoir_tracker_pt/doc/settings2.png deleted file mode 100644 index c6cfd1f3..00000000 Binary files a/ftnoir_tracker_pt/doc/settings2.png and /dev/null differ diff --git a/ftnoir_tracker_pt/doc/settings3.png b/ftnoir_tracker_pt/doc/settings3.png deleted file mode 100644 index 5922403d..00000000 Binary files a/ftnoir_tracker_pt/doc/settings3.png and /dev/null differ diff --git a/ftnoir_tracker_pt/doc/style.css b/ftnoir_tracker_pt/doc/style.css deleted file mode 100644 index 0c3d29a6..00000000 --- a/ftnoir_tracker_pt/doc/style.css +++ /dev/null @@ -1,131 +0,0 @@ -body { - width: 1000px; - font-size: 13px; - color: #000000; - padding: 0; - margin: 0 auto; - background: #444444; - font-family: verdana,arial; -} - -table { - border-width: 3px; - border-color: #0000FF; - border-style: ridge; - margin-top: 5px; - background-color: #E0E0FF; -} - -table.blind { - border: none; - background-color: #E6E6E6; -} - -fieldset.blind { - border: none; -} - -h1 { font-size: 160%; } -h2 { font-size: 140%; } -h3 { font-size: 115%; } - -.indent { - margin-left: 25px; -} - -p -{ - margin-left: 10px; -} - -li -{ - margin: 10px; -} - - -dl -{ - /*width: 80%;*/ - border-bottom: 1px solid #999; -} - -dt -{ - padding-top: 5px; - font-weight: bold; - border-top: 1px solid #999; -} - -dd -{ - padding: 5px; -} - - -hr { - color: #688938; -} - -a:link, a:visited { - color: #0000BF; -} -a:hover { - color: #0000FF; -} - -a.nav { - position: relative; - top: -30px; - display: block; - visibility: hidden; -} - -#navbar { - width: 1000px; - height: 30px; - background-color:#1a1a1b; - position: fixed; - margin: 0 auto; - padding: 0; -} - -#navbar ul -{ - list-style-type: none; - margin: 0 auto; - padding: 0; - overflow: hidden; -} - -#navbar li -{ - margin: 0 auto; - padding: 5px; - float:left; -} - -#navbar a:link,a:visited -{ - display:block; - width:150px; - font-weight:bold; - color:#e85d02; - text-align:center; - /*padding:4px;*/ - text-decoration:none; - /*text-transform:uppercase;*/ -} - -#navbar a:hover,a:active -{ - color:#ffffff; -} - -#content { - background-color:#ffffff; - padding: 15px; - padding-top: 40px; - padding-right: 40px; - margin: 0 auto; -} diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp deleted file mode 100644 index 15a60962..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (c) 2012 Patrick Ruoff - * Copyright (c) 2014-2015 Stanislaw Halik - * - * 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_tracker_pt.h" -#include -#include -#include -#include -#include -#include "opentrack/camera-names.hpp" - -//#define PT_PERF_LOG //log performance - -//----------------------------------------------------------------------------- -Tracker_PT::Tracker_PT() - : mutex(QMutex::Recursive), - commands(0), - video_widget(NULL), - video_frame(NULL), - ever_success(false) -{ - connect(s.b.get(), SIGNAL(saving()), this, SLOT(apply_settings())); -} - -Tracker_PT::~Tracker_PT() -{ - set_command(ABORT); - wait(); - delete video_widget; - video_widget = NULL; - if (video_frame->layout()) delete video_frame->layout(); - camera.stop(); -} - -void Tracker_PT::set_command(Command command) -{ - //QMutexLocker lock(&mutex); - commands |= command; -} - -void Tracker_PT::reset_command(Command command) -{ - //QMutexLocker lock(&mutex); - commands &= ~command; -} - -bool Tracker_PT::get_focal_length(float& ret) -{ - QMutexLocker l(&camera_mtx); - CamInfo info; - const bool res = camera.get_info(info); - if (res) - { - static constexpr double pi = 3.14159265359; - const int w = info.res_x, h = info.res_y; - const double diag = sqrt(1. + h/(double)w * h/(double)w); - const double diag_fov = static_cast(s.fov) * pi / 180.; - const double fov = 2.*atan(tan(diag_fov/2.0)/diag); - ret = .5 / tan(.5 * fov); - return true; - } - return false; -} - -void Tracker_PT::run() -{ -#ifdef PT_PERF_LOG - QFile log_file(QCoreApplication::applicationDirPath() + "/PointTrackerPerformance.txt"); - if (!log_file.open(QIODevice::WriteOnly | QIODevice::Text)) return; - QTextStream log_stream(&log_file); -#endif - - apply_settings(); - - while((commands & ABORT) == 0) - { - const double dt = time.elapsed() * 1e-9; - time.start(); - cv::Mat frame; - bool new_frame; - - { - QMutexLocker l(&camera_mtx); - new_frame = camera.get_frame(dt, &frame); - } - - if (new_frame && !frame.empty()) - { - QMutexLocker lock(&mutex); - - std::vector points = point_extractor.extract_points(frame); - - // blobs are sorted in order of circularity - if (points.size() > PointModel::N_POINTS) - points.resize(PointModel::N_POINTS); - - bool success = points.size() == PointModel::N_POINTS; - - float fx; - if (!get_focal_length(fx)) - continue; - - if (success) - { - point_tracker.track(points, PointModel(s), fx, s.dynamic_pose, s.init_phase_timeout); - } - - Affine X_CM = pose(); - - ever_success |= success; - - { - Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below - Affine X_GH = X_CM * X_MH; - cv::Vec3f p = X_GH.t; // head (center?) position in global space - cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx); // projected to screen - points.push_back(p_); - } - - for (unsigned i = 0; i < points.size(); i++) - { - auto& p = points[i]; - auto p2 = cv::Point(p[0] * frame.cols + frame.cols/2, -p[1] * frame.cols + frame.rows/2); - cv::Scalar color(0, 255, 0); - if (i == points.size()-1) - color = cv::Scalar(0, 0, 255); - cv::line(frame, - cv::Point(p2.x - 20, p2.y), - cv::Point(p2.x + 20, p2.y), - color, - 4); - cv::line(frame, - cv::Point(p2.x, p2.y - 20), - cv::Point(p2.x, p2.y + 20), - color, - 4); - } - - video_widget->update_image(frame); - } -#ifdef PT_PERF_LOG - log_stream<<"dt: "<video_frame = parent_window; - video_frame->setAttribute(Qt::WA_NativeWindow); - video_frame->show(); - video_widget = new PTVideoWidget(video_frame); - QHBoxLayout* video_layout = new QHBoxLayout(parent_window); - video_layout->setContentsMargins(0, 0, 0, 0); - video_layout->addWidget(video_widget); - video_frame->setLayout(video_layout); - video_widget->resize(video_frame->width(), video_frame->height()); - start(); -} - -void Tracker_PT::data(double *data) -{ - if (ever_success) - { - Affine X_CM = pose(); - - Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); - Affine X_GH = X_CM * X_MH; - - cv::Matx33f R = X_GH.R; - cv::Vec3f t = X_GH.t; - - // translate rotation matrix from opengl (G) to roll-pitch-yaw (E) frame - // -z -> x, y -> z, x -> -y - cv::Matx33f R_EG(0, 0,-1, - -1, 0, 0, - 0, 1, 0); - R = R_EG * R * R_EG.t(); - - // extract rotation angles - float alpha, beta, gamma; - beta = atan2( -R(2,0), sqrt(R(2,1)*R(2,1) + R(2,2)*R(2,2)) ); - alpha = atan2( R(1,0), R(0,0)); - gamma = atan2( R(2,1), R(2,2)); - - // extract rotation angles - data[Yaw] = rad2deg * alpha; - data[Pitch] = -rad2deg * beta; - data[Roll] = rad2deg * gamma; - // get translation(s) - data[TX] = t[0] / 10.0; // convert to cm - data[TY] = t[1] / 10.0; - data[TZ] = t[2] / 10.0; - } -} - -#include "ftnoir_tracker_pt_dialog.h" -OPENTRACK_DECLARE_TRACKER(Tracker_PT, TrackerDialog_PT, TrackerDll) - diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.h b/ftnoir_tracker_pt/ftnoir_tracker_pt.h deleted file mode 100644 index f73d106b..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.h +++ /dev/null @@ -1,86 +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. - */ - -#ifndef FTNOIR_TRACKER_PT_H -#define FTNOIR_TRACKER_PT_H - -#include "opentrack/plugin-api.hpp" -#include "ftnoir_tracker_pt_settings.h" -#include "camera.h" -#include "point_extractor.h" -#include "point_tracker.h" -#include "pt_video_widget.h" -#include "opentrack-compat/timer.hpp" -#include "opentrack/opencv-camera-dialog.hpp" - -#include -#include -#include -#include -#include -#include -#include - -class TrackerDialog_PT; - -//----------------------------------------------------------------------------- -// Constantly processes the tracking chain in a separate thread -class Tracker_PT : public QThread, public ITracker -{ - Q_OBJECT - friend class camera_dialog; - friend class TrackerDialog_PT; -public: - Tracker_PT(); - ~Tracker_PT() override; - void start_tracker(QFrame* parent_window) override; - void data(double* data) override; - - Affine pose() { QMutexLocker lock(&mutex); return point_tracker.pose(); } - int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); } - bool get_cam_info(CamInfo* info) { QMutexLocker lock(&camera_mtx); return camera.get_info(*info); } -public slots: - void apply_settings(); -protected: - void run() override; -private: - QMutex mutex; - // thread commands - enum Command { - ABORT = 1<<0 - }; - void set_command(Command command); - void reset_command(Command command); - - bool get_focal_length(float &ret); - - volatile int commands; - - QMutex camera_mtx; - CVCamera camera; - PointExtractor point_extractor; - PointTracker point_tracker; - - PTVideoWidget* video_widget; - QFrame* video_frame; - - settings_pt s; - Timer time; - - volatile bool ever_success; - - static constexpr double rad2deg = 180.0/3.14159265; - static constexpr double deg2rad = 3.14159265/180.0; -}; - -class TrackerDll : public Metadata -{ - QString name() { return QString("PointTracker 1.1"); } - QIcon icon() { return QIcon(":/Resources/Logo_IR.png"); } -}; - -#endif // FTNOIR_TRACKER_PT_H diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc b/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc deleted file mode 100644 index a8f9a1af..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc +++ /dev/null @@ -1,9 +0,0 @@ - - - Resources/cap_front.png - Resources/cap_side.png - Resources/clip_front.png - Resources/clip_side.png - Resources/Logo_IR.png - - diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp deleted file mode 100644 index b1ae2238..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright (c) 2012 Patrick Ruoff - * Copyright (c) 2014-2015 Stanislaw Halik - * - * 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_tracker_pt_dialog.h" - -#include -#include -#include -#include -#include "opentrack/camera-names.hpp" -#include - -//----------------------------------------------------------------------------- -TrackerDialog_PT::TrackerDialog_PT() - : tracker(NULL), - timer(this), - trans_calib_running(false) -{ - ui.setupUi( this ); - - ui.camdevice_combo->addItems(get_camera_names()); - - tie_setting(s.camera_name, ui.camdevice_combo); - tie_setting(s.cam_res_x, ui.res_x_spin); - tie_setting(s.cam_res_y, ui.res_y_spin); - tie_setting(s.cam_fps, ui.fps_spin); - - tie_setting(s.threshold, ui.threshold_slider); - - tie_setting(s.min_point_size, ui.mindiam_spin); - tie_setting(s.max_point_size, ui.maxdiam_spin); - - tie_setting(s.clip_by, ui.clip_bheight_spin); - tie_setting(s.clip_bz, ui.clip_blength_spin); - tie_setting(s.clip_ty, ui.clip_theight_spin); - tie_setting(s.clip_tz, ui.clip_tlength_spin); - - tie_setting(s.cap_x, ui.cap_width_spin); - tie_setting(s.cap_y, ui.cap_height_spin); - tie_setting(s.cap_z, ui.cap_length_spin); - - tie_setting(s.m01_x, ui.m1x_spin); - tie_setting(s.m01_y, ui.m1y_spin); - tie_setting(s.m01_z, ui.m1z_spin); - - tie_setting(s.m02_x, ui.m2x_spin); - tie_setting(s.m02_y, ui.m2y_spin); - tie_setting(s.m02_z, ui.m2z_spin); - - tie_setting(s.t_MH_x, ui.tx_spin); - tie_setting(s.t_MH_y, ui.ty_spin); - tie_setting(s.t_MH_z, ui.tz_spin); - - tie_setting(s.fov, ui.fov); - - tie_setting(s.active_model_panel, ui.model_tabs); - - tie_setting(s.dynamic_pose, ui.dynamic_pose); - tie_setting(s.init_phase_timeout, ui.init_phase_timeout); - - tie_setting(s.auto_threshold, ui.auto_threshold); - - connect( ui.tcalib_button,SIGNAL(toggled(bool)), this,SLOT(startstop_trans_calib(bool)) ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info())); - connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings())); - timer.start(100); -} - -void TrackerDialog_PT::camera_settings() -{ - if (tracker) - open_camera_settings(static_cast(tracker->camera), s.camera_name, &tracker->camera_mtx); - else - open_camera_settings(nullptr, s.camera_name, nullptr); -} - -void TrackerDialog_PT::startstop_trans_calib(bool start) -{ - if (start) - { - qDebug()<<"TrackerDialog:: Starting translation calibration"; - trans_calib.reset(); - trans_calib_running = true; - s.t_MH_x = 0; - s.t_MH_y = 0; - s.t_MH_z = 0; - } - else - { - qDebug()<<"TrackerDialog:: Stopping translation calibration"; - trans_calib_running = false; - { - auto tmp = trans_calib.get_estimate(); - s.t_MH_x = tmp[0]; - s.t_MH_y = tmp[1]; - s.t_MH_z = tmp[2]; - } - } -} - -void TrackerDialog_PT::poll_tracker_info() -{ - CamInfo info; - if (tracker && tracker->get_cam_info(&info)) - { - QString to_print; - { - // display caminfo - to_print = QString::number(info.res_x)+"x"+QString::number(info.res_y)+" @ "+QString::number(info.fps)+" FPS"; - } - ui.caminfo_label->setText(to_print); - - // display pointinfo - int n_points = tracker->get_n_points(); - to_print = QString::number(n_points); - if (n_points == 3) - to_print += " OK!"; - else - to_print += " BAD!"; - ui.pointinfo_label->setText(to_print); - - // update calibration - if (trans_calib_running) trans_calib_step(); - } - else - { - ui.caminfo_label->setText("Tracker offline"); - ui.pointinfo_label->setText(""); - } -} - -void TrackerDialog_PT::trans_calib_step() -{ - if (tracker) - { - Affine X_CM = tracker->pose(); - trans_calib.update(X_CM.R, X_CM.t); - } -} - -void TrackerDialog_PT::save() -{ - s.b->save(); -} - -void TrackerDialog_PT::doOK() -{ - save(); - close(); -} - -void TrackerDialog_PT::doCancel() -{ - s.b->reload(); - close(); -} - -void TrackerDialog_PT::register_tracker(ITracker *t) -{ - qDebug()<<"TrackerDialog:: Tracker registered"; - tracker = static_cast(t); - ui.tcalib_button->setEnabled(true); - //ui.center_button->setEnabled(true); -} - -void TrackerDialog_PT::unregister_tracker() -{ - qDebug()<<"TrackerDialog:: Tracker un-registered"; - tracker = NULL; - ui.tcalib_button->setEnabled(false); - //ui.center_button->setEnabled(false); -} - diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h deleted file mode 100644 index 3502e227..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h +++ /dev/null @@ -1,51 +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. - */ - -#ifndef FTNOIR_TRACKER_PT_DIALOG_H -#define FTNOIR_TRACKER_PT_DIALOG_H - -#include "opentrack/plugin-api.hpp" -#include "ftnoir_tracker_pt_settings.h" -#include "ftnoir_tracker_pt.h" -#include "trans_calib.h" -#include "pt_video_widget.h" -#include "ui_FTNoIR_PT_Controls.h" -#include "opentrack/opencv-camera-dialog.hpp" - -#include - -//----------------------------------------------------------------------------- -// The dialog that shows up when the user presses "Settings" -class TrackerDialog_PT : public ITrackerDialog, protected camera_dialog -{ - Q_OBJECT -public: - TrackerDialog_PT(); - void register_tracker(ITracker *tracker) override; - void unregister_tracker() override; - void save(); - void trans_calib_step(); - -public slots: - void doOK(); - void doCancel(); - - void startstop_trans_calib(bool start); - void poll_tracker_info(); - void camera_settings(); -private: - settings_pt s; - Tracker_PT* tracker; - QTimer timer; - - TranslationCalibrator trans_calib; - bool trans_calib_running; - - Ui::UICPTClientControls ui; -}; - -#endif //FTNOIR_TRACKER_PT_DIALOG_H diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h deleted file mode 100644 index 85eec8f9..00000000 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2012 Patrick Ruoff - * Copyright (c) 2014-2015 Stanislaw Halik - * - * 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. - */ - -#ifndef FTNOIR_TRACKER_PT_SETTINGS_H -#define FTNOIR_TRACKER_PT_SETTINGS_H - -#include "opentrack/options.hpp" -using namespace options; - -struct settings_pt : opts -{ - value camera_name; - value cam_res_x, - cam_res_y, - cam_fps, - threshold; - value min_point_size, max_point_size; - - value m01_x, m01_y, m01_z; - value m02_x, m02_y, m02_z; - - value t_MH_x, t_MH_y, t_MH_z; - - value clip_ty, clip_tz, clip_by, clip_bz; - value active_model_panel, cap_x, cap_y, cap_z; - - value fov; - - value dynamic_pose; - value init_phase_timeout; - value auto_threshold; - - settings_pt() : - opts("tracker-pt"), - camera_name(b, "camera-name", ""), - cam_res_x(b, "camera-res-width", 640), - cam_res_y(b, "camera-res-height", 480), - cam_fps(b, "camera-fps", 30), - threshold(b, "threshold-primary", 128), - min_point_size(b, "min-point-size", 1), - max_point_size(b, "max-point-size", 50), - m01_x(b, "m_01-x", 0), - m01_y(b, "m_01-y", 0), - m01_z(b, "m_01-z", 0), - m02_x(b, "m_02-x", 0), - m02_y(b, "m_02-y", 0), - m02_z(b, "m_02-z", 0), - t_MH_x(b, "model-centroid-x", 0), - t_MH_y(b, "model-centroid-y", 0), - t_MH_z(b, "model-centroid-z", 0), - clip_ty(b, "clip-ty", 40), - clip_tz(b, "clip-tz", 30), - clip_by(b, "clip-by", 70), - clip_bz(b, "clip-bz", 80), - active_model_panel(b, "active-model-panel", 0), - cap_x(b, "cap-x", 40), - cap_y(b, "cap-y", 60), - cap_z(b, "cap-z", 100), - fov(b, "camera-fov", 56), - dynamic_pose(b, "dynamic-pose-resolution", true), - init_phase_timeout(b, "init-phase-timeout", 500), - auto_threshold(b, "automatic-threshold", false) - {} -}; - -#endif //FTNOIR_TRACKER_PT_SETTINGS_H diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp deleted file mode 100644 index ec37dd00..00000000 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (c) 2012 Patrick Ruoff - * Copyright (c) 2014-2015 Stanislaw Halik - * - * 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 "point_extractor.h" -#include - -#ifdef DEBUG_EXTRACTION -# include "opentrack-compat/timer.hpp" -#endif - -PointExtractor::PointExtractor(){ - //if (!AllocConsole()){} - //else SetConsoleTitle("debug"); - //freopen("CON", "w", stdout); - //freopen("CON", "w", stderr); -} -// ---------------------------------------------------------------------------- -std::vector PointExtractor::extract_points(cv::Mat& frame) -{ - const int W = frame.cols; - const int H = frame.rows; - - // convert to grayscale - cv::Mat frame_gray; - cv::cvtColor(frame, frame_gray, cv::COLOR_RGB2GRAY); - - const double region_size_min = s.min_point_size; - const double region_size_max = s.max_point_size; - - struct blob - { - double radius; - cv::Vec2d pos; - double confid; - bool taken; - double area; - blob(double radius, const cv::Vec2d& pos, double confid, double area) : radius(radius), pos(pos), confid(confid), taken(false), area(area) - { - //qDebug() << "radius" << radius << "pos" << pos[0] << pos[1] << "confid" << confid; - } - bool inside(const blob& other) - { - cv::Vec2d tmp = pos - other.pos; - return sqrt(tmp.dot(tmp)) < radius; - } - }; - - // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) - cv::Mat frame_bin = cv::Mat::zeros(H, W, CV_8U); - - std::vector blobs; - std::vector> contours; - - const int thres = s.threshold; - if (!s.auto_threshold) - { - cv::Mat frame_bin_; - cv::threshold(frame_gray, frame_bin_, thres, 255, cv::THRESH_BINARY); - frame_bin.setTo(170, frame_bin_); - cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); - } - else - { - cv::Mat hist; - cv::calcHist(std::vector { frame_gray }, - std::vector { 0 }, - cv::Mat(), - hist, - std::vector { 256 }, - std::vector { 0, 256 }, - false); - const int sz = hist.rows*hist.cols; - int val = 0; - int cnt = 0; - constexpr int min_pixels = 250; - const auto pixels_to_include = std::max(0, min_pixels * s.threshold/100.); - for (int i = sz-1; i >= 0; i--) - { - cnt += hist.at(i); - if (cnt >= pixels_to_include) - { - val = i; - break; - } - } - val *= 240./256.; - //qDebug() << "val" << val; - - cv::Mat frame_bin_; - cv::threshold(frame_gray, frame_bin_, val, 255, CV_THRESH_BINARY); - frame_bin.setTo(170, frame_bin_); - cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); - } - - int cnt = 0; - - for (auto& c : contours) - { - if (cnt++ > 30) - break; - - const auto m = cv::moments(cv::Mat(c)); - const double area = m.m00; - if (area == 0.) - continue; - const cv::Vec2d pos(m.m10 / m.m00, m.m01 / m.m00); - - double radius; -// following based on OpenCV SimpleBlobDetector - { - std::vector dists; - for (auto& k : c) - { - dists.push_back(cv::norm(pos - cv::Vec2d(k.x, k.y))); - } - std::sort(dists.begin(), dists.end()); - radius = (dists[(dists.size() - 1)/2] + dists[dists.size()/2])/2; - } - - if (radius < region_size_min || radius > region_size_max) - continue; - - double confid = 1; - { - double denominator = std::sqrt(std::pow(2 * m.mu11, 2) + std::pow(m.mu20 - m.mu02, 2)); - const double eps = 1e-2; - if (denominator > eps) - { - double cosmin = (m.mu20 - m.mu02) / denominator; - double sinmin = 2 * m.mu11 / denominator; - double cosmax = -cosmin; - double sinmax = -sinmin; - - double imin = 0.5 * (m.mu20 + m.mu02) - 0.5 * (m.mu20 - m.mu02) * cosmin - m.mu11 * sinmin; - double imax = 0.5 * (m.mu20 + m.mu02) - 0.5 * (m.mu20 - m.mu02) * cosmax - m.mu11 * sinmax; - confid = imin / imax; - } - } -// end SimpleBlobDetector - - { - char buf[64]; - sprintf(buf, "%.2fpx %.2fc", radius, confid); - cv::putText(frame, buf, cv::Point(pos[0]+30, pos[1]+20), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 255), 1); - } - - blobs.push_back(blob(radius, pos, confid, area)); - } - - // clear old points - points.clear(); - - using b = const blob; - std::sort(blobs.begin(), blobs.end(), [](b& b1, b& b2) {return b1.confid > b2.confid;}); - - for (auto& b : blobs) - { - cv::Vec2f p((b.pos[0] - W/2)/W, -(b.pos[1] - H/2)/W); - points.push_back(p); - } - - // draw output image - std::vector channels_; - cv::split(frame, channels_); - std::vector channels; - { - cv::Mat frame_bin__ = frame_bin * .5; - channels.push_back(channels_[0] + frame_bin__); - channels.push_back(channels_[1] - frame_bin__); - channels.push_back(channels_[2] - frame_bin__); - cv::merge(channels, frame); - } - - return points; -} diff --git a/ftnoir_tracker_pt/point_extractor.h b/ftnoir_tracker_pt/point_extractor.h deleted file mode 100644 index b9368ab6..00000000 --- a/ftnoir_tracker_pt/point_extractor.h +++ /dev/null @@ -1,33 +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. - */ - -#ifndef POINTEXTRACTOR_H -#define POINTEXTRACTOR_H - -#include -#include - -#include "ftnoir_tracker_pt_settings.h" - -// ---------------------------------------------------------------------------- -// Extracts points from an opencv image -class PointExtractor -{ -public: - // extracts points from frame and draws some processing info into frame, if draw_output is set - // dt: time since last call in seconds - // WARNING: returned reference is valid as long as object - std::vector extract_points(cv::Mat &frame); - const std::vector& get_points() { return points; } - PointExtractor(); - - settings_pt s; -private: - std::vector points; -}; - -#endif //POINTEXTRACTOR_H diff --git a/ftnoir_tracker_pt/point_tracker.cpp b/ftnoir_tracker_pt/point_tracker.cpp deleted file mode 100644 index 924b75de..00000000 --- a/ftnoir_tracker_pt/point_tracker.cpp +++ /dev/null @@ -1,267 +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. - */ - -#include "point_tracker.h" - -#include -#include -#include - -#include - -const float PI = 3.14159265358979323846f; - -static void get_row(const cv::Matx33f& m, int i, cv::Vec3f& v) -{ - v[0] = m(i,0); - v[1] = m(i,1); - v[2] = m(i,2); -} - -static void set_row(cv::Matx33f& m, int i, const cv::Vec3f& v) -{ - m(i,0) = v[0]; - m(i,1) = v[1]; - m(i,2) = v[2]; -} - -static bool d_vals_sort(const std::pair a, const std::pair b) -{ - return a.first < b.first; -} - -void PointModel::get_d_order(const std::vector& points, int d_order[], cv::Vec2f d) const -{ - // fit line to orthographically projected points - std::vector> d_vals; - // get sort indices with respect to d scalar product - for (unsigned i = 0; i(d.dot(points[i]), i)); - - std::sort(d_vals.begin(), - d_vals.end(), - d_vals_sort - ); - - for (unsigned i = 0; i& points, const PointModel& model, float f) -{ - PointTracker::PointOrder p; - p.points[0] = project(cv::Vec3f(0,0,0), f); - p.points[1] = project(model.M01, f); - p.points[2] = project(model.M02, f); - - // set correspondences by minimum distance to projected model point - bool point_taken[PointModel::N_POINTS]; - for (int i=0; i& points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout) -{ - PointOrder order; - - if (t.elapsed_ms() > init_phase_timeout) - { - t.start(); - init_phase = true; - } - - if (!dynamic_pose || init_phase) - order = find_correspondences(points, model); - else - order = find_correspondences_previous(points, model, f); - - POSIT(model, order, f); - init_phase = false; - t.start(); -} - -PointTracker::PointOrder PointTracker::find_correspondences(const std::vector& points, const PointModel& model) -{ - // We do a simple freetrack-like sorting in the init phase... - // sort points - int point_d_order[PointModel::N_POINTS]; - int model_d_order[PointModel::N_POINTS]; - cv::Vec2f d(model.M01[0]-model.M02[0], model.M01[1]-model.M02[1]); - model.get_d_order(points, point_d_order, d); - // calculate d and d_order for simple freetrack-like point correspondence - model.get_d_order(std::vector { - cv::Vec2f{0,0}, - cv::Vec2f(model.M01[0], model.M01[1]), - cv::Vec2f(model.M02[0], model.M02[1]) - }, - model_d_order, - d); - // set correspondences - PointOrder p; - for (int i=0; i and - cv::Vec2f I0_M0i(order[1][0]*(1.0 + epsilon_1) - order[0][0], - order[2][0]*(1.0 + epsilon_2) - order[0][0]); - cv::Vec2f J0_M0i(order[1][1]*(1.0 + epsilon_1) - order[0][1], - order[2][1]*(1.0 + epsilon_2) - order[0][1]); - - // construct projection of I, J onto M0i plane: I0 and J0 - I0_coeff = model.P * I0_M0i; - J0_coeff = model.P * J0_M0i; - I0 = I0_coeff[0]*model.M01 + I0_coeff[1]*model.M02; - J0 = J0_coeff[0]*model.M01 + J0_coeff[1]*model.M02; - - // calculate u component of I, J - float II0 = I0.dot(I0); - float IJ0 = I0.dot(J0); - float JJ0 = J0.dot(J0); - float rho, theta; - if (JJ0 == II0) { - rho = std::sqrt(std::abs(2*IJ0)); - theta = -PI/4; - if (IJ0<0) theta *= -1; - } - else { - rho = sqrt(sqrt( (JJ0-II0)*(JJ0-II0) + 4*IJ0*IJ0 )); - theta = atan( -2*IJ0 / (JJ0-II0) ); - if (JJ0 - II0 < 0) theta += PI; - theta /= 2; - } - - // construct the two solutions - I_1 = I0 + rho*cos(theta)*model.u; - I_2 = I0 - rho*cos(theta)*model.u; - - J_1 = J0 + rho*sin(theta)*model.u; - J_2 = J0 - rho*sin(theta)*model.u; - - float norm_const = 1.0/cv::norm(I_1); // all have the same norm - - // create rotation matrices - I_1 *= norm_const; J_1 *= norm_const; - I_2 *= norm_const; J_2 *= norm_const; - - set_row(R_1, 0, I_1); - set_row(R_1, 1, J_1); - set_row(R_1, 2, I_1.cross(J_1)); - - set_row(R_2, 0, I_2); - set_row(R_2, 1, J_2); - set_row(R_2, 2, I_2.cross(J_2)); - - // the single translation solution - Z0 = norm_const * focal_length; - - // pick the rotation solution closer to the expected one - // in simple metric d(A,B) = || I - A * B^T || - float R_1_deviation = cv::norm(cv::Matx33f::eye() - R_expected * R_1.t()); - float R_2_deviation = cv::norm(cv::Matx33f::eye() - R_expected * R_2.t()); - - if (R_1_deviation < R_2_deviation) - R_current = &R_1; - else - R_current = &R_2; - - get_row(*R_current, 2, k); - - // check for convergence condition - if (std::abs(epsilon_1 - old_epsilon_1) + std::abs(epsilon_2 - old_epsilon_2) < EPS_THRESHOLD) - break; - old_epsilon_1 = epsilon_1; - old_epsilon_2 = epsilon_2; - } - - // apply results - X_CM.R = *R_current; - X_CM.t[0] = order[0][0] * Z0/focal_length; - X_CM.t[1] = order[0][1] * Z0/focal_length; - X_CM.t[2] = Z0; - - //qDebug() << "iter:" << i; - - return i; -} - -cv::Vec2f PointTracker::project(const cv::Vec3f& v_M, float f) -{ - cv::Vec3f v_C = X_CM * v_M; - return cv::Vec2f(f*v_C[0]/v_C[2], f*v_C[1]/v_C[2]); -} diff --git a/ftnoir_tracker_pt/point_tracker.h b/ftnoir_tracker_pt/point_tracker.h deleted file mode 100644 index fd002948..00000000 --- a/ftnoir_tracker_pt/point_tracker.h +++ /dev/null @@ -1,147 +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. - */ - -#ifndef POINTTRACKER_H -#define POINTTRACKER_H - -#include -#include -#include -#include "opentrack-compat/timer.hpp" -#include "ftnoir_tracker_pt_settings.h" - -#include - -// ---------------------------------------------------------------------------- -// Affine frame trafo -class Affine -{ -public: - Affine() : R(cv::Matx33f::eye()), t(0,0,0) {} - Affine(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {} - - cv::Matx33f R; - cv::Vec3f t; -}; - -inline Affine operator*(const Affine& X, const Affine& Y) -{ - return Affine(X.R*Y.R, X.R*Y.t + X.t); -} - -inline Affine operator*(const cv::Matx33f& X, const Affine& Y) -{ - return Affine(X*Y.R, X*Y.t); -} - -inline Affine operator*(const Affine& X, const cv::Matx33f& Y) -{ - return Affine(X.R*Y, X.t); -} - -inline cv::Vec3f operator*(const Affine& X, const cv::Vec3f& v) -{ - return X.R*v + X.t; -} - - -// ---------------------------------------------------------------------------- -// Describes a 3-point model -// nomenclature as in -// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] -class PointModel -{ - friend class PointTracker; -public: - static constexpr int N_POINTS = 3; - - cv::Vec3f M01; // M01 in model frame - cv::Vec3f M02; // M02 in model frame - - cv::Vec3f u; // unit vector perpendicular to M01,M02-plane - - cv::Matx22f P; - - enum Model { Clip = 0, Cap = 1, Custom = 2 }; - - PointModel(settings_pt& s) - { - set_model(s); - // calculate u - u = M01.cross(M02); - u /= norm(u); - - // calculate projection matrix on M01,M02 plane - float s11 = M01.dot(M01); - float s12 = M01.dot(M02); - float s22 = M02.dot(M02); - P = 1.0/(s11*s22-s12*s12) * cv::Matx22f(s22, -s12, -s12, s11); - } - - void set_model(settings_pt& s) - { - switch (s.active_model_panel) - { - case Clip: - M01 = cv::Vec3f(0, static_cast(s.clip_ty), -static_cast(s.clip_tz)); - M02 = cv::Vec3f(0, -static_cast(s.clip_by), -static_cast(s.clip_bz)); - break; - case Cap: - M01 = cv::Vec3f(-static_cast(s.cap_x), -static_cast(s.cap_y), -static_cast(s.cap_z)); - M02 = cv::Vec3f(static_cast(s.cap_x), -static_cast(s.cap_y), -static_cast(s.cap_z)); - break; - case Custom: - M01 = cv::Vec3f(s.m01_x, s.m01_y, s.m01_z); - M02 = cv::Vec3f(s.m02_x, s.m02_y, s.m02_z); - break; - } - } - - void get_d_order(const std::vector& points, int* d_order, cv::Vec2f d) const; -}; - -// ---------------------------------------------------------------------------- -// Tracks a 3-point model -// implementing the POSIT algorithm for coplanar points as presented in -// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] -class PointTracker -{ -public: - PointTracker(); - // track the pose using the set of normalized point coordinates (x pos in range -0.5:0.5) - // f : (focal length)/(sensor width) - // dt : time since last call - void track(const std::vector& projected_points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout); - Affine pose() const { return X_CM; } - cv::Vec2f project(const cv::Vec3f& v_M, float f); - void reset(const Affine& pose) - { - X_CM = pose; - } -private: - // the points in model order - struct PointOrder - { - cv::Vec2f points[PointModel::N_POINTS]; - PointOrder() - { - for (int i = 0; i < PointModel::N_POINTS; i++) - points[i] = cv::Vec2f(0, 0); - } - }; - - PointOrder find_correspondences(const std::vector& projected_points, const PointModel &model); - PointOrder find_correspondences_previous(const std::vector& points, const PointModel &model, float f); - int POSIT(const PointModel& point_model, const PointOrder& order, float focal_length); // The POSIT algorithm, returns the number of iterations - - Affine X_CM; // trafo from model to camera - - Timer t; - bool init_phase; -}; - -#endif //POINTTRACKER_H diff --git a/ftnoir_tracker_pt/pt_video_widget.cpp b/ftnoir_tracker_pt/pt_video_widget.cpp deleted file mode 100644 index cbb7c268..00000000 --- a/ftnoir_tracker_pt/pt_video_widget.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (c) 2012 Patrick Ruoff - * Copyright (c) 2015 Stanislaw Halik - * - * 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. - * - * 20130312, WVR: Add 7 lines to resizeGL after resize_frame. This should lower CPU-load. - */ - -#include "pt_video_widget.h" - -void PTVideoWidget::update_image(const cv::Mat& frame) -{ - QMutexLocker foo(&mtx); - - if (!freshp) - { - _frame = frame.clone(); - freshp = true; - } -} - -void PTVideoWidget::update_and_repaint() -{ - QImage qframe; - { - QMutexLocker foo(&mtx); - if (_frame.empty() || !freshp) - return; - qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); - freshp = false; - uchar* data = qframe.bits(); - const int pitch = qframe.bytesPerLine(); - unsigned char *input = (unsigned char*) _frame.data; - const int chans = _frame.channels(); - for (int y = 0; y < _frame.rows; y++) - { - const int step = y * _frame.step; - const int pitch_ = y * pitch; - for (int x = 0; x < _frame.cols; x++) - { - data[pitch_ + x * 3 + 0] = input[step + x * chans + 2]; - data[pitch_ + x * 3 + 1] = input[step + x * chans + 1]; - data[pitch_ + x * 3 + 2] = input[step + x * chans + 0]; - } - } - } - qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); - { - QMutexLocker foo(&mtx); - texture = qframe; - } - update(); -} diff --git a/ftnoir_tracker_pt/pt_video_widget.h b/ftnoir_tracker_pt/pt_video_widget.h deleted file mode 100644 index af1d60fd..00000000 --- a/ftnoir_tracker_pt/pt_video_widget.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2012 Patrick Ruoff - * Copyright (c) 2014 Stanislaw Halik - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -class PTVideoWidget : public QWidget -{ - Q_OBJECT - -public: - PTVideoWidget(QWidget *parent) : - QWidget(parent), - freshp(false) - { - connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); - timer.start(40); - } - void update_image(const cv::Mat &frame); -protected slots: - void paintEvent( QPaintEvent* e ) { - QMutexLocker foo(&mtx); - QPainter painter(this); - painter.drawImage(e->rect(), texture); - } - void update_and_repaint(); -private: - QMutex mtx; - QImage texture; - QTimer timer; - cv::Mat _frame; - bool freshp; -}; diff --git a/ftnoir_tracker_pt/trans_calib.cpp b/ftnoir_tracker_pt/trans_calib.cpp deleted file mode 100644 index a1a4b641..00000000 --- a/ftnoir_tracker_pt/trans_calib.cpp +++ /dev/null @@ -1,41 +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. - */ - -#include "trans_calib.h" - -TranslationCalibrator::TranslationCalibrator() -{ - reset(); -} - -void TranslationCalibrator::reset() -{ - P = cv::Matx66f::zeros(); - y = cv::Vec6f(0,0,0, 0,0,0); -} - -void TranslationCalibrator::update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k) -{ - cv::Matx H_k_T = cv::Matx::zeros(); - for (int i=0; i<3; ++i) { - for (int j=0; j<3; ++j) { - H_k_T(i,j) = R_CM_k(j,i); - } - } - for (int i=0; i<3; ++i) - { - H_k_T(3+i,i) = 1.0; - } - P += H_k_T * H_k_T.t(); - y += H_k_T * t_CM_k; -} - -cv::Vec3f TranslationCalibrator::get_estimate() -{ - cv::Vec6f x = P.inv() * y; - return cv::Vec3f(-x[0], -x[1], -x[2]); -} diff --git a/ftnoir_tracker_pt/trans_calib.h b/ftnoir_tracker_pt/trans_calib.h deleted file mode 100644 index e20fc767..00000000 --- a/ftnoir_tracker_pt/trans_calib.h +++ /dev/null @@ -1,39 +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. - */ - -#ifndef TRANSCALIB_H -#define TRANSCALIB_H - -#include - -//----------------------------------------------------------------------------- -// Calibrates the translation from head to model = t_MH -// by recursive least squares / -// kalman filter in information form with identity noise covariance -// measurement equation when head position = t_CH is fixed: -// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k - -class TranslationCalibrator -{ -public: - TranslationCalibrator(); - - // reset the calibration process - void reset(); - - // update the current estimate - void update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k); - - // get the current estimate for t_MH - cv::Vec3f get_estimate(); - -private: - cv::Matx66f P; // normalized precision matrix = inverse covariance - cv::Vec6f y; // P*(-t_MH, t_CH) -}; - -#endif //TRANSCALIB_H diff --git a/ftnoir_tracker_rift_025/ftnoir_rift_025.qrc b/ftnoir_tracker_rift_025/ftnoir_rift_025.qrc deleted file mode 100644 index cd174fc4..00000000 --- a/ftnoir_tracker_rift_025/ftnoir_rift_025.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - images/rift_medium.png - images/rift_small.png - images/rift_tiny.png - - diff --git a/ftnoir_tracker_rift_025/ftnoir_rift_clientcontrols_025.ui b/ftnoir_tracker_rift_025/ftnoir_rift_clientcontrols_025.ui deleted file mode 100644 index 20c8f00b..00000000 --- a/ftnoir_tracker_rift_025/ftnoir_rift_clientcontrols_025.ui +++ /dev/null @@ -1,176 +0,0 @@ - - - UIRiftControls - - - Qt::NonModal - - - - 0 - 0 - 218 - 200 - - - - - 0 - 0 - - - - Oculus Rift tracker settings FaceTrackNoIR - - - - images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png - - - Qt::LeftToRight - - - false - - - - - - Yaw spring - - - - - - Enable - - - - - - - Persistence - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.900000000000000 - - - 1.000000000000000 - - - 0.001000000000000 - - - - - - - Constant drift - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.000100000000000 - - - 0.100000000000000 - - - 0.001000000000000 - - - - - - - Deadzone - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.100000000000000 - - - 0.010000000000000 - - - - - - - - - - - 0 - 0 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.cpp b/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.cpp deleted file mode 100644 index 9588aaf8..00000000 --- a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ -#include "ftnoir_tracker_rift_025.h" -#include "opentrack/plugin-api.hpp" -#include "OVR.h" -#include - -using namespace OVR; - -Rift_Tracker::Rift_Tracker() -{ - pManager = NULL; - pSensor = NULL; - pSFusion = NULL; - old_yaw = 0; -} - -Rift_Tracker::~Rift_Tracker() -{ - if (pSensor) - pSensor->Release(); - if (pSFusion) - delete pSFusion; - if (pManager) - pManager->Release(); - System::Destroy(); -} - -void Rift_Tracker::start_tracker(QFrame*) -{ - System::Init(Log::ConfigureDefaultLog(LogMask_All)); - pManager = DeviceManager::Create(); - if (pManager != NULL) - { - DeviceEnumerator enumerator = pManager->EnumerateDevices(); - if (enumerator.IsAvailable()) - { - pSensor = enumerator.CreateDevice(); - - if (pSensor) - { - pSFusion = new OVR::SensorFusion(); - pSFusion->Reset(); - pSFusion->AttachToSensor(pSensor); - } - else - { - QMessageBox::warning(0,"Error", "Unable to create Rift sensor",QMessageBox::Ok,QMessageBox::NoButton); - } - - } - else - { - QMessageBox::warning(0,"Error", "Unable to enumerate Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); - } - } - else - { - QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); - } -} - - -void Rift_Tracker::data(double *data) -{ - if (pSFusion != NULL && pSensor != NULL) - { - Quatf hmdOrient = pSFusion->GetOrientation(); - double newHeadPose[6]; - - float yaw = 0.0f; - float pitch = 0.0f; - float roll = 0.0f; - hmdOrient.GetEulerAngles(&yaw, &pitch , &roll); - newHeadPose[Pitch] = pitch; - newHeadPose[Roll] = roll; - newHeadPose[Yaw] = yaw; - if (s.useYawSpring) - { - newHeadPose[Yaw] = old_yaw*s.persistence + (yaw-old_yaw); - if(newHeadPose[Yaw] > s.deadzone) - newHeadPose[Yaw] -= s.constant_drift; - if(newHeadPose[Yaw] < -s.deadzone) - newHeadPose[Yaw] += s.constant_drift; - old_yaw=yaw; - } - data[Yaw] = newHeadPose[Yaw] * 57.295781f; - data[Pitch] = newHeadPose[Pitch] * 57.295781f; - data[Roll] = newHeadPose[Roll] * 57.295781f; - } -} - -OPENTRACK_DECLARE_TRACKER(Rift_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h b/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h deleted file mode 100644 index 2bd5024b..00000000 --- a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_025.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include "ui_ftnoir_rift_clientcontrols_025.h" -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "OVR.h" -#include -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value useYawSpring; - value constant_drift, persistence, deadzone; - settings() : - opts("Rift-025"), - useYawSpring(b, "yaw-spring", false), - constant_drift(b, "constant-drift", 0.000005), - persistence(b, "persistence", 0.99999), - deadzone(b, "deadzone", 0.02) - {} -}; - -class Rift_Tracker : public ITracker -{ -public: - Rift_Tracker(); - virtual ~Rift_Tracker() override; - void start_tracker(QFrame *) override; - void data(double *data) override; -private: - double old_yaw; - settings s; - static bool isInitialised; - OVR::DeviceManager* pManager; - OVR::SensorDevice* pSensor; - OVR::SensorFusion* pSFusion; -}; - -class TrackerControls: public ITrackerDialog -{ - Q_OBJECT -public: - TrackerControls(); - - void register_tracker(ITracker *) {} - void unregister_tracker() {} - -private: - Ui::UIRiftControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_TrackerDll : public Metadata -{ -public: - QString name() { return QString("Oculus Rift runtime 0.2.5 -- HMD"); } - QIcon icon() { return QIcon(":/images/rift_tiny.png"); } -}; - diff --git a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_dialog_025.cpp b/ftnoir_tracker_rift_025/ftnoir_tracker_rift_dialog_025.cpp deleted file mode 100644 index 8100e362..00000000 --- a/ftnoir_tracker_rift_025/ftnoir_tracker_rift_dialog_025.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ftnoir_tracker_rift_025.h" -#include "opentrack/plugin-api.hpp" - -TrackerControls::TrackerControls() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.constant_drift, ui.constantDrift); - tie_setting(s.deadzone, ui.deadzone); - tie_setting(s.persistence, ui.persistence); - tie_setting(s.useYawSpring, ui.yawSpring); -} - -void TrackerControls::doOK() { - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() { - s.b->reload(); - close(); -} - diff --git a/ftnoir_tracker_rift_025/images/medium.png b/ftnoir_tracker_rift_025/images/medium.png deleted file mode 100644 index a5ba49e7..00000000 Binary files a/ftnoir_tracker_rift_025/images/medium.png and /dev/null differ diff --git a/ftnoir_tracker_rift_025/images/rift_medium.png b/ftnoir_tracker_rift_025/images/rift_medium.png deleted file mode 100644 index a5ba49e7..00000000 Binary files a/ftnoir_tracker_rift_025/images/rift_medium.png and /dev/null differ diff --git a/ftnoir_tracker_rift_025/images/rift_small.png b/ftnoir_tracker_rift_025/images/rift_small.png deleted file mode 100644 index 3f18080c..00000000 Binary files a/ftnoir_tracker_rift_025/images/rift_small.png and /dev/null differ diff --git a/ftnoir_tracker_rift_025/images/rift_tiny.png b/ftnoir_tracker_rift_025/images/rift_tiny.png deleted file mode 100644 index 76fe0f58..00000000 Binary files a/ftnoir_tracker_rift_025/images/rift_tiny.png and /dev/null differ diff --git a/ftnoir_tracker_rift_025/images/small.png b/ftnoir_tracker_rift_025/images/small.png deleted file mode 100644 index 3f18080c..00000000 Binary files a/ftnoir_tracker_rift_025/images/small.png and /dev/null differ diff --git a/ftnoir_tracker_rift_025/images/tiny.png b/ftnoir_tracker_rift_025/images/tiny.png deleted file mode 100644 index 76fe0f58..00000000 Binary files a/ftnoir_tracker_rift_025/images/tiny.png and /dev/null differ diff --git a/ftnoir_tracker_rift_042/ftnoir_rift_042.qrc b/ftnoir_tracker_rift_042/ftnoir_rift_042.qrc deleted file mode 100644 index cd174fc4..00000000 --- a/ftnoir_tracker_rift_042/ftnoir_rift_042.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - images/rift_medium.png - images/rift_small.png - images/rift_tiny.png - - diff --git a/ftnoir_tracker_rift_042/ftnoir_rift_clientcontrols_042.ui b/ftnoir_tracker_rift_042/ftnoir_rift_clientcontrols_042.ui deleted file mode 100644 index 20c8f00b..00000000 --- a/ftnoir_tracker_rift_042/ftnoir_rift_clientcontrols_042.ui +++ /dev/null @@ -1,176 +0,0 @@ - - - UIRiftControls - - - Qt::NonModal - - - - 0 - 0 - 218 - 200 - - - - - 0 - 0 - - - - Oculus Rift tracker settings FaceTrackNoIR - - - - images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png - - - Qt::LeftToRight - - - false - - - - - - Yaw spring - - - - - - Enable - - - - - - - Persistence - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.900000000000000 - - - 1.000000000000000 - - - 0.001000000000000 - - - - - - - Constant drift - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.000100000000000 - - - 0.100000000000000 - - - 0.001000000000000 - - - - - - - Deadzone - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.100000000000000 - - - 0.010000000000000 - - - - - - - - - - - 0 - 0 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.cpp b/ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.cpp deleted file mode 100644 index deea4a08..00000000 --- a/ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ -#include "ftnoir_tracker_rift_042.h" -#include "opentrack/plugin-api.hpp" -#include "OVR_CAPI.h" -#include "Kernel/OVR_Math.h" -#include - -using namespace OVR; - -Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr) -{ -} - -Rift_Tracker::~Rift_Tracker() -{ - ovrHmd_Destroy(hmd); - ovr_Shutdown(); -} - -void Rift_Tracker::start_tracker(QFrame*) -{ - ovr_Initialize(); - hmd = ovrHmd_Create(0); - if (hmd) - { - ovrHmd_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation); - } - else - { - // XXX need change ITracker et al api to allow for failure reporting - // this qmessagebox doesn't give any relevant details either -sh 20141012 - QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); - } -} - - -void Rift_Tracker::data(double *data) -{ - if (hmd) - { - ovrHSWDisplayState hsw; - if (ovrHmd_GetHSWDisplayState(hmd, &hsw), hsw.Displayed) - ovrHmd_DismissHSWDisplay(hmd); - ovrTrackingState ss = ovrHmd_GetTrackingState(hmd, 0); - if(ss.StatusFlags & ovrStatus_OrientationTracked) { - auto pose = ss.HeadPose.ThePose; - Quatf quat = pose.Orientation; - float yaw, pitch, roll; - quat.GetEulerAngles(&yaw, &pitch, &roll); - // XXX TODO move to core - if (s.useYawSpring) - { - yaw = old_yaw*s.persistence + (yaw-old_yaw); - if(yaw > s.deadzone) - yaw -= s.constant_drift; - if(yaw < -s.deadzone) - yaw += s.constant_drift; - old_yaw=yaw; - } - constexpr double d2r = 57.295781; - data[Yaw] = yaw * -d2r; - data[Pitch] = pitch * d2r; - data[Roll] = roll * d2r; - data[TX] = pose.Position.x * -1e2; - data[TY] = pose.Position.y * 1e2; - data[TZ] = pose.Position.z * 1e2; - } - } -} - -OPENTRACK_DECLARE_TRACKER(Rift_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.h b/ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.h deleted file mode 100644 index 437a2a39..00000000 --- a/ftnoir_tracker_rift_042/ftnoir_tracker_rift_042.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include "ui_ftnoir_rift_clientcontrols_042.h" -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "OVR.h" -#include -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value useYawSpring; - value constant_drift, persistence, deadzone; - settings() : - opts("Rift"), - useYawSpring(b, "yaw-spring", false), - constant_drift(b, "constant-drift", 0.000005), - persistence(b, "persistence", 0.99999), - deadzone(b, "deadzone", 0.02) - {} -}; - -class Rift_Tracker : public ITracker -{ -public: - Rift_Tracker(); - virtual ~Rift_Tracker() override; - void start_tracker(QFrame *) override; - void data(double *data) override; -private: - double old_yaw; - ovrHmd hmd; - settings s; -}; - -class TrackerControls: public ITrackerDialog -{ - Q_OBJECT -public: - TrackerControls(); - - void register_tracker(ITracker *) {} - void unregister_tracker() {} - -private: - Ui::UIRiftControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_TrackerDll : public Metadata -{ -public: - QString name() { return QString("Oculus Rift runtime 0.4.2 -- HMD"); } - QIcon icon() { return QIcon(":/images/rift_tiny.png"); } -}; - diff --git a/ftnoir_tracker_rift_042/ftnoir_tracker_rift_dialog_042.cpp b/ftnoir_tracker_rift_042/ftnoir_tracker_rift_dialog_042.cpp deleted file mode 100644 index 9a8b7549..00000000 --- a/ftnoir_tracker_rift_042/ftnoir_tracker_rift_dialog_042.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ftnoir_tracker_rift_042.h" -#include "opentrack/plugin-api.hpp" - -TrackerControls::TrackerControls() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.constant_drift, ui.constantDrift); - tie_setting(s.deadzone, ui.deadzone); - tie_setting(s.persistence, ui.persistence); - tie_setting(s.useYawSpring, ui.yawSpring); -} - -void TrackerControls::doOK() { - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() { - s.b->reload(); - close(); -} - diff --git a/ftnoir_tracker_rift_042/images/medium.png b/ftnoir_tracker_rift_042/images/medium.png deleted file mode 100644 index a5ba49e7..00000000 Binary files a/ftnoir_tracker_rift_042/images/medium.png and /dev/null differ diff --git a/ftnoir_tracker_rift_042/images/rift_medium.png b/ftnoir_tracker_rift_042/images/rift_medium.png deleted file mode 100644 index a5ba49e7..00000000 Binary files a/ftnoir_tracker_rift_042/images/rift_medium.png and /dev/null differ diff --git a/ftnoir_tracker_rift_042/images/rift_small.png b/ftnoir_tracker_rift_042/images/rift_small.png deleted file mode 100644 index 3f18080c..00000000 Binary files a/ftnoir_tracker_rift_042/images/rift_small.png and /dev/null differ diff --git a/ftnoir_tracker_rift_042/images/rift_tiny.png b/ftnoir_tracker_rift_042/images/rift_tiny.png deleted file mode 100644 index 76fe0f58..00000000 Binary files a/ftnoir_tracker_rift_042/images/rift_tiny.png and /dev/null differ diff --git a/ftnoir_tracker_rift_042/images/small.png b/ftnoir_tracker_rift_042/images/small.png deleted file mode 100644 index 3f18080c..00000000 Binary files a/ftnoir_tracker_rift_042/images/small.png and /dev/null differ diff --git a/ftnoir_tracker_rift_042/images/tiny.png b/ftnoir_tracker_rift_042/images/tiny.png deleted file mode 100644 index 76fe0f58..00000000 Binary files a/ftnoir_tracker_rift_042/images/tiny.png and /dev/null differ diff --git a/ftnoir_tracker_rift_080/ftnoir_rift_080.qrc b/ftnoir_tracker_rift_080/ftnoir_rift_080.qrc deleted file mode 100644 index cd174fc4..00000000 --- a/ftnoir_tracker_rift_080/ftnoir_rift_080.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - images/rift_medium.png - images/rift_small.png - images/rift_tiny.png - - diff --git a/ftnoir_tracker_rift_080/ftnoir_rift_clientcontrols_080.ui b/ftnoir_tracker_rift_080/ftnoir_rift_clientcontrols_080.ui deleted file mode 100644 index 20c8f00b..00000000 --- a/ftnoir_tracker_rift_080/ftnoir_rift_clientcontrols_080.ui +++ /dev/null @@ -1,176 +0,0 @@ - - - UIRiftControls - - - Qt::NonModal - - - - 0 - 0 - 218 - 200 - - - - - 0 - 0 - - - - Oculus Rift tracker settings FaceTrackNoIR - - - - images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png - - - Qt::LeftToRight - - - false - - - - - - Yaw spring - - - - - - Enable - - - - - - - Persistence - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.900000000000000 - - - 1.000000000000000 - - - 0.001000000000000 - - - - - - - Constant drift - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.000100000000000 - - - 0.100000000000000 - - - 0.001000000000000 - - - - - - - Deadzone - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - 5 - - - 0.100000000000000 - - - 0.010000000000000 - - - - - - - - - - - 0 - 0 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp b/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp deleted file mode 100644 index 889ac8c3..00000000 --- a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ -#include "ftnoir_tracker_rift_080.h" -#include "opentrack/plugin-api.hpp" -#include "OVR_CAPI.h" -#include "Extras/OVR_Math.h" -#include "OVR_CAPI_0_8_0.h" -#include - -using namespace OVR; - -Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr) -{ -} - -Rift_Tracker::~Rift_Tracker() -{ - if (hmd) - ovr_Destroy(hmd); - ovr_Shutdown(); -} - -void Rift_Tracker::start_tracker(QFrame*) -{ - { - ovrInitParams args = {0}; - if (!OVR_SUCCESS(ovr_Initialize(&args))) - goto error; - } - { - ovrGraphicsLuid luid = {0}; - ovrResult res = ovr_Create(&hmd, &luid); - if (OVR_SUCCESS(res)) - { - ovr_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation); - } - else - goto error; - } - return; -error: - QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); -} - -void Rift_Tracker::data(double *data) -{ - if (hmd) - { - ovrTrackingState ss = ovr_GetTrackingState(hmd, 0, false); - if(ss.StatusFlags & ovrStatus_OrientationTracked) { - auto pose = ss.HeadPose.ThePose; - Quatf quat = pose.Orientation; - float yaw, pitch, roll; - quat.GetEulerAngles(&yaw, &pitch, &roll); - // XXX TODO move to core - if (s.useYawSpring) - { - yaw = old_yaw*s.persistence + (yaw-old_yaw); - if(yaw > s.deadzone) - yaw -= s.constant_drift; - if(yaw < -s.deadzone) - yaw += s.constant_drift; - old_yaw=yaw; - } - constexpr double d2r = 57.295781; - data[Yaw] = yaw * -d2r; - data[Pitch] = pitch * d2r; - data[Roll] = roll * d2r; - data[TX] = pose.Position.x * -1e2; - data[TY] = pose.Position.y * 1e2; - data[TZ] = pose.Position.z * 1e2; - } - } -} - -OPENTRACK_DECLARE_TRACKER(Rift_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.h b/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.h deleted file mode 100644 index 08684dd2..00000000 --- a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_080.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include "ui_ftnoir_rift_clientcontrols_080.h" -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "OVR.h" -#include -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value useYawSpring; - value constant_drift, persistence, deadzone; - settings() : - opts("Rift"), - useYawSpring(b, "yaw-spring", false), - constant_drift(b, "constant-drift", 0.000005), - persistence(b, "persistence", 0.99999), - deadzone(b, "deadzone", 0.02) - {} -}; - -class Rift_Tracker : public ITracker -{ -public: - Rift_Tracker(); - ~Rift_Tracker() override; - void start_tracker(QFrame *) override; - void data(double *data) override; -private: - double old_yaw; - ovrSession hmd; - settings s; -}; - -class TrackerControls: public ITrackerDialog -{ - Q_OBJECT -public: - TrackerControls(); - - void register_tracker(ITracker *) {} - void unregister_tracker() {} - -private: - Ui::UIRiftControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_TrackerDll : public Metadata -{ -public: - QString name() { return QString("Oculus Rift runtime 0.8.0 -- HMD"); } - QIcon icon() { return QIcon(":/images/rift_tiny.png"); } -}; - diff --git a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_dialog_080.cpp b/ftnoir_tracker_rift_080/ftnoir_tracker_rift_dialog_080.cpp deleted file mode 100644 index 0bf797be..00000000 --- a/ftnoir_tracker_rift_080/ftnoir_tracker_rift_dialog_080.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ftnoir_tracker_rift_080.h" -#include "opentrack/plugin-api.hpp" - -TrackerControls::TrackerControls() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.constant_drift, ui.constantDrift); - tie_setting(s.deadzone, ui.deadzone); - tie_setting(s.persistence, ui.persistence); - tie_setting(s.useYawSpring, ui.yawSpring); -} - -void TrackerControls::doOK() { - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() { - s.b->reload(); - close(); -} - diff --git a/ftnoir_tracker_rift_080/images/medium.png b/ftnoir_tracker_rift_080/images/medium.png deleted file mode 100644 index a5ba49e7..00000000 Binary files a/ftnoir_tracker_rift_080/images/medium.png and /dev/null differ diff --git a/ftnoir_tracker_rift_080/images/rift_medium.png b/ftnoir_tracker_rift_080/images/rift_medium.png deleted file mode 100644 index a5ba49e7..00000000 Binary files a/ftnoir_tracker_rift_080/images/rift_medium.png and /dev/null differ diff --git a/ftnoir_tracker_rift_080/images/rift_small.png b/ftnoir_tracker_rift_080/images/rift_small.png deleted file mode 100644 index 3f18080c..00000000 Binary files a/ftnoir_tracker_rift_080/images/rift_small.png and /dev/null differ diff --git a/ftnoir_tracker_rift_080/images/rift_tiny.png b/ftnoir_tracker_rift_080/images/rift_tiny.png deleted file mode 100644 index 76fe0f58..00000000 Binary files a/ftnoir_tracker_rift_080/images/rift_tiny.png and /dev/null differ diff --git a/ftnoir_tracker_rift_080/images/small.png b/ftnoir_tracker_rift_080/images/small.png deleted file mode 100644 index 3f18080c..00000000 Binary files a/ftnoir_tracker_rift_080/images/small.png and /dev/null differ diff --git a/ftnoir_tracker_rift_080/images/tiny.png b/ftnoir_tracker_rift_080/images/tiny.png deleted file mode 100644 index 76fe0f58..00000000 Binary files a/ftnoir_tracker_rift_080/images/tiny.png and /dev/null differ diff --git a/ftnoir_tracker_rs/README.md b/ftnoir_tracker_rs/README.md deleted file mode 100644 index 5fca4392..00000000 --- a/ftnoir_tracker_rs/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Intel® RealSenseâ„¢ plugin for opentrack -This is a tracker providing markerless 3D head tracking using the Intel® RealSenseâ„¢ SDK and the Intel® RealSenseâ„¢ front-facing cameras. - -More information on RealSense can be found on [Intel.com](http://www.intel.com/content/www/us/en/architecture-and-technology/realsense-overview.html) - -This tracker uses a separate process that gets data from the SDK. Its sources are under rs_impl and can be recompiled by calling build.bat, which depends on -Microsoft Visual C++ Compiler and the [Intel® RealSenseâ„¢ SDK R4](https://software.intel.com/en-us/intel-realsense-sdk) - -# ISC License -Copyright (c) 2015, Intel Corporation - - Author: Xavier Hallade - -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. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/ftnoir_tracker_rs/ftnoir_tracker_rs.cpp b/ftnoir_tracker_rs/ftnoir_tracker_rs.cpp deleted file mode 100644 index 3e9b23c8..00000000 --- a/ftnoir_tracker_rs/ftnoir_tracker_rs.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ftnoir_tracker_rs.h" -#include "ftnoir_tracker_rs_controls.h" - -#include "opentrack/plugin-api.hpp" -#include - -RSTracker::RSTracker() : mPose{ 0,0,0, 0,0,0 } { - mThread.setObjectName("RSTrackerWorkerThread"); - - mRealSenseImplProcess.moveToThread(&mThread); - mSocket.moveToThread(&mThread); - - connect(&mRealSenseImplProcess, SIGNAL(finished(int)), - this, SLOT(rsImplProcessFinished(int)), Qt::QueuedConnection); - - qRegisterMetaType("QProcess::ProcessError"); - connect(&mRealSenseImplProcess, SIGNAL(error(QProcess::ProcessError)), - this, SLOT(rsImplProcessError(QProcess::ProcessError)), Qt::QueuedConnection); - - connect(&mSocket, SIGNAL(readyRead()), - this, SLOT(readPendingUdpPoseData()), Qt::DirectConnection); - - connect(&mThread, &QThread::started, - &mThread, [this]{ - mSocket.bind(QHostAddress::LocalHost, 4242, QUdpSocket::DontShareAddress); - mRealSenseImplProcess.start("opentrack-tracker-rs-impl.exe", QProcess::NotOpen); - }, Qt::DirectConnection); - - connect(&mThread, &QThread::finished, - &mThread, [this]{ - mRealSenseImplProcess.kill(); - mRealSenseImplProcess.waitForFinished(); - }, Qt::DirectConnection); -} - -void RSTracker::start_tracker(QFrame*) -{ - mThread.start(); -} - -void RSTracker::readPendingUdpPoseData(){ - double pose[6]; - - while(mSocket.hasPendingDatagrams()) { - mSocket.readDatagram((char*)pose, sizeof(pose)); - QMutexLocker foo(&mMutex); - memcpy(mPose, pose, sizeof(pose)); - } -} - -void RSTracker::rsImplProcessError(QProcess::ProcessError error){ - if(error == QProcess::FailedToStart){ - QMessageBox::warning(NULL, "RealSense Tracking Error", "Couldn't start the RealSense tracking module.\nMaybe opentrack-tracker-rs-impl.exe is missing.", QMessageBox::Ok); - } - else if(error == QProcess::Crashed){ - QMessageBox::warning(NULL, "RealSense Tracking Error", "The RealSense tracking module has crashed.", QMessageBox::Ok); - } -} - - -void RSTracker::rsImplProcessFinished(int exitCode){ - if(exitCode!=0){ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText("RealSense Tracking Error"); - if(exitCode==-101){ //The implementation got an invalid handle from the RealSense SDK session/modules - msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please install SDK Runtime R4."); - } - else { - msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime R4 to be installed."); - } - QPushButton* triggerSdkInstallation = msgBox.addButton("Install Runtime", QMessageBox::ActionRole); - msgBox.addButton(QMessageBox::Ok); - msgBox.exec(); - - if(msgBox.clickedButton() == triggerSdkInstallation){ - bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); - if(!pStarted){ - QMessageBox::warning(0, "Intel® RealSenseâ„¢ Runtime Installation", "Installation process failed to start.", QMessageBox::Ok); - } - } - } -} - -void RSTracker::data(double *data) -{ - QMutexLocker foo(&mMutex); - memcpy(data, mPose, sizeof(mPose)); -} - -RSTracker::~RSTracker() { - mThread.quit(); - mThread.wait(); -} - -QString RSTrackerMetaData::name() { - return QString("Intel® RealSenseâ„¢ Technology"); -} - -QIcon RSTrackerMetaData::icon() { - return QIcon(":/images/intel-16x16.png"); -} - -OPENTRACK_DECLARE_TRACKER(RSTracker, RSTrackerControls, RSTrackerMetaData) diff --git a/ftnoir_tracker_rs/ftnoir_tracker_rs.h b/ftnoir_tracker_rs/ftnoir_tracker_rs.h deleted file mode 100644 index 7cda7370..00000000 --- a/ftnoir_tracker_rs/ftnoir_tracker_rs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include "ui_ftnoir_tracker_rs_controls.h" -#include "opentrack/plugin-api.hpp" -#include -#include -#include -#include - -class RSTracker : protected QObject, public ITracker -{ - Q_OBJECT - -public: - RSTracker(); - ~RSTracker(); - void start_tracker(QFrame *) override; - void data(double *data) override; - -private: - QMutex mMutex; - QThread mThread; - QProcess mRealSenseImplProcess; - QUdpSocket mSocket; - double mPose[6]; - -private slots: - void rsImplProcessError(QProcess::ProcessError); - void rsImplProcessFinished(int); - void readPendingUdpPoseData(); - -}; - -class RSTrackerMetaData : public Metadata -{ -public: - QString name(); - QIcon icon(); -}; diff --git a/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.cpp b/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.cpp deleted file mode 100644 index 6c71d58f..00000000 --- a/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ftnoir_tracker_rs_controls.h" - -#include -#include - -RSTrackerControls::RSTrackerControls() -{ - ui.setupUi(this); - connect(ui.triggerSDKInstallButton, SIGNAL(clicked(bool)), this, SLOT(doInstallRSRuntime())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); -} - -void RSTrackerControls::doInstallRSRuntime() -{ - bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); - if(processStarted){ - this->close(); - } - else{ - QMessageBox::warning(0, "Intel® RealSenseTM Runtime Installation", "Installation process failed to start.", QMessageBox::Ok); - } -} - -void RSTrackerControls::doOK() -{ - this->close(); -} - -void RSTrackerControls::doCancel() -{ - this->close(); -} diff --git a/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.h b/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.h deleted file mode 100644 index 010dac99..00000000 --- a/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ftnoir_tracker_rs.h" - -class RSTrackerControls : public ITrackerDialog -{ - Q_OBJECT -public: - RSTrackerControls(); - void register_tracker(ITracker *) {} - void unregister_tracker() {} -private: - Ui::UIRSControls ui; - private slots: - void doOK(); - void doCancel(); - void doInstallRSRuntime(); -}; diff --git a/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.ui b/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.ui deleted file mode 100644 index 834803d1..00000000 --- a/ftnoir_tracker_rs/ftnoir_tracker_rs_controls.ui +++ /dev/null @@ -1,67 +0,0 @@ - - - UIRSControls - - - Qt::NonModal - - - - 0 - 0 - 378 - 193 - - - - RealSense 3D Tracker settings - - - - images/RS.pngimages/RS.png - - - Qt::LeftToRight - - - false - - - - - - There is no configuration available at the moment. - -The application will activate your camera for face tracking by the -Intel® RealSenseâ„¢ SDK. By design, the application has no direct access -to any camera images. - -In order to use this tracker, you need a PC equipped with -an Intel® RealSenseâ„¢ R200 camera and the RealSenseâ„¢ SDK R4 runtime. - - - - - - - Install SDK Runtime R4 - - - - - - - QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_rs/images/RS.png b/ftnoir_tracker_rs/images/RS.png deleted file mode 100644 index 4ca11aac..00000000 Binary files a/ftnoir_tracker_rs/images/RS.png and /dev/null differ diff --git a/ftnoir_tracker_rs/images/intel-16x16.png b/ftnoir_tracker_rs/images/intel-16x16.png deleted file mode 100644 index e985ace1..00000000 Binary files a/ftnoir_tracker_rs/images/intel-16x16.png and /dev/null differ diff --git a/ftnoir_tracker_rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe b/ftnoir_tracker_rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe deleted file mode 100644 index 34ecc9df..00000000 Binary files a/ftnoir_tracker_rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe and /dev/null differ diff --git a/ftnoir_tracker_rs/rs_impl/bin/opentrack-tracker-rs-impl.exe b/ftnoir_tracker_rs/rs_impl/bin/opentrack-tracker-rs-impl.exe deleted file mode 100644 index 1e2a57f1..00000000 Binary files a/ftnoir_tracker_rs/rs_impl/bin/opentrack-tracker-rs-impl.exe and /dev/null differ diff --git a/ftnoir_tracker_rs/rs_impl/build.bat b/ftnoir_tracker_rs/rs_impl/build.bat deleted file mode 100644 index 15206431..00000000 --- a/ftnoir_tracker_rs/rs_impl/build.bat +++ /dev/null @@ -1,2 +0,0 @@ -cd "%VS120COMNTOOLS%\..\..\VC" -vcvarsall x64 && cd %~dp0 && CL /nologo /Ox /DUNICODE /D_UNICODE /MT /I"%RSSDK_DIR%\opensource\include" ftnoir_tracker_rs_impl.cpp udp_sender.cpp "%RSSDK_DIR%\opensource\src\libpxc\libpxc.cpp" /link ADVAPI32.LIB Ws2_32.lib /SUBSYSTEM:CONSOLE /OUT:bin\opentrack-tracker-rs-impl.exe \ No newline at end of file diff --git a/ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.cpp b/ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.cpp deleted file mode 100644 index c1ba5c75..00000000 --- a/ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ftnoir_tracker_rs_impl.h" -#include -#include - -PXCSenseManager* g_senseManager = NULL; -PXCFaceData* g_faceData = NULL; - -pxcStatus rs_tracker_set_configuration(PXCFaceModule *faceModule){ - pxcStatus retStatus; - PXCFaceConfiguration *faceConfig = NULL; - - if (faceModule == NULL) - return PXC_STATUS_HANDLE_INVALID; - - faceConfig = faceModule->CreateActiveConfiguration(); - if (faceConfig == NULL){ - return PXC_STATUS_HANDLE_INVALID; - } - - faceConfig->pose.isEnabled = true; - faceConfig->pose.maxTrackedFaces = 1; - faceConfig->pose.smoothingLevel = PXCFaceConfiguration::SmoothingLevelType::SMOOTHING_DISABLED; - faceConfig->strategy = PXCFaceConfiguration::STRATEGY_CLOSEST_TO_FARTHEST; - faceConfig->detection.isEnabled = false; - faceConfig->landmarks.isEnabled = false; - faceConfig->DisableAllAlerts(); - faceConfig->SetTrackingMode(PXCFaceConfiguration::FACE_MODE_COLOR_PLUS_DEPTH); - - retStatus = faceConfig->ApplyChanges(); - if (retStatus != PXC_STATUS_NO_ERROR){ - faceConfig->Release(); - return retStatus; - } - - faceConfig->Release(); - return PXC_STATUS_NO_ERROR; -} - -int rs_tracker_impl_start(){ - pxcStatus retStatus; - PXCFaceModule *faceModule = NULL; - - g_senseManager = PXCSenseManager::CreateInstance(); - if (g_senseManager == NULL){ - rs_tracker_impl_end(); - return PXC_STATUS_HANDLE_INVALID; - } - - retStatus = g_senseManager->EnableFace(); - if (retStatus != PXC_STATUS_NO_ERROR){ - rs_tracker_impl_end(); - return retStatus; - } - - faceModule = g_senseManager->QueryFace(); - if (faceModule == NULL){ - rs_tracker_impl_end(); - return PXC_STATUS_HANDLE_INVALID; - } - - retStatus = rs_tracker_set_configuration(faceModule); - if (retStatus != PXC_STATUS_NO_ERROR){ - rs_tracker_impl_end(); - return PXC_STATUS_HANDLE_INVALID; - } - - retStatus = g_senseManager->Init(); - if (retStatus != PXC_STATUS_NO_ERROR){ - rs_tracker_impl_end(); - return retStatus; - } - - g_faceData = faceModule->CreateOutput(); - if (g_faceData == NULL){ - rs_tracker_impl_end(); - return PXC_STATUS_HANDLE_INVALID; - } - - return PXC_STATUS_NO_ERROR; -} - -int rs_tracker_impl_update_pose(double *data){ - pxcStatus retStatus; - PXCFaceData::PoseEulerAngles angles; - PXCFaceData::HeadPosition headPosition; - PXCFaceData::Face *face = NULL; - PXCFaceData::PoseData *pose = NULL; - bool poseAnglesAvailable = false; - bool headPositionAvailable = false; - - if (g_senseManager != NULL && g_faceData != NULL - && (retStatus = g_senseManager->AcquireFrame(true, 16)) == PXC_STATUS_NO_ERROR){ - - retStatus = g_faceData->Update(); - if (retStatus != PXC_STATUS_NO_ERROR){ - rs_tracker_impl_end(); - return retStatus; - } - - pxcI32 numberOfDetectedFaces = g_faceData->QueryNumberOfDetectedFaces(); - for (pxcI32 i = 0; i < numberOfDetectedFaces; ++i) { - face = g_faceData->QueryFaceByIndex(0); - if (face == NULL) continue; - - pose = face->QueryPose(); - if (pose == NULL) continue; - - poseAnglesAvailable = pose->QueryPoseAngles(&angles); - if (!poseAnglesAvailable) continue; - - headPositionAvailable = pose->QueryHeadPosition(&headPosition); - if (!headPositionAvailable) continue; - - //TODO: use pxcI32 pose->QueryConfidence(); ? for data[6] or to filter here ? - - //x, y, z: cm - data[0] = headPosition.headCenter.x / 10.; - data[1] = headPosition.headCenter.y / 10.; - data[2] = headPosition.headCenter.z / 10.; - - //yaw, pitch, roll: degrees - data[3] = -angles.yaw; - data[4] = angles.pitch; - data[5] = -angles.roll; - } - - g_senseManager->ReleaseFrame(); - } - - return retStatus; -} - -int rs_tracker_impl_end(){ - if (g_faceData != NULL){ - g_faceData->Release(); - g_faceData = NULL; - } - - if (g_senseManager != NULL){ - g_senseManager->Release(); - g_senseManager = NULL; - } - return PXC_STATUS_NO_ERROR; -} diff --git a/ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.h b/ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.h deleted file mode 100644 index 0e4073d0..00000000 --- a/ftnoir_tracker_rs/rs_impl/ftnoir_tracker_rs_impl.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once -#ifdef EXPORT_RS_IMPL -#define RSTRACKERIMPL_VISIBILITY __declspec( dllexport ) -#else -#define RSTRACKERIMPL_VISIBILITY -#endif - -extern "C" { - RSTRACKERIMPL_VISIBILITY int rs_tracker_impl_start(); - RSTRACKERIMPL_VISIBILITY int rs_tracker_impl_update_pose(double *pose); - RSTRACKERIMPL_VISIBILITY int rs_tracker_impl_end(); -} diff --git a/ftnoir_tracker_rs/rs_impl/udp_sender.cpp b/ftnoir_tracker_rs/rs_impl/udp_sender.cpp deleted file mode 100644 index 095edd8f..00000000 --- a/ftnoir_tracker_rs/rs_impl/udp_sender.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation - * Author: Xavier Hallade - * 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. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ftnoir_tracker_rs_impl.h" -#include -#include -#include -#include - -#define UDP_PORT 4242 - -int main(){ - double pose[6] = { 0., 0., 0., 0., 0., 0. }; - struct sockaddr_in socketInfo; - SOCKET s = 0; - WSADATA wsa; - - int retStatus = rs_tracker_impl_start(); - if (retStatus != 0){ - exit(retStatus); - } - - if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) //init winsocketapi - exit(EXIT_FAILURE); - - memset(&socketInfo, 0, sizeof(socketInfo)); - socketInfo.sin_family = AF_INET; - socketInfo.sin_port = htons(UDP_PORT); - InetPton(AF_INET, L"127.0.0.1", &socketInfo.sin_addr.S_un.S_addr); - - if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) //create UDP socket - exit(EXIT_FAILURE); - - for(;;) { - retStatus = rs_tracker_impl_update_pose(pose); - if(retStatus == 0){ //no error - if (sendto(s, (char*)&pose, sizeof(pose), 0, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) == SOCKET_ERROR) //send new data - exit(EXIT_FAILURE); - } - - if(retStatus != 0 && retStatus != -303)// -303=timeout and 0 are ok, else we've got to stop. - break; - } - - closesocket(s); - WSACleanup(); - - return retStatus; -} diff --git a/ftnoir_tracker_rs/rs_tracker.qrc b/ftnoir_tracker_rs/rs_tracker.qrc deleted file mode 100644 index 155a5bd1..00000000 --- a/ftnoir_tracker_rs/rs_tracker.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - images/RS.png - images/intel-16x16.png - - diff --git a/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui b/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui deleted file mode 100644 index cb9362ca..00000000 --- a/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui +++ /dev/null @@ -1,208 +0,0 @@ - - - UICFTNClientControls - - - Qt::NonModal - - - - 0 - 0 - 195 - 224 - - - - UDP tracker settings - - - - ../facetracknoir/images/facetracknoir.png../facetracknoir/images/facetracknoir.png - - - Qt::LeftToRight - - - false - - - - - - - 0 - 0 - - - - - - - - - - Port - - - - - - - 0 - - - 65535 - - - - - - - - - - Add to axis - - - - - - yaw - - - - - - - - 0 - - - - - +90 - - - - - -90 - - - - - +180 - - - - - -180 - - - - - - - - pitch - - - - - - - roll - - - - - - - - 0 - - - - - +90 - - - - - -90 - - - - - +180 - - - - - -180 - - - - - - - - - 0 - - - - - +90 - - - - - -90 - - - - - +180 - - - - - -180 - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp deleted file mode 100644 index 1610f917..00000000 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2014, Stanislaw Halik - - * 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_tracker_udp.h" -#include "opentrack/plugin-api.hpp" - -FTNoIR_Tracker::FTNoIR_Tracker() : last_recv_pose { 0,0,0, 0,0,0 }, should_quit(false) {} - -FTNoIR_Tracker::~FTNoIR_Tracker() -{ - should_quit = true; - wait(); -} - -void FTNoIR_Tracker::run() { - QByteArray datagram; - datagram.resize(sizeof(last_recv_pose)); - (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); - for (;;) { - if (should_quit) - break; - { - QMutexLocker foo(&mutex); - while (sock.hasPendingDatagrams()) { - sock.readDatagram((char * ) last_recv_pose, sizeof(double[6])); - } - } - msleep(1); - } -} - -void FTNoIR_Tracker::start_tracker(QFrame*) -{ - start(); - sock.moveToThread(this); -} - -void FTNoIR_Tracker::data(double *data) -{ - QMutexLocker foo(&mutex); - for (int i = 0; i < 6; i++) - data[i] = last_recv_pose[i]; - - int values[] = { - 0, - 90, - -90, - 180, - -180, - }; - int indices[] = { - s.add_yaw, - s.add_pitch, - s.add_roll, - }; - - for (int i = 0; i < 3; i++) - { - int k = std::min(sizeof(values)/sizeof(values[0]), std::max(0, indices[i])); - data[Yaw + i] += values[k]; - } -} - - -OPENTRACK_DECLARE_TRACKER(FTNoIR_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.h b/ftnoir_tracker_udp/ftnoir_tracker_udp.h deleted file mode 100644 index 6de5b295..00000000 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include "ui_ftnoir_ftnclientcontrols.h" -#include -#include -#include -#include "opentrack/plugin-api.hpp" -#include "opentrack/options.hpp" -using namespace options; - -struct settings : opts { - value port; - value add_yaw, add_pitch, add_roll; - settings() : - opts("udp-tracker"), - port(b, "port", 4242), - add_yaw(b, "add-yaw", 0), - add_pitch(b, "add-pitch", 0), - add_roll(b, "add-roll", 0) - {} -}; - -class FTNoIR_Tracker : public ITracker, protected QThread -{ -public: - FTNoIR_Tracker(); - ~FTNoIR_Tracker() override; - void start_tracker(QFrame *) override; - void data(double *data) override; -protected: - void run() override; -private: - QUdpSocket sock; - double last_recv_pose[6]; - QMutex mutex; - settings s; - volatile bool should_quit; -}; - -class TrackerControls: public ITrackerDialog -{ - Q_OBJECT -public: - TrackerControls(); - void register_tracker(ITracker *) override {} - void unregister_tracker() override {} -private: - Ui::UICFTNClientControls ui; - settings s; -private slots: - void doOK(); - void doCancel(); -}; - -class FTNoIR_TrackerDll : public Metadata -{ -public: - QString name() { return QString("UDP sender"); } - QIcon icon() { return QIcon(":/images/facetracknoir.png"); } -}; - diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp deleted file mode 100644 index 5e7d5437..00000000 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ftnoir_tracker_udp.h" -#include "opentrack/plugin-api.hpp" - -TrackerControls::TrackerControls() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.port, ui.spinPortNumber); - tie_setting(s.add_yaw, ui.add_yaw); - tie_setting(s.add_pitch, ui.add_pitch); - tie_setting(s.add_roll, ui.add_roll); -} - -void TrackerControls::doOK() { - s.b->save(); - this->close(); -} - -void TrackerControls::doCancel() { - s.b->reload(); - this->close(); -} - diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt new file mode 100644 index 00000000..4f5fd724 --- /dev/null +++ b/opentrack-compat/CMakeLists.txt @@ -0,0 +1,4 @@ +opentrack_boilerplate(opentrack-compat STATIC NO-COMPAT) +if(NOT WIN32 AND NOT APPLE) + target_link_libraries(opentrack-compat rt) +endif() diff --git a/opentrack/CMakeLists.txt b/opentrack/CMakeLists.txt new file mode 100644 index 00000000..4581f394 --- /dev/null +++ b/opentrack/CMakeLists.txt @@ -0,0 +1,10 @@ +opentrack_boilerplate(opentrack-api NO-LIBRARY) +opentrack_qt(opentrack-api) +add_library(opentrack-api STATIC ${opentrack-api-all}) +opentrack_compat(opentrack-api) +target_link_libraries(opentrack-api ${MY_QT_LIBS}) +if(NOT WIN32) + target_link_libraries(opentrack-api dl) +else() + target_link_libraries(opentrack-api winmm) +endif() diff --git a/opentrack/mappings.hpp b/opentrack/mappings.hpp index 2391efd1..bb38a3ca 100644 --- a/opentrack/mappings.hpp +++ b/opentrack/mappings.hpp @@ -10,7 +10,7 @@ #include #include "options.hpp" using namespace options; -#include "qfunctionconfigurator/functionconfig.h" +#include "spline-widget/functionconfig.h" #include "main-settings.hpp" class Mapping { diff --git a/opentrack/tracker.h b/opentrack/tracker.h index b0e89455..890660e1 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -16,7 +16,7 @@ #include "simple-mat.hpp" #include "selected-libraries.hpp" -#include "qfunctionconfigurator/functionconfig.h" +#include "spline-widget/functionconfig.h" #include "main-settings.hpp" #include "options.hpp" diff --git a/pose-widget/CMakeLists.txt b/pose-widget/CMakeLists.txt new file mode 100644 index 00000000..66891c21 --- /dev/null +++ b/pose-widget/CMakeLists.txt @@ -0,0 +1,6 @@ +opentrack_boilerplate(opentrack-pose-widget NO-LIBRARY) +opentrack_qt(opentrack-pose-widget) +add_library(opentrack-pose-widget STATIC ${opentrack-pose-widget-all}) +opentrack_compat(opentrack-pose-widget) +target_include_directories(opentrack-pose-widget PUBLIC pose-widget/) # else Qt moc breaks +target_link_libraries(opentrack-pose-widget ${MY_QT_LIBS}) diff --git a/protocol-fg/CMakeLists.txt b/protocol-fg/CMakeLists.txt new file mode 100644 index 00000000..151b30ee --- /dev/null +++ b/protocol-fg/CMakeLists.txt @@ -0,0 +1 @@ +opentrack_boilerplate(opentrack-proto-fgfs) diff --git a/protocol-fg/fg-protocol.qrc b/protocol-fg/fg-protocol.qrc new file mode 100644 index 00000000..1c685437 --- /dev/null +++ b/protocol-fg/fg-protocol.qrc @@ -0,0 +1,5 @@ + + + images/flightgear.png + + diff --git a/protocol-fg/fgtypes.h b/protocol-fg/fgtypes.h new file mode 100644 index 00000000..2e493f46 --- /dev/null +++ b/protocol-fg/fgtypes.h @@ -0,0 +1,27 @@ +/******************************************************************************** +* FaceTrackNoIR This program is a private project of the some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2010 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage * +* * +* Type definitions for the FlightGear server. * +********************************************************************************/ +#pragma once +#ifndef INCLUDED_FGTYPES_H +#define INCLUDED_FGTYPES_H + +// +// x,y,z position in metres, heading, pitch and roll in degrees... +// +#pragma pack(push, 2) +struct TFlightGearData { + double x, y, z, h, p, r; + int status; +}; +#pragma pack(pop) + +#endif//INCLUDED_FGTYPES_H diff --git a/protocol-fg/ftnoir_fgcontrols.ui b/protocol-fg/ftnoir_fgcontrols.ui new file mode 100644 index 00000000..575549d6 --- /dev/null +++ b/protocol-fg/ftnoir_fgcontrols.ui @@ -0,0 +1,143 @@ + + + UICFGControls + + + Qt::NonModal + + + + 0 + 0 + 415 + 112 + + + + FlightGear protocol settings + + + + :/images/filter-16.png:/images/filter-16.png + + + Qt::LeftToRight + + + false + + + + + + IP-address remote PC + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + Port-number + + + + + + + 1000 + + + 10000 + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + spinIPFirstNibble + spinIPSecondNibble + spinIPThirdNibble + spinIPFourthNibble + spinPortNumber + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-fg/ftnoir_protocol_fg.cpp b/protocol-fg/ftnoir_protocol_fg.cpp new file mode 100644 index 00000000..660a7352 --- /dev/null +++ b/protocol-fg/ftnoir_protocol_fg.cpp @@ -0,0 +1,38 @@ +/* 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_fg.h" +#include "opentrack/plugin-api.hpp" + +// For Todd and Arda Kutlu + +void FTNoIR_Protocol::pose(const double* headpose) { + FlightData.x = headpose[TX] * 1e-2; + FlightData.y = headpose[TY] * 1e-2; + FlightData.z = headpose[TZ] * 1e-2; + FlightData.p = headpose[Pitch]; + FlightData.h = headpose[Yaw]; + FlightData.r = headpose[Roll]; + FlightData.status = 1; + QHostAddress destIP(QString("%1.%2.%3.%4").arg( + QString::number(static_cast(s.ip1)), + QString::number(static_cast(s.ip2)), + QString::number(static_cast(s.ip3)), + QString::number(static_cast(s.ip4)))); + int destPort = s.port; + (void) outSocket.writeDatagram(reinterpret_cast(&FlightData), sizeof(FlightData), destIP, static_cast(destPort)); +} + +bool FTNoIR_Protocol::correct() +{ + return outSocket.bind(QHostAddress::Any, 0, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FGControls, FTNoIR_ProtocolDll) diff --git a/protocol-fg/ftnoir_protocol_fg.h b/protocol-fg/ftnoir_protocol_fg.h new file mode 100644 index 00000000..de528270 --- /dev/null +++ b/protocol-fg/ftnoir_protocol_fg.h @@ -0,0 +1,69 @@ +/* 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. * + */ +#pragma once +#include "ui_ftnoir_fgcontrols.h" +#include "fgtypes.h" +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value ip1, ip2, ip3, ip4; + value port; + settings() : + opts("flightgear-proto"), + ip1(b, "ip1", 192), + ip2(b, "ip2", 168), + ip3(b, "ip3", 0), + ip4(b, "ip4", 2), + port(b, "port", 5542) + {} +}; + +class FTNoIR_Protocol : public IProtocol +{ +public: + bool correct(); + void pose(const double *headpose); + QString game_name() { + return "FlightGear"; + } +private: + settings s; + TFlightGearData FlightData; + QUdpSocket outSocket; +}; + +// Widget that has controls for FTNoIR protocol client-settings. +class FGControls: public IProtocolDialog +{ + Q_OBJECT +public: + FGControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} +private: + Ui::UICFGControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("FlightGear"); } + QIcon icon() { return QIcon(":/images/flightgear.png"); } +}; diff --git a/protocol-fg/ftnoir_protocol_fg_dialog.cpp b/protocol-fg/ftnoir_protocol_fg_dialog.cpp new file mode 100644 index 00000000..1d583115 --- /dev/null +++ b/protocol-fg/ftnoir_protocol_fg_dialog.cpp @@ -0,0 +1,46 @@ +/* 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_fg.h" +#include +#include +#include "opentrack/plugin-api.hpp" + +//******************************************************************************************************* +// FaceTrackNoIR Client Settings-dialog. +//******************************************************************************************************* + +// +// Constructor for server-settings-dialog +// +FGControls::FGControls() +{ + ui.setupUi( this ); + + tie_setting(s.ip1, ui.spinIPFirstNibble); + tie_setting(s.ip2, ui.spinIPSecondNibble); + tie_setting(s.ip3, ui.spinIPThirdNibble); + tie_setting(s.ip4, ui.spinIPFourthNibble); + tie_setting(s.port, ui.spinPortNumber); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); +} + +void FGControls::doOK() { + s.b->save(); + this->close(); +} + +void FGControls::doCancel() { + s.b->reload(); + this->close(); +} + diff --git a/protocol-fg/images/flightgear.png b/protocol-fg/images/flightgear.png new file mode 100644 index 00000000..2a546642 Binary files /dev/null and b/protocol-fg/images/flightgear.png differ diff --git a/protocol-fsuipc/CMakeLists.txt b/protocol-fsuipc/CMakeLists.txt new file mode 100644 index 00000000..ec897ae8 --- /dev/null +++ b/protocol-fsuipc/CMakeLists.txt @@ -0,0 +1,11 @@ +if(WIN32) + set(SDK_FSUIPC "" CACHE PATH "FSUIPC for older MS FSX path") + if(SDK_FSUIPC) + opentrack_boilerplate(opentrack-proto-fsuipc) + target_link_libraries(opentrack-proto-fsuipc ${SDK_FSUIPC}/FSUIPC_User.lib) + target_include_directories(opentrack-proto-fsuipc SYSTEM PUBLIC ${SDK_FSUIPC}) + if(MSVC) + set_target_properties(opentrack-proto-fsuipc PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBC.lib") + endif() + endif() +endif() diff --git a/protocol-fsuipc/fsuipc-protocol.qrc b/protocol-fsuipc/fsuipc-protocol.qrc new file mode 100644 index 00000000..34756f84 --- /dev/null +++ b/protocol-fsuipc/fsuipc-protocol.qrc @@ -0,0 +1,5 @@ + + + images/fs9.png + + diff --git a/protocol-fsuipc/ftnoir_fsuipccontrols.ui b/protocol-fsuipc/ftnoir_fsuipccontrols.ui new file mode 100644 index 00000000..637e4dba --- /dev/null +++ b/protocol-fsuipc/ftnoir_fsuipccontrols.ui @@ -0,0 +1,134 @@ + + + UICFSUIPCControls + + + Qt::NonModal + + + + 0 + 0 + 512 + 100 + + + + FSUIPC settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + 230 + 0 + + + + Location of FSUIPC.dll + + + QFrame::Box + + + QFrame::Sunken + + + 1 + + + Location of FSUIPC.dll + + + + + + + The DLL should be located in the Modules/ directory of MS FS 2004 + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 35 + 16777215 + + + + ... + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-fsuipc/ftnoir_protocol_fsuipc.cpp b/protocol-fsuipc/ftnoir_protocol_fsuipc.cpp new file mode 100644 index 00000000..702a92d4 --- /dev/null +++ b/protocol-fsuipc/ftnoir_protocol_fsuipc.cpp @@ -0,0 +1,149 @@ +/* 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 "opentrack/plugin-api.hpp" + +FTNoIR_Protocol::FTNoIR_Protocol() +{ + prevPosX = 0.0f; + prevPosY = 0.0f; + prevPosZ = 0.0f; + prevRotX = 0.0f; + prevRotY = 0.0f; + prevRotZ = 0.0f; +} + +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + FSUIPC_Close(); + FSUIPCLib.unload(); +} + +int FTNoIR_Protocol::scale2AnalogLimits( float x, float min_x, float max_x ) { +double y; +double local_x; + + local_x = x; + if (local_x > max_x) { + local_x = max_x; + } + if (local_x < min_x) { + local_x = min_x; + } + y = ( 16383 * local_x ) / max_x; + + return (int) y; +} + +void FTNoIR_Protocol::pose(const double *headpose ) { + DWORD result; + TFSState pitch; + TFSState yaw; + TFSState roll; + WORD FSZoom; + + float virtPosX; + float virtPosY; + float virtPosZ; + + float virtRotX; + float virtRotY; + float virtRotZ; + +// qDebug() << "FSUIPCServer::run() says: started!"; + + virtRotX = -headpose[Pitch]; // degrees + virtRotY = headpose[Yaw]; + virtRotZ = headpose[Roll]; + + virtPosX = 0.0f; // cm, X and Y are not working for FS2002/2004! + virtPosY = 0.0f; + virtPosZ = headpose[TZ]; + + // + // Init. the FSUIPC offsets (derived from Free-track...) + // + pitch.Control = 66503; + yaw.Control = 66504; + roll.Control = 66505; + + // + // Only do this when the data has changed. This way, the HAT-switch can be used when tracking is OFF. + // + if ((prevPosX != virtPosX) || (prevPosY != virtPosY) || (prevPosZ != virtPosZ) || + (prevRotX != virtRotX) || (prevRotY != virtRotY) || (prevRotZ != virtRotZ)) { + // + // Open the connection + // + 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))) { +// qDebug() << "FSUIPCServer::run() says: FSUIPC opened succesfully"; + // + // Write the 4! DOF-data to FS. Only rotations and zoom are possible. + // + pitch.Value = scale2AnalogLimits(virtRotX, -180, 180); + FSUIPC_Write(0x3110, 8, &pitch, &result); + + yaw.Value = scale2AnalogLimits(virtRotY, -180, 180); + FSUIPC_Write(0x3110, 8, &yaw, &result); + + roll.Value = scale2AnalogLimits(virtRotZ, -180, 180); + FSUIPC_Write(0x3110, 8, &roll, &result); + + FSZoom = (WORD) (64/50) * virtPosZ + 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(); + } + } + } + + prevPosX = virtPosX; + prevPosY = virtPosY; + prevPosZ = virtPosZ; + prevRotX = virtRotX; + prevRotY = virtRotY; + prevRotZ = virtRotZ; +} + +bool FTNoIR_Protocol::correct() +{ + qDebug() << "correct says: Starting Function"; + + // + // Load the DLL. + // + FSUIPCLib.setFileName( s.LocationOfDLL ); + if (FSUIPCLib.load() != true) { + qDebug() << "correct says: Error loading FSUIPC DLL"; + return false; + } + else { + qDebug() << "correct says: FSUIPC DLL loaded."; + } + + return true; +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FSUIPCControls, FTNoIR_ProtocolDll) diff --git a/protocol-fsuipc/ftnoir_protocol_fsuipc.h b/protocol-fsuipc/ftnoir_protocol_fsuipc.h new file mode 100644 index 00000000..c8e91a42 --- /dev/null +++ b/protocol-fsuipc/ftnoir_protocol_fsuipc.h @@ -0,0 +1,90 @@ +/* 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. * + */ +#pragma once +#ifndef INCLUDED_FSUIPCSERVER_H +#define INCLUDED_FSUIPCSERVER_H + +#include +#include +#include "FSUIPC_User.h" +#include "opentrack/plugin-api.hpp" +#include "ui_ftnoir_fsuipccontrols.h" +#include +#include +#include +#include +#include +#include +#include +#include "opentrack/options.hpp" +using namespace options; + +#define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll" + +struct settings : opts { + value LocationOfDLL; + settings() : + opts("proto-fsuipc"), + LocationOfDLL(b, "dll-location", FSUIPC_FILENAME) + {} +}; + +#pragma pack(push,1) // All fields in structure must be byte aligned. +typedef struct +{ + int Control; // Control identifier + int Value; // Value of DOF +} TFSState; +#pragma pack(pop) + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol(); + ~FTNoIR_Protocol() override; + bool correct(); + void pose(const double* headpose); + QString game_name() { + return "Microsoft Flight Simulator X"; + } +private: + QLibrary FSUIPCLib; + double prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ; + static int scale2AnalogLimits( float x, float min_x, float max_x ); + settings s; +}; + +class FSUIPCControls: public IProtocolDialog +{ + Q_OBJECT +public: + FSUIPCControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} +private: + Ui::UICFSUIPCControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); + void getLocationOfDLL(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("FSUIPC -- Microsoft FS2002/FS2004"); } + QIcon icon() { return QIcon(":/images/fs9.png"); } +}; + + +#endif//INCLUDED_FSUIPCSERVER_H +//END diff --git a/protocol-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp b/protocol-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp new file mode 100644 index 00000000..d573420a --- /dev/null +++ b/protocol-fsuipc/ftnoir_protocol_fsuipc_dialog.cpp @@ -0,0 +1,43 @@ +/* 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 "opentrack/plugin-api.hpp" + +FSUIPCControls::FSUIPCControls() +{ + ui.setupUi( this ); + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); + connect(ui.btnFindDLL, SIGNAL(clicked()), this, SLOT(getLocationOfDLL())); + + tie_setting(s.LocationOfDLL, ui.txtLocationOfDLL); +} + +void FSUIPCControls::doOK() { + s.b->save(); + this->close(); +} + +void FSUIPCControls::doCancel() { + s.b->reload(); + close(); +} + +void FSUIPCControls::getLocationOfDLL() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Locate file"), + ui.txtLocationOfDLL->text(), + tr("FSUIPC DLL file (FSUIPC*.dll);;All Files (*)")); + if (!fileName.isEmpty()) { + s.LocationOfDLL = fileName; + } +} + diff --git a/protocol-fsuipc/images/fs9.png b/protocol-fsuipc/images/fs9.png new file mode 100644 index 00000000..914c9dcb Binary files /dev/null and b/protocol-fsuipc/images/fs9.png differ diff --git a/protocol-fsuipc/images/fs91.png b/protocol-fsuipc/images/fs91.png new file mode 100644 index 00000000..f9540d1d Binary files /dev/null and b/protocol-fsuipc/images/fs91.png differ diff --git a/protocol-ft/CMakeLists.txt b/protocol-ft/CMakeLists.txt new file mode 100644 index 00000000..44f95ba3 --- /dev/null +++ b/protocol-ft/CMakeLists.txt @@ -0,0 +1,4 @@ +if(WIN32) + opentrack_boilerplate(opentrack-proto-freetrack) + target_link_libraries(opentrack-proto-freetrack opentrack-csv opentrack-compat) +endif() diff --git a/protocol-ft/ft-protocol.qrc b/protocol-ft/ft-protocol.qrc new file mode 100644 index 00000000..c04959f0 --- /dev/null +++ b/protocol-ft/ft-protocol.qrc @@ -0,0 +1,5 @@ + + + images/freetrack.png + + diff --git a/protocol-ft/ftnoir_ftcontrols.ui b/protocol-ft/ftnoir_ftcontrols.ui new file mode 100644 index 00000000..5356d2e5 --- /dev/null +++ b/protocol-ft/ftnoir_ftcontrols.ui @@ -0,0 +1,182 @@ + + + UICFTControls + + + Qt::NonModal + + + true + + + + 0 + 0 + 422 + 305 + + + + + 0 + 0 + + + + + 0 + 0 + + + + freetrack protocol settings + + + + :/images/freetrack.png:/images/freetrack.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + TIRViews + + + Qt::AlignJustify|Qt::AlignTop + + + false + + + + + + Qt::RightToLeft + + + Memory hacks + + + + + + + Only for very old and buggy old games such as CFS3. + + + false + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + + + + + 0 + 0 + + + + Repair NPClient location + + + Qt::AlignJustify|Qt::AlignTop + + + false + + + + + + Locate DLL + + + + + + + Replace the registry entry if you want to use other software with the NPClient protocol and it doesn't work automatically. + + + true + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + 0 + 0 + + + + Select interface + + + Qt::AlignJustify|Qt::AlignTop + + + false + + + + + + + + + Disable one of the protocols if game is confused by presence of both at the same time. + + + true + + + + + + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-ft/ftnoir_protocol_ft.cpp b/protocol-ft/ftnoir_protocol_ft.cpp new file mode 100644 index 00000000..05253174 --- /dev/null +++ b/protocol-ft/ftnoir_protocol_ft.cpp @@ -0,0 +1,166 @@ +/* Copyright (c) 2013-2015 Stanislaw Halik + * 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_ft.h" +#include "csv/csv.h" + +FTNoIR_Protocol::FTNoIR_Protocol() : + shm(FREETRACK_HEAP, FREETRACK_MUTEX, sizeof(FTHeap)), + pMemData((FTHeap*) shm.ptr()), + viewsStart(nullptr), + viewsStop(nullptr), + intGameID(0) +{ +} + +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + if (viewsStop != NULL) { + viewsStop(); + FTIRViewsLib.unload(); + } + dummyTrackIR.terminate(); + dummyTrackIR.kill(); + dummyTrackIR.waitForFinished(50); +} + +void FTNoIR_Protocol::pose(const double* headpose) { + float yaw = -getRadsFromDegrees(headpose[Yaw]); + float pitch = -getRadsFromDegrees(headpose[Pitch]); + float roll = getRadsFromDegrees(headpose[Roll]); + float tx = headpose[TX] * 10.f; + float ty = headpose[TY] * 10.f; + float tz = headpose[TZ] * 10.f; + + FTHeap* ft = pMemData; + FTData* data = &ft->data; + + data->RawX = 0; + data->RawY = 0; + data->RawZ = 0; + data->RawPitch = 0; + data->RawYaw = 0; + data->RawRoll = 0; + + data->X = tx; + data->Y = ty; + data->Z = tz; + data->Yaw = yaw; + data->Pitch = pitch; + data->Roll = roll; + + data->X1 = data->DataID; + data->X2 = 0; + data->X3 = 0; + data->X4 = 0; + data->Y1 = 0; + data->Y2 = 0; + data->Y3 = 0; + data->Y4 = 0; + + int32_t id = ft->GameID; + + if (intGameID != id) + { + QString gamename; + { + unsigned char table[8]; + if (CSV::getGameData(id, table, gamename)) + for (int i = 0; i < 8; i++) pMemData->table[i] = table[i]; + } + ft->GameID2 = id; + intGameID = id; + QMutexLocker foo(&this->game_name_mutex); + connected_game = gamename; + } + + data->DataID += 1; +} + +void FTNoIR_Protocol::start_tirviews() { + QString aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll"; + if ( QFile::exists( aFileName )) { + FTIRViewsLib.setFileName(aFileName); + FTIRViewsLib.load(); + + viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart"); + if (viewsStart == NULL) { + qDebug() << "FTServer::run() says: TIRViewsStart function not found in DLL!"; + } + else { + qDebug() << "FTServer::run() says: TIRViewsStart executed!"; + viewsStart(); + } + + // + // Load the Stop function from TIRViews.dll. Call it when terminating the thread. + // + viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop"); + if (viewsStop == NULL) { + qDebug() << "FTServer::run() says: TIRViewsStop function not found in DLL!"; + } + } +} + +void FTNoIR_Protocol::start_dummy() { + + + QString program = QCoreApplication::applicationDirPath() + "/TrackIR.exe"; + dummyTrackIR.setProgram("\"" + program + "\""); + dummyTrackIR.start(); +} + +bool FTNoIR_Protocol::correct() +{ + // Registry settings (in HK_USER) + QSettings settings("Freetrack", "FreetrackClient"); + QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); + + if (!shm.success()) + return false; + + QString aLocation = QCoreApplication::applicationDirPath() + "/"; + + switch (s.intUsedInterface) { + case 0: + // Use both interfaces + settings.setValue( "Path" , aLocation ); + settingsTIR.setValue( "Path" , aLocation ); + break; + case 1: + // Use FreeTrack, disable TrackIR + settings.setValue( "Path" , aLocation ); + settingsTIR.setValue( "Path" , "" ); + break; + case 2: + // Use TrackIR, disable FreeTrack + settings.setValue( "Path" , "" ); + settingsTIR.setValue( "Path" , aLocation ); + break; + default: + break; + } + + if (s.useTIRViews) { + start_tirviews(); + } + + // more games need the dummy executable than previously thought + start_dummy(); + + pMemData->data.DataID = 1; + pMemData->data.CamWidth = 100; + pMemData->data.CamHeight = 250; + pMemData->GameID2 = 0; + for (int i = 0; i < 8; i++) + pMemData->table[i] = 0; + + return true; +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FTControls, FTNoIR_ProtocolDll) diff --git a/protocol-ft/ftnoir_protocol_ft.h b/protocol-ft/ftnoir_protocol_ft.h new file mode 100644 index 00000000..8e50f1cb --- /dev/null +++ b/protocol-ft/ftnoir_protocol_ft.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2013-2015 Stanislaw Halik + * 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. + */ + +#pragma once +#include "ui_ftnoir_ftcontrols.h" +#include "opentrack/plugin-api.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "opentrack-compat/shm.h" +#include "opentrack/options.hpp" +#include "freetrackclient/fttypes.h" +using namespace options; + +struct settings : opts { + value intUsedInterface; + value useTIRViews; + settings() : + opts("proto-freetrack"), + intUsedInterface(b, "used-interfaces", 0), + useTIRViews(b, "use-memory-hacks", false) + {} +}; + +typedef void (__stdcall *importTIRViewsStart)(void); +typedef void (__stdcall *importTIRViewsStop)(void); + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol(); + ~FTNoIR_Protocol() override; + bool correct(); + void pose( const double *headpose ); + QString game_name() override { + QMutexLocker foo(&game_name_mutex); + return connected_game; + } +private: + settings s; + PortableLockedShm shm; + FTHeap *pMemData; + + QLibrary FTIRViewsLib; + QProcess dummyTrackIR; + importTIRViewsStart viewsStart; + importTIRViewsStop viewsStop; + + int intGameID; + QString connected_game; + QMutex game_name_mutex; + + static inline double getRadsFromDegrees(double degrees) { return degrees * 0.017453; } + void start_tirviews(); + void start_dummy(); +}; + +class FTControls: public IProtocolDialog +{ + Q_OBJECT +public: + FTControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} +private: + Ui::UICFTControls ui; + settings s; +private slots: + void selectDLL(); + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("freetrack 2.0 Enhanced"); } + QIcon icon() { return QIcon(":/images/freetrack.png"); } +}; diff --git a/protocol-ft/ftnoir_protocol_ft_dialog.cpp b/protocol-ft/ftnoir_protocol_ft_dialog.cpp new file mode 100644 index 00000000..25f3a4cb --- /dev/null +++ b/protocol-ft/ftnoir_protocol_ft_dialog.cpp @@ -0,0 +1,60 @@ +/* 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_ft.h" +#include +#include + +FTControls::FTControls() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + connect(ui.bntLocateNPClient, SIGNAL(clicked()), this, SLOT(selectDLL())); + + tie_setting(s.useTIRViews, ui.chkTIRViews); + + ui.cbxSelectInterface->addItem("Enable both"); + ui.cbxSelectInterface->addItem("Use FreeTrack, hide TrackIR"); + ui.cbxSelectInterface->addItem("Use TrackIR, hide FreeTrack"); + + tie_setting(s.intUsedInterface, ui.cbxSelectInterface); + + QFile memhacks_pathname(QCoreApplication::applicationDirPath() + "/TIRViews.dll"); + if (!memhacks_pathname.exists()) { + ui.chkTIRViews->setChecked( false ); + ui.chkTIRViews->setEnabled ( false ); + } + else { + ui.chkTIRViews->setEnabled ( true ); + } +} + +void FTControls::doOK() { + s.b->save(); + this->close(); +} + +void FTControls::doCancel() { + s.b->reload(); + this->close(); +} + +void FTControls::selectDLL() { + QString filename = QFileDialog::getOpenFileName( this, tr("Select the desired NPClient DLL"), QCoreApplication::applicationDirPath() + "/NPClient.dll", tr("Dll file (*.dll);;All Files (*)")); + + if (! filename.isEmpty() ) { + QSettings node("NaturalPoint", "NATURALPOINT\\NPClient Location"); + QFileInfo dllname(filename); + node.setValue( "Path" , dllname.dir().path() ); + } +} + diff --git a/protocol-ft/images/freetrack.png b/protocol-ft/images/freetrack.png new file mode 100644 index 00000000..c184dc88 Binary files /dev/null and b/protocol-ft/images/freetrack.png differ diff --git a/protocol-ftn/CMakeLists.txt b/protocol-ftn/CMakeLists.txt new file mode 100644 index 00000000..a0b74d9c --- /dev/null +++ b/protocol-ftn/CMakeLists.txt @@ -0,0 +1 @@ +opentrack_boilerplate(opentrack-proto-udp) diff --git a/protocol-ftn/ftnoir_ftncontrols.ui b/protocol-ftn/ftnoir_ftncontrols.ui new file mode 100644 index 00000000..ca811e99 --- /dev/null +++ b/protocol-ftn/ftnoir_ftncontrols.ui @@ -0,0 +1,266 @@ + + + UICFTNControls + + + Qt::NonModal + + + + 0 + 0 + 411 + 169 + + + + UDP protocol settings + + + + :/images/facetracknoir.png:/images/facetracknoir.png + + + Qt::LeftToRight + + + false + + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + IP-address remote PC + + + + + + + Port-number + + + + + + + 1000 + + + 10000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Enter IP-address and port-number for the remote PC. + + + true + + + + + + + Remember: you may have to change firewall-settings too! + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + spinIPFirstNibble + spinIPSecondNibble + spinIPThirdNibble + spinIPFourthNibble + spinPortNumber + btnOK + btnCancel + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-ftn/ftnoir_protocol_ftn.cpp b/protocol-ftn/ftnoir_protocol_ftn.cpp new file mode 100644 index 00000000..db852f55 --- /dev/null +++ b/protocol-ftn/ftnoir_protocol_ftn.cpp @@ -0,0 +1,34 @@ +/* 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_ftn.h" +#include +#include "opentrack/plugin-api.hpp" + +FTNoIR_Protocol::FTNoIR_Protocol() +{ +} + +void FTNoIR_Protocol::pose(const double *headpose) { + int destPort = s.port; + QHostAddress destIP(QString("%1.%2.%3.%4").arg( + QString::number(static_cast(s.ip1)), + QString::number(static_cast(s.ip2)), + QString::number(static_cast(s.ip3)), + QString::number(static_cast(s.ip4)))); + outSocket.writeDatagram((const char *) headpose, sizeof( double[6] ), destIP, destPort); +} + +bool FTNoIR_Protocol::correct() +{ + return outSocket.bind(QHostAddress::Any, 0, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FTNControls, FTNoIR_ProtocolDll) diff --git a/protocol-ftn/ftnoir_protocol_ftn.h b/protocol-ftn/ftnoir_protocol_ftn.h new file mode 100644 index 00000000..7fe6c225 --- /dev/null +++ b/protocol-ftn/ftnoir_protocol_ftn.h @@ -0,0 +1,69 @@ +/* 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. * + */ +#pragma once + +#include "ui_ftnoir_ftncontrols.h" +#include +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value ip1, ip2, ip3, ip4, port; + settings() : + opts("udp-proto"), + ip1(b, "ip1", 192), + ip2(b, "ip2", 168), + ip3(b, "ip3", 0), + ip4(b, "ip4", 2), + port(b, "port", 4242) + {} +}; + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol(); + bool correct(); + void pose(const double *headpose); + QString game_name() { + return "UDP Tracker"; + } +private: + QUdpSocket outSocket; + settings s; +}; + +// Widget that has controls for FTNoIR protocol client-settings. +class FTNControls: public IProtocolDialog +{ + Q_OBJECT +public: + FTNControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} +private: + Ui::UICFTNControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("UDP receiver"); } + QIcon icon() { return QIcon(":/images/facetracknoir.png"); } +}; diff --git a/protocol-ftn/ftnoir_protocol_ftn_dialog.cpp b/protocol-ftn/ftnoir_protocol_ftn_dialog.cpp new file mode 100644 index 00000000..77a1508a --- /dev/null +++ b/protocol-ftn/ftnoir_protocol_ftn_dialog.cpp @@ -0,0 +1,42 @@ +/* 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_ftn.h" +#include "opentrack/plugin-api.hpp" + +FTNControls::FTNControls() +{ + ui.setupUi( this ); + + tie_setting(s.ip1, ui.spinIPFirstNibble); + tie_setting(s.ip2, ui.spinIPSecondNibble); + tie_setting(s.ip3, ui.spinIPThirdNibble); + tie_setting(s.ip4, ui.spinIPFourthNibble); + tie_setting(s.port, ui.spinPortNumber); + + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); +} + +// +// OK clicked on server-dialog +// +void FTNControls::doOK() { + s.b->save(); + this->close(); +} + +// +// Cancel clicked on server-dialog +// +void FTNControls::doCancel() { + s.b->reload(); + this->close(); +} diff --git a/protocol-libevdev/CMakeLists.txt b/protocol-libevdev/CMakeLists.txt new file mode 100644 index 00000000..960a1271 --- /dev/null +++ b/protocol-libevdev/CMakeLists.txt @@ -0,0 +1,10 @@ +if(LINUX OR APPLE) + set(SDK_ENABLE_LIBEVDEV FALSE CACHE BOOL "libevdev virtual joystick protocol support") + if(SDK_ENABLE_LIBEVDEV) + include(FindPkgConfig) + opentrack_boilerplate(opentrack-proto-libevdev) + pkg_check_modules(libevdev REQUIRED QUIET libevdev) + target_link_libraries(opentrack-proto-libevdev ${libevdev_LIBRARIES}) + include_directories(opentrack-proto-libevdev SYSTEM PUBLIC ${libevdev_INCLUDE_DIRS}) + endif() +endif() diff --git a/protocol-libevdev/ftnoir_libevdev_controls.ui b/protocol-libevdev/ftnoir_libevdev_controls.ui new file mode 100644 index 00000000..d2b86445 --- /dev/null +++ b/protocol-libevdev/ftnoir_libevdev_controls.ui @@ -0,0 +1,111 @@ + + + UICLibevdevControls + + + Qt::NonModal + + + + 0 + 0 + 228 + 69 + + + + VJoy + + + + :/images/vjoy.png:/images/vjoy.png + + + Qt::LeftToRight + + + false + + + + + + Make sure rw for /dev/input/uinput! + + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + + + + btnOK + btnCancel + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-libevdev/ftnoir_protocol_libevdev.cpp b/protocol-libevdev/ftnoir_protocol_libevdev.cpp new file mode 100644 index 00000000..96805b39 --- /dev/null +++ b/protocol-libevdev/ftnoir_protocol_libevdev.cpp @@ -0,0 +1,97 @@ +#include "ftnoir_protocol_libevdev.h" +#include "opentrack/plugin-api.hpp" +#include +#include + +#include +#include + +#define CHECK_LIBEVDEV(expr) if ((error = (expr)) != 0) goto error; + +static const int max_input = 65535; +static const int mid_input = 32767; +static const int min_input = 0; + +FTNoIR_Protocol::FTNoIR_Protocol() : dev(NULL), uidev(NULL) +{ + int error = 0; + + dev = libevdev_new(); + + if (!dev) + goto error; + + CHECK_LIBEVDEV(libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD)); + + libevdev_set_name(dev, "opentrack headpose"); + + struct input_absinfo absinfo; + + absinfo.minimum = min_input; + absinfo.maximum = max_input; + absinfo.resolution = 1; + absinfo.value = mid_input; + absinfo.flat = 1; + absinfo.fuzz = 0; + + CHECK_LIBEVDEV(libevdev_enable_event_type(dev, EV_ABS)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_X, &absinfo)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_Y, &absinfo)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_Z, &absinfo)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RX, &absinfo)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RY, &absinfo)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RZ, &absinfo)); + + /* do not remove next 3 lines or udev scripts won't assign 0664 permissions -sh */ + CHECK_LIBEVDEV(libevdev_enable_event_type(dev, EV_KEY)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_KEY, BTN_JOYSTICK, NULL)); + CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_KEY, BTN_TRIGGER, NULL)); + + CHECK_LIBEVDEV(libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev)); + + return; +error: + if (uidev) + libevdev_uinput_destroy(uidev); + if (dev) + libevdev_free(dev); + if (error) + fprintf(stderr, "libevdev error: %d\n", error); + uidev = NULL; + dev = NULL; +} + +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + if (uidev) + libevdev_uinput_destroy(uidev); + if (dev) + libevdev_free(dev); +} + +void FTNoIR_Protocol::pose(const double* headpose) { + static const int axes[] = { + /* translation goes first */ + ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ + }; + + static const int max_value[] = { + 100, + 100, + 100, + 180, + 90, + 180 + }; + + for (int i = 0; i < 6; i++) + { + int value = headpose[i] * mid_input / max_value[i] + mid_input; + int normalized = std::max(std::min(max_input, value), min_input); + (void) libevdev_uinput_write_event(uidev, EV_ABS, axes[i], normalized); + } + + (void) libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0); +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, LibevdevControls, FTNoIR_ProtocolDll) diff --git a/protocol-libevdev/ftnoir_protocol_libevdev.h b/protocol-libevdev/ftnoir_protocol_libevdev.h new file mode 100644 index 00000000..ecb3b201 --- /dev/null +++ b/protocol-libevdev/ftnoir_protocol_libevdev.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2013 Stanislaw Halik + * + * 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 "ui_ftnoir_libevdev_controls.h" + +#include +#include "opentrack/plugin-api.hpp" + +extern "C" { +# include +# include +} + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol(); + ~FTNoIR_Protocol() override; + bool correct() { + return dev != NULL; + } + void pose(const double *headpose); + QString game_name() { + return "Virtual joystick for Linux"; + } +private: + struct libevdev* dev; + struct libevdev_uinput* uidev; +}; + +class LibevdevControls: public IProtocolDialog +{ + Q_OBJECT +public: + LibevdevControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} + +private: + Ui::UICLibevdevControls ui; + void save(); + +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("libevdev joystick receiver"); } + QIcon icon() { return QIcon(":/images/linux.png"); } +}; diff --git a/protocol-libevdev/ftnoir_protocol_libevdev_dialog.cpp b/protocol-libevdev/ftnoir_protocol_libevdev_dialog.cpp new file mode 100644 index 00000000..70495a8f --- /dev/null +++ b/protocol-libevdev/ftnoir_protocol_libevdev_dialog.cpp @@ -0,0 +1,21 @@ +#include "ftnoir_protocol_libevdev.h" +#include "opentrack/plugin-api.hpp" + +LibevdevControls::LibevdevControls() +{ + ui.setupUi( this ); + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); +} + +void LibevdevControls::doOK() { + save(); + this->close(); +} + +void LibevdevControls::doCancel() { + this->close(); +} + +void LibevdevControls::save() { +} diff --git a/protocol-libevdev/images/linux.png b/protocol-libevdev/images/linux.png new file mode 100644 index 00000000..8836c0e2 Binary files /dev/null and b/protocol-libevdev/images/linux.png differ diff --git a/protocol-libevdev/libevdev-protocol.qrc b/protocol-libevdev/libevdev-protocol.qrc new file mode 100644 index 00000000..70bb415f --- /dev/null +++ b/protocol-libevdev/libevdev-protocol.qrc @@ -0,0 +1,5 @@ + + + images/linux.png + + diff --git a/protocol-mouse/CMakeLists.txt b/protocol-mouse/CMakeLists.txt new file mode 100644 index 00000000..b221c79c --- /dev/null +++ b/protocol-mouse/CMakeLists.txt @@ -0,0 +1,3 @@ +if(WIN32) + opentrack_boilerplate(opentrack-proto-win32-mouse) +endif() diff --git a/protocol-mouse/ftnoir_mousecontrols.ui b/protocol-mouse/ftnoir_mousecontrols.ui new file mode 100644 index 00000000..b1f4bcf8 --- /dev/null +++ b/protocol-mouse/ftnoir_mousecontrols.ui @@ -0,0 +1,188 @@ + + + UICMOUSEControls + + + Qt::NonModal + + + + 0 + 0 + 280 + 106 + + + + Mouse protocol settings + + + + :/images/mouse.png:/images/mouse.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + Map mouse X to: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 16777215 + + + + Select Number + + + QComboBox::InsertAlphabetically + + + + None + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + + + + + 80 + 16777215 + + + + Select Number + + + QComboBox::InsertAlphabetically + + + + None + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + + + + + 0 + 0 + + + + Map mouse Y to: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-mouse/ftnoir_protocol_mouse.cpp b/protocol-mouse/ftnoir_protocol_mouse.cpp new file mode 100644 index 00000000..c0a0a868 --- /dev/null +++ b/protocol-mouse/ftnoir_protocol_mouse.cpp @@ -0,0 +1,54 @@ +/* Copyright (c) 2015 Stanislaw Halik + * + * 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_mouse.h" +#include "opentrack/plugin-api.hpp" +#include + +#ifndef MOUSEEVENTF_MOVE_NOCOALESCE +# define MOUSEEVENTF_MOVE_NOCOALESCE 0x2000 +#endif + +void FTNoIR_Protocol::pose(const double *headpose ) { + RECT desktop; + const HWND hDesktop = GetDesktopWindow(); + if (hDesktop != NULL && GetWindowRect(hDesktop, &desktop)) { + // XXX TODO remove axis selector, use mapping window's + // axis selection. Mention in UI axis used. -sh 20140920 + int axis_x = s.Mouse_X; + int axis_y = s.Mouse_Y; + + int mouse_x = 0, mouse_y = 0; + + if (axis_x > 0 && axis_x <= 6) + mouse_x = headpose[axis_x-1] / (axis_x <= 3 ? 100 : 180) * 10 * desktop.right/2; + + if (axis_y > 0 && axis_y <= 6) + mouse_y = headpose[axis_y-1] / (axis_y <= 3 ? 100 : 180) * 10 * desktop.bottom/2; + + MOUSEINPUT mi; + mi.dx = mouse_x - last_x; + mi.dy = mouse_y - last_y; + mi.mouseData = 0; + mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_MOVE_NOCOALESCE; + mi.time = 0; + mi.dwExtraInfo = 0; + INPUT input; + input.type = INPUT_MOUSE; + input.mi = mi; + (void) SendInput(1, &input, sizeof(INPUT)); + + last_x = mouse_x; + last_y = mouse_y; + } +} + +bool FTNoIR_Protocol::correct() +{ + return true; +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, MOUSEControls, FTNoIR_ProtocolDll) diff --git a/protocol-mouse/ftnoir_protocol_mouse.h b/protocol-mouse/ftnoir_protocol_mouse.h new file mode 100644 index 00000000..595be393 --- /dev/null +++ b/protocol-mouse/ftnoir_protocol_mouse.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2015 Stanislaw Halik + * + * 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 "ui_ftnoir_mousecontrols.h" +#include +#include "opentrack/plugin-api.hpp" +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value Mouse_X, Mouse_Y; + settings() : + opts("mouse-proto"), + Mouse_X(b, "mouse-x", 0), + Mouse_Y(b, "mouse-y", 0) + {} +}; + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol() : last_x(0), last_y(0) {} + bool correct(); + void pose( const double *headpose); + QString game_name() { + return "Mouse tracker"; + } + int last_x, last_y; +private: + struct settings s; +}; + +class MOUSEControls: public IProtocolDialog +{ + Q_OBJECT +public: + MOUSEControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} +private: + Ui::UICMOUSEControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("mouse emulation"); } + QIcon icon() { return QIcon(":/images/mouse.png"); } +}; diff --git a/protocol-mouse/ftnoir_protocol_mouse_dialog.cpp b/protocol-mouse/ftnoir_protocol_mouse_dialog.cpp new file mode 100644 index 00000000..bb5fe3b8 --- /dev/null +++ b/protocol-mouse/ftnoir_protocol_mouse_dialog.cpp @@ -0,0 +1,24 @@ +#include "ftnoir_protocol_mouse.h" +#include "opentrack/plugin-api.hpp" + +MOUSEControls::MOUSEControls() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.Mouse_X, ui.cbxSelectMouse_X); + tie_setting(s.Mouse_Y, ui.cbxSelectMouse_Y); +} + +void MOUSEControls::doOK() { + s.b->save(); + this->close(); +} + +void MOUSEControls::doCancel() { + s.b->reload(); + this->close(); +} + diff --git a/protocol-mouse/images/mouse.png b/protocol-mouse/images/mouse.png new file mode 100644 index 00000000..c6f9ea26 Binary files /dev/null and b/protocol-mouse/images/mouse.png differ diff --git a/protocol-mouse/win32-mouse-protocol.qrc b/protocol-mouse/win32-mouse-protocol.qrc new file mode 100644 index 00000000..ed6a71be --- /dev/null +++ b/protocol-mouse/win32-mouse-protocol.qrc @@ -0,0 +1,5 @@ + + + images/mouse.png + + diff --git a/protocol-sc/CMakeLists.txt b/protocol-sc/CMakeLists.txt new file mode 100644 index 00000000..bd83e944 --- /dev/null +++ b/protocol-sc/CMakeLists.txt @@ -0,0 +1,3 @@ +if(WIN32) + opentrack_boilerplate(opentrack-proto-simconnect) +endif() diff --git a/protocol-sc/ftnoir-protocol-sc.rc b/protocol-sc/ftnoir-protocol-sc.rc new file mode 100644 index 00000000..c89eb9a7 --- /dev/null +++ b/protocol-sc/ftnoir-protocol-sc.rc @@ -0,0 +1,4 @@ +#include +142 RT_MANIFEST scserver.manifest +143 RT_MANIFEST scserver_sp2.manifest +144 RT_MANIFEST scserver_acceleration.manifest \ No newline at end of file diff --git a/protocol-sc/ftnoir_protocol_sc.cpp b/protocol-sc/ftnoir_protocol_sc.cpp new file mode 100644 index 00000000..0c6cb486 --- /dev/null +++ b/protocol-sc/ftnoir_protocol_sc.cpp @@ -0,0 +1,189 @@ +/* Homepage http://facetracknoir.sourceforge.net/home/default.htm * + * * + * ISC License (ISC) * + * * + * Copyright (c) 2015, Wim Vriend + * Copyright (c) 2014, Stanislaw Halik + * * + * 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_sc.h" +#include "opentrack/plugin-api.hpp" + +FTNoIR_Protocol::FTNoIR_Protocol() : should_stop(false), hSimConnect(nullptr) +{ +} + +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + should_stop = true; + wait(); +} + +void FTNoIR_Protocol::run() +{ + HANDLE event = CreateEvent(NULL, FALSE, FALSE, nullptr); + + if (event == nullptr) + { + qDebug() << "simconnect: event create" << GetLastError(); + return; + } + + while (!should_stop) + { + if (SUCCEEDED(simconnect_open(&hSimConnect, "opentrack", NULL, 0, event, 0))) + { + simconnect_subscribetosystemevent(hSimConnect, 0, "Frame"); + + while (!should_stop) + { + if (WaitForSingleObject(event, 10) == WAIT_OBJECT_0) + { + if (FAILED(simconnect_calldispatch(hSimConnect, processNextSimconnectEvent, reinterpret_cast(this)))) + break; + } + } + + (void) simconnect_close(hSimConnect); + } + + if (!should_stop) + Sleep(100); + } + + CloseHandle(event); +} + +void FTNoIR_Protocol::pose( const double *headpose ) { + virtSCRotX = -headpose[Pitch]; // degrees + virtSCRotY = headpose[Yaw]; + virtSCRotZ = headpose[Roll]; + + virtSCPosX = headpose[TX]/100.f; // cm to meters + virtSCPosY = headpose[TY]/100.f; + virtSCPosZ = -headpose[TZ]/100.f; +} + +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +class ActivationContext { +public: + ActivationContext(const int resid) : ok(false) { + hactctx = INVALID_HANDLE_VALUE; + actctx_cookie = 0; + ACTCTXA actx = {0}; + actx.cbSize = sizeof(ACTCTXA); + actx.lpResourceName = MAKEINTRESOURCEA(resid); + actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; +#ifdef _MSC_VER +# define PREFIX "" +#else +# define PREFIX "lib" +#endif + QString path = QCoreApplication::applicationDirPath() + "/" PREFIX "opentrack-proto-simconnect.dll"; + QByteArray name = QFile::encodeName(path); + actx.lpSource = name.constData(); + hactctx = CreateActCtxA(&actx); + actctx_cookie = 0; + if (hactctx != INVALID_HANDLE_VALUE) { + if (!ActivateActCtx(hactctx, &actctx_cookie)) { + qDebug() << "SC: can't set win32 activation context" << GetLastError(); + ReleaseActCtx(hactctx); + hactctx = INVALID_HANDLE_VALUE; + } + else + ok = true; + } else { + qDebug() << "SC: can't create win32 activation context" << GetLastError(); + } + } + ~ActivationContext() { + if (hactctx != INVALID_HANDLE_VALUE) + { + DeactivateActCtx(0, actctx_cookie); + ReleaseActCtx(hactctx); + } + } + bool is_ok() { return ok; } +private: + ULONG_PTR actctx_cookie; + HANDLE hactctx; + bool ok; +}; + +bool FTNoIR_Protocol::correct() +{ + if (!SCClientLib.isLoaded()) + { + ActivationContext ctx(142 + static_cast(s.sxs_manifest)); + + if (ctx.is_ok()) + { + SCClientLib.setFileName("SimConnect.dll"); + if (!SCClientLib.load()) { + qDebug() << "SC load" << SCClientLib.errorString(); + return false; + } + } + else + return false; + } + + simconnect_open = (importSimConnect_Open) SCClientLib.resolve("SimConnect_Open"); + if (simconnect_open == NULL) { + qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_Open function not found in DLL!"; + return false; + } + simconnect_set6DOF = (importSimConnect_CameraSetRelative6DOF) SCClientLib.resolve("SimConnect_CameraSetRelative6DOF"); + if (simconnect_set6DOF == NULL) { + qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_CameraSetRelative6DOF function not found in DLL!"; + return false; + } + simconnect_close = (importSimConnect_Close) SCClientLib.resolve("SimConnect_Close"); + if (simconnect_close == NULL) { + qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_Close function not found in DLL!"; + return false; + } + + simconnect_calldispatch = (importSimConnect_CallDispatch) SCClientLib.resolve("SimConnect_CallDispatch"); + if (simconnect_calldispatch == NULL) { + qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_CallDispatch function not found in DLL!"; + return false; + } + + simconnect_subscribetosystemevent = (importSimConnect_SubscribeToSystemEvent) SCClientLib.resolve("SimConnect_SubscribeToSystemEvent"); + if (simconnect_subscribetosystemevent == NULL) { + qDebug() << "FTNoIR_Protocol::correct() says: SimConnect_SubscribeToSystemEvent function not found in DLL!"; + return false; + } + + start(); + + return true; +} + +void FTNoIR_Protocol::handle() +{ + (void) simconnect_set6DOF(hSimConnect, virtSCPosX, virtSCPosY, virtSCPosZ, virtSCRotX, virtSCRotZ, virtSCRotY); +} + +void CALLBACK FTNoIR_Protocol::processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD, void *self_) +{ + FTNoIR_Protocol& self = *reinterpret_cast(self_); + + switch(pData->dwID) + { + default: + break; + case SIMCONNECT_RECV_ID_EVENT_FRAME: + self.handle(); + break; + } +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, SCControls, FTNoIR_ProtocolDll) diff --git a/protocol-sc/ftnoir_protocol_sc.h b/protocol-sc/ftnoir_protocol_sc.h new file mode 100644 index 00000000..671a3500 --- /dev/null +++ b/protocol-sc/ftnoir_protocol_sc.h @@ -0,0 +1,108 @@ +/* Homepage http://facetracknoir.sourceforge.net/home/default.htm * + * * + * ISC License (ISC) * + * * + * Copyright (c) 2015, Wim Vriend * + * Copyright (c) 2014, Stanislaw Halik * + * * + * 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 "opentrack/plugin-api.hpp" + +#include "ui_ftnoir_sccontrols.h" +#include +#include +#include +#include +#include +#include +#include +#include "opentrack/options.hpp" +using namespace options; +#include + +struct settings : opts { + value sxs_manifest; + settings() : + opts("proto-simconnect"), + sxs_manifest(b, "sxs-manifest-version", 0) + {} +}; + +class FTNoIR_Protocol : public IProtocol, private QThread +{ +public: + FTNoIR_Protocol(); + ~FTNoIR_Protocol() override; + bool correct(); + void pose(const double* headpose); + void handle(); + QString game_name() { + 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; + + volatile float virtSCPosX; + volatile float virtSCPosY; + volatile float virtSCPosZ; + volatile float virtSCRotX; + volatile float virtSCRotY; + volatile float virtSCRotZ; + + importSimConnect_Open simconnect_open; + importSimConnect_Close simconnect_close; + importSimConnect_CameraSetRelative6DOF simconnect_set6DOF; + importSimConnect_CallDispatch simconnect_calldispatch; + importSimConnect_SubscribeToSystemEvent simconnect_subscribetosystemevent; + + HANDLE hSimConnect; + static void CALLBACK processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext); + settings s; + QLibrary SCClientLib; +}; + +class SCControls: public IProtocolDialog +{ + Q_OBJECT +public: + SCControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} +private: + Ui::UICSCControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("Microsoft FSX SimConnect"); } + QIcon icon() { return QIcon(":/images/fsx.png"); } +}; diff --git a/protocol-sc/ftnoir_protocol_sc_dialog.cpp b/protocol-sc/ftnoir_protocol_sc_dialog.cpp new file mode 100644 index 00000000..7c2ecfd4 --- /dev/null +++ b/protocol-sc/ftnoir_protocol_sc_dialog.cpp @@ -0,0 +1,35 @@ +/* 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_sc.h" +#include +#include "opentrack/plugin-api.hpp" + +SCControls::SCControls() +{ + ui.setupUi( this ); + + // Connect Qt signals to member-functions + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.sxs_manifest, ui.comboBox); +} + +void SCControls::doOK() { + s.b->save(); + this->close(); +} + +void SCControls::doCancel() { + s.b->reload(); + close(); +} + diff --git a/protocol-sc/ftnoir_sccontrols.ui b/protocol-sc/ftnoir_sccontrols.ui new file mode 100644 index 00000000..5b2fd291 --- /dev/null +++ b/protocol-sc/ftnoir_sccontrols.ui @@ -0,0 +1,72 @@ + + + UICSCControls + + + Qt::NonModal + + + + 0 + 0 + 290 + 79 + + + + SimConnect settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + FSX version + + + + + + + + SP1 + + + + + SP2 + + + + + Acceleration + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-sc/images/fsx.png b/protocol-sc/images/fsx.png new file mode 100644 index 00000000..16b072a1 Binary files /dev/null and b/protocol-sc/images/fsx.png differ diff --git a/protocol-sc/images/fsx1.png b/protocol-sc/images/fsx1.png new file mode 100644 index 00000000..a1f0f188 Binary files /dev/null and b/protocol-sc/images/fsx1.png differ diff --git a/protocol-sc/sc-protocol.qrc b/protocol-sc/sc-protocol.qrc new file mode 100644 index 00000000..127d5180 --- /dev/null +++ b/protocol-sc/sc-protocol.qrc @@ -0,0 +1,5 @@ + + + images/fsx.png + + diff --git a/protocol-sc/scserver.manifest b/protocol-sc/scserver.manifest new file mode 100644 index 00000000..d342cfda --- /dev/null +++ b/protocol-sc/scserver.manifest @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/protocol-sc/scserver_acceleration.manifest b/protocol-sc/scserver_acceleration.manifest new file mode 100644 index 00000000..06459587 --- /dev/null +++ b/protocol-sc/scserver_acceleration.manifest @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/protocol-sc/scserver_sp2.manifest b/protocol-sc/scserver_sp2.manifest new file mode 100644 index 00000000..3020d16c --- /dev/null +++ b/protocol-sc/scserver_sp2.manifest @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/protocol-vjoy/CMakeLists.txt b/protocol-vjoy/CMakeLists.txt new file mode 100644 index 00000000..22678c32 --- /dev/null +++ b/protocol-vjoy/CMakeLists.txt @@ -0,0 +1,14 @@ +if(WIN32) + set(SDK_VJOY "" CACHE PATH "VJoy SDK path") + if(SDK_VJOY) + opentrack_boilerplate(opentrack-proto-vjoy GNU-LINK "-Wl,--enable-stdcall-fixup") + if(MSVC) + set(ext .lib) + else() + set(ext .dll) + endif() + target_link_libraries(opentrack-proto-vjoy ${MY_QT_LIBS} ${SDK_VJOY}/VJoy${ext}) + target_include_directories(opentrack-proto-vjoy SYSTEM PUBLIC ${SDK_VJOY}) + install(FILES "${SDK_VJOY}/VJoy.dll" DESTINATION . ${opentrack-perms}) + endif() +endif() diff --git a/protocol-vjoy/ftnoir_protocol_vjoy.cpp b/protocol-vjoy/ftnoir_protocol_vjoy.cpp new file mode 100644 index 00000000..24148c63 --- /dev/null +++ b/protocol-vjoy/ftnoir_protocol_vjoy.cpp @@ -0,0 +1,33 @@ +#include "ftnoir_protocol_vjoy.h" +#include "opentrack/plugin-api.hpp" + +FTNoIR_Protocol::FTNoIR_Protocol() +{ + static char meh[1] = {0}; + VJoy_Initialize(meh, meh); +} + +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + VJoy_Shutdown(); +} + +void FTNoIR_Protocol::pose( const double *headpose ) { +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + JOYSTICK_STATE state[2] = { 0 }; + + state[0].POV = (4 << 12) | (4 << 8) | (4 << 4) | 4; + + state[0].XAxis = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[Yaw] * VJOY_AXIS_MAX / 180.0)); + state[0].YAxis = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[Pitch] * VJOY_AXIS_MAX / 180.0)); + state[0].ZAxis = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[Roll] * VJOY_AXIS_MAX / 180.0)); + state[0].XRotation = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[TX] * VJOY_AXIS_MAX / 100.0)); + state[0].YRotation = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[TY] * VJOY_AXIS_MAX / 100.0)); + state[0].ZRotation = std::min(VJOY_AXIS_MAX, std::max(VJOY_AXIS_MIN, headpose[TZ] * VJOY_AXIS_MAX / 100.0)); + + VJoy_UpdateJoyState(0, state); +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, VJoyControls, FTNoIR_ProtocolDll) diff --git a/protocol-vjoy/ftnoir_protocol_vjoy.h b/protocol-vjoy/ftnoir_protocol_vjoy.h new file mode 100644 index 00000000..118306b5 --- /dev/null +++ b/protocol-vjoy/ftnoir_protocol_vjoy.h @@ -0,0 +1,91 @@ +/* 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. * + */ +#pragma once +#include "ui_ftnoir_vjoy_controls.h" +#include +#include "opentrack/plugin-api.hpp" + +#define FT_PROGRAMID "FT_ProgramID" + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol(); + ~FTNoIR_Protocol() override; + bool correct() { + return true; + } + void pose( const double *headpose ); + QString game_name() { + return "Virtual joystick"; + } +private: +}; + +// Widget that has controls for FTNoIR protocol client-settings. +class VJoyControls: public IProtocolDialog +{ + Q_OBJECT +public: + + explicit VJoyControls(); + void register_protocol(IProtocol *) {} + void unregister_protocol() {} + +private: + Ui::UICVJoyControls ui; + void save(); + +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() { return QString("Joystick emulation -- VJoy"); } + QIcon icon() { return QIcon(":/images/vjoy.png"); } +}; + +#define VJOY_AXIS_MIN -32768 +#define VJOY_AXIS_NIL 0 +#define VJOY_AXIS_MAX 32767 + +#include + +#include + +typedef struct _JOYSTICK_STATE +{ + UCHAR ReportId; // Report Id + SHORT XAxis; // X Axis + SHORT YAxis; // Y Axis + SHORT ZAxis; // Z Axis + SHORT XRotation; // X Rotation + SHORT YRotation; // Y Rotation + SHORT ZRotation; // Z Rotation + SHORT Slider; // Slider + SHORT Dial; // Dial + USHORT POV; // POV + UINT32 Buttons; // 32 Buttons +} JOYSTICK_STATE, * PJOYSTICK_STATE; + +#ifndef _MSC_VER +EXTERN_C BOOL __stdcall VJoy_Initialize(PCHAR name, PCHAR serial); +EXTERN_C VOID __stdcall VJoy_Shutdown(); +EXTERN_C BOOL __stdcall VJoy_UpdateJoyState(int id, PJOYSTICK_STATE pJoyState); +#else +#define VJOY_API __declspec(dllimport) +VJOY_API BOOL __stdcall VJoy_Initialize(PCHAR name, PCHAR serial); +VJOY_API VOID __stdcall VJoy_Shutdown(); +VJOY_API BOOL __stdcall VJoy_UpdateJoyState(int id, PJOYSTICK_STATE pJoyState); +#endif diff --git a/protocol-vjoy/ftnoir_protocol_vjoy_dialog.cpp b/protocol-vjoy/ftnoir_protocol_vjoy_dialog.cpp new file mode 100644 index 00000000..08c65558 --- /dev/null +++ b/protocol-vjoy/ftnoir_protocol_vjoy_dialog.cpp @@ -0,0 +1,22 @@ +#include "ftnoir_protocol_vjoy.h" +#include "opentrack/plugin-api.hpp" + +VJoyControls::VJoyControls() +{ + ui.setupUi( this ); + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); +} + +void VJoyControls::doOK() { + save(); + this->close(); +} + +void VJoyControls::doCancel() { + this->close(); +} + +void VJoyControls::save() { +} + diff --git a/protocol-vjoy/ftnoir_vjoy_controls.ui b/protocol-vjoy/ftnoir_vjoy_controls.ui new file mode 100644 index 00000000..2214b887 --- /dev/null +++ b/protocol-vjoy/ftnoir_vjoy_controls.ui @@ -0,0 +1,113 @@ + + + UICVJoyControls + + + Qt::NonModal + + + + 0 + 0 + 228 + 69 + + + + VJoy + + + + :/images/vjoy.png:/images/vjoy.png + + + Qt::LeftToRight + + + false + + + + + + No settings necessary + + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + + + + btnOK + btnCancel + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-vjoy/images/vjoy.png b/protocol-vjoy/images/vjoy.png new file mode 100644 index 00000000..8eb14be8 Binary files /dev/null and b/protocol-vjoy/images/vjoy.png differ diff --git a/protocol-vjoy/vjoy-protocol.qrc b/protocol-vjoy/vjoy-protocol.qrc new file mode 100644 index 00000000..7b3741f1 --- /dev/null +++ b/protocol-vjoy/vjoy-protocol.qrc @@ -0,0 +1,5 @@ + + + images/vjoy.png + + diff --git a/protocol-vjoy/vjoy.def b/protocol-vjoy/vjoy.def new file mode 100644 index 00000000..aea590a4 --- /dev/null +++ b/protocol-vjoy/vjoy.def @@ -0,0 +1,5 @@ +LIBRARY vjoy.dll +IMPORTS +VJoy_Initialize = _VJoy_Initialize +VJoy_Shutdown = _VJoy_Shutdown +VJoy_UpdateJoyState = _VJoy_UpdateJoyState diff --git a/protocol-wine/CMakeLists.txt b/protocol-wine/CMakeLists.txt new file mode 100644 index 00000000..682e50de --- /dev/null +++ b/protocol-wine/CMakeLists.txt @@ -0,0 +1,26 @@ +if(NOT WIN32) + set(SDK_WINE_PREFIX "" CACHE PATH "Wine install prefix") + set(SDK_WINE_NO_WRAPPER FALSE CACHE BOOL "disable Wine wrapper -- use Wine only for X-Plane") + if(SDK_WINE_PREFIX) + opentrack_boilerplate(opentrack-proto-wine) + target_link_libraries(opentrack-proto-wine opentrack-compat opentrack-csv) + if(NOT SDK_WINE_NO_WRAPPER) + set(my-rt -lrt) + if(APPLE) + set(my-rt) + endif() + file(GLOB wine-deps ${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/*.cxx) + add_custom_command( + OUTPUT opentrack-wrapper-wine.exe.so + DEPENDS ${wine-deps} + COMMAND ${SDK_WINE_PREFIX}/bin/wineg++ -g -DNOMINMAX -O2 -m32 -std=c++11 -o + opentrack-wrapper-wine.exe -I "${CMAKE_SOURCE_DIR}" + ${wine-deps} + ${my-rt}) + add_custom_target(wine-wrapper ALL DEPENDS opentrack-wrapper-wine.exe.so) + add_dependencies(opentrack-proto-wine wine-wrapper) + add_dependencies(wine-wrapper opentrack-compat) + install(FILES "${CMAKE_BINARY_DIR}/opentrack-wrapper-wine.exe.so" DESTINATION .) + endif() + endif() +endif() diff --git a/protocol-wine/ftnoir_protocol_wine.cpp b/protocol-wine/ftnoir_protocol_wine.cpp new file mode 100644 index 00000000..99ad30a2 --- /dev/null +++ b/protocol-wine/ftnoir_protocol_wine.cpp @@ -0,0 +1,59 @@ +#include "ftnoir_protocol_wine.h" +#include +#include +#include /* For mode constants */ +#include /* For O_* constants */ +#include "csv/csv.h" + +FTNoIR_Protocol::FTNoIR_Protocol() : lck_shm(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)), shm(NULL), gameid(0) +{ + if (lck_shm.success()) { + shm = (WineSHM*) lck_shm.ptr(); + memset(shm, 0, sizeof(*shm)); + } + wrapper.start("wine", QStringList() << (QCoreApplication::applicationDirPath() + "/opentrack-wrapper-wine.exe.so")); +} + +FTNoIR_Protocol::~FTNoIR_Protocol() +{ + if (shm) { + shm->stop = true; + wrapper.waitForFinished(100); + } + wrapper.terminate(); + if (!wrapper.waitForFinished(100)) + { + wrapper.kill(); + wrapper.waitForFinished(42); + } + //shm_unlink("/" WINE_SHM_NAME); +} + +void FTNoIR_Protocol::pose( const double *headpose ) { + if (shm) + { + lck_shm.lock(); + for (int i = 3; i < 6; i++) + shm->data[i] = headpose[i] / 57.295781; + for (int i = 0; i < 3; i++) + shm->data[i] = headpose[i] * 10; + if (shm->gameid != gameid) + { + QString gamename; + QMutexLocker foo(&game_name_mutex); + /* only EZCA for FSX requires dummy process, and FSX doesn't work on Linux */ + /* memory-hacks DLL can't be loaded into a Linux process, either */ + CSV::getGameData(shm->gameid, shm->table, gamename); + gameid = shm->gameid2 = shm->gameid; + connected_game = gamename; + } + lck_shm.unlock(); + } +} + +bool FTNoIR_Protocol::correct() +{ + return lck_shm.success(); +} + +OPENTRACK_DECLARE_PROTOCOL(FTNoIR_Protocol, FTControls, FTNoIR_ProtocolDll) diff --git a/protocol-wine/ftnoir_protocol_wine.h b/protocol-wine/ftnoir_protocol_wine.h new file mode 100644 index 00000000..2aeb4608 --- /dev/null +++ b/protocol-wine/ftnoir_protocol_wine.h @@ -0,0 +1,57 @@ +#pragma once + +#include "ui_ftnoir_winecontrols.h" +#include +#include +#include +#include +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "opentrack-compat/shm.h" +#include "ftnoir_protocol_wine/wine-shm.h" + +class FTNoIR_Protocol : public IProtocol +{ +public: + FTNoIR_Protocol(); + ~FTNoIR_Protocol() override; + + bool correct() override; + void pose(const double* headpose) override; + QString game_name() override { + QMutexLocker foo(&game_name_mutex); + return connected_game; + } +private: + PortableLockedShm lck_shm; + WineSHM* shm; + QProcess wrapper; + int gameid; + QString connected_game; + QMutex game_name_mutex; +}; + +class FTControls: public IProtocolDialog +{ + Q_OBJECT +public: + FTControls(); + void register_protocol(IProtocol *) override {} + void unregister_protocol() override {} + +private: + Ui::UICFTControls ui; + +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_ProtocolDll : public Metadata +{ +public: + QString name() override { return QString("Wine -- Windows layer for Unix"); } + QIcon icon() override { return QIcon(":/images/wine.png"); } +}; diff --git a/protocol-wine/ftnoir_protocol_wine_dialog.cpp b/protocol-wine/ftnoir_protocol_wine_dialog.cpp new file mode 100644 index 00000000..e4027c73 --- /dev/null +++ b/protocol-wine/ftnoir_protocol_wine_dialog.cpp @@ -0,0 +1,19 @@ +#include "ftnoir_protocol_wine.h" +#include +#include "opentrack/plugin-api.hpp" + +FTControls::FTControls() +{ + ui.setupUi( this ); + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); +} + +void FTControls::doOK() { + this->close(); +} + +void FTControls::doCancel() { + this->close(); +} + diff --git a/protocol-wine/ftnoir_winecontrols.ui b/protocol-wine/ftnoir_winecontrols.ui new file mode 100644 index 00000000..9356c448 --- /dev/null +++ b/protocol-wine/ftnoir_winecontrols.ui @@ -0,0 +1,170 @@ + + + UICFTControls + + + Qt::NonModal + + + + 0 + 0 + 409 + 110 + + + + FreeTrack settings FaceTrackNoIR + + + + images/freetrack.pngimages/freetrack.png + + + Qt::LeftToRight + + + false + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + There are no settings necessary for the Wine protocol. + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/protocol-wine/images/wine.png b/protocol-wine/images/wine.png new file mode 100644 index 00000000..bcf3a012 Binary files /dev/null and b/protocol-wine/images/wine.png differ diff --git a/protocol-wine/opentrack-wrapper-wine-main.cxx b/protocol-wine/opentrack-wrapper-wine-main.cxx new file mode 100644 index 00000000..ffe8938d --- /dev/null +++ b/protocol-wine/opentrack-wrapper-wine-main.cxx @@ -0,0 +1,80 @@ +#include +// OSX sdk 10.8 build error otherwise +#ifdef _LIBCPP_MSVCRT +# undef _LIBCPP_MSVCRT +#endif +#include +#include "freetrackclient/fttypes.h" +#include "ftnoir_protocol_wine/wine-shm.h" +#include "opentrack-compat/export.hpp" + +enum Axis { + TX = 0, TY, TZ, Yaw, Pitch, Roll +}; + +#include "opentrack-compat/shm.h" + +void create_registry_key(void); + +class ShmPosix { +public: + ShmPosix(const char *shmName, const char *mutexName, int mapSize); + ~ShmPosix(); + void lock(); + void unlock(); + bool success(); + inline void* ptr() { return mem; } +private: + void* mem; + int fd, size; +}; + +class ShmWine { +public: + ShmWine(const char *shmName, const char *mutexName, int mapSize); + ~ShmWine(); + void lock(); + void unlock(); + bool success(); + inline void* ptr() { return mem; } +private: + void* mem; + void *hMutex, *hMapFile; +}; +#include + +int main(void) +{ + ShmPosix lck_posix(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)); + ShmWine lck_wine("FT_SharedMem", "FT_Mutext", sizeof(FTHeap)); + if(!lck_posix.success()) { + printf("Can't open posix map: %d\n", errno); + return 1; + } + if(!lck_wine.success()) { + printf("Can't open Wine map\n"); + return 1; + } + WineSHM* shm_posix = (WineSHM*) lck_posix.ptr(); + FTHeap* shm_wine = (FTHeap*) lck_wine.ptr(); + FTData* data = &shm_wine->data; + create_registry_key(); + while (1) { + if (shm_posix->stop) + break; + data->Yaw = -shm_posix->data[Yaw]; + data->Pitch = -shm_posix->data[Pitch]; + data->Roll = shm_posix->data[Roll]; + data->X = shm_posix->data[TX]; + data->Y = shm_posix->data[TY]; + data->Z = shm_posix->data[TZ]; + data->DataID++; + data->CamWidth = 250; + data->CamHeight = 100; + shm_wine->GameID2 = shm_posix->gameid2; + shm_posix->gameid = shm_wine->GameID; + for (int i = 0; i < 8; i++) + shm_wine->table[i] = shm_posix->table[i]; + (void) Sleep(4); + } +} diff --git a/protocol-wine/opentrack-wrapper-wine-posix.cxx b/protocol-wine/opentrack-wrapper-wine-posix.cxx new file mode 100644 index 00000000..50cce728 --- /dev/null +++ b/protocol-wine/opentrack-wrapper-wine-posix.cxx @@ -0,0 +1,7 @@ +#ifdef _WIN32 +# undef _WIN32 +#endif + +#define PortableLockedShm ShmPosix +#include "opentrack-compat/shm.h" +#include "opentrack-compat/shm.cpp" diff --git a/protocol-wine/opentrack-wrapper-wine-windows.cxx b/protocol-wine/opentrack-wrapper-wine-windows.cxx new file mode 100644 index 00000000..19ee8ffd --- /dev/null +++ b/protocol-wine/opentrack-wrapper-wine-windows.cxx @@ -0,0 +1,40 @@ +#ifndef __WIN32 +# error "bad cross" +#endif + +#define PortableLockedShm ShmWine +#include "opentrack-compat/shm.h" +#include "opentrack-compat/shm.cpp" +#include "wine-shm.h" + +static void write_path(const char* key, const char* subkey) +{ + char dir[8192]; + + if (GetCurrentDirectoryA(8192, dir) < 8190) + { + HKEY hkpath; + if (RegCreateKeyExA(HKEY_CURRENT_USER, + key, + 0, + NULL, + 0, + KEY_ALL_ACCESS, + NULL, + &hkpath, + NULL) == ERROR_SUCCESS) + { + for (int i = 0; dir[i]; i++) + if (dir[i] == '\\') + dir[i] = '/'; + strcat(dir, "/"); + (void) RegSetValueExA(hkpath, subkey, 0, REG_SZ, (BYTE*) dir, strlen(dir) + 1); + RegCloseKey(hkpath); + } + } +} + +void create_registry_key(void) { + write_path("Software\\NaturalPoint\\NATURALPOINT\\NPClient Location", "Path"); + write_path("Software\\Freetrack\\FreeTrackClient", "Path"); +} diff --git a/protocol-wine/wine-protocol.qrc b/protocol-wine/wine-protocol.qrc new file mode 100644 index 00000000..af81caea --- /dev/null +++ b/protocol-wine/wine-protocol.qrc @@ -0,0 +1,5 @@ + + + images/wine.png + + diff --git a/protocol-wine/wine-shm.h b/protocol-wine/wine-shm.h new file mode 100644 index 00000000..c7e29abb --- /dev/null +++ b/protocol-wine/wine-shm.h @@ -0,0 +1,20 @@ +#pragma once + +#define WINE_SHM_NAME "facetracknoir-wine-shm" +#define WINE_MTX_NAME "facetracknoir-wine-mtx" + +// OSX sdk 10.8 build error otherwise +#ifdef _LIBCPP_MSVCRT +# undef _LIBCPP_MSVCRT +#endif + +#include + +template using ptr = std::shared_ptr; + +struct WineSHM { + double data[6]; + int gameid, gameid2; + unsigned char table[8]; + bool stop; +}; diff --git a/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp deleted file mode 100644 index 1a9da10a..00000000 --- a/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (c) 2011-2012 Stanislaw Halik - * Adapted to FaceTrackNoIR by 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 "qfunctionconfigurator.h" - -#include -#include "qfunctionconfiguratorplugin.h" - - -QFunctionConfiguratorPlugin::QFunctionConfiguratorPlugin(QObject *parent) - : QObject(parent) -{ - initialized = false; -} - -void QFunctionConfiguratorPlugin::initialize(QDesignerFormEditorInterface *) -{ - if (initialized) - return; - - initialized = true; -} - -bool QFunctionConfiguratorPlugin::isInitialized() const -{ - return initialized; -} - -QWidget *QFunctionConfiguratorPlugin::createWidget(QWidget *parent) -{ - return new QFunctionConfigurator(parent); -} - -QString QFunctionConfiguratorPlugin::name() const -{ - return "QFunctionConfigurator"; -} - -QString QFunctionConfiguratorPlugin::group() const -{ - return "My Plugins"; -} - -QIcon QFunctionConfiguratorPlugin::icon() const -{ - return QIcon(); -} - -QString QFunctionConfiguratorPlugin::toolTip() const -{ - return QString(); -} - -QString QFunctionConfiguratorPlugin::whatsThis() const -{ - return QString(); -} - -bool QFunctionConfiguratorPlugin::isContainer() const -{ - return false; -} - -QString QFunctionConfiguratorPlugin::domXml() const -{ - return "\n" - " \n" - " \n" - " 0\n" - " 0\n" - " 161\n" - " 220\n" - " \n" - " \n" - " \n" - " \n" - " 255\n" - " 170\n" - " 0\n" - " \n" - " \n" - " \n" - " Input Yaw (degr.)\n" - " \n" - " \n" - " Output Yaw (degr.)\n" - " \n" - " \n" - " 50\n" - " \n" - " \n" - " 180\n" - " \n" - " \n" - " 2\n" - " \n" - " \n" - " 1\n" - " \n" - "\n"; -} - -QString QFunctionConfiguratorPlugin::includeFile() const -{ - return "qfunctionconfigurator.h"; -} - -Q_EXPORT_PLUGIN2(qfunctionconfigurator, QFunctionConfiguratorPlugin) diff --git a/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h deleted file mode 100644 index ca68e0e2..00000000 --- a/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2011-2012 Stanislaw Halik - * Adapted to FaceTrackNoIR by 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. - */ -#ifndef QFUNCTIONCONFIGURATORPLUGIN_H -#define QFUNCTIONCONFIGURATORPLUGIN_H - -#include - -class QFunctionConfiguratorPlugin : public QObject, public QDesignerCustomWidgetInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "analogclock.json") - Q_INTERFACES(QDesignerCustomWidgetInterface) - -public: - QFunctionConfiguratorPlugin(QObject *parent = 0); - - bool isContainer() const; - bool isInitialized() const; - QIcon icon() const; - QString domXml() const; - QString group() const; - QString includeFile() const; - QString name() const; - QString toolTip() const; - QString whatsThis() const; - QWidget *createWidget(QWidget *parent); - void initialize(QDesignerFormEditorInterface *core); -private: - bool initialized; -}; - -#endif // QFUNCTIONCONFIGURATORPLUGIN_H diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp deleted file mode 100644 index 27f3bf40..00000000 --- a/qfunctionconfigurator/functionconfig.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright (c) 2012-2015, Stanislaw Halik - - * 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 -#include -#include -#include -#include "functionconfig.h" -#include -#include -#include -#include -#include -#include - -void Map::setTrackingActive(bool blnActive) -{ - activep = blnActive; -} - -Map::Map() : - _mutex(QMutex::Recursive), - activep(false), - max_x(0), - max_y(0) -{ -} - -float Map::getValue(float x) { - QMutexLocker foo(&_mutex); - float q = x * precision(); - int xi = (int)q; - float yi = getValueInternal(xi); - float yiplus1 = getValueInternal(xi+1); - float f = (q-xi); - float ret = yiplus1 * f + yi * (1.0f - f); // at least do a linear interpolation. - last_input_value.setX(std::fabs(x)); - last_input_value.setY(std::fabs(ret)); - return ret; -} - -bool Map::getLastPoint(QPointF& point ) { - QMutexLocker foo(&_mutex); - point = last_input_value; - return activep; -} - -float Map::getValueInternal(int x) { - float sign = x < 0 ? -1 : 1; - x = abs(x); - float ret; - int sz = cur.data.size(); - if (sz == 0) - ret = 0; - else - ret = cur.data[std::min(x, sz-1)]; - return ret * sign; -} - -static QPointF ensureInBounds(QList points, int i) { - int siz = points.size(); - if (siz == 0 || i < 0) - return QPointF(0, 0); - if (siz > i) - return points[i]; - return points[siz - 1]; -} - -static bool sortFn(const QPointF& one, const QPointF& two) { - return one.x() < two.x(); -} - -void Map::reload() { - if (cur.input.size()) - { - qStableSort(cur.input.begin(), cur.input.end(), sortFn); - - QList input = cur.input; - auto& data = cur.data; - - data = std::vector(value_count); - const int mult = precision(); - const int mult_ = mult * 30; - - const int sz = data.size(); - - for (int i = 0; i < sz; i++) - data[i] = -1; - - if (input.size() == 1 && input[0].x() > 1e-2) - { - for (int k = 0; k < input[0].x() * mult; k++) { - if (k < sz) - data[k] = input[0].y() * k / (input[0].x() * mult); - } - } - else if (input[0].x() > 1e-2) - input.prepend(QPointF(0, 0)); - - for (int i = 0; i < sz; i++) { - const QPointF p0 = ensureInBounds(input, i - 1); - const QPointF p1 = ensureInBounds(input, i); - const QPointF p2 = ensureInBounds(input, i + 1); - const QPointF p3 = ensureInBounds(input, i + 2); - - const float p0_x = p0.x(), p1_x = p1.x(), p2_x = p2.x(), p3_x = p3.x(); - const float p0_y = p0.y(), p1_y = p1.y(), p2_y = p2.y(), p3_y = p3.y(); - - // multiplier helps fill in all the x's needed - const int end = std::min(sz, p2.x() * mult_); - const int start = p1.x() * mult; - - for (int j = start; j < end; j++) { - const float t = (j - start) / (float) (end - start); - const float t2 = t*t; - const float t3 = t*t*t; - - const int x = .5 * ((2. * p1_x) + - (-p0_x + p2_x) * t + - (2. * p0_x - 5. * p1_x + 4. * p2_x - p3_x) * t2 + - (-p0_x + 3. * p1_x - 3. * p2_x + p3_x) * t3) - * mult; - - const float y = .5 * ((2. * p1_y) + - (-p0_y + p2_y) * t + - (2. * p0_y - 5. * p1_y + 4. * p2_y - p3_y) * t2 + - (-p0_y + 3. * p1_y - 3. * p2_y + p3_y) * t3); - - if (x >= 0 && x < sz) - data[x] = y; - } - } - - float last = 0; - for (int i = 0; i < sz; i++) - { - if (data[i] < 0) - data[i] = last; - last = data[i]; - } - } - else - cur.data.clear(); -} - -void Map::removePoint(int i) { - QMutexLocker foo(&_mutex); - if (i >= 0 && i < cur.input.size()) - { - cur.input.removeAt(i); - reload(); - } -} - -void Map::addPoint(QPointF pt) { - QMutexLocker foo(&_mutex); - cur.input.append(pt); - reload(); - qStableSort(cur.input.begin(), cur.input.end(), sortFn); -} - -void Map::movePoint(int idx, QPointF pt) { - QMutexLocker foo(&_mutex); - if (idx >= 0 && idx < cur.input.size()) - { - cur.input[idx] = pt; - reload(); - // we don't allow points to be reordered, so no sort here - } -} - -const QList Map::getPoints() { - QMutexLocker foo(&_mutex); - return cur.input; -} - -void Map::invalidate_unsaved_settings() -{ - QMutexLocker foo(&_mutex); - cur = saved; - reload(); -} - -void Map::loadSettings(QSettings& settings, const QString& title) { - QMutexLocker foo(&_mutex); - QPointF newPoint; - QList points; - settings.beginGroup(QString("Curves-%1").arg(title)); - - int max = settings.value("point-count", 0).toInt(); - - for (int i = 0; i < max; i++) { - newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toDouble(), - settings.value(QString("point-%1-y").arg(i), 0).toDouble()); - if (newPoint.x() > max_x) { - newPoint.setX(max_x); - } - if (newPoint.y() > max_y) { - newPoint.setY(max_y); - } - points.append(newPoint); - } - - settings.endGroup(); - - if (max == 0) - points.append(QPointF(maxInput(), maxOutput())); - - cur.input = points; - reload(); - saved = cur; -} - -void Map::saveSettings(QSettings& settings, const QString& title) { - QMutexLocker foo(&_mutex); - settings.beginGroup(QString("Curves-%1").arg(title)); - int max = cur.input.size(); - settings.setValue("point-count", max); - - for (int i = 0; i < max; i++) { - settings.setValue(QString("point-%1-x").arg(i), cur.input[i].x()); - settings.setValue(QString("point-%1-y").arg(i), cur.input[i].y()); - } - - for (int i = max; true; i++) - { - QString x = QString("point-%1-x").arg(i); - if (!settings.contains(x)) - break; - settings.remove(x); - settings.remove(QString("point-%1-y").arg(i)); - } - - saved = cur; - - settings.endGroup(); -} - - -int Map::precision() const { - if (cur.input.size()) - return value_count / std::max(1.f, (cur.input[cur.input.size() - 1].x())); - return 1; -} diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h deleted file mode 100644 index 6d76d0de..00000000 --- a/qfunctionconfigurator/functionconfig.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2012-2015, Stanislaw Halik - - * 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 -#include -#include -#include -#include -#include -#include -#include "opentrack-compat/qcopyable-mutex.hpp" - -class Map { -private: - static constexpr int value_count = 10000; - - struct State { - QList input; - std::vector data; - }; - - int precision() const; - void reload(); - float getValueInternal(int x); - - MyMutex _mutex; - QPointF last_input_value; - volatile bool activep; - double max_x; - double max_y; - - State cur, saved; -public: - double maxInput() const { return max_x; } - double maxOutput() const { return max_y; } - Map(); - Map(double maxx, double maxy) - { - setMaxInput(maxx); - setMaxOutput(maxy); - reload(); - } - - float getValue(float x); - bool getLastPoint(QPointF& point); - void removePoint(int i); - void removeAllPoints() { - QMutexLocker foo(&_mutex); - cur.input.clear(); - reload(); - } - - void addPoint(QPointF pt); - void movePoint(int idx, QPointF pt); - const QList getPoints(); - void setMaxInput(double MaxInput) { - max_x = MaxInput; - } - void setMaxOutput(double MaxOutput) { - max_y = MaxOutput; - } - - void saveSettings(QSettings& settings, const QString& title); - void loadSettings(QSettings& settings, const QString& title); - void invalidate_unsaved_settings(); - - void setTrackingActive(bool blnActive); -}; diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp deleted file mode 100644 index bcb895ec..00000000 --- a/qfunctionconfigurator/qfunctionconfigurator.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/* Copyright (c) 2012-2015 Stanislaw Halik - * - * 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 "opentrack/options.hpp" -using namespace options; -#include "qfunctionconfigurator/qfunctionconfigurator.h" -#include -#include -#include -#include -#include -#include - -static const int pointSize = 5; - -QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) : - QWidget(parent), - _config(nullptr), - moving_control_point_idx(-1), - _draw_function(true) -{ - update_range(); - setMouseTracking(true); -} - -void QFunctionConfigurator::setConfig(Map* config, const QString& name) { - mem iniFile = group::ini_file(); - if (name != "") - config->loadSettings(*iniFile, name); - _config = config; - _draw_function = true; - update_range(); - update(); -} - -void QFunctionConfigurator::drawBackground() -{ - if (!_config) - return; - _background = QPixmap(width(), height()); - - QPainter painter(&_background); - painter.fillRect(rect(), QColor::fromRgb(204, 204, 204)); - - QColor bg_color(112, 154, 209); - if (!isEnabled()) - bg_color = QColor(176,176,180); - painter.fillRect(pixel_bounds, bg_color); - - QFont font; - font.setPointSize(8); - painter.setFont(font); - QFontMetrics metrics(font); - - QColor color__(176, 190, 209, 127); - - if (!isEnabled()) - color__ = QColor(70, 90, 100, 96); - - QPen pen(color__, 1, Qt::SolidLine); - - const int xstep = 10, ystep = 10; - const double maxx = _config->maxInput(); - const double maxy = _config->maxOutput(); - - // horizontal grid - for (int i = 0; i < maxy; i += xstep) - { - double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y(); - drawLine(&painter, - QPointF(pixel_bounds.x(), y), - QPointF(pixel_bounds.x() + pixel_bounds.width(), y), - pen); - painter.drawText(QRectF(10, - y - metrics.height()/2, - pixel_bounds.left(), - metrics.height()), - QString::number(i)); - } - - { - const double i = maxy; - double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y(); - drawLine(&painter, - QPointF(pixel_bounds.x(), y), - QPointF(pixel_bounds.x() + pixel_bounds.width(), y), - pen); - painter.drawText(QRectF(10, - y - metrics.height()/2, - pixel_bounds.x() - 10, - metrics.height()), - QString::number(i)); - } - - // vertical grid - for (int i = 0; i < maxx; i += ystep) - { - double x = pixel_bounds.x() + i * c.x(); - drawLine(&painter, - QPointF(x, pixel_bounds.y()), - QPointF(x, pixel_bounds.y() + pixel_bounds.height()), - pen); - const QString text = QString::number(i); - painter.drawText(QRectF(x - metrics.width(text)/2, - pixel_bounds.height() + 10 + metrics.height(), - metrics.width(text), - metrics.height()), - text); - } - { - const double i = maxx; - double x = pixel_bounds.x() + i * c.x(); - drawLine(&painter, - QPointF(x, pixel_bounds.y()), - QPointF(x, pixel_bounds.y() + pixel_bounds.height()), - pen); - const QString text = QString::number(i); - painter.drawText(QRectF(x - metrics.width(text)/2, - pixel_bounds.height() + 10 + metrics.height(), - metrics.width(text), - metrics.height()), - text); - } -} - -void QFunctionConfigurator::drawFunction() -{ - if (!_config) - return; - - _function = QPixmap(_background); - QPainter painter(&_function); - painter.setRenderHint(QPainter::Antialiasing, true); - - QList points = _config->getPoints(); - - const int alpha = !isEnabled() ? 64 : 120; - for (int i = 0; i < points.size(); i++) { - drawPoint(&painter, - point_to_pixel(points[i]), - QColor(200, 200, 210, alpha), - isEnabled() ? QColor(50, 100, 120, 200) : QColor(200, 200, 200, 96)); - } - - QColor color = spline_color; - - if (!isEnabled()) - { - const int avg = 176; - auto color_ = color; - color = QColor(color_.red() * .5 + avg * .5, - color_.green() * .5 + avg * .5, - color_.blue() * .5 + avg * .5, - 96); - } - - QPen pen(color, 1.2, Qt::SolidLine); - - const double max = _config->maxInput(); - const double step = std::max(1e-2, max / 1000.); - - QPointF prev = point_to_pixel(QPointF(0, 0)); - for (double i = 0; i < max; i += step) { - double val = _config->getValue(i); - QPointF cur = point_to_pixel(QPointF(i, val)); - drawLine(&painter, prev, cur, pen); - prev = cur; - } -} - -void QFunctionConfigurator::paintEvent(QPaintEvent *e) -{ - QPainter p(this); - - if (_background.isNull()) - { - _draw_function = true; - drawBackground(); - } - - if (_draw_function) { - _draw_function = false; - drawFunction(); - } - - p.drawPixmap(e->rect(), _function); - - if (_config) { - QPen pen(Qt::white, 1, Qt::SolidLine); - QList points = _config->getPoints(); - if (points.size() && moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) { - if (points[0].x() > 1e-2) - points.prepend(QPointF(0, 0)); - QPointF prev = point_to_pixel(points[0]); - for (int i = 1; i < points.size(); i++) { - auto tmp = point_to_pixel(points[i]); - drawLine(&p, prev, tmp, pen); - prev = tmp; - } - } - - // If the Tracker is active, the 'Last Point' it requested is recorded. - // Show that point on the graph, with some lines to assist. - // This new feature is very handy for tweaking the curves! - QPointF last; - if (_config->getLastPoint(last) && isEnabled()) { - QPointF pixel_pos = point_to_pixel(last); - drawPoint(&p, pixel_pos, QColor(255, 0, 0, 120)); - } - } -} - -void QFunctionConfigurator::drawPoint(QPainter *painter, const QPointF &pos, QColor colBG, QColor border) -{ - painter->save(); - painter->setPen(border); - painter->setBrush( colBG ); - painter->drawEllipse(QRectF(pos.x() - pointSize, - pos.y() - pointSize, - pointSize*2, pointSize*2)); - painter->restore(); -} - -void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen &pen) -{ - painter->save(); - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawLine(start, end); - painter->restore(); -} - -void QFunctionConfigurator::mousePressEvent(QMouseEvent *e) -{ - if (!_config || !isEnabled()) - return; - QList points = _config->getPoints(); - if (e->button() == Qt::LeftButton) { - bool bTouchingPoint = false; - moving_control_point_idx = -1; - if (_config) { - for (int i = 0; i < points.size(); i++) { - if (point_within_pixel(points[i], e->pos())) { - bTouchingPoint = true; - moving_control_point_idx = i; - break; - } - } - if (!bTouchingPoint) { - bool too_close = false; - const auto pos = e->pos(); - - for (int i = 0; i < points.size(); i++) - { - const QPointF pt = point_to_pixel(points[i]); - const auto x = pt.x() - pos.x(); - if (point_closeness_limit * point_closeness_limit >= x * x) - { - too_close = true; - break; - } - } - - if (!too_close) - _config->addPoint(pixel_coord_to_point(e->pos())); - } - } - } - - if (e->button() == Qt::RightButton) { - if (_config) { - int found_pt = -1; - for (int i = 0; i < points.size(); i++) { - if (point_within_pixel(points[i], e->pos())) { - found_pt = i; - break; - } - } - - if (found_pt != -1) { - _config->removePoint(found_pt); - } - moving_control_point_idx = -1; - } - } - _draw_function = true; - update(); -} - -void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e) -{ - if (!_config || !isEnabled()) - return; - - QList points = _config->getPoints(); - - if (moving_control_point_idx != -1 && moving_control_point_idx < points.size()) { - setCursor(Qt::ClosedHandCursor); - - bool overlap = false; - - QPoint pix = e->pos(); - QPointF new_pt = pixel_coord_to_point(pix); - - for (int i = 0; i < 2; i++) - { - bool bad = false; - if (moving_control_point_idx + 1 < points.size()) - { - auto other = points[moving_control_point_idx+1]; - auto other_pix = point_to_pixel(other); - bad = pix.x() + point_closeness_limit > other_pix.x(); - if (i == 0 && bad) - { - pix.setX(other_pix.x() - point_closeness_limit - 1); - new_pt = pixel_coord_to_point(pix); - } - else - overlap |= bad; - } - if (moving_control_point_idx != 0) - { - auto other = points[moving_control_point_idx-1]; - auto other_pix = point_to_pixel(other); - bad = pix.x() - point_closeness_limit < other_pix.x(); - if (i == 0 && bad) - { - pix.setX(other_pix.x() + point_closeness_limit + 1); - new_pt = pixel_coord_to_point(pix); - } - else - overlap |= bad; - } - if (!bad) - break; - } - - if (!overlap) - { - points[moving_control_point_idx] = new_pt; - _config->movePoint(moving_control_point_idx, new_pt); - _draw_function = true; - update(); - } - } - else { - bool is_on_point = false; - for (int i = 0; i < points.size(); i++) { - const QPoint pos = e->pos(); - if (point_within_pixel(points[i], pos)) { - is_on_point = true; - break; - } - } - - if (is_on_point) { - setCursor(Qt::OpenHandCursor); - } - else { - setCursor(Qt::ArrowCursor); - } - } -} - -void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e) -{ - if (!_config || !isEnabled()) - return; - - if (e->button() == Qt::LeftButton) { - mouseMoveEvent(e); - setCursor(Qt::ArrowCursor); - moving_control_point_idx = -1; - - _draw_function = true; - update(); - } -} - -void QFunctionConfigurator::update_range() -{ - if (!_config) - return; - - const double w = width(), h = height(); - const double mwl = 40, mhl = 20; - const double mwr = 15, mhr = 35; - - pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr)); - c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput()); - _draw_function = true; - - _background = QPixmap(); - _function = QPixmap(); - - update(); -} - -bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel) -{ - QPointF pixel2 = point_to_pixel(pt); - return pixel2.x() >= pixel.x() - pointSize && pixel2.x() < pixel.x() + pointSize && - pixel2.y() >= pixel.y() - pointSize && pixel2.y() < pixel.y() + pointSize; -} - -QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point) -{ - if (!_config) - return QPointF(-1, -1); - - double x = (point.x() - pixel_bounds.x()) / c.x(); - double y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y(); - - if (x < 0) - x = 0; - if (x > _config->maxInput()) - x = _config->maxInput(); - - if (y < 0) - y = 0; - if (y > _config->maxOutput()) - y = _config->maxOutput(); - - return QPointF(x, y); -} - -QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point) -{ - return QPointF(pixel_bounds.x() + point.x() * c.x(), - pixel_bounds.y() + pixel_bounds.height() - point.y() * c.y()); -} - -void QFunctionConfigurator::resizeEvent(QResizeEvent *) -{ - update_range(); -} diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h deleted file mode 100644 index 667886cd..00000000 --- a/qfunctionconfigurator/qfunctionconfigurator.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2012-2015 Stanislaw Halik - * - * 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. - */ - -// Adapted to FaceTrackNoIR by Wim Vriend. - -#pragma once - -#include -#include -#include -#include "qfunctionconfigurator/functionconfig.h" -#include "opentrack/plugin-api.hpp" - -class QFunctionConfigurator : public QWidget -{ - Q_OBJECT - Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier) -public: - QFunctionConfigurator(QWidget *parent = 0); - - Map* config(); - void setConfig(Map* config, const QString &name); - - QColor colorBezier() const - { - return spline_color; - } - void setColorBezier(QColor color) - { - spline_color = color; - update(); - } - void force_redraw() - { - _background = QPixmap(); - update(); - } -protected slots: - void paintEvent(QPaintEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; -private: - void drawBackground(); - void drawFunction(); - void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG, QColor border = QColor(50, 100, 120, 200)); - void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen& pen); - bool point_within_pixel(const QPointF& pt, const QPointF& pixel); -protected: - void resizeEvent(QResizeEvent *) override; -private: - void update_range(); - static constexpr int point_closeness_limit = 12; - - QPointF pixel_coord_to_point (const QPointF& point); - QPointF point_to_pixel (const QPointF& point); - - Map* _config; - - // bounds of the rectangle user can interact with - QRectF pixel_bounds; - - int moving_control_point_idx; - QPointF c; - - QColor spline_color; - - QPixmap _background; - QPixmap _function; - bool _draw_function; -}; diff --git a/settings/facetracknoir supported games.csv b/settings/facetracknoir supported games.csv new file mode 100644 index 00000000..cf43d7f6 --- /dev/null +++ b/settings/facetracknoir supported games.csv @@ -0,0 +1,576 @@ +No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID +1;18 Wheels of Steel: Haulin';FreeTrack20;V160;V;doc-uk;13601;000121F172F35116A02100 +2;1944 D-Day;FreeTrack20;V160;;;15701;00022E542A6A0575F05200 +497;2KMarinNEXT;FreeTrack20;V170;;;3425;0D614F6A0820D1EA8EE800 +3;3D Instructor;FreeTrack20;V160;;;20490;00034B0FC367116611B100 +4;3D Interactive;FreeTrack20;V160;;;20425;0004C6371D77135815A600 +505;3D Interieur Visualisation;FreeTrack20;V160;;;20815;01F9EDEE75DAC2968D9A00 +5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00 +6;3D-Fahrschule Driving Simulator;FreeTrack20;V160;;;20020;000601075146E0E9625B00 +7;3ds Max;FreeTrack20;V160;;;8601;00077A32A1A7523A4DE700 +8;Aaaaa!;FreeTrack20;V160;;;1775;00085485D831DA62CA7E00 +9;Accessible Computer Games;FreeTrack20;V160;;;4301;000916BC07A2F9B35B6300 +10;Aces High II;FreeTrack20;V160;V;bash1;2701;000A4B798B7221A72E5800 +11;ADS;FreeTrack20;V160;;;20690;000BB25377780C8A894400 +12;Aerofly FS;FreeTrack20;V160;V;V4Friend;2025;000C3797169752CAB39A00 +13;Affineon;FreeTrack20;V160;;;20405;000D662B0374339635A000 +14;Air Battles: Sky Defender;FreeTrack20;V160;;;7003;000E7C822098630A2ED700 +15;Air Phobia;FreeTrack20;V160;;;20100;000F0108339B3E78525B00 +16;Air Traffic Control Tower;FreeTrack20;V160;;;3601;0010432C28637A8EF97400 +17;AirBook;FreeTrack20;V160;;;15201;0011D615A9C8430A201A00 +18;America's Army;FreeTrack20;V160;;;4101;00120BCF5753D98399E200 +19;America's Army 3;FreeTrack20;V170;;;14203;00133F3206BCEA252BB700 +20;ANAG 3D;FreeTrack20;V160;;;20250;0014E2D1D7780A72166300 +21;Apache: Air Assault;FreeTrack20;V160;V;paleta77;1875;001591D997A2D912AAA200 +519;Apex Motorsports;FreeTrack20;V160;;;3675;02078F3159271BBE676800 +22;Aprisoft Gartenplaner;FreeTrack20;V160;;;20014;0016F2F27A5762FA937A00 +23;Aprisoft Traumhaus Designer;FreeTrack20;V160;;;20013;00174655E792BB825B9300 +498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200 +24;ArmA;FreeTrack20;V160;V;EmBeES;10601;0018F2F27A57631A40F200 +25;ArmA 2;FreeTrack20;V170;V;V4Friend Ronski;7502;0019EB3616B3A44F05B900 +26;ArmA 2 Operation Arrowhead;FreeTrack20;V160;V;vn88holden;0;001ABC224B7783DAF0D500 +27;ArmA 3;FreeTrack20;V170;;;7503;001BB69411ABD4E2B39900 +28;Armored Assault - Gold Edition;FreeTrack20;V170;;;1303;001CA7F7CAA00814ECA700 +559;Artificial Head;FreeTrack20;V160;;;20380;022F3A9DCD1F7E0D62C000 +29;Arvoch Alliance;FreeTrack20;V160;;;14908;001D318F8773BAE29A9300 +30;Arvoch Conflict;FreeTrack20;V160;;;14901;001E5C1FDE722DAE2BA900 +31;Auditory Displays for the blind;FreeTrack20;V160;;;20035;001F0FC9FF862F9D34BA00 +486;Autodesk;FreeTrack20;V160;;;20755;01E6953FA7F759AF33AC00 +32;AV Core Technology;FreeTrack20;V160;;;20016;00204655E791166FEB5300 +33;AVRS;FreeTrack20;V160;;;20340;0021231517525830F41D00 +482;B.O.M.B.;FreeTrack20;V160;;;3325;01E248ECCB81191AD49F00 +34;BAE Systems HILAS cockpit;FreeTrack20;V160;;;20019;00220D9C887FD88E98B300 +35;Battle of Britain (iENT);FreeTrack20;V170;;;1305;00230BA119195B701AED00 +36;Battle of Britain II - Wings of Victory;FreeTrack20;V160;V;Normalguy;7001;002452135882CA6419E200 +37;Battlecruiser;FreeTrack20;V160;;;6101;00257C822098728A442900 +38;Battlefield 2;FreeTrack20;V170;;;9601;0026B1560A2A7327659200 +39;Battlefield 2 Trauma Studios;FreeTrack20;V160;;;6501;002720C7529B733AE2EA00 +40;Battlefield 2142;FreeTrack20;V170;;;9602;00281C739AD3817FD43300 +41;Battleground Europe : World War II Online;FreeTrack20;V160;;;3301;0029F07957792CAD3DAF00 +42;Battleground Europe : WWII Online;FreeTrack20;V160;;;11201;002A985017330A844A1200 +573;Beamng.drive;FreeTrack20;V160;;;4525;023D0291C9C05323AC9500 +43;Beckman Institute UIUC;FreeTrack20;V160;;;20012;002BB59DEFA8322A926A00 +44;Beyond The Red Line;FreeTrack20;V160;;;13301;002CE7A7FAA27424BA2A00 +45;BF2 (Unsupported Demo);FreeTrack20;V160;;;9651;002DC6371D86156AEB6000 +46;Big Scale Racing;FreeTrack20;V160;;;8301;002E4655E7A24ADDB99200 +47;Birds of Prey;FreeTrack20;V160;;;1601;002FBF8C4EAA57730B3200 +48;Birds of Steel;FreeTrack20;V160;;;1878;0030D7690F607233A21E00 +49;Boeing;FreeTrack20;V160;;;20351;0031044872BA630A033E00 +50;Boeing Demo;FreeTrack20;V160;;;20350;003228C57B369A37B13600 +51;Bomber Squadron;FreeTrack20;V160;;;1850;00338481733B9E32A83A00 +52;Brain-IT Group;FreeTrack20;V160;;;20050;0034E482F5772C9330B100 +53;Brothers In Arms;FreeTrack20;V160;;;13501;003503FB872CA8439D1F00 +82;C-Spine;FreeTrack20;V160;;;4901;00525FD692C188FB8B2D00 +54;C.A.R.S.;FreeTrack20;V170;;;2825;003698EFE2EB6EE8E11300 +55;C.U.B.;FreeTrack20;V160;;;20505;0037848174F986FD85F500 +56;CameraGripTools;FreeTrack20;V160;;;20150;003870A8B761FA524A4200 +57;Caterpillar Simulators;FreeTrack20;V160;;;23080;0039F52E4221742FA63100 +58;CCG Metamedia;FreeTrack20;V160;;;20009;003A6FA8A8DD86FE8BDB00 +547;CDF Ghostship;FreeTrack20;V160;;;4150;02230A04C45292CC5DA400 +568;CDF Starfighter;FreeTrack20;V160;;;4153;0238E7D9A14B2A1AE98900 +59;CEWIT Immersive Cabin;FreeTrack20;V160;;;20370;003B90B5780C90078DEE00 +60;Chopper;FreeTrack20;V160;;;3150;003CC166C8632A32EA2300 +61;Clearbox;FreeTrack20;V160;;;20565;003D5C1FDE74279D1DB800 +62;CNKFsoft;FreeTrack20;V160;;;20495;003ED7690F6073187B0000 +558;Code 10;FreeTrack20;V160;;;2975;022E45423D22193FF81900 +487;Cognitics;FreeTrack20;V160;;;20760;01E715A96D19515BFC1500 +63;Colin McRae DiRT 2;FreeTrack20;V170;V;V4Friend;8107;003F7815C5379491C73300 +64;Colin McRae Rally 04;FreeTrack20;V160;;;8103;0040D13C2A843DA526A610 +65;Comanche;FreeTrack20;V160;;;2275;00414097C36A12BA32BA00 +569;Combat Air Patrol 2;FreeTrack20;V160;;;4425;02399AAA88F5062AB14500 +66;Combat Flight Simulator 3;FreeTrack20;V160;V;V4Friend;2304;00420EC5F763AB21CA7310 +67;Combat Helo;FreeTrack20;V160;;;2001;004329DFA863FAE1EA7300 +515;Combined Arms;FreeTrack20;V160;;;1309;0203387EDB1A5AFEADB600 +68;Commandos Strike Force;FreeTrack20;V160;;;8801;0044C1BBF892DB037A7200 +555;COMPUTERGRAFIK;FreeTrack20;V160;;;20900;022B5BB1CE1DAA0B1DEB00 +69;Concept RS;FreeTrack20;V160;;;10701;004537971697736A72DA00 +70;Condor: The Competitive Soaring Simulator;FreeTrack20;V160;V;MicheleF;5901;004670A8B762DA623A1300 +71;Conflict Taiwan;FreeTrack20;V160;;;1950;0047D7690F6073399E2000 +72;Corys;FreeTrack20;V160;;;20550;0048157D78738A342A8D00 +73;Counter Strike;FreeTrack20;V160;;;12501;004953FE1E862AB73DA600 +74;Crane Simulator;FreeTrack20;V160;;;20048;004A6B62C6A7931972DA00 +567;Cranfield University;FreeTrack20;V160;;;20905;0237A8C5B26E7A38A66500 +75;Crashday;FreeTrack20;V160;;;5601;004BD6E585F893D933BA00 +76;Creanex Training Simulator;FreeTrack20;V160;;;20205;004CF478D277A40A929A00 +77;Creative Labs headset;FreeTrack20;V160;;;20018;004D348B1743E961FA6300 +78;Cross Racing Championship;FreeTrack20;V160;;;4801;004E20C763AB232B5E8900 +79;Crysis Mod;FreeTrack20;V160;;;1625;004F90B57839B231A24200 +80;Crystal Growth Simulation;FreeTrack20;V160;;;20029;005026F79742FB241A6200 +81;Crytek;FreeTrack20;V170;;;2775;0051D5F1EBBAD81C714600 +571;CS GO MOD;FreeTrack20;V160;;;12504;023BCA154A55F9587FC500 +562;Cypher City;FreeTrack20;V160;;;4250;023259070AE238A9E78100 +83;D2x-XL;FreeTrack20;V160;;;16001;00532E20237BEDABEB8A00 +84;Dark Horizons Lore;FreeTrack20;V160;;;7901;005487801A852AA7385200 +85;Dawn of Aces - Gold Edition;FreeTrack20;V170;;;1304;0055A9ED7700814190DE00 +86;Dawn of Aces II;FreeTrack20;V160;;;1302;00566925967C2BB0285500 +513;Dawn of Aces/Red Baron;FreeTrack20;V160;;;1307;0201916C14F32918D9B800 +87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200 +88;DCS: Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00 +89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91 Shadow;1003;0059B6DCD15F5A572F6500 +90;Dead Reckoning;FreeTrack20;V160;;;10401;005A4C2F6752F912D66200 +91;Delivery;FreeTrack20;V160;;;15901;005BF3E85B1A8534AE3400 +471;Demon Core;FreeTrack20;V160;;;3225;01D7D1DC6052A165A7AC00 +563;Descent: Underground;FreeTrack20;V160;;;4275;023355381D3CCBD801D700 +92;DiRT;FreeTrack20;V160;;;8104;005C72456F7523881F1800 +93;DiRT 3;FreeTrack20;V170;;;8108;005DABA016ED2DFBDF6F00 +94;Door3;FreeTrack20;V160;;;20665;005ED13C2A853DA82F6B00 +528;Dovetail Games;FreeTrack20;V160;;;3850;0210EE3E0DA9BC1B888100 +534;Dovetail Train Simulator 2015;FreeTrack20;V160;;;3851;02160B238D555F3D389E00 +95;Down In Flames;FreeTrack20;V160;;;1025;005F29DFA873FB82A66000 +96;Driver Test;FreeTrack20;V160;;;20265;00609343487C3FAA429D00 +97;Driver's Republic;FreeTrack20;V160;;;14001;0061D24C3F8A3F9C33AB00 +98;DriveSim;FreeTrack20;V160;;;5001;0062DD7CC2B47830A14400 +99;Driving Simulator;FreeTrack20;V160;;;13001;00630AC67539AC3F9F3A00 +100;dSphere TBA;FreeTrack20;V160;;;2425;0064A2AE4981FB5389A300 +101;DTS;FreeTrack20;V160;;;20625;006505B37C12868B3E8500 +102;Dungeons and Dragons Online;FreeTrack20;V170;;;1575;0066BD4D4DDC6BB6818800 +103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00 +104;EADS Testing;FreeTrack20;V160;;;20303;00680288709760D5512900 +504;EAFIT;FreeTrack20;V160;;;20810;01F8D2675ABC163E99B000 +105;Eagle Lander 3D;FreeTrack20;V160;;;11901;00697686E5A7B209C27900 +106;EasyVR;FreeTrack20;V160;;;20220;006A68292872FAC4588100 +107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500 +508;Elite: Dangerous;FreeTrack20;V170;;;3475;0D93A9485EECA12E18BE00 +481;Embers of Caerus;FreeTrack20;V170;;;3275;0CCB4134258D7E10119E00 +108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500 +109;Enemy Engaged 2;FreeTrack20;V160;;;2102;006D010873EA635AEDC800 +110;Enemy Engaged: Commanche vs Hokum;FreeTrack20;V160;;;2101;006E157D789379636AED00 +524;Enemy Starfighter;FreeTrack20;V160;;;3725;020C7EF3AC4F08C8787600 +111;Envision TE;FreeTrack20;V160;;;20320;006FD13C2A863CAF26AB00 +112;EON Reality;FreeTrack20;V160;;;20410;0070B6C6142771F82EE900 +113;eSigma;FreeTrack20;V160;;;20700;0071950F9AA60DAD2E9F00 +114;Euro Truck Simulator;FreeTrack20;V160;V;mamsa;13602;00721B4BFF8B3EA3296600 +115;EVE Online;FreeTrack20;V160;;;11801;0073F47CC377C2388DC900 +550;EVE Valkyrie;FreeTrack20;V170;;;4175;104F28E121C07E6D84C200 +116;Eventology;FreeTrack20;V160;;;12201;0074849F8B469C2BAC3600 +117;EVOC-101 Training;FreeTrack20;V160;;;20038;00756925967D2088FC6200 +118;Evochron Alliance 2.0;FreeTrack20;V160;;;14904;00767A32A1A8735A022900 +557;Evochron Legacy;FreeTrack20;V160;;;14909;022D84A6946770E4EFD800 +119;Evochron Legends;FreeTrack20;V160;;;14906;0077D6E585F8B41A12BA00 +120;Evochron Mercenary;FreeTrack20;V160;V;Scavenger4711 ;14907;00783752FBC7B42B221A00 +121;Evochron Renegades;FreeTrack20;V160;;;14905;0079621E7763FB421A1300 +122;EZCA;FreeTrack20;V160;V;dennison ;2475;007A6DBB52F7B147510601 +572;EZCamViews;FreeTrack20;V160;;;4475;023CF141A5E222B5ACE000 +125;F-22 Total Air War;FreeTrack20;V160;;;1750;007D20C79F475F0621DB00 +126;F-35 PTA;FreeTrack20;V160;;;20185;007E26F7977E96C0352100 +148;F-Trainer;FreeTrack20;V160;;;20615;0094C6371D8AFB8C3E9900 +123;F1 2011/2012;FreeTrack20;V170;;;8109;007B265ECD74893EA12900 +531;F1 2015;FreeTrack20;V170;;;8110;1FAE39C238A4D2D6541200 +124;F1 Challenge 99-02;FreeTrack20;V160;;;4401;007CA15F278FB660C9D210 +127;FAAC;FreeTrack20;V160;;;20500;007F0F00F489118300C000 +128;Farmer Simulator 2009;FreeTrack20;V160;;;1725;0080926ED8A1EB628AB300 +129;Faros Driving Simulator;FreeTrack20;V160;;;8001;0081B1C6647A1EA839A800 +130;Faubert Lab Car Simulator;FreeTrack20;V160;;;20480;00822E542A7F2DB61F9700 +131;Ferrari Virtual Academy;FreeTrack20;V160;V;sosna1983 ;0;0083C0AF8C24B62D974000 +132;FIFA 09;FreeTrack20;V170;;;9002;0084288979C65B0DAA0D00 +133;Fighter Ace;FreeTrack20;V160;;;8401;0085E2D1D77D259837B700 +134;Fighter Ops;FreeTrack20;V160;;;9301;00860FC9FF8B23A033BA00 +135;Fighter Squadron: Screamin Demons Over Europe;FreeTrack20;V160;;;1675;00872E20237D259A27A600 +136;First Eagles Wings Over Europe Strike Fighters;FreeTrack20;V160;;;1101;0088311857638A73BB7E00 +469;Flight Gear;FreeTrack20;V160;;;12901;01D5D896C66B030606E000 +466;Flight Simulator 2002;FreeTrack20;V160;;;2302;01D21F7650E254B4514B00 +467;Flight Simulator 2004;FreeTrack20;V160;;;2303;01D3E91BAAB385B2362E00 +468;Flight Simulator X;FreeTrack20;V160;;;2305;01D41C31F42FAF32603600 +137;FlightGear;FlightGear;V110;V;V4Friend;0;0089054E8839A02FAB2F00 +138;Flyboys / Warbirds;FreeTrack20;V160;;;1301;008ABB5BF72C8934AB2B00 +139;Flyer;FreeTrack20;V160;;;1650;008BD1C9F27826AE2CA500 +140;Flying Tigers;FreeTrack20;V160;;;7002;008C91D997F29A930B0200 +141;FlyingGuns;FreeTrack20;V160;;;14801;008D7A32A1A882BAA28A00 +142;Ford Racing 3;FreeTrack20;V160;;;6901;008E27D5047C2BA62F5800 +561;Forklift Simulator;FreeTrack20;V160;;;20885;02314A30F16DAF63EABB00 +542;Fractured Space;FreeTrack20;V170;;;3976;0F88A4D88906429E684E00 +143;Free Falcon 4.0;FreeTrack20;V160;;;1901;008F157D78A3B962E55000 +144;Free Falcon 4.0: Allied Force;FreeTrack20;V160;;;8901;0090656DD6793CA9325900 +145;Free Falcon 5;FreeTrack20;V160;V;V4Friend;1902;00911038C3AAB32590E900 +146;FreeSpace2;FreeTrack20;V160;;;13302;0092C8CDF8C2EA63496300 +552;FSX Steam Edition;FreeTrack20;V160;;;3852;02287F45F0FFBEF6102900 +147;FTAlpha;FreeTrack20;V160;;;20270;00936C69677F1D772AA900 +149;Full Out;FreeTrack20;V160;;;1701;009527D5047C31A0375800 +150;Future Pinball;FreeTrack20;V160;V;V4Friend;13101;00969343487E42B541AA00 +151;Game VR;FreeTrack20;V160;;;20325;009756BA018030B0355500 +152;GameLab;FreeTrack20;V160;;;20555;00985485D891DB23092200 +472;Games Farm;FreeTrack20;V160;;;3250;01D875C0981E627E5C7600 +153;Gamma;FreeTrack20;V160;;;1050;009921007D1B9D38A76F00 +503;Garry's Mod;FreeTrack20;V160;;;12503;01F74EEB71FA7F37856900 +532;Gavap Simulator;FreeTrack20;V160;;;20850;0214C254E2B970AA7A6200 +483;Generic Robotics;FreeTrack20;V160;;;20750;01E3FE7B4F05872A415400 +548;Ghostship Aftermath;FreeTrack20;V160;;;4151;02243F473BAD82FFD14A00 +475;Glider Sim;FreeTrack20;V160;;;20720;01DB42130C4B0620871C00 +154;Global Ground Support Deicing Simulation;FreeTrack20;V160;;;20330;009ACFE709237A3AA11F00 +546;GoD Factory: Wingmen;FreeTrack20;V160;;;4125;0222C0ECA71AD9C75AD100 +155;GosNIIAS Sim Trainer;FreeTrack20;V160;;;20355;009BB78B06EC8A2DB81800 +156;Gothic 3;FreeTrack20;V160;;;14401;009C37971697B36AD32A00 +157;Grand Prix Legends;FreeTrack20;V160;;;6701;009D521358D3D933B96E01 +158;Grand Theft Auto: San Andreas;FreeTrack20;V160;;;7808;009E5F3D95777D3BA23700 +159;GRID;FreeTrack20;V160;V;LeapoEclipse ;8105;009FD8175F8D1D7C0D3800 +160;GSE Power Plant Simulation;FreeTrack20;V160;;;20044;00A0432C28C217BEF93300 +161;GT Legends;FreeTrack20;V160;V;TrickyDee ;3902;00A116BC08020581CA8200 +162;GTR;FreeTrack20;V160;;;3901;00A2FD6BFE39A881B85B00 +163;GTR2 EVO;FreeTrack20;V160;V;zild1221 ;0;00A34B0FC37B2198F96300 +164;Gun Commander;FreeTrack20;V160;;;2675;00A4E2D1D77E319FEE8600 +520;H1Z1;FreeTrack20;V170;;;6004;1774F090B1BA9E782D0800 +165;Half Life 2;FreeTrack20;V160;;;7806;00A556BA018130AF365500 +166;Halo;FreeTrack20;V160;;;3801;00A656BA018130AF3F9C00 +502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00 +167;Hardware Control Simulator Railway Electronics;FreeTrack20;V160;;;20705;00A7F3E85B1A8930B42F00 +168;Harrier Attack II;FreeTrack20;V160;;;1175;00A8F2F27A57D20A940900 +499;Harry's Hard Choices Interactive;FreeTrack20;V160;;;20800;01F33A21BAE3DB6D48A000 +169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000 +170;Herissons (Paris France);FreeTrack20;V160;;;20001;00AAEA1CBED8C20B430B00 +523;hiCRANE2;FreeTrack20;V160;;;20835;020BA8FC8C7DFFA1381A00 +171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900 +172;HoverAssault;FreeTrack20;V160;;;5303;00AC521358E3AA832A4000 +173;HPC;FreeTrack20;V160;;;20600;00AD0FC9FF8D0A7CEF9500 +174;HPG Tracking;FreeTrack20;V160;;;20255;00AE0288A1879D98930900 +175;HTW;FreeTrack20;V160;;;20630;00AF26F797911901C22C00 +176;Huawei Software;FreeTrack20;V160;;;20660;00B04655E8030A733AB300 +177;HueSpace;FreeTrack20;V160;;;20510;00B1231517C44960FB6300 +178;Hyper Vision;FreeTrack20;V160;;;15101;00B2DB242B657D43B32300 +179;iAmFootball;FreeTrack20;V160;;;1250;00B3B59DEFAAAFDB301A00 +180;id Research;FreeTrack20;V170;;;2950;00B4E723B873D7FC87D700 +181;IESA;FreeTrack20;V160;;;20037;00B5157D78D0E840AD7100 +182;IL-2 Cliffs of Dover;FreeTrack20;V160;V;V4Friend;0;00B6282282095F00521000 +183;IL-2 Forgotten Battles ACE Pacific Fighters;FreeTrack20;V160;V;Glenn;1001;00B722FD79137100621100 +484;IL-2 Sturmovik: Battle of Stalingrad;FreeTrack20;V170;;;1008;03F04D5368D1FD2DF2AE00 +184;Illumina;FreeTrack20;V160;;;1350;00B8054E8B39A33DB02400 +185;ILP;FreeTrack20;V160;;;20310;00B9F07957801789C9A600 +186;Imagine 3D ATC Tower Simulation;FreeTrack20;V160;;;20032;00BAEF7A8F4B8812B95300 +187;In Touch Technologies Inc.;FreeTrack20;V160;;;20006;00BB84817A3A5124B23D00 +188;Inglobe;FreeTrack20;V160;;;20360;00BCE7A7FAA27B2DA82700 +189;Innovatec Simulator;FreeTrack20;V160;;;20036;00BD22FD7935B23DB82C00 +190;Insurgency;FreeTrack20;V160;;;9401;00BEB6C61427B3EA744B00 +575;Interstellar Rift;FreeTrack20;V160;;;4550;023FF83230A370CBC6AC00 +191;Intific;FreeTrack20;V160;;;20655;00BF2BCA747F2AA8309D00 +566;Into the Dungeon;FreeTrack20;V160;;;4375;0236B346990ACCFC047A00 +192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900 +193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00 +536;ISAMM;FreeTrack20;V160;;;20860;0218303730165E681DB000 +194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00 +506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100 +195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00 +196;J.J. Keller and Associates;FreeTrack20;V160;;;20002;00C4E482F57FE77CF46300 +197;Janes F18;FreeTrack20;V160;;;9001;00C55F3D9577802AAF2E00 +198;Javal Ent.;FreeTrack20;V160;;;2650;00C622FD7A28BA2FAEEA00 +199;JC Demo;FreeTrack20;V160;;;20470;00C70AC67B0A630D9B3900 +200;Jet Thunder;FreeTrack20;V160;;;4501;00C82100801FA4EA9A3500 +201;Jetfighter V;FreeTrack20;V160;;;2501;00C9F52E42217B33A63200 +202;JFIST;FreeTrack20;V160;;;20560;00CAC932727C0F8D208600 +203;John Deere Vehicle Simulator;FreeTrack20;V160;;;20175;00CB29DFA8D3FA92A66000 +204;Jump to Lightspeed;FreeTrack20;V160;;;6001;00CCC166C8D3FA12E52400 +205;Jumpgate;FreeTrack20;V160;;;15001;00CD26F797B32A63E99200 +206;Jumpgate Evolution;FreeTrack20;V170;;;15002;00CE5936D4F93DCE0CE700 +207;KAF Keymapper;FreeTrack20;V160;;;3101;00CF934348830E87EB8300 +476;KAI FLight Simulator;FreeTrack20;V160;;;20725;01DCC522132A5C01EDE500 +560;Keita Head Tracking;FreeTrack20;V160;;;20385;02307E33478667072B0800 +208;Key Macro View;FreeTrack20;V160;;;12001;00D016BC08431B1EF90100 +209;kiwi.vg;FreeTrack20;V160;;;20395;00D1409A430AB33633E900 +521;Kongsberg GlobalSim;FreeTrack20;V160;;;20825;0209B2C573D990BF764700 +210;L-3;FreeTrack20;V160;;;20465;00D2F885EFA8DE67878B00 +211;L-3 Communications;FreeTrack20;V160;;;20051;00D3D6E585F92F765E7800 +522;LG Electronics;FreeTrack20;V160;;;20830;020A3678F5833D513DCA00 +212;Lionhead MGS Game Research;FreeTrack20;V160;;;15301;00D4C1BBF9227B238AE200 +213;Live For Speed;FreeTrack20;V160;V;zild1221 ;7101;00D528228526A833521300 +214;Live for Speed S2;FreeTrack20;V160;;;11601;00D63752FBC8235B923500 +218;Lock-On: Modern Air Combat;FreeTrack20;V160;;;1002;00DAAC156D903C993B6200 +215;Lockheed Martin Littoral Combat Ship simulator;FreeTrack20;V160;;;20025;00D771ED5E802A9827A000 +216;Lockheed Martin Prepar3D;SimConnect;V130;V;elelbe ;0;00D8D615A9C8F36932AA00 +217;LockOn: Flaming Cliffs 2;FreeTrack20;V170;V;EmBeES ;1005;00D9AFB0D279F3A6F72200 +219;London NHS;FreeTrack20;V160;;;20640;00DB2E2023832BA123A100 +220;Lore (Dark Horizons);FreeTrack20;V160;;;5302;00DCF478D27833DB62D500 +221;Love;FreeTrack20;V160;;;3125;00DD71ED5E802AAB214800 +222;Lucid Engine;FreeTrack20;V160;;;10501;00DE71ED5E803098259C00 +514;M4 Tank Brigade;FreeTrack20;V160;;;1308;02024ED5A3A26741604300 +223;M4 Tank Platoon;FreeTrack20;V160;;;1306;00DFDCC441A8E036320900 +224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000 +549;MAG WIP;FreeTrack20;V160;;;4152;02252A1C82FD29D9FFB900 +225;ManuVAR;FreeTrack20;V160;;;20455;00E153FE1E901CB0448800 +226;MaqSIM4;FreeTrack20;V160;;;20026;00E28F54A207D29B611700 +227;Mech Tactical Sim;FreeTrack20;V160;;;9501;00E3F3E85B1A8E34A53300 +228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200 +516;MechWarrior Online;FreeTrack20;V170;;;3026;0BD2E0DCBC723836CD2400 +229;Medical Image Visualization;FreeTrack20;V160;;;20295;00E59343488532A5359B00 +230;Meggitt Defense Systems;FreeTrack20;V160;;;20045;00E6926ED9122AB22AF300 +231;MetaVR;FreeTrack20;V160;;;20545;00E7C5BEE48120A8308800 +232;Meteoroid Maze;FreeTrack20;V160;;;13003;00E8F079578430AD2EB200 +233;MeVEA;FreeTrack20;V160;;;2250;00E9D24C3F933289028700 +234;Micro Flight;FreeTrack20;V160;V;V4Friend;5101;00EABA89D078439932EA00 +235;Microsoft ESP;FreeTrack20;V160;;;2306;00EB0AC67E30A63BA53F00 +236;Microsoft Flight;FreeTrack20;V170;V;V4Friend;2307;00ECAFBC54959539C51500 +237;Microsoft Flight Simulator 3;FreeTrack20;V160;V;V4Friend;0;00ED5909437D36963EA810 +238;Microsoft FS2002/2004;FSUIPC;V130;V;V4Friend;0;00EE44958F34992CB43A00 +239;Microsoft FSX;SimConnect;V130;V;V4Friend;0;00EFF478D278437A73AA00 +240;Microsoft Train Simulator;FreeTrack20;V160;;;7805;00F00449225A439A13FB00 +494;MiddleVR;FreeTrack20;V160;;;20785;01EE1227DF43CA90C26100 +241;Mig Alley;FreeTrack20;V160;;;1501;00F17686E5A83289CDA700 +242;Mimik Vehicle Simulator;FreeTrack20;V160;;;20585;00F2AB1D58A8E35A531A00 +243;Miner Wars;FreeTrack20;V160;;;2550;00F3C5BEE48124A234A400 +244;MKMapper Keymapper;FreeTrack20;V160;;;2201;00F487801A8E14822EA200 +245;ModelSim;FreeTrack20;V160;;;20540;00F544958F3A9A1FB11A00 +246;Morgan State University;FreeTrack20;V160;;;20010;00F65909437D3CA5339A00 +247;Motor Company;FreeTrack20;V160;;;11501;00F70288F37A629A7DD700 +248;Motorsport Simulators;FreeTrack20;V160;;;4201;00F8F52E42217E3DA63B00 +249;Mouse Emulation;FreeTrack20;V160;;;8501;00F9950F9A8E29B93A9700 +250;MS World Tour Kart 2004;FreeTrack20;V160;;;6601;00FA9F819CA27F10591600 +251;MSN Virtual Earth;FreeTrack20;V160;;;2309;00FBF47CC37842091DC900 +252;mTBI Balance;FreeTrack20;V160;;;20420;00FC72456F9E0E78145800 +253;NASA Crew Exploration Vehicle;FreeTrack20;V160;;;20017;00FD028900985FA5501A00 +254;NASCAR Heat;FreeTrack20;V160;;;2602;00FE311857E10880B84100 +255;NASCAR Racing 2003 season;FreeTrack20;V160;;;7804;00FFDE661F6D920B87FC10 +256;NASCAR SimRacing;FreeTrack20;V160;;;6201;01004098708870D761A500 +535;Navi Trainer Professional;FreeTrack20;V160;;;20855;0217C0E0793305EE8D5200 +257;NecroVisioN;FreeTrack20;V160;;;15601;0101621E77F2EA830A8100 +258;NetKar Pro;FreeTrack20;V160;V;sosna1983 ;10901;01028C3958334A5169A300 +259;Nitro Stunt Racing;FreeTrack20;V160;;;13901;0103C0AF9428B82DA5ED00 +260;North Eastern University;FreeTrack20;V160;;;20003;0104A2AE4823BB7449DE00 +261;Novint;FreeTrack20;V160;;;2725;01051C76F8137B823A4300 +262;NVH Sound Simulator;FreeTrack20;V160;;;20695;010655A2AA93158DDE9500 +479;OHJCH;FreeTrack20;V160;;;20740;01DF992E6C0DA43A703600 +551;Omni-Directional Movement;FreeTrack20;V160;;;20870;0227088B794053785DBE00 +263;OMSI Bus Simulator;FreeTrack20;V160;V;Thiago ;2225;0107F47CC37861A9606600 +264;Onadime - Realtime Animation;FreeTrack20;V160;;;20049;010853FE1E9229A3339B00 +265;Open Falcon 4.5;FreeTrack20;V160;V;muplex ;0;0109B1C664832D9B385500 +266;Operation Air Assault 2;FreeTrack20;V160;;;5401;010ABB5BF72C9238973B00 +267;Operation Flashpoint 2 (inactive);FreeTrack20;V160;;;7601;010BD1C9F2812A9A399400 +268;Operation Flashpoint(r): Dragon Rising(tm);FreeTrack20;V170;;;8106;010C3328780E1322676100 +269;OptiMetrics;FreeTrack20;V160;;;20011;010D55A2AA942FB9288F00 +270;OpusFSX;FreeTrack20;V160;;;3175;010E1C76F8238B72D7C100 +271;Orbiter 2005 Plug-In;FreeTrack20;V160;;;10301;010F87801A903B9736A600 +272;Orbiter 2006;FreeTrack20;V160;V;Ripley;10303;0110D24C3F953F9526BA00 +273;Orbiter 2006 Plug-In;FreeTrack20;V160;;;10302;0111054E913F9931B72000 +274;Oryx Vehicle Simulators;FreeTrack20;V160;;;20028;0112C8CDF952EBA4763100 +275;Outer Conflict: Frontiers;FreeTrack20;V160;;;1900;01136C6967883EAA23AB00 +276;Over Flanders Fields;FreeTrack20;V160;V;Summelar ;2325;0114A59E68873E9B315210 +277;PanoPro;FreeTrack20;V160;;;20525;0115B6C61428231A23E900 +278;Paraworld;FreeTrack20;V160;;;14501;0116656DD6832BB62EB000 +279;Phoenix R/C;FreeTrack20;V160;;;3075;0117B6C61428238A334B00 +280;Pivot Maritime;FreeTrack20;V160;;;20365;01187686E5A8628AB2AA00 +281;PlanetSide 2;FreeTrack20;V170;;;6002;0119BB34B53FDC5C5AAF00 +474;PlanetSide 2 M.E.;FreeTrack20;V160;;;6003;01DA321EF31DA48C159A00 +282;Pointman;FreeTrack20;V160;;;7525;011ACFE70923833D9B2B00 +538;Police 1013;FreeTrack20;V160;;;3925;021ABAE5040512FE42CA00 +283;Power Driving Simulator;FreeTrack20;V160;;;20675;011BB78B06EC932DBC2F00 +470;Prepar3D;FreeTrack20;V160;;;20440;01D6DA768CE8AA43D8DC00 +284;Priston Tale;FreeTrack20;V160;;;9701;011C849F9642A030AC3600 +285;Project Reality (BF2 Mod);FreeTrack20;V160;;;9201;011D3C2C1C922CB239A800 +286;Project Torque (Invictus);FreeTrack20;V160;;;4802;011E612F28540B52797100 +287;Project X;FreeTrack20;V160;;;20022;011FE9D85E4842DA439900 +529;Puegeot PSA Simulator;FreeTrack20;V160;;;20840;021127A7344E7C044E9500 +545;PULSAR: Lost Colony;FreeTrack20;V160;;;4075;02214BC732C034C3620400 +553;QSTP;FreeTrack20;V160;;;20875;0229A3C108BE55FFF2BC00 +288;Quanser;FreeTrack20;V160;;;20435;0120950F9A922FA535A500 +289;QuantaDyn;FreeTrack20;V160;;;20575;012199BB5C9433A739B600 +290;Quest 3D Xframe Plugin;FreeTrack20;V160;;;20043;0122FD6BFE39A923C98200 +291;Quest3D;FreeTrack20;V160;;;1425;01234B0FC38542AB3BB700 +292;Quest3D - CINEACT integration;FreeTrack20;V160;;;20040;0124A15F28340AB3CA9000 +303;R-concept X (AdrenalinStorm);FreeTrack20;V160;;;9101;012F72456F83E6993AA600 +293;R.U.D.O. Tools;FreeTrack20;V160;;;20039;0125612F287FB9BEA76E00 +294;RACE (the WTCC game);FreeTrack20;V160;;;3904;01263C2C1C94FA86146300 +295;RACE 07 RACE GTR 2;FreeTrack20;V160;V;zild1221 TrickyDee ;3903;0127C0AF9800870056FD00 +296;RaceOn;FreeTrack20;V160;V;zild1221 ;0;0128621E7832AA82388200 +297;Racer;FreeTrack20;V160;;;2401;01296D2D103862E932EA00 +298;Racer S;FreeTrack20;V160;;;20030;012AEA1CBED961CA52CB00 +490;RaceRoom Racing Experience;FreeTrack20;V160;;;3905;01EA9124F663AF03BBC500 +299;Rail Simulator 1;FreeTrack20;V160;;;1550;012BB253778929A0395900 +300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100 +301;RailWorks 2;FreeTrack20;V160;;;2750;012D3919C4972D9D299000 +507;RailWorks 5 (TS2014);FreeTrack20;V160;;;1551;01FB8B5232CB1502C95A00 +302;Raydon Driving Simulator;FreeTrack20;V160;;;3701;012E5485D941DBE2FB5300 +574;RCPlugin;FreeTrack20;V160;;;23090;023E0448BCFD48E0149D00 +304;Real Time Visual;FreeTrack20;V160;;;9901;0130B1C664862297365500 +305;RealFlight;FreeTrack20;V160;;;4001;0131AC6E87892E993A8B00 +306;Reality Manager;FreeTrack20;V160;;;20046;0132DB242B65872FA42A00 +307;RealWorld;FreeTrack20;V160;;;20215;0133B59DEFA9322A727800 +308;Red Baron 3D;FreeTrack20;V160;;;1125;0134C6371D96349CEB7A00 +309;Red Orchestra: Heroes of Stalingrad;FreeTrack20;V170;;;12602;013521F9121056CD997300 +310;Red Orchestra: Ostfront;FreeTrack20;V170;;;12601;01369A9A2BE97252BB9000 +311;Redline Monitor;FreeTrack20;V160;;;20210;01373752FBC8831A72AA00 +312;REFLEX XTR;FreeTrack20;V160;;;2150;0138054E94127D14881300 +313;Remote Presence;FreeTrack20;V160;;;20710;01399BC3BDA93229D2BB00 +314;rFactor;FreeTrack20;V160;V;V4Friend;7401;013AEF7A8F4B8AA0495200 +315;rFactor Pro;FreeTrack20;V170;;;7403;013B175198D74BE8E89600 +316;rFactor2;FreeTrack20;V170;;;7402;013CBFF3A86D34DA24C000 +533;rFPro;FreeTrack20;V170;;;7404;1CEC6BE26009B31DE7BC00 +317;Richard Burns Rally;FreeTrack20;V160;V;zild1221;3401;013D42868B339A31A73C10 +318;RidingStar;FreeTrack20;V160;;;1475;013E3919C497359826A700 +544;Rift's Cave;FreeTrack20;V160;;;4050;02209C681EAD3B06D15A00 +319;Rig N Roll;FreeTrack20;V160;;;9801;013FD1C9F284239CE68100 +320;Rio Tinto Resource Development;FreeTrack20;V160;;;20033;01401039831B5EC8D31900 +321;Rise of Flight;FreeTrack20;V160;V;Seborgarsen ;11401;0141AA71218335A51F5100 +322;Rise: The Vieneo Province;FreeTrack20;V160;;;6301;0142DEE3582F9837A82D00 +323;Rising Conflicts;FreeTrack20;V160;;;12101;014384818335A439B12F00 +492;RITS;FreeTrack20;V160;;;20775;01ECEE745B83DD3A0DBE00 +324;Road Legends;FreeTrack20;V160;;;1876;0144379716986369A2E600 +325;Rogue Space;FreeTrack20;V160;;;3050;014588F5872C9C30ABE900 +326;Rogue Warrior;FreeTrack20;V160;;;14202;0146432C2973D9D45A8E00 +530;RoRo Simulator;FreeTrack20;V160;;;20845;02123A5F2F98EF4D0F0700 +327;ROV Sim;FreeTrack20;V160;;;20530;0147FA04BD27891D9ADD00 +328;Rowan's Battle Of Britain;FreeTrack20;V160;;;1502;014821008829A72CB4F300 +329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00 +330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200 +331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400 +540;Rust;FreeTrack20;V170;;;3950;0F6EF7CEF7DFA93405D700 +511;Sail;FreeTrack20;V160;;;3575;01FF2916D764159099F800 +332;Sail Simulator 5;FreeTrack20;V160;;;1975;014CE2D1D78A1D9A3B6300 +333;Sailors of the Sky;FreeTrack20;V160;;;10201;014D17BE02961FAF3AB100 +334;Santa Cruz Watermill;FreeTrack20;V160;;;20290;014E88F5881EA32FA7E900 +335;SCANeR Studio Plugin;FreeTrack20;V160;;;20445;014FA2AE4870F861E9A100 +336;SEGA Demo;FreeTrack20;V160;;;2075;015016BC08C117F1163000 +337;Seven-G;FreeTrack20;V160;;;2350;01510F00F49635B822A200 +338;SFSPC;FreeTrack20;V160;;;2801;0152F885EFA9400981B700 +339;Ship Simulator 2006;FreeTrack20;V160;;;5002;015329DFA9638AA2C66100 +340;Ship Simulator 2008;FreeTrack20;V160;V;djj3ff ;5003;01545213599339B3D52100 +341;Shiphandling Simulator;FreeTrack20;V160;;;20570;01553FD0FC9D8B37AD3700 +554;ShiVa;FreeTrack20;V160;;;4225;022AA2A7DC2F7222696C00 +342;Shooting Simulator;FreeTrack20;V160;;;20047;0156F2F27A58827A63DA00 +343;SIA Games;FreeTrack20;V160;;;20015;0157926ED970685DA8D200 +344;Silent Wings;FreeTrack20;V160;;;8701;0158D615A9C96309C24A00 +345;SilverHat;FreeTrack20;V160;;;12401;0159D8175F99349F3F9600 +346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00 +347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00 +348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00 +518;SimCraft;FreeTrack20;V160;;;3650;02065BA013963203CB1900 +349;SimCreator;FreeTrack20;V160;;;20520;015D3752FBC8935B001A00 +350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100 +351;SimQuest immersion system;FreeTrack20;V160;;;20023;015F6C69678C32A30FAE00 +352;SimSol;FreeTrack20;V160;;;20034;01602315187389E0FB5300 +491;Simumak;FreeTrack20;V160;;;20770;01EB119629980784DCE600 +510;Sir You Are Being Hunted;FreeTrack20;V160;;;3550;01FEDAB345FA104ED4A100 +353;Sirocco Racing;FreeTrack20;V160;;;5801;01612BCA748925A6369A00 +354;Sky God: Military Freefall;FreeTrack20;V170;;;1526;01622C0104385FD1C44400 +355;Soft fx Demo;FreeTrack20;V160;;;2125;01632E20238A2B99335200 +537;Solitude;FreeTrack20;V160;;;3875;02199BA2A9B217BB4B7200 +356;Source Engine (Half-Life 2);FreeTrack20;V160;;;12502;0164E482F58829A739A600 +357;Space Shuttle Mission 2007;FreeTrack20;V160;V;purewhitewings ;1225;0165662B03863D912F9700 +517;Spaze;FreeTrack20;V160;;;3625;020573F9D3ED8C43B8DC00 +358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100 +359;Stanford University;FreeTrack20;V160;;;20004;0167CE35BAF9933A62AA00 +500;Star Citizen;FreeTrack20;V170;;;3450;0D7AF4CE4E343EC6B4A200 +360;Starshatter;FreeTrack20;V160;;;6401;0168F079578A3F9A3BB600 +361;Steel Beasts 2;FreeTrack20;V160;;;11703;0169DCC441A9443A831A00 +362;Steel Beasts Pro;FreeTrack20;V160;;;11701;016A8F54A20833CAA23900 +363;Steel Beasts Pro Personal;FreeTrack20;V160;;;11702;016BF3E85B1A9443A73000 +565;Steel Beasts Professional;FreeTrack20;V160;;;4350;02356C64A9AFBB37E56E00 +364;Stoked Rider;FreeTrack20;V160;;;14701;016CC166C963EA32997300 +365;Storm of War: the Battle of Britain;FreeTrack20;V170;;;11001;016D8F54A68B71F25D0200 +495;STRAFT;FreeTrack20;V160;;;3375;01EF1329E014ADF98D6B00 +366;Stride;FreeTrack20;V170;;;2310;016EC784B21E4B21984400 +541;Strike Suit Zero;FreeTrack20;V170;;;3975;0F87E77F3BD3DB8821A200 +367;STS Driving Simulator;FreeTrack20;V160;;;20300;016FA59E688B1C89DE7600 +368;Sunaerosys;FreeTrack20;V160;;;20475;01700449831AF28973EB00 +369;Superkarting;FreeTrack20;V160;;;14903;0171DE661F6D973FA41F00 +370;SuperX Research;FreeTrack20;V160;;;15401;0172BA89D078A45A021A00 +371;SWRI Demo;FreeTrack20;V160;;;20230;01730AC6841E9512561000 +372;Syncon Robot Control;FreeTrack20;V160;;;20415;0174C1BBF9937B12DB5200 +373;Synergy Simulation;FreeTrack20;V160;;;20595;0175926ED9736B220B8200 +374;T and TS Corp.;FreeTrack20;V160;;;20005;017617BE0297DDA73CA600 +539;Tacview;FreeTrack20;V160;;;20865;021B1F0CFB651B91405C00 +375;Take On Helicopters;FreeTrack20;V170;;;7504;0177513CB40C0623B96A00 +376;Target: Korea;FreeTrack20;V160;;;1201;0178F52E4221852FA43300 +377;Target: Rabaul;FreeTrack20;V160;;;1202;0179E9D85E4881CA736900 +378;Targeting Demo;FreeTrack20;V160;;;13002;017AAB1D58A952DAA2F900 +379;TD Demo;FreeTrack20;V160;;;1925;017BC5BEE488FE54139700 +489;TeachLive;FreeTrack20;V160;;;20765;01E905245B5AC5484FC100 +380;Telepresence;FreeTrack20;V160;;;20450;017CF478D278B33B02DA00 +381;Tenstar Simulator;FreeTrack20;V160;;;20605;017D318F88A2EA62DBA200 +382;Test Drive Unlimited;FreeTrack20;V160;;;13201;017E6F2699559730A84000 +509;Tetrahedral;FreeTrack20;V160;;;3525;01FDCFF1C56D6F757E8200 +501;The Crew;FreeTrack20;V170;;;1009;03F1F534E94F4834D9B100 +488;The Gallery;FreeTrack20;V160;;;3350;01E8CE152EDE5FFD267700 +383;The Sky Gods;FreeTrack20;V170;;;1525;017FDFF782DCCEEA27C200 +384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000 +385;thriXXX HII 3D;FreeTrack20;V160;;;13403;0181FA04BD27AB36B62700 +386;thriXXX Jenna;FreeTrack20;V160;;;13401;01829F819CA2A625AB2800 +387;ThriXXX Technology;FreeTrack20;V160;;;13402;0183F47CC378B35B526900 +388;tir2joy;FreeTrack20;V160;;;2202;018487801AB532A7FE9C00 +389;TIRF4;FreeTrack20;V160;;;2203;0185311858418870E77000 +390;TNO;FreeTrack20;V160;;;20285;01861AAF6870A853D64900 +391;ToCA Race Driver 2;FreeTrack20;V160;;;8102;0187FFE9E886F286297910 +392;Toca Race Driver 3;FreeTrack20;V160;;;8101;01884098D36972B551A900 +393;Tom Clancy's H.A.W.X.;FreeTrack20;V170;V;EmBeES ;1004;0189AA4D48E85966FBAA00 +394;Tom Clancy's H.A.W.X. 2;FreeTrack20;V170;;;1007;018A1B7583521C12406F00 +395;Torque Game Engine;FreeTrack20;V160;;;5301;018BC0AF9A2EB62CAB3300 +396;Total War;FreeTrack20;V160;;;1375;018C72456F8529AA2CA400 +397;Tower Crane Simulator;FreeTrack20;V160;;;20670;018D03FB9929B034A7D900 +398;Tower I;FreeTrack20;V160;;;1325;018E662B03873CA731A400 +399;TPL Testing;FreeTrack20;V160;;;20260;018F849F9A2083DC8C2C00 +400;trackd;FreeTrack20;V160;;;20580;019053FE1EB72DA3329D00 +401;TrackMapper2;FreeTrack20;V160;;;2175;0191CE35BAF9A31A61FA00 +402;TrainMaster;FreeTrack20;V160;;;20042;01925C1FDE852D9925B400 +403;Trainz;FreeTrack20;V160;;;4701;0193D1C9F2862C9630A100 +404;TraumTek;FreeTrack20;V160;;;20650;0194A2AE4883EA645A2100 +405;Turismo Carretera;FreeTrack20;V160;;;15801;01956F2699559740A73500 +406;UK Rally Champion;FreeTrack20;V160;;;5701;019679EC0E28B196522A00 +407;ULAN;FreeTrack20;V160;;;20645;01974ADE68E16780D97A00 +473;Underwater Navigation;FreeTrack20;V160;;;20715;01D9FE2B94FB03772DE200 +408;Unity 3D Plugin;FreeTrack20;V160;;;20430;0198D24C3F9B3B9C31BF00 +525;Unity 64-bit;FreeTrack20;V160;;;3750;020DC8AB18AF3539FA5200 +556;Unity Plugin (64-bit);FreeTrack20;V160;;;20880;022C55B8AAD3A670670100 +409;Untitled 10tacle;FreeTrack20;V160;;;13701;0199FFE9E886F28728AA00 +410;Untitled 3D People;FreeTrack20;V160;;;15501;019A6925968D38AD23A900 +411;Untitled Apportmedia;FreeTrack20;V160;;;6801;019B3C2C1C9728B738B700 +412;Untitled Combat Flight Sim;FreeTrack20;V160;;;13801;019CA59E688D36AA28A600 +413;Untitled Deep Silver;FreeTrack20;V160;;;14601;019D656DD68838B836AD00 +414;Untitled G5 Software;FreeTrack20;V160;;;7301;019E318F88B37AC23BA300 +415;Untitled Microsoft;FreeTrack20;V160;;;2308;019FA15F28739BA32A9300 +416;Untitled Research;FreeTrack20;V160;;;1075;01A07686E5A8B2DA924A00 +417;Untitled Ron E;FreeTrack20;V160;;;14902;01A14ADE68E38AB28B9300 +418;Untitled Sega of America;FreeTrack20;V160;;;12801;01A27A32A1A972DA528A00 +419;Untitled Simbin;FreeTrack20;V160;;;3902;01A36C69678E37AA27AD00 +420;Untitled WorkShield;FreeTrack20;V160;;;4601;01A442868E38AB32BA3600 +421;Untitled ZootFly;FreeTrack20;V160;;;12701;01A5348B1863AA527A6300 +422;UQO;FreeTrack20;V160;;;23085;01A67C822099A187FE3600 +423;UVEG Machinery Simulator;FreeTrack20;V160;;;20024;01A73118585257A0F63100 +424;VAR;FreeTrack20;V160;;;20460;01A8950F9A97FA96FD2E00 +425;VBS2;FreeTrack20;V160;;;7501;01A999BB5C990099FCBF00 +485;VBS2 2.0;FreeTrack20;V170;;;7505;1D51EB3616B3A44F05B900 +527;VCORP RBR2 MOD;FreeTrack20;V160;;;3825;020FEE9EA847F2ADB45800 +426;Vehicle Simulator (Quality Simulations);FreeTrack20;V160;;;5102;01AA0FC9FF9B1FA134A900 +478;Vehicle Simulator Direction;FreeTrack20;V160;;;20735;01DEB88CF58E570F1CEF00 +427;Vestibular Ocular Reflex;FreeTrack20;V160;;;20008;01AB3919C49B31A731A200 +428;Viper Arena;FreeTrack20;V160;;;3501;01AC6F2699559934A53100 +429;VIRTools Engine;FreeTrack20;V160;;;10801;01AD1AAF68905881EB5300 +430;Virtools Plugin;FreeTrack20;V160;;;20200;01AE03FB9B23AB43A42900 +431;Virtual Driving;FreeTrack20;V160;;;20245;01AF99BB5C9927B83FB700 +432;Virtual Heroes;FreeTrack20;V160;;;20375;01B0621E78732B732AE200 +433;Virtual RC Racing;FreeTrack20;V160;;;8201;01B16D2D1038A36A23DA00 +434;Virtual Sailor;FreeTrack20;V160;;;5201;01B25F3D95778C32B33D00 +435;Virtual Shopper;FreeTrack20;V160;;;20610;01B3B78B06EC9927B73E00 +436;Virtual Supermarket;FreeTrack20;V160;;;20280;01B4849F9C39A931AD2800 +496;VirtualiTeach;FreeTrack20;V160;;;20790;01F062AE1CAB33B52D0700 +480;Vizard;FreeTrack20;V160;;;20745;01E0C1F20A79D7C0561300 +437;VizRD;FreeTrack20;V160;;;20031;01B55485D9825BF1D8AB00 +438;Void War;FreeTrack20;V160;;;10001;01B65C1FDE872AA1206600 +564;VR Truck Simulator;FreeTrack20;V160;;;4325;02344CAEE1BC9E243D9F00 +477;VRPlayer;FreeTrack20;V160;;;20730;01DD6787E57245201D5000 +439;VT08;FreeTrack20;V160;;;1275;01B7B78B06EC9912750200 +440;VVVV Plugin;FreeTrack20;V160;;;20075;01B8B1C6648A138C205500 +441;VW Testing;FreeTrack20;V160;;;20275;01B9AC6E878D205822AA00 +442;Walkabout3d;FreeTrack20;V160;;;20125;01BA2822901E9E39932F00 +443;Wallbusters;FreeTrack20;V160;;;1450;01BB88F58C1EA127A83F00 +444;War Thunder;FreeTrack20;V160;;;0;01BC17BE029A1FB8ED9600 +445;WAVES;FreeTrack20;V160;;;20515;01BD05B38FFE89008B8B00 +446;Welding Simulator;FreeTrack20;V160;;;2625;01BE348B188319D229B300 +447;West Racing;FreeTrack20;V160;;;1801;01BF91D999022A33B62000 +448;Whirlwind of Vietnam;FreeTrack20;V160;;;11101;01C0054E9935A03AAF3200 +449;Wikid FJ;FreeTrack20;V160;;;20685;01C19BC3BDA98269B25A00 +450;Wings of Prey;FreeTrack20;V160;V;V4Friend;1877;01C25909438736A133AC00 +451;Wings of War;FreeTrack20;V160;;;7807;01C34B0FC38B36B42FB610 +512;Wings: Over Flanders Fields;FreeTrack20;V160;;;2326;02008AE39AAA4624B33C00 +570;Wingsuit Simulator;FreeTrack20;V160;;;4450;023A472FA37FCD7427D900 +543;World of Diving;FreeTrack20;V160;;;4025;021F27B7B28D5012E1B300 +452;World Racing 2;FreeTrack20;V160;;;7201;01C41AAF68A2BA836AAE00 +453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100 +454;X Motor Racing;FreeTrack20;V160;;;1150;01C669259690E98629A900 +526;X-Camera;FreeTrack20;V160;;;3775;020E1C4055DE39CBC03D00 +458;X-Cockpit for X-Plane;FreeTrack20;V160;;;2901;01CA1C76F8BF4852999300 +459;X-Plane (32 and 64 bit);FreeTrack20;V160;V;EmBeES ;7701;01CB3FD0FC9D90FB943300 +460;X-Plane 6DOF Plugin;FreeTrack20;V160;;;10101;01CCA15F28AF7963596300 +461;X-Plane Pilot View (32 and 64 bit);FreeTrack20;V160;V;V4Friend;11301;01CD79EC0E28EFA953CA00 +462;X-Tower for X-Plane;FreeTrack20;V160;;;3001;01CE05B390EA872AAF3200 +455;X1Alpha;FreeTrack20;V160;;;1825;01C76D2D1038CFD7135A00 +456;X2: The Threat;FreeTrack20;V160;;;5501;01C81039EF980EC8D30900 +457;X3: Albion Prelude and Reunion;FreeTrack20;V170;V;V4Friend;5502;01C97E101A708F8524E300 +463;Xyphoid;FreeTrack20;V160;;;14301;01CF656DD68B43B435A800 +464;zedasoft F-35 Demo;FreeTrack20;V160;;;20041;01D02100B01F942CB93C00 +493;ZKT;FreeTrack20;V160;;;20780;01ED2BAA723F3C097EE800 +465;Zombie AA Research;FreeTrack20;V160;;;14201;01D1AA71218B3B9F1C9A00 diff --git a/spline-widget/CMakeLists.txt b/spline-widget/CMakeLists.txt new file mode 100644 index 00000000..522491ea --- /dev/null +++ b/spline-widget/CMakeLists.txt @@ -0,0 +1,6 @@ +opentrack_boilerplate(opentrack-spline-widget NO-LIBRARY) +opentrack_qt(opentrack-spline-widget) +add_library(opentrack-spline-widget STATIC ${opentrack-spline-widget-all}) +opentrack_compat(opentrack-spline-widget) +target_include_directories(opentrack-spline-widget PUBLIC qfunctionconfigurator/) +target_link_libraries(opentrack-spline-widget ${MY_QT_LIBS}) diff --git a/spline-widget/broken/qfunctionconfiguratorplugin.cpp b/spline-widget/broken/qfunctionconfiguratorplugin.cpp new file mode 100644 index 00000000..1a9da10a --- /dev/null +++ b/spline-widget/broken/qfunctionconfiguratorplugin.cpp @@ -0,0 +1,111 @@ +/* Copyright (c) 2011-2012 Stanislaw Halik + * Adapted to FaceTrackNoIR by 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 "qfunctionconfigurator.h" + +#include +#include "qfunctionconfiguratorplugin.h" + + +QFunctionConfiguratorPlugin::QFunctionConfiguratorPlugin(QObject *parent) + : QObject(parent) +{ + initialized = false; +} + +void QFunctionConfiguratorPlugin::initialize(QDesignerFormEditorInterface *) +{ + if (initialized) + return; + + initialized = true; +} + +bool QFunctionConfiguratorPlugin::isInitialized() const +{ + return initialized; +} + +QWidget *QFunctionConfiguratorPlugin::createWidget(QWidget *parent) +{ + return new QFunctionConfigurator(parent); +} + +QString QFunctionConfiguratorPlugin::name() const +{ + return "QFunctionConfigurator"; +} + +QString QFunctionConfiguratorPlugin::group() const +{ + return "My Plugins"; +} + +QIcon QFunctionConfiguratorPlugin::icon() const +{ + return QIcon(); +} + +QString QFunctionConfiguratorPlugin::toolTip() const +{ + return QString(); +} + +QString QFunctionConfiguratorPlugin::whatsThis() const +{ + return QString(); +} + +bool QFunctionConfiguratorPlugin::isContainer() const +{ + return false; +} + +QString QFunctionConfiguratorPlugin::domXml() const +{ + return "\n" + " \n" + " \n" + " 0\n" + " 0\n" + " 161\n" + " 220\n" + " \n" + " \n" + " \n" + " \n" + " 255\n" + " 170\n" + " 0\n" + " \n" + " \n" + " \n" + " Input Yaw (degr.)\n" + " \n" + " \n" + " Output Yaw (degr.)\n" + " \n" + " \n" + " 50\n" + " \n" + " \n" + " 180\n" + " \n" + " \n" + " 2\n" + " \n" + " \n" + " 1\n" + " \n" + "\n"; +} + +QString QFunctionConfiguratorPlugin::includeFile() const +{ + return "qfunctionconfigurator.h"; +} + +Q_EXPORT_PLUGIN2(qfunctionconfigurator, QFunctionConfiguratorPlugin) diff --git a/spline-widget/broken/qfunctionconfiguratorplugin.h b/spline-widget/broken/qfunctionconfiguratorplugin.h new file mode 100644 index 00000000..ca68e0e2 --- /dev/null +++ b/spline-widget/broken/qfunctionconfiguratorplugin.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2011-2012 Stanislaw Halik + * Adapted to FaceTrackNoIR by 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. + */ +#ifndef QFUNCTIONCONFIGURATORPLUGIN_H +#define QFUNCTIONCONFIGURATORPLUGIN_H + +#include + +class QFunctionConfiguratorPlugin : public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "analogclock.json") + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + QFunctionConfiguratorPlugin(QObject *parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget *createWidget(QWidget *parent); + void initialize(QDesignerFormEditorInterface *core); +private: + bool initialized; +}; + +#endif // QFUNCTIONCONFIGURATORPLUGIN_H diff --git a/spline-widget/functionconfig.cpp b/spline-widget/functionconfig.cpp new file mode 100644 index 00000000..27f3bf40 --- /dev/null +++ b/spline-widget/functionconfig.cpp @@ -0,0 +1,249 @@ +/* Copyright (c) 2012-2015, Stanislaw Halik + + * 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 +#include +#include +#include +#include "functionconfig.h" +#include +#include +#include +#include +#include +#include + +void Map::setTrackingActive(bool blnActive) +{ + activep = blnActive; +} + +Map::Map() : + _mutex(QMutex::Recursive), + activep(false), + max_x(0), + max_y(0) +{ +} + +float Map::getValue(float x) { + QMutexLocker foo(&_mutex); + float q = x * precision(); + int xi = (int)q; + float yi = getValueInternal(xi); + float yiplus1 = getValueInternal(xi+1); + float f = (q-xi); + float ret = yiplus1 * f + yi * (1.0f - f); // at least do a linear interpolation. + last_input_value.setX(std::fabs(x)); + last_input_value.setY(std::fabs(ret)); + return ret; +} + +bool Map::getLastPoint(QPointF& point ) { + QMutexLocker foo(&_mutex); + point = last_input_value; + return activep; +} + +float Map::getValueInternal(int x) { + float sign = x < 0 ? -1 : 1; + x = abs(x); + float ret; + int sz = cur.data.size(); + if (sz == 0) + ret = 0; + else + ret = cur.data[std::min(x, sz-1)]; + return ret * sign; +} + +static QPointF ensureInBounds(QList points, int i) { + int siz = points.size(); + if (siz == 0 || i < 0) + return QPointF(0, 0); + if (siz > i) + return points[i]; + return points[siz - 1]; +} + +static bool sortFn(const QPointF& one, const QPointF& two) { + return one.x() < two.x(); +} + +void Map::reload() { + if (cur.input.size()) + { + qStableSort(cur.input.begin(), cur.input.end(), sortFn); + + QList input = cur.input; + auto& data = cur.data; + + data = std::vector(value_count); + const int mult = precision(); + const int mult_ = mult * 30; + + const int sz = data.size(); + + for (int i = 0; i < sz; i++) + data[i] = -1; + + if (input.size() == 1 && input[0].x() > 1e-2) + { + for (int k = 0; k < input[0].x() * mult; k++) { + if (k < sz) + data[k] = input[0].y() * k / (input[0].x() * mult); + } + } + else if (input[0].x() > 1e-2) + input.prepend(QPointF(0, 0)); + + for (int i = 0; i < sz; i++) { + const QPointF p0 = ensureInBounds(input, i - 1); + const QPointF p1 = ensureInBounds(input, i); + const QPointF p2 = ensureInBounds(input, i + 1); + const QPointF p3 = ensureInBounds(input, i + 2); + + const float p0_x = p0.x(), p1_x = p1.x(), p2_x = p2.x(), p3_x = p3.x(); + const float p0_y = p0.y(), p1_y = p1.y(), p2_y = p2.y(), p3_y = p3.y(); + + // multiplier helps fill in all the x's needed + const int end = std::min(sz, p2.x() * mult_); + const int start = p1.x() * mult; + + for (int j = start; j < end; j++) { + const float t = (j - start) / (float) (end - start); + const float t2 = t*t; + const float t3 = t*t*t; + + const int x = .5 * ((2. * p1_x) + + (-p0_x + p2_x) * t + + (2. * p0_x - 5. * p1_x + 4. * p2_x - p3_x) * t2 + + (-p0_x + 3. * p1_x - 3. * p2_x + p3_x) * t3) + * mult; + + const float y = .5 * ((2. * p1_y) + + (-p0_y + p2_y) * t + + (2. * p0_y - 5. * p1_y + 4. * p2_y - p3_y) * t2 + + (-p0_y + 3. * p1_y - 3. * p2_y + p3_y) * t3); + + if (x >= 0 && x < sz) + data[x] = y; + } + } + + float last = 0; + for (int i = 0; i < sz; i++) + { + if (data[i] < 0) + data[i] = last; + last = data[i]; + } + } + else + cur.data.clear(); +} + +void Map::removePoint(int i) { + QMutexLocker foo(&_mutex); + if (i >= 0 && i < cur.input.size()) + { + cur.input.removeAt(i); + reload(); + } +} + +void Map::addPoint(QPointF pt) { + QMutexLocker foo(&_mutex); + cur.input.append(pt); + reload(); + qStableSort(cur.input.begin(), cur.input.end(), sortFn); +} + +void Map::movePoint(int idx, QPointF pt) { + QMutexLocker foo(&_mutex); + if (idx >= 0 && idx < cur.input.size()) + { + cur.input[idx] = pt; + reload(); + // we don't allow points to be reordered, so no sort here + } +} + +const QList Map::getPoints() { + QMutexLocker foo(&_mutex); + return cur.input; +} + +void Map::invalidate_unsaved_settings() +{ + QMutexLocker foo(&_mutex); + cur = saved; + reload(); +} + +void Map::loadSettings(QSettings& settings, const QString& title) { + QMutexLocker foo(&_mutex); + QPointF newPoint; + QList points; + settings.beginGroup(QString("Curves-%1").arg(title)); + + int max = settings.value("point-count", 0).toInt(); + + for (int i = 0; i < max; i++) { + newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toDouble(), + settings.value(QString("point-%1-y").arg(i), 0).toDouble()); + if (newPoint.x() > max_x) { + newPoint.setX(max_x); + } + if (newPoint.y() > max_y) { + newPoint.setY(max_y); + } + points.append(newPoint); + } + + settings.endGroup(); + + if (max == 0) + points.append(QPointF(maxInput(), maxOutput())); + + cur.input = points; + reload(); + saved = cur; +} + +void Map::saveSettings(QSettings& settings, const QString& title) { + QMutexLocker foo(&_mutex); + settings.beginGroup(QString("Curves-%1").arg(title)); + int max = cur.input.size(); + settings.setValue("point-count", max); + + for (int i = 0; i < max; i++) { + settings.setValue(QString("point-%1-x").arg(i), cur.input[i].x()); + settings.setValue(QString("point-%1-y").arg(i), cur.input[i].y()); + } + + for (int i = max; true; i++) + { + QString x = QString("point-%1-x").arg(i); + if (!settings.contains(x)) + break; + settings.remove(x); + settings.remove(QString("point-%1-y").arg(i)); + } + + saved = cur; + + settings.endGroup(); +} + + +int Map::precision() const { + if (cur.input.size()) + return value_count / std::max(1.f, (cur.input[cur.input.size() - 1].x())); + return 1; +} diff --git a/spline-widget/functionconfig.h b/spline-widget/functionconfig.h new file mode 100644 index 00000000..6d76d0de --- /dev/null +++ b/spline-widget/functionconfig.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2012-2015, Stanislaw Halik + + * 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 +#include +#include +#include +#include +#include +#include +#include "opentrack-compat/qcopyable-mutex.hpp" + +class Map { +private: + static constexpr int value_count = 10000; + + struct State { + QList input; + std::vector data; + }; + + int precision() const; + void reload(); + float getValueInternal(int x); + + MyMutex _mutex; + QPointF last_input_value; + volatile bool activep; + double max_x; + double max_y; + + State cur, saved; +public: + double maxInput() const { return max_x; } + double maxOutput() const { return max_y; } + Map(); + Map(double maxx, double maxy) + { + setMaxInput(maxx); + setMaxOutput(maxy); + reload(); + } + + float getValue(float x); + bool getLastPoint(QPointF& point); + void removePoint(int i); + void removeAllPoints() { + QMutexLocker foo(&_mutex); + cur.input.clear(); + reload(); + } + + void addPoint(QPointF pt); + void movePoint(int idx, QPointF pt); + const QList getPoints(); + void setMaxInput(double MaxInput) { + max_x = MaxInput; + } + void setMaxOutput(double MaxOutput) { + max_y = MaxOutput; + } + + void saveSettings(QSettings& settings, const QString& title); + void loadSettings(QSettings& settings, const QString& title); + void invalidate_unsaved_settings(); + + void setTrackingActive(bool blnActive); +}; diff --git a/spline-widget/qfunctionconfigurator.cpp b/spline-widget/qfunctionconfigurator.cpp new file mode 100644 index 00000000..7ab1e360 --- /dev/null +++ b/spline-widget/qfunctionconfigurator.cpp @@ -0,0 +1,440 @@ +/* Copyright (c) 2012-2015 Stanislaw Halik + * + * 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 "opentrack/options.hpp" +using namespace options; +#include "spline-widget/qfunctionconfigurator.h" +#include +#include +#include +#include +#include +#include + +static const int pointSize = 5; + +QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) : + QWidget(parent), + _config(nullptr), + moving_control_point_idx(-1), + _draw_function(true) +{ + update_range(); + setMouseTracking(true); +} + +void QFunctionConfigurator::setConfig(Map* config, const QString& name) { + mem iniFile = group::ini_file(); + if (name != "") + config->loadSettings(*iniFile, name); + _config = config; + _draw_function = true; + update_range(); + update(); +} + +void QFunctionConfigurator::drawBackground() +{ + if (!_config) + return; + _background = QPixmap(width(), height()); + + QPainter painter(&_background); + painter.fillRect(rect(), QColor::fromRgb(204, 204, 204)); + + QColor bg_color(112, 154, 209); + if (!isEnabled()) + bg_color = QColor(176,176,180); + painter.fillRect(pixel_bounds, bg_color); + + QFont font; + font.setPointSize(8); + painter.setFont(font); + QFontMetrics metrics(font); + + QColor color__(176, 190, 209, 127); + + if (!isEnabled()) + color__ = QColor(70, 90, 100, 96); + + QPen pen(color__, 1, Qt::SolidLine); + + const int xstep = 10, ystep = 10; + const double maxx = _config->maxInput(); + const double maxy = _config->maxOutput(); + + // horizontal grid + for (int i = 0; i < maxy; i += xstep) + { + double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y(); + drawLine(&painter, + QPointF(pixel_bounds.x(), y), + QPointF(pixel_bounds.x() + pixel_bounds.width(), y), + pen); + painter.drawText(QRectF(10, + y - metrics.height()/2, + pixel_bounds.left(), + metrics.height()), + QString::number(i)); + } + + { + const double i = maxy; + double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y(); + drawLine(&painter, + QPointF(pixel_bounds.x(), y), + QPointF(pixel_bounds.x() + pixel_bounds.width(), y), + pen); + painter.drawText(QRectF(10, + y - metrics.height()/2, + pixel_bounds.x() - 10, + metrics.height()), + QString::number(i)); + } + + // vertical grid + for (int i = 0; i < maxx; i += ystep) + { + double x = pixel_bounds.x() + i * c.x(); + drawLine(&painter, + QPointF(x, pixel_bounds.y()), + QPointF(x, pixel_bounds.y() + pixel_bounds.height()), + pen); + const QString text = QString::number(i); + painter.drawText(QRectF(x - metrics.width(text)/2, + pixel_bounds.height() + 10 + metrics.height(), + metrics.width(text), + metrics.height()), + text); + } + { + const double i = maxx; + double x = pixel_bounds.x() + i * c.x(); + drawLine(&painter, + QPointF(x, pixel_bounds.y()), + QPointF(x, pixel_bounds.y() + pixel_bounds.height()), + pen); + const QString text = QString::number(i); + painter.drawText(QRectF(x - metrics.width(text)/2, + pixel_bounds.height() + 10 + metrics.height(), + metrics.width(text), + metrics.height()), + text); + } +} + +void QFunctionConfigurator::drawFunction() +{ + if (!_config) + return; + + _function = QPixmap(_background); + QPainter painter(&_function); + painter.setRenderHint(QPainter::Antialiasing, true); + + QList points = _config->getPoints(); + + const int alpha = !isEnabled() ? 64 : 120; + for (int i = 0; i < points.size(); i++) { + drawPoint(&painter, + point_to_pixel(points[i]), + QColor(200, 200, 210, alpha), + isEnabled() ? QColor(50, 100, 120, 200) : QColor(200, 200, 200, 96)); + } + + QColor color = spline_color; + + if (!isEnabled()) + { + const int avg = 176; + auto color_ = color; + color = QColor(color_.red() * .5 + avg * .5, + color_.green() * .5 + avg * .5, + color_.blue() * .5 + avg * .5, + 96); + } + + QPen pen(color, 1.2, Qt::SolidLine); + + const double max = _config->maxInput(); + const double step = std::max(1e-2, max / 1000.); + + QPointF prev = point_to_pixel(QPointF(0, 0)); + for (double i = 0; i < max; i += step) { + double val = _config->getValue(i); + QPointF cur = point_to_pixel(QPointF(i, val)); + drawLine(&painter, prev, cur, pen); + prev = cur; + } +} + +void QFunctionConfigurator::paintEvent(QPaintEvent *e) +{ + QPainter p(this); + + if (_background.isNull()) + { + _draw_function = true; + drawBackground(); + } + + if (_draw_function) { + _draw_function = false; + drawFunction(); + } + + p.drawPixmap(e->rect(), _function); + + if (_config) { + QPen pen(Qt::white, 1, Qt::SolidLine); + QList points = _config->getPoints(); + if (points.size() && moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) { + if (points[0].x() > 1e-2) + points.prepend(QPointF(0, 0)); + QPointF prev = point_to_pixel(points[0]); + for (int i = 1; i < points.size(); i++) { + auto tmp = point_to_pixel(points[i]); + drawLine(&p, prev, tmp, pen); + prev = tmp; + } + } + + // If the Tracker is active, the 'Last Point' it requested is recorded. + // Show that point on the graph, with some lines to assist. + // This new feature is very handy for tweaking the curves! + QPointF last; + if (_config->getLastPoint(last) && isEnabled()) { + QPointF pixel_pos = point_to_pixel(last); + drawPoint(&p, pixel_pos, QColor(255, 0, 0, 120)); + } + } +} + +void QFunctionConfigurator::drawPoint(QPainter *painter, const QPointF &pos, QColor colBG, QColor border) +{ + painter->save(); + painter->setPen(border); + painter->setBrush( colBG ); + painter->drawEllipse(QRectF(pos.x() - pointSize, + pos.y() - pointSize, + pointSize*2, pointSize*2)); + painter->restore(); +} + +void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen &pen) +{ + painter->save(); + painter->setPen(pen); + painter->setBrush(Qt::NoBrush); + painter->drawLine(start, end); + painter->restore(); +} + +void QFunctionConfigurator::mousePressEvent(QMouseEvent *e) +{ + if (!_config || !isEnabled()) + return; + QList points = _config->getPoints(); + if (e->button() == Qt::LeftButton) { + bool bTouchingPoint = false; + moving_control_point_idx = -1; + if (_config) { + for (int i = 0; i < points.size(); i++) { + if (point_within_pixel(points[i], e->pos())) { + bTouchingPoint = true; + moving_control_point_idx = i; + break; + } + } + if (!bTouchingPoint) { + bool too_close = false; + const auto pos = e->pos(); + + for (int i = 0; i < points.size(); i++) + { + const QPointF pt = point_to_pixel(points[i]); + const auto x = pt.x() - pos.x(); + if (point_closeness_limit * point_closeness_limit >= x * x) + { + too_close = true; + break; + } + } + + if (!too_close) + _config->addPoint(pixel_coord_to_point(e->pos())); + } + } + } + + if (e->button() == Qt::RightButton) { + if (_config) { + int found_pt = -1; + for (int i = 0; i < points.size(); i++) { + if (point_within_pixel(points[i], e->pos())) { + found_pt = i; + break; + } + } + + if (found_pt != -1) { + _config->removePoint(found_pt); + } + moving_control_point_idx = -1; + } + } + _draw_function = true; + update(); +} + +void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e) +{ + if (!_config || !isEnabled()) + return; + + QList points = _config->getPoints(); + + if (moving_control_point_idx != -1 && moving_control_point_idx < points.size()) { + setCursor(Qt::ClosedHandCursor); + + bool overlap = false; + + QPoint pix = e->pos(); + QPointF new_pt = pixel_coord_to_point(pix); + + for (int i = 0; i < 2; i++) + { + bool bad = false; + if (moving_control_point_idx + 1 < points.size()) + { + auto other = points[moving_control_point_idx+1]; + auto other_pix = point_to_pixel(other); + bad = pix.x() + point_closeness_limit > other_pix.x(); + if (i == 0 && bad) + { + pix.setX(other_pix.x() - point_closeness_limit - 1); + new_pt = pixel_coord_to_point(pix); + } + else + overlap |= bad; + } + if (moving_control_point_idx != 0) + { + auto other = points[moving_control_point_idx-1]; + auto other_pix = point_to_pixel(other); + bad = pix.x() - point_closeness_limit < other_pix.x(); + if (i == 0 && bad) + { + pix.setX(other_pix.x() + point_closeness_limit + 1); + new_pt = pixel_coord_to_point(pix); + } + else + overlap |= bad; + } + if (!bad) + break; + } + + if (!overlap) + { + points[moving_control_point_idx] = new_pt; + _config->movePoint(moving_control_point_idx, new_pt); + _draw_function = true; + update(); + } + } + else { + bool is_on_point = false; + for (int i = 0; i < points.size(); i++) { + const QPoint pos = e->pos(); + if (point_within_pixel(points[i], pos)) { + is_on_point = true; + break; + } + } + + if (is_on_point) { + setCursor(Qt::OpenHandCursor); + } + else { + setCursor(Qt::ArrowCursor); + } + } +} + +void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e) +{ + if (!_config || !isEnabled()) + return; + + if (e->button() == Qt::LeftButton) { + mouseMoveEvent(e); + setCursor(Qt::ArrowCursor); + moving_control_point_idx = -1; + + _draw_function = true; + update(); + } +} + +void QFunctionConfigurator::update_range() +{ + if (!_config) + return; + + const double w = width(), h = height(); + const double mwl = 40, mhl = 20; + const double mwr = 15, mhr = 35; + + pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr)); + c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput()); + _draw_function = true; + + _background = QPixmap(); + _function = QPixmap(); + + update(); +} + +bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel) +{ + QPointF pixel2 = point_to_pixel(pt); + return pixel2.x() >= pixel.x() - pointSize && pixel2.x() < pixel.x() + pointSize && + pixel2.y() >= pixel.y() - pointSize && pixel2.y() < pixel.y() + pointSize; +} + +QPointF QFunctionConfigurator::pixel_coord_to_point(const QPointF& point) +{ + if (!_config) + return QPointF(-1, -1); + + double x = (point.x() - pixel_bounds.x()) / c.x(); + double y = (pixel_bounds.height() - point.y() + pixel_bounds.y()) / c.y(); + + if (x < 0) + x = 0; + if (x > _config->maxInput()) + x = _config->maxInput(); + + if (y < 0) + y = 0; + if (y > _config->maxOutput()) + y = _config->maxOutput(); + + return QPointF(x, y); +} + +QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point) +{ + return QPointF(pixel_bounds.x() + point.x() * c.x(), + pixel_bounds.y() + pixel_bounds.height() - point.y() * c.y()); +} + +void QFunctionConfigurator::resizeEvent(QResizeEvent *) +{ + update_range(); +} diff --git a/spline-widget/qfunctionconfigurator.h b/spline-widget/qfunctionconfigurator.h new file mode 100644 index 00000000..baea9e34 --- /dev/null +++ b/spline-widget/qfunctionconfigurator.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2012-2015 Stanislaw Halik + * + * 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. + */ + +// Adapted to FaceTrackNoIR by Wim Vriend. + +#pragma once + +#include +#include +#include +#include "spline-widget/functionconfig.h" +#include "opentrack/plugin-api.hpp" + +class QFunctionConfigurator : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier) +public: + QFunctionConfigurator(QWidget *parent = 0); + + Map* config(); + void setConfig(Map* config, const QString &name); + + QColor colorBezier() const + { + return spline_color; + } + void setColorBezier(QColor color) + { + spline_color = color; + update(); + } + void force_redraw() + { + _background = QPixmap(); + update(); + } +protected slots: + void paintEvent(QPaintEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; +private: + void drawBackground(); + void drawFunction(); + void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG, QColor border = QColor(50, 100, 120, 200)); + void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen& pen); + bool point_within_pixel(const QPointF& pt, const QPointF& pixel); +protected: + void resizeEvent(QResizeEvent *) override; +private: + void update_range(); + static constexpr int point_closeness_limit = 12; + + QPointF pixel_coord_to_point (const QPointF& point); + QPointF point_to_pixel (const QPointF& point); + + Map* _config; + + // bounds of the rectangle user can interact with + QRectF pixel_bounds; + + int moving_control_point_idx; + QPointF c; + + QColor spline_color; + + QPixmap _background; + QPixmap _function; + bool _draw_function; +}; diff --git a/tracker-aruco/CMakeLists.txt b/tracker-aruco/CMakeLists.txt new file mode 100644 index 00000000..ed52eee6 --- /dev/null +++ b/tracker-aruco/CMakeLists.txt @@ -0,0 +1,8 @@ +find_package(OpenCV 3.0) +set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Aruco paper marker tracker static library path") +if(SDK_ARUCO_LIBPATH) + opentrack_boilerplate(opentrack-tracker-aruco) + target_link_libraries(opentrack-tracker-aruco ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS}) + target_include_directories(opentrack-tracker-aruco SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) + link_with_dinput8(opentrack-tracker-aruco) +endif() diff --git a/tracker-aruco/ar_video_widget.cpp b/tracker-aruco/ar_video_widget.cpp new file mode 100644 index 00000000..1c3af262 --- /dev/null +++ b/tracker-aruco/ar_video_widget.cpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2014 Stanislaw Halik + * + * 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 "ar_video_widget.h" + +void ArucoVideoWidget::update_image(const cv::Mat& frame) +{ + QMutexLocker foo(&mtx); + if (!fresh) + { + _frame = frame.clone(); + fresh = true; + } +} + +void ArucoVideoWidget::update_and_repaint() +{ + QImage qframe; + + { + QMutexLocker foo(&mtx); + if (_frame.cols*_frame.rows <= 0 || !fresh) + return; + fresh = false; + qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); + uchar* data = qframe.bits(); + const int pitch = qframe.bytesPerLine(); + unsigned char *input = (unsigned char*)(_frame.data); + const int chans = _frame.channels(); + for (int y = 0; y < _frame.rows; y++) + { + const int step = y * _frame.step; + const int pitch_ = y * pitch; + for (int x = 0; x < _frame.cols; x++) + { + data[pitch_ + x * 3 + 0] = input[step + x * chans + 2]; + data[pitch_ + x * 3 + 1] = input[step + x * chans + 1]; + data[pitch_ + x * 3 + 2] = input[step + x * chans + 0]; + } + } + } + + qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); + + { + QMutexLocker foo(&mtx); + texture = qframe; + } + + update(); +} + +void ArucoVideoWidget::paintEvent(QPaintEvent* e) +{ + QMutexLocker foo(&mtx); + QPainter(this).drawImage(e->rect(), texture); +} + +ArucoVideoWidget::ArucoVideoWidget(QWidget* parent): QWidget(parent), fresh(false) +{ + connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); + timer.start(60); +} diff --git a/tracker-aruco/ar_video_widget.h b/tracker-aruco/ar_video_widget.h new file mode 100644 index 00000000..6df2d626 --- /dev/null +++ b/tracker-aruco/ar_video_widget.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2014 Stanislaw Halik + * + * 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 +#include +#include +#include +#include +#include +#include + +class ArucoVideoWidget : public QWidget +{ + Q_OBJECT +private: + QMutex mtx; + QImage texture; + QTimer timer; + cv::Mat _frame; + bool fresh; +private slots: + void update_and_repaint(); +public: + ArucoVideoWidget(QWidget *parent); + void update_image(const cv::Mat& frame); + void paintEvent( QPaintEvent*) override; +}; diff --git a/tracker-aruco/aruco-tracker.qrc b/tracker-aruco/aruco-tracker.qrc new file mode 100644 index 00000000..70859876 --- /dev/null +++ b/tracker-aruco/aruco-tracker.qrc @@ -0,0 +1,5 @@ + + + images/aruco.png + + diff --git a/tracker-aruco/aruco-trackercontrols.ui b/tracker-aruco/aruco-trackercontrols.ui new file mode 100644 index 00000000..7e32936c --- /dev/null +++ b/tracker-aruco/aruco-trackercontrols.ui @@ -0,0 +1,281 @@ + + + Form + + + Qt::NonModal + + + + 0 + 0 + 485 + 202 + + + + + 0 + 0 + + + + Tracker settings + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + Frames per second + + + + + + + + 0 + 0 + + + + + 640x480 + + + + + 320x240 + + + + + 320x200 + + + + + Default (not recommended!) + + + + + + + + Camera name + + + + + + + Resolution + + + + + + + Diagonal FOV + + + + + + + + 0 + 0 + + + + + Default + + + + + 30 + + + + + 60 + + + + + 125 + + + + + 200 + + + + + + + + + 0 + 0 + + + + + + + + Camera settings + + + + + + + Open + + + + + + + + 0 + 0 + + + + + + + 10 + + + 180 + + + + + + + + + + + + + Head X + + + + + + + + 0 + 0 + + + + -10000.000000000000000 + + + 10000.000000000000000 + + + + + + + + 0 + 0 + + + + -10000.000000000000000 + + + 10000.000000000000000 + + + + + + + + 0 + 0 + + + + -10000.000000000000000 + + + 10000.000000000000000 + + + + + + + Head Z + + + + + + + Head Y + + + + + + + Toggle calibration + + + true + + + + + + + + + + + + + 10 + + + 10 + + + false + + + false + + + true + + + diff --git a/tracker-aruco/ftnoir_tracker_aruco.cpp b/tracker-aruco/ftnoir_tracker_aruco.cpp new file mode 100644 index 00000000..570c2e0d --- /dev/null +++ b/tracker-aruco/ftnoir_tracker_aruco.cpp @@ -0,0 +1,444 @@ +/* Copyright (c) 2013-2015 Stanislaw Halik + * + * 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 +#include +#include +#include +#include +#include "./include/markerdetector.h" +#include "ftnoir_tracker_aruco.h" +#include "opentrack/plugin-api.hpp" +#include +#include +#include +#include "opentrack/camera-names.hpp" +#include "opentrack-compat/sleep.hpp" + +typedef struct { + int width; + int height; +} resolution_tuple; + +static resolution_tuple resolution_choices[] = { + { 640, 480 }, + { 320, 240 }, + { 320, 200 }, + { 0, 0 } +}; + +Tracker::Tracker() : stop(false), layout(nullptr), videoWidget(nullptr) +{ +} + +Tracker::~Tracker() +{ + stop = true; + wait(); + if (videoWidget) + delete videoWidget; + if(layout) + delete layout; + camera.release(); +} + +void Tracker::start_tracker(QFrame* videoframe) +{ + videoframe->show(); + videoWidget = new ArucoVideoWidget(videoframe); + QHBoxLayout* layout = new QHBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(videoWidget); + if (videoframe->layout()) + delete videoframe->layout(); + videoframe->setLayout(layout); + videoWidget->show(); + start(); + for (int i = 0; i < 6; i++) + pose[i] = 0; + this->layout = layout; +} + +#define HT_PI 3.1415926535 + +void Tracker::getRT(cv::Matx33d& r_, cv::Vec3d& t_) +{ + QMutexLocker l(&mtx); + + r_ = r; + t_ = t; +} + +void Tracker::run() +{ + int rint = s.resolution; + if (rint < 0 || rint >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple))) + rint = 0; + resolution_tuple res = resolution_choices[rint]; + int fps; + switch (static_cast(s.force_fps)) + { + default: + case 0: + fps = 0; + break; + case 1: + fps = 30; + break; + case 2: + fps = 60; + break; + case 3: + fps = 125; + break; + case 4: + fps = 200; + break; + } + + { + QMutexLocker l(&camera_mtx); + + camera = cv::VideoCapture(camera_name_to_index(s.camera_name)); + if (res.width) + { + camera.set(cv::CAP_PROP_FRAME_WIDTH, res.width); + camera.set(cv::CAP_PROP_FRAME_HEIGHT, res.height); + } + if (fps) + camera.set(cv::CAP_PROP_FPS, fps); + + if (!camera.isOpened()) + { + qDebug() << "aruco tracker: can't open camera"; + return; + } + } + + aruco::MarkerDetector detector; + detector.setDesiredSpeed(3); + + cv::Rect last_roi(65535, 65535, 0, 0); + + auto freq = cv::getTickFrequency(); + auto last_time = cv::getTickCount(); + double cur_fps = 0; + std::vector box_sizes { 5, 7, 9, 11 }; + int box_idx = 0; + double failed = 0; + const double max_failed = 1.25; + cv::Vec3d rvec, tvec; + cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1); + cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1); + bool otsu = false; + + while (!stop) + { + cv::Mat color; + { + QMutexLocker l(&camera_mtx); + + if (!camera.read(color)) + continue; + } + static constexpr int thres_param2 = 5; + cv::Mat grayscale; + cv::cvtColor(color, grayscale, cv::COLOR_RGB2GRAY); + + const int scale = grayscale.cols > 480 ? 2 : 1; + detector.setThresholdParams(box_sizes[box_idx], thres_param2); + + static constexpr double pi = 3.1415926f; + const int w = grayscale.cols, h = grayscale.rows; + const double diag_fov = static_cast(s.fov) * pi / 180.; + const double fov_w = 2.*atan(tan(diag_fov/2.)/sqrt(1. + h/(double)w * h/(double)w)); + const double fov_h = 2.*atan(tan(diag_fov/2.)/sqrt(1. + w/(double)h * w/(double)h)); + const float focal_length_w = .5 * w / tan(.5 * fov_w); + const float focal_length_h = .5 * h / tan(.5 * fov_h); + + intrinsics.at (0, 0) = focal_length_w; + intrinsics.at (1, 1) = focal_length_h; + intrinsics.at (0, 2) = grayscale.cols/2; + intrinsics.at (1, 2) = grayscale.rows/2; + + std::vector< aruco::Marker > markers; + + const double size_min = 0.05; + const double size_max = 0.3; + + bool roi_valid = false; + + auto time = cv::getTickCount(); + + const double dt = (time - last_time) / freq; + last_time = time; + cur_fps = cur_fps * 0.97 + 0.03 * (dt == 0 ? 0 : 1./dt); + + if (last_roi.width > 0 && last_roi.height) + { + detector.setThresholdParams(box_sizes[box_idx], thres_param2); + detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width), + std::min(1.0, size_max * grayscale.cols / last_roi.width)); + + cv::Mat grayscale_ = grayscale(last_roi).clone(); + if (detector.detect(grayscale_, markers, cv::Mat(), cv::Mat(), -1, false), + markers.size() == 1 && markers[0].size() == 4) + { + failed = std::max(0., failed - dt); + auto& m = markers.at(0); + for (int i = 0; i < 4; i++) + { + auto& p = m.at(i); + p.x += last_roi.x; + p.y += last_roi.y; + } + roi_valid = true; + } + } + + if (!roi_valid) + { + otsu = !otsu; + detector._thresMethod = otsu ? aruco::MarkerDetector::FIXED_THRES : aruco::MarkerDetector::ADPT_THRES; + failed += dt; + if (failed > max_failed) + { + box_idx++; + box_idx %= box_sizes.size(); + qDebug() << "aruco: box size now" << box_sizes[box_idx]; + failed = 0; + } + detector.setThresholdParams(box_sizes[box_idx], thres_param2); + detector.setMinMaxSize(size_min, size_max); + detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false); + } + + if (markers.size() == 1 && markers[0].size() == 4) { + const auto& m = markers.at(0); + for (int i = 0; i < 4; i++) + cv::line(color, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), scale, 8); + } + + char buf[128]; + + frame = color.clone(); + + ::sprintf(buf, "Hz: %d", (int)cur_fps); + cv::putText(frame, buf, cv::Point(10, 32), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(0, 255, 0), scale*2); + + if (markers.size() == 1 && markers[0].size() == 4) { + const auto& m = markers.at(0); + const float size = 40; + + cv::Mat obj_points(4,3,CV_32FC1); + const int x1=1, x2=2, x3=3, x4=0; + obj_points.at(x1,0)=-size + s.headpos_x; + obj_points.at(x1,1)=-size + s.headpos_y; + obj_points.at(x1,2)= 0 + s.headpos_z; + + obj_points.at(x2,0)=size + s.headpos_x; + obj_points.at(x2,1)=-size + s.headpos_y; + obj_points.at(x2,2)= 0 + s.headpos_z; + + obj_points.at(x3,0)=size + s.headpos_x; + obj_points.at(x3,1)=size + s.headpos_y; + obj_points.at(x3,2)= 0 + s.headpos_z; + + obj_points.at(x4,0)= -size + s.headpos_x; + obj_points.at(x4,1)= size + s.headpos_y; + obj_points.at(x4,2)= 0 + s.headpos_z; + + std::vector img_points = m; + if (!cv::solvePnP(obj_points, img_points, intrinsics, dist_coeffs, rvec, tvec, false, cv::SOLVEPNP_ITERATIVE)) + goto fail; + + { + std::vector repr2; + std::vector centroid; + centroid.push_back(cv::Point3f(0, 0, 0)); + cv::projectPoints(centroid, rvec, tvec, intrinsics, dist_coeffs, repr2); + + { + auto s = cv::Scalar(255, 0, 255); + cv::circle(frame, repr2.at(0), 4, s, -1); + } + } + + for (int i = 0; i < 4; i++) + { + obj_points.at(i, 0) -= s.headpos_x; + obj_points.at(i, 1) -= s.headpos_y; + obj_points.at(i, 2) -= s.headpos_z; + } + + cv::Mat rvec_, tvec_; + cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec_, tvec_, false, cv::SOLVEPNP_ITERATIVE); + + cv::Mat roi_points = obj_points * c_search_window; + std::vector roi_projection(4); + cv::projectPoints(roi_points, rvec_, tvec_, intrinsics, dist_coeffs, roi_projection); + + last_roi = cv::Rect(color.cols-1, color.rows-1, 0, 0); + + for (int i = 0; i < 4; i++) + { + auto proj = roi_projection[i]; + int min_x = std::min(proj.x, last_roi.x), + min_y = std::min(proj.y, last_roi.y); + + int max_x = std::max(proj.x, last_roi.width), + max_y = std::max(proj.y, last_roi.height); + + last_roi.x = min_x; + last_roi.y = min_y; + + last_roi.width = max_x; + last_roi.height = max_y; + } + + if (last_roi.x < 0) + last_roi.x = 0; + if (last_roi.y < 0) + last_roi.y = 0; + if (last_roi.width < 0) + last_roi.width = 0; + if (last_roi.height < 0) + last_roi.height = 0; + if (last_roi.x >= color.cols-1) + last_roi.x = color.cols-1; + if (last_roi.width >= color.cols-1) + last_roi.width = color.cols-1; + if (last_roi.y >= color.rows-1) + last_roi.y= color.rows-1; + if (last_roi.height >= color.rows-1) + last_roi.height = color.rows-1; + + last_roi.width -= last_roi.x; + last_roi.height -= last_roi.y; + + auto rmat = cv::Matx33d::zeros(); + cv::Matx33d m_r(3, 3, CV_64FC1), m_q(3, 3, CV_64FC1); + cv::Rodrigues(rvec, rmat); + + { + cv::Vec3d euler = cv::RQDecomp3x3(rmat, m_r, m_q); + + QMutexLocker lck(&mtx); + + for (int i = 0; i < 3; i++) + pose[i] = tvec(i); + pose[Yaw] = euler[1]; + pose[Pitch] = -euler[0]; + pose[Roll] = euler[2]; + + r = rmat; + t = cv::Vec3d(tvec[0], -tvec[1], tvec[2]); + } + + if (roi_valid) + cv::rectangle(frame, last_roi, cv::Scalar(255, 0, 255), 1); + } + else +fail: + last_roi = cv::Rect(65535, 65535, 0, 0); + + if (frame.rows > 0) + videoWidget->update_image(frame); + } + + // give opencv time to exit camera threads, etc. + portable::sleep(500); +} + +void Tracker::data(double *data) +{ + QMutexLocker lck(&mtx); + + data[Yaw] = pose[Yaw]; + data[Pitch] = pose[Pitch]; + data[Roll] = pose[Roll]; + data[TX] = pose[TX] * .1; + data[TY] = pose[TY] * .1; + data[TZ] = pose[TZ] * .1; +} + +TrackerControls::TrackerControls() +{ + tracker = nullptr; + calib_timer.setInterval(200); + ui.setupUi(this); + setAttribute(Qt::WA_NativeWindow, true); + ui.cameraName->addItems(get_camera_names()); + tie_setting(s.camera_name, ui.cameraName); + tie_setting(s.resolution, ui.resolution); + tie_setting(s.force_fps, ui.cameraFPS); + tie_setting(s.fov, ui.cameraFOV); + tie_setting(s.headpos_x, ui.cx); + tie_setting(s.headpos_y, ui.cy); + tie_setting(s.headpos_z, ui.cz); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + connect(ui.btn_calibrate, SIGNAL(clicked()), this, SLOT(toggleCalibrate())); + connect(this, SIGNAL(destroyed()), this, SLOT(cleanupCalib())); + connect(&calib_timer, SIGNAL(timeout()), this, SLOT(update_tracker_calibration())); + connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings())); +} + +void TrackerControls::toggleCalibrate() +{ + if (!calib_timer.isActive()) + { + s.headpos_x = 0; + s.headpos_y = 0; + s.headpos_z = 0; + calibrator.reset(); + calib_timer.start(); + } else { + cleanupCalib(); + + auto pos = calibrator.get_estimate(); + s.headpos_x = pos(0); + s.headpos_y = pos(1); + s.headpos_z = pos(2); + } +} + +void TrackerControls::cleanupCalib() +{ + if (calib_timer.isActive()) + calib_timer.stop(); +} + +void TrackerControls::update_tracker_calibration() +{ + if (calib_timer.isActive() && tracker) + { + cv::Matx33d r; + cv::Vec3d t; + tracker->getRT(r, t); + calibrator.update(r, t); + } +} + +void TrackerControls::doOK() +{ + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() +{ + s.b->reload(); + this->close(); +} + +void TrackerControls::camera_settings() +{ + open_camera_settings(tracker ? &tracker->camera : nullptr, s.camera_name, tracker ? &tracker->camera_mtx : nullptr); +} + +OPENTRACK_DECLARE_TRACKER(Tracker, TrackerControls, TrackerDll) diff --git a/tracker-aruco/ftnoir_tracker_aruco.h b/tracker-aruco/ftnoir_tracker_aruco.h new file mode 100644 index 00000000..f827da77 --- /dev/null +++ b/tracker-aruco/ftnoir_tracker_aruco.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2013-2015 Stanislaw Halik + * + * 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 "ui_aruco-trackercontrols.h" +#include "ar_video_widget.h" +#include +#include +#include +#include +#include +#include +#include "opentrack/options.hpp" +#include "trans_calib.h" +#include "opentrack/plugin-api.hpp" +#include "opentrack/opencv-camera-dialog.hpp" + +#include +#include + +using namespace options; + +struct settings : opts { + value fov; + value headpos_x, headpos_y, headpos_z; + value camera_name; + value force_fps, resolution; + settings() : + opts("aruco-tracker"), + fov(b, "field-of-view", 56), + headpos_x(b, "headpos-x", 0), + headpos_y(b, "headpos-y", 0), + headpos_z(b, "headpos-z", 0), + camera_name(b, "camera-name", ""), + force_fps(b, "force-fps", 0), + resolution(b, "force-resolution", 0) + {} +}; + +class TrackerControls; + +class Tracker : protected QThread, public ITracker +{ + Q_OBJECT + friend class TrackerControls; + static constexpr double c_search_window = 2.65; +public: + Tracker(); + ~Tracker() override; + void start_tracker(QFrame* frame) override; + void data(double *data) override; + void run() override; + void getRT(cv::Matx33d &r, cv::Vec3d &t); +private: + cv::VideoCapture camera; + QMutex camera_mtx; + QMutex mtx; + volatile bool stop; + QHBoxLayout* layout; + ArucoVideoWidget* videoWidget; + settings s; + double pose[6]; + cv::Mat frame; + cv::Matx33d r; + cv::Vec3d t; +}; + +class TrackerControls : public ITrackerDialog, protected camera_dialog +{ + Q_OBJECT +public: + TrackerControls(); + void register_tracker(ITracker * x) override { tracker = static_cast(x); } + void unregister_tracker() override { tracker = nullptr; } +private: + Ui::Form ui; + Tracker* tracker; + settings s; + TranslationCalibrator calibrator; + QTimer calib_timer; +private slots: + void doOK(); + void doCancel(); + void toggleCalibrate(); + void cleanupCalib(); + void update_tracker_calibration(); + void camera_settings(); +}; + +class TrackerDll : public Metadata +{ + QString name() { return QString("aruco -- paper marker tracker"); } + QIcon icon() { return QIcon(":/images/aruco.png"); } +}; diff --git a/tracker-aruco/images/aruco.png b/tracker-aruco/images/aruco.png new file mode 100644 index 00000000..491c39e6 Binary files /dev/null and b/tracker-aruco/images/aruco.png differ diff --git a/tracker-aruco/include/aruco.h b/tracker-aruco/include/aruco.h new file mode 100644 index 00000000..569b95fb --- /dev/null +++ b/tracker-aruco/include/aruco.h @@ -0,0 +1,134 @@ +/** + +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. + + + + \mainpage ArUco: Augmented Reality library from the University of Cordoba + + +ArUco is a minimal C++ library for detection of Augmented Reality markers based on OpenCv exclusively. + +It is an educational project to show student how to detect augmented reality markers and it is provided under BSD license. + + +\section INTRODUCTION INTRODUCTION + +The library relies on the use of coded markers. Each marker has an unique code indicated by the black and white colors in it. The libary detect borders, and analyzes into the rectangular regions which of them are likely to be markers. Then, a decoding is performed and if the code is valid, it is considered that the rectangle is a marker. + +The codification included into the marker is a slighly modified version of the Hamming Code. It has a total a 25 bits didived in 5 rows of 5 bits each. So, we have 5 words of 5 bits. Each word, contains only 2 bits of real information, the rest is for and error detection/correction (error correction is yet to be done). As a conclusion, a marker contains 10 bits of real information wich allows 1024 different markers. + + +\section BOARDS BOARDS + +Aruco allows the possibility to employ board. Boards are markers composed by an array of markers arranged in a known order. The advantages of using boards instead of simple markers are: + - More robusteness. The misdetection of several markers of the board is not a problem as long as a minimum set of them are detected. + - More precision. Since there are a larger number of corners, camera pose estimation becomes more precise. + + +\section APPLICATIONS APPLICATIONS + +The library comes with five applications that will help you to learn how to use the library: + - aruco_create_marker: which creates marker and saves it in a jpg file you can print. + - aruco_simple : simple test aplication that detects the markers in a image + - aruco_test: this is the main application for detection. It reads images either from the camera of from a video and detect markers. Additionally, if you provide the intrinsics of the camera(obtained by OpenCv calibration) and the size of the marker in meters, the library calculates the marker intrinsics so that you can easily create your AR applications. + - aruco_test_gl: shows how to use the library AR applications using OpenGL for rendering + - aruco_create_board: application that helps you to create a board + - aruco_simple_board: simple test aplication that detects a board of markers in a image + - aruco_test_board: application that detects boards + - aruco_test_board_gl: application that detects boards and uses OpenGL to draw + +\section LIBRARY LIBRARY DESCRIPTION: + +The ArUco library contents are divided in two main directories. The src directory, which contains the library itself. And the utils directory which contains the applications. + +The library main classes are: + - aruco::CameraParameters: represent the information of the camera that captures the images. Here you must set the calibration info. + - aruco::Marker: which represent a marker detected in the image + - aruco::MarkerDetector: that is in charge of deteting the markers in a image Detection is done by simple calling the member funcion ArMarkerDetector::detect(). Additionally, the classes contain members to create the required matrices for rendering using OpenGL. See aruco_test_gl for details + - aruco::BoardConfiguration: A board is an array of markers in a known order. BoardConfiguracion is the class that defines a board by indicating the id of its markers. In addition, it has informacion about the distance between the markers so that extrinsica camera computations can be done. + - aruco::Board: This class defines a board detected in a image. The board has the extrinsic camera parameters as public atributes. In addition, it has a method that allows obtain the matrix for getting its position in OpenGL (see aruco_test_board_gl for details). + - aruco::BoardDetector : This is the class in charge of detecting a board in a image. You must pass to it the set of markers detected by ArMarkerDetector and the BoardConfiguracion of the board you want to detect. This class will do the rest for you, even calculating the camera extrinsics. + + +\section COMPILING COMPILING THE LIBRARY: +\subsection Linux +Go to the aruco library and do +\verbatim +>mkdir build +>cd build +>cmake .. +>make +>make install (optional) +\endverbatim + +NOTE ON OPENGL: The library supports eaily the integration with OpenGL. In order to compile with support for OpenGL, you just have installed in your system the develop packages for GL and glut (or freeglut). + +\subsection WINDOWS + +The library has been compiled using MinGW and codeblocks. Below I describe the best way to compile it that I know. If you know better, please let me know. + - step 1) codeblocks + -# Download codeblocks. I recommend to download the version 10.5 with mingw included (codeblocks-10.05mingw-setup.exe) + -# Install and set the PATH variable so that the codeblock/mingw/bin directory is included. In my case c:/codeblocks/mingw/bin. This will allow cmake to find the compiler. + -# The codeblock program will not find the mingw path by deafult. So, run codeblocks and go to setting->Compuiler debugger and set the correct path to the MinGW dir. + - step 2) cmake + -# Download and install the last version of cmake. + - step 3) OpenCv + -# Download the source code and compile it using cmake and codeblocks. Note: install the library in C:\ if you want it to be easily detected by cmake afterwards + - step 4) aruco + -# Download and decompress. + -# Open cmake gui application and set the path to the main library directory and also set a path where the project is going to be built. + -# Generate the codeblock project. + -# Open the project with codeblock and compile then, install. The programs will be probably generated into the bin directory + +OpenGL: by default, the mingw version installed has not the glut library. So, the opengl programs are not compiled. If you want to compile with OpenGL support, you must install glut, or prefereably freeglut. +Thus, + - Download the library (http://www.martinpayne.me.uk/software/development/GLUT/freeglut-MinGW.zip) for mingw. + - Decompress in a directory X. + - Then, rerun cmake setting the variable GLU_PATH to that directory (>cmake .. -DGLUT_PATH="C:\X") + - Finally, recompile and test. Indeed, you should move the freeglut.dll to the directory with the binaries or to any other place in the PATH. + + +CONCLUSION: Move to Linux, things are simpler :P + + +\section Testing + +For testing the applications, the library provides videos and the corresponding camera parameters of these videos. Into the directories you will find information on how to run the examples. + +\section Final Notes + + - REQUIREMENTS: OpenCv >= 2.1.0. and OpenGL for (aruco_test_gl and aruco_test_board_gl) + - CONTACT: Rafael Munoz-Salinas: rmsalinas@uco.es + - This libary is free software and come with no guaratee! + +*/ + +#include "markerdetector.h" +#include "boarddetector.h" +#include "cvdrawingutils.h" + diff --git a/tracker-aruco/include/arucofidmarkers.h b/tracker-aruco/include/arucofidmarkers.h new file mode 100644 index 00000000..7dad4672 --- /dev/null +++ b/tracker-aruco/include/arucofidmarkers.h @@ -0,0 +1,119 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ + +#ifndef ArucoFiducicalMarkerDetector_H +#define ArucoFiducicalMarkerDetector_H +#include +#include "exports.h" +#include "marker.h" +#include "board.h" +namespace aruco { + +class ARUCO_EXPORTS FiducidalMarkers { +public: + /** + * \brief Creates an ar marker with the id specified using a modified version of the hamming code. + * There are two type of markers: a) These of 10 bits b) these of 3 bits. The latter are employed for applications + * that need few marker but they must be small. The two type of markers are distinguished by their ids. While the first type + * of markers have ids in the interval [0-1023], the second type ids in the interval [2000-2006]. + * + * + * 10 bits markers + * ----------------------- + * There are a total of 5 rows of 5 cols. Each row encodes a total of 2 bits, so there are 2^10 bits:(0-1023). + * + * The least significative bytes are first (from left-up to to right-bottom) + * + * Example: the id = 110 (decimal) is be represented in binary as : 00 01 10 11 10. + * + * Then, it will generate the following marker: + * + * -# 1st row encodes 00: 1 0 0 0 0 : hex 0x10 + * -# 2nd row encodes 01: 1 0 1 1 1 : hex 0x17 + * -# 3nd row encodes 10: 0 1 0 0 1 : hex 0x09 + * -# 4th row encodes 11: 0 1 1 1 0 : hex 0x0e + * -# 5th row encodes 10: 0 1 0 0 1 : hex 0x09 + * + * Note that : The first bit, is the inverse of the hamming parity. This avoids the 0 0 0 0 0 to be valid + * These marker are detected by the function getFiduciadlMarker_Aruco_Type1 + */ + static cv::Mat createMarkerImage(int id,int size) throw (cv::Exception); + + /** Detection of fiducidal aruco markers (10 bits) + * @param in input image with the patch that contains the possible marker + * @param nRotations number of 90deg rotations in clockwise direction needed to set the marker in correct position + * @return -1 if the image passed is a not a valid marker, and its id in case it really is a marker + */ + static int detect(const cv::Mat &in,int &nRotations); + + /**Similar to createMarkerImage. Instead of returning a visible image, returns a 8UC1 matrix of 0s and 1s with the marker info + */ + static cv::Mat getMarkerMat(int id) throw (cv::Exception); + + + /**Creates a printable image of a board + * @param gridSize grid layout (numer of sqaures in x and Y) + * @param MarkerSize size of markers sides in pixels + * @param MarkerDistance distance between the markers + * @param TInfo output + * @param excludedIds set of ids excluded from the board + */ + static cv::Mat createBoardImage( cv::Size gridSize,int MarkerSize,int MarkerDistance, BoardConfiguration& TInfo ,vector *excludedIds=NULL ) throw (cv::Exception); + + + /**Creates a printable image of a board in chessboard_like manner + * @param gridSize grid layout (numer of sqaures in x and Y) + * @param MarkerSize size of markers sides in pixels + * @param TInfo output + * @param setDataCentered indicates if the center is set at the center of the board. Otherwise it is the left-upper corner + * + */ + static cv::Mat createBoardImage_ChessBoard( cv::Size gridSize,int MarkerSize, BoardConfiguration& TInfo ,bool setDataCentered=true ,vector *excludedIds=NULL) throw (cv::Exception); + + /**Creates a printable image of a board in a frame fashion + * @param gridSize grid layout (numer of sqaures in x and Y) + * @param MarkerSize size of markers sides in pixels + * @param MarkerDistance distance between the markers + * @param TInfo output + * @param setDataCentered indicates if the center is set at the center of the board. Otherwise it is the left-upper corner + * + */ + static cv::Mat createBoardImage_Frame( cv::Size gridSize,int MarkerSize,int MarkerDistance, BoardConfiguration& TInfo ,bool setDataCentered=true,vector *excludedIds=NULL ) throw (cv::Exception); + +private: + + static vector getListOfValidMarkersIds_random(int nMarkers,vector *excluded) throw (cv::Exception); + static cv::Mat rotate(const cv::Mat & in); + static int hammDistMarker(cv::Mat bits); + static int analyzeMarkerImage(cv::Mat &grey,int &nRotations); + static bool correctHammMarker(cv::Mat &bits); +}; + +} + +#endif diff --git a/tracker-aruco/include/board.h b/tracker-aruco/include/board.h new file mode 100644 index 00000000..ec7dd43f --- /dev/null +++ b/tracker-aruco/include/board.h @@ -0,0 +1,168 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ +#ifndef _Aruco_board_h +#define _Aruco_board_h +#include +#include +#include +#include "exports.h" +#include "marker.h" +namespace aruco { +using namespace std; +/** + * 3d representation of a marker + */ +struct ARUCO_EXPORTS MarkerInfo:public vector { + MarkerInfo() {} + MarkerInfo(int _id) {id=_id; } + MarkerInfo(const MarkerInfo&MI): vector(MI){id=MI.id; } + MarkerInfo & operator=(const MarkerInfo&MI){ + vector ::operator=(MI); + id=MI.id; + return *this; + } + int id;//maker id +}; + +/**\brief This class defines a board with several markers. + * A Board contains several markers so that they are more robustly detected. + * + * In general, a board is a set of markers. So BoardConfiguration is only a list + * of the id of the markers along with the position of their corners. + * + * The position of the corners can be specified either in pixels (in a non-specific size) or in meters. + * The first is the typical case in which you generate the image of board and the print it. Since you do not know in advance the real + * size of the markers, their corners are specified in pixels, and then, the translation to meters can be made once you know the real size. + * + * On the other hand, you may want to have the information of your boards in meters. The BoardConfiguration allows you to do so. + * + * The point is in the mInfoType variable. It can be either PIX or METERS according to your needs. + * +*/ + + +class ARUCO_EXPORTS BoardConfiguration: public vector +{ + friend class Board; +public: + enum MarkerInfoType {NONE=-1,PIX=0,METERS=1};//indicates if the data in MakersInfo is expressed in meters or in pixels so as to do conversion internally + //variable indicates if the data in MakersInfo is expressed in meters or in pixels so as to do conversion internally + int mInfoType; + /** + */ + BoardConfiguration(); + + /** + */ + BoardConfiguration(const BoardConfiguration &T); + + /** + */ + BoardConfiguration & operator=(const BoardConfiguration &T); + /**Saves the board info to a file + */ + void saveToFile(string sfile)throw (cv::Exception); + /**Reads board info from a file + */ + void readFromFile(string sfile)throw (cv::Exception); + /**Indicates if the corners are expressed in meters + */ + bool isExpressedInMeters()const { + return mInfoType==METERS; + } + /**Indicates if the corners are expressed in meters + */ + bool isExpressedInPixels()const { + return mInfoType==PIX; + } + /**Returns the index of the marker with id indicated, if is in the list + */ + int getIndexOfMarkerId(int id)const; + /**Returns the Info of the marker with id specified. If not in the set, throws exception + */ + const MarkerInfo& getMarkerInfo(int id)const throw (cv::Exception); + /**Set in the list passed the set of the ids + */ + void getIdList(vector &ids,bool append=true)const; +private: + /**Saves the board info to a file + */ + void saveToFile(cv::FileStorage &fs)throw (cv::Exception); + /**Reads board info from a file + */ + void readFromFile(cv::FileStorage &fs)throw (cv::Exception); +}; + +/** +*/ +class ARUCO_EXPORTS Board:public vector +{ + +public: + BoardConfiguration conf; + //matrices of rotation and translation respect to the camera + cv::Mat Rvec,Tvec; + /** + */ + Board() + { + Rvec.create(3,1,CV_32FC1); + Tvec.create(3,1,CV_32FC1); + for (int i=0;i<3;i++) + Tvec.at(i,0)=Rvec.at(i,0)=-999999; + } + + /**Given the extrinsic camera parameters returns the GL_MODELVIEW matrix for opengl. + * Setting this matrix, the reference corrdinate system will be set in this board + */ + void glGetModelViewMatrix(double modelview_matrix[16])throw(cv::Exception); + + /** + * Returns position vector and orientation quaternion for an Ogre scene node or entity. + * Use: + * ... + * Ogre::Vector3 ogrePos (position[0], position[1], position[2]); + * Ogre::Quaternion ogreOrient (orientation[0], orientation[1], orientation[2], orientation[3]); + * mySceneNode->setPosition( ogrePos ); + * mySceneNode->setOrientation( ogreOrient ); + * ... + */ + void OgreGetPoseParameters( double position[3], double orientation[4] )throw(cv::Exception); + + + /**Save this from a file + */ + void saveToFile(string filePath)throw(cv::Exception); + /**Read this from a file + */ + void readFromFile(string filePath)throw(cv::Exception); + +}; +} + +#endif diff --git a/tracker-aruco/include/boarddetector.h b/tracker-aruco/include/boarddetector.h new file mode 100644 index 00000000..619b4798 --- /dev/null +++ b/tracker-aruco/include/boarddetector.h @@ -0,0 +1,138 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ +#ifndef _Aruco_BoardDetector_H +#define _Aruco_BoardDetector_H +#include +#include "exports.h" +#include "board.h" +#include "cameraparameters.h" +#include "markerdetector.h" + +namespace aruco +{ +using namespace std; +/**\brief This class detects AR boards + * Version 1.2 + * There are two modes for board detection. + * First, the old way. (You first detect markers with MarkerDetector and then call to detect in this class. + * + * Second: New mode, marker detection is included in the class + * \code + + CameraParameters CP; + CP.readFromFile(path_cp) + BoardConfiguration BC; + BC.readFromFile(path_bc); + BoardDetector BD; + BD.setParams(BC,CP); //or only BD.setParams(BC) + //capture image + cv::Mat im; + capture_image(im); + + float prob=BD.detect(im); + if (prob>0.3) + CvDrawingUtils::draw3DAxis(im,BD.getDetectedBoard(),CP); + + \endcode + * +*/ +class ARUCO_EXPORTS BoardDetector +{ +public: + /** See discussion in @see enableRotateXAxis. + * Do not change unless you know what you are doing + */ + BoardDetector(bool setYPerperdicular=true); + + + /** + * Use if you plan to let this class to perform marker detection too + */ + void setParams(const BoardConfiguration &bc,const CameraParameters &cp, float markerSizeMeters=-1); + void setParams(const BoardConfiguration &bc); + /** + * Detect markers, and then, look for the board indicated in setParams() + * @return value indicating the likelihood of having found the marker + */ + float detect(const cv::Mat &im)throw (cv::Exception); + /**Returns a reference to the board detected + */ + Board & getDetectedBoard(){return _boardDetected;} + /**Returns a reference to the internal marker detector + */ + MarkerDetector &getMarkerDetector(){return _mdetector;} + /**Returns the vector of markers detected + */ + vector &getDetectedMarkers(){return _vmarkers;} + + + //ALTERNATIVE DETECTION METHOD, BASED ON MARKERS PREVIOUSLY DETECTED + + /** Given the markers detected, determines if there is the board passed + * @param detectedMarkers result provided by aruco::ArMarkerDetector + * @param BConf the board you want to see if is present + * @param Bdetected output information of the detected board + * @param camMatrix camera matrix with intrinsics + * @param distCoeff camera distorsion coeff + * @param camMatrix intrinsic camera information. + * @param distCoeff camera distorsion coefficient. If set Mat() if is assumed no camera distorion + * @param markerSizeMeters size of the marker sides expressed in meters + * @return value indicating the likelihood of having found the marker + */ + float detect(const vector &detectedMarkers,const BoardConfiguration &BConf, Board &Bdetected, cv::Mat camMatrix=cv::Mat(),cv::Mat distCoeff=cv::Mat(), float markerSizeMeters=-1 )throw (cv::Exception); + float detect(const vector &detectedMarkers,const BoardConfiguration &BConf, Board &Bdetected,const CameraParameters &cp, float markerSizeMeters=-1 )throw (cv::Exception); + + + /** + * By default, the Y axis is set to point up. However this is not the default + * operation mode of opencv, which produces the Z axis pointing up instead. + * So, to achieve this change, we have to rotate the X axis. + */ + void setYPerperdicular(bool enable){_setYPerperdicular=enable;} + + + + +private: + void rotateXAxis(cv::Mat &rotation); + bool _setYPerperdicular; + + //-- Functionality to detect markers inside + bool _areParamsSet; + BoardConfiguration _bconf; + Board _boardDetected; + float _markerSize; + CameraParameters _camParams; + MarkerDetector _mdetector;//internal markerdetector + vector _vmarkers;//markers detected in the call to : float detect(const cv::Mat &im); + +}; + +}; +#endif + diff --git a/tracker-aruco/include/cameraparameters.h b/tracker-aruco/include/cameraparameters.h new file mode 100644 index 00000000..083d5f96 --- /dev/null +++ b/tracker-aruco/include/cameraparameters.h @@ -0,0 +1,138 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ +#ifndef _Aruco_CameraParameters_H +#define _Aruco_CameraParameters_H +#include "exports.h" +#include +#include + +namespace aruco +{ +using namespace std; +/**\brief Parameters of the camera + */ + +class ARUCO_EXPORTS CameraParameters +{ +public: + + // 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1) + cv::Mat CameraMatrix; + //4x1 matrix (k1,k2,p1,p2) + cv::Mat Distorsion; + //size of the image + cv::Size CamSize; + + /**Empty constructor + */ + CameraParameters() ; + /**Creates the object from the info passed + * @param cameraMatrix 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1) + * @param distorsionCoeff 4x1 matrix (k1,k2,p1,p2) + * @param size image size + */ + CameraParameters(cv::Mat cameraMatrix,cv::Mat distorsionCoeff,cv::Size size) throw(cv::Exception); + /**Sets the parameters + * @param cameraMatrix 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1) + * @param distorsionCoeff 4x1 matrix (k1,k2,p1,p2) + * @param size image size + */ + void setParams(cv::Mat cameraMatrix,cv::Mat distorsionCoeff,cv::Size size) throw(cv::Exception); + /**Copy constructor + */ + CameraParameters(const CameraParameters &CI) ; + + /**Indicates whether this object is valid + */ + bool isValid()const { + return CameraMatrix.rows!=0 && CameraMatrix.cols!=0 && Distorsion.rows!=0 && Distorsion.cols!=0 && CamSize.width!=-1 && CamSize.height!=-1; + } + /**Assign operator + */ + CameraParameters & operator=(const CameraParameters &CI); + /**Reads the camera parameters from a file generated using saveToFile. + */ + void readFromFile(string path)throw(cv::Exception); + /**Saves this to a file + */ + void saveToFile(string path,bool inXML=true)throw(cv::Exception); + + /**Reads from a YAML file generated with the opencv2.2 calibration utility + */ + void readFromXMLFile(string filePath)throw(cv::Exception); + + /**Adjust the parameters to the size of the image indicated + */ + void resize(cv::Size size)throw(cv::Exception); + + /**Returns the location of the camera in the reference system given by the rotation and translation vectors passed + * NOT TESTED + */ + static cv::Point3f getCameraLocation(cv::Mat Rvec,cv::Mat Tvec); + + /**Given the intrinsic camera parameters returns the GL_PROJECTION matrix for opengl. + * PLease NOTE that when using OpenGL, it is assumed no camera distorsion! So, if it is not true, you should have + * undistor image + * + * @param orgImgSize size of the original image + * @param size of the image/window where to render (can be different from the real camera image). Please not that it must be related to CamMatrix + * @param proj_matrix output projection matrix to give to opengl + * @param gnear,gfar: visible rendering range + * @param invert: indicates if the output projection matrix has to yield a horizontally inverted image because image data has not been stored in the order of glDrawPixels: bottom-to-top. + */ + void glGetProjectionMatrix( cv::Size orgImgSize, cv::Size size,double proj_matrix[16],double gnear,double gfar,bool invert=false )throw(cv::Exception); + + /** + * setup camera for an Ogre project. + * Use: + * ... + * Ogre::Matrix4 PM(proj_matrix[0], proj_matrix[1], ... , proj_matrix[15]); + * yourCamera->setCustomProjectionMatrix(true, PM); + * yourCamera->setCustomViewMatrix(true, Ogre::Matrix4::IDENTITY); + * ... + * As in OpenGL, it assumes no camera distorsion + */ + void OgreGetProjectionMatrix( cv::Size orgImgSize, cv::Size size,double proj_matrix[16],double gnear,double gfar,bool invert=false )throw(cv::Exception); + + +private: + //GL routines + + static void argConvGLcpara2( double cparam[3][4], int width, int height, double gnear, double gfar, double m[16], bool invert )throw(cv::Exception); + static int arParamDecompMat( double source[3][4], double cpara[3][4], double trans[3][4] )throw(cv::Exception); + static double norm( double a, double b, double c ); + static double dot( double a1, double a2, double a3, + double b1, double b2, double b3 ); + + +}; + +} +#endif + + diff --git a/tracker-aruco/include/cvdrawingutils.h b/tracker-aruco/include/cvdrawingutils.h new file mode 100644 index 00000000..ff67242f --- /dev/null +++ b/tracker-aruco/include/cvdrawingutils.h @@ -0,0 +1,52 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ +#ifndef _ArUco_DrawUtils_H_ +#define _ArUco_DrawUtils_H_ +#include "exports.h" +#include "aruco.h" +namespace aruco +{ + /**\brief A set of functions to draw in opencv images + */ + class ARUCO_EXPORTS CvDrawingUtils + { + public: + + static void draw3dAxis(cv::Mat &Image,Marker &m,const CameraParameters &CP); + + static void draw3dCube(cv::Mat &Image,Marker &m,const CameraParameters &CP); + + static void draw3dAxis(cv::Mat &Image,Board &m,const CameraParameters &CP); + + static void draw3dCube(cv::Mat &Image,Board &m,const CameraParameters &CP); + + }; +}; + +#endif + diff --git a/tracker-aruco/include/exports.h b/tracker-aruco/include/exports.h new file mode 100644 index 00000000..8f7dab8c --- /dev/null +++ b/tracker-aruco/include/exports.h @@ -0,0 +1,46 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ + + + +#ifndef __OPENARUCO_CORE_TYPES_H__ +#define __OPENARUCO_CORE_TYPES_H__ + +#if !defined _CRT_SECURE_NO_DEPRECATE && _MSC_VER > 1300 +#define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio 2005 warnings */ +#endif + + +#if ((defined WIN32 || defined _WIN32 || defined WINCE) && defined DSO_EXPORTS) || defined(_MSC_VER) + #define ARUCO_EXPORTS __declspec(dllexport) +#else + #define ARUCO_EXPORTS __attribute__ ((visibility ("default"))) +#endif + + +#endif diff --git a/tracker-aruco/include/marker.h b/tracker-aruco/include/marker.h new file mode 100644 index 00000000..efc3e5fe --- /dev/null +++ b/tracker-aruco/include/marker.h @@ -0,0 +1,143 @@ +/***************************** +Copyright 2011 Rafael Muñoz Salinas. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Rafael Muñoz Salinas. +********************************/ +#ifndef _Aruco_Marker_H +#define _Aruco_Marker_H +#include +#include +#include +#include "exports.h" +#include "cameraparameters.h" +namespace aruco { +using namespace std; +/**\brief This class represents a marker. It is a vector of the fours corners ot the marker + * + */ + +class ARUCO_EXPORTS Marker: public std::vector +{ +public: + //id of the marker + int id; + //size of the markers sides in meters + float ssize; + //matrices of rotation and translation respect to the camera + cv::Mat Rvec,Tvec; + + /** + */ + Marker(); + /** + */ + Marker(const Marker &M); + /** + */ + Marker(const std::vector &corners,int _id=-1); + /** + */ + ~Marker() {} + /**Indicates if this object is valid + */ + bool isValid()const{return id!=-1 && size()==4;} + + /**Draws this marker in the input image + */ + void draw(cv::Mat &in, cv::Scalar color, int lineWidth=1,bool writeId=true)const; + + /**Calculates the extrinsics (Rvec and Tvec) of the marker with respect to the camera + * @param markerSize size of the marker side expressed in meters + * @param CP parmeters of the camera + * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis + */ + void calculateExtrinsics(float markerSize,const CameraParameters &CP,bool setYPerperdicular=true)throw(cv::Exception); + /**Calculates the extrinsics (Rvec and Tvec) of the marker with respect to the camera + * @param markerSize size of the marker side expressed in meters + * @param CameraMatrix matrix with camera parameters (fx,fy,cx,cy) + * @param Distorsion matrix with distorsion parameters (k1,k2,p1,p2) + * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis + */ + void calculateExtrinsics(float markerSize,cv::Mat CameraMatrix,cv::Mat Distorsion=cv::Mat(),bool setYPerperdicular=true)throw(cv::Exception); + + /**Given the extrinsic camera parameters returns the GL_MODELVIEW matrix for opengl. + * Setting this matrix, the reference coordinate system will be set in this marker + */ + void glGetModelViewMatrix( double modelview_matrix[16])throw(cv::Exception); + + /** + * Returns position vector and orientation quaternion for an Ogre scene node or entity. + * Use: + * ... + * Ogre::Vector3 ogrePos (position[0], position[1], position[2]); + * Ogre::Quaternion ogreOrient (orientation[0], orientation[1], orientation[2], orientation[3]); + * mySceneNode->setPosition( ogrePos ); + * mySceneNode->setOrientation( ogreOrient ); + * ... + */ + void OgreGetPoseParameters( double position[3], double orientation[4] )throw(cv::Exception); + + /**Returns the centroid of the marker + */ + cv::Point2f getCenter()const; + /**Returns the perimeter of the marker + */ + float getPerimeter()const; + /**Returns the area + */ + float getArea()const; + /** + */ + /** + */ + friend bool operator<(const Marker &M1,const Marker&M2) + { + return M1.id +#include +#include +#include "cameraparameters.h" +#include "exports.h" +#include "marker.h" + +namespace aruco +{ +using namespace std; +/**\brief Main class for marker detection + * + */ +class ARUCO_EXPORTS MarkerDetector +{ + //Represent a candidate to be a maker + class MarkerCandidate: public Marker{ + public: + MarkerCandidate(){} + MarkerCandidate(const Marker &M): Marker(M){} + MarkerCandidate(const MarkerCandidate &M): Marker(M){ + contour=M.contour; + idx=M.idx; + } + MarkerCandidate & operator=(const MarkerCandidate &M){ + (*(Marker*)this)=(*(Marker*)&M); + contour=M.contour; + idx=M.idx; + return *this; + } + + vector contour;//all the points of its contour + int idx;//index position in the global contour list + }; +public: + + /** + * See + */ + MarkerDetector(); + + /** + */ + ~MarkerDetector(); + + /**Detects the markers in the image passed + * + * If you provide information about the camera parameters and the size of the marker, then, the extrinsics of the markers are detected + * + * @param input input color image + * @param detectedMarkers output vector with the markers detected + * @param camMatrix intrinsic camera information. + * @param distCoeff camera distorsion coefficient. If set Mat() if is assumed no camera distorion + * @param markerSizeMeters size of the marker sides expressed in meters + * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis + */ + void detect(const cv::Mat &input,std::vector &detectedMarkers,cv::Mat camMatrix=cv::Mat(),cv::Mat distCoeff=cv::Mat(),float markerSizeMeters=-1,bool setYPerperdicular=true) throw (cv::Exception); + /**Detects the markers in the image passed + * + * If you provide information about the camera parameters and the size of the marker, then, the extrinsics of the markers are detected + * + * @param input input color image + * @param detectedMarkers output vector with the markers detected + * @param camParams Camera parameters + * @param markerSizeMeters size of the marker sides expressed in meters + * @param setYPerperdicular If set the Y axis will be perpendicular to the surface. Otherwise, it will be the Z axis + */ + void detect(const cv::Mat &input,std::vector &detectedMarkers, CameraParameters camParams,float markerSizeMeters=-1,bool setYPerperdicular=true) throw (cv::Exception); + + /**This set the type of thresholding methods available + */ + + enum ThresholdMethods {FIXED_THRES,ADPT_THRES,CANNY}; + + + + /**Sets the threshold method + */ + void setThresholdMethod(ThresholdMethods m) { + _thresMethod=m; + } + /**Returns the current threshold method + */ + ThresholdMethods getThresholdMethod()const { + return _thresMethod; + } + /** + * Set the parameters of the threshold method + * We are currently using the Adptive threshold ee opencv doc of adaptiveThreshold for more info + * @param param1: blockSize of the pixel neighborhood that is used to calculate a threshold value for the pixel + * @param param2: The constant subtracted from the mean or weighted mean + */ + void setThresholdParams(double param1,double param2) { + _thresParam1=param1; + _thresParam2=param2; + } + /** + * Set the parameters of the threshold method + * We are currently using the Adptive threshold ee opencv doc of adaptiveThreshold for more info + * param1: blockSize of the pixel neighborhood that is used to calculate a threshold value for the pixel + * param2: The constant subtracted from the mean or weighted mean + */ + void getThresholdParams(double ¶m1,double ¶m2)const { + param1=_thresParam1; + param2=_thresParam2; + } + + + /**Returns a reference to the internal image thresholded. It is for visualization purposes and to adjust manually + * the parameters + */ + const cv::Mat & getThresholdedImage() { + return thres; + } + /**Methods for corner refinement + */ + enum CornerRefinementMethod {NONE,HARRIS,SUBPIX,LINES}; + /** + */ + void setCornerRefinementMethod(CornerRefinementMethod method) { + _cornerMethod=method; + } + /** + */ + CornerRefinementMethod getCornerRefinementMethod()const { + return _cornerMethod; + } + /**Specifies the min and max sizes of the markers as a fraction of the image size. By size we mean the maximum + * of cols and rows. + * @param min size of the contour to consider a possible marker as valid (0,1] + * @param max size of the contour to consider a possible marker as valid [0,1) + * + */ + void setMinMaxSize(float min=0.03,float max=0.5)throw(cv::Exception); + + /**reads the min and max sizes employed + * @param min output size of the contour to consider a possible marker as valid (0,1] + * @param max output size of the contour to consider a possible marker as valid [0,1) + * + */ + void getMinMaxSize(float &min,float &max){min=_minSize;max=_maxSize;} + + /**Enables/Disables erosion process that is REQUIRED for chessboard like boards. + * By default, this property is enabled + */ + void enableErosion(bool enable){_doErosion=enable;} + + /** + * Specifies a value to indicate the required speed for the internal processes. If you need maximum speed (at the cost of a lower detection rate), + * use the value 3, If you rather a more precise and slow detection, set it to 0. + * + * Actually, the main differences are that in highspeed mode, we employ setCornerRefinementMethod(NONE) and internally, we use a small canonical + * image to detect the marker. In low speed mode, we use setCornerRefinementMethod(HARRIS) and a bigger size for the canonical marker image + */ + void setDesiredSpeed(int val); + /** + */ + int getDesiredSpeed()const { + return _speed; + } + + /** + * Allows to specify the function that identifies a marker. Therefore, you can create your own type of markers different from these + * employed by default in the library. + * The marker function must have the following structure: + * + * int myMarkerIdentifier(const cv::Mat &in,int &nRotations); + * + * The marker function receives the image 'in' with the region that migh contain one of your markers. These are the rectangular regions with black + * in the image. + * + * As output your marker function must indicate the following information. First, the output parameter nRotations must indicate how many times the marker + * must be rotated clockwise 90 deg to be in its ideal position. (The way you would see it when you print it). This is employed to know + * always which is the corner that acts as reference system. Second, the function must return -1 if the image does not contains one of your markers, and its id otherwise. + * + */ + void setMakerDetectorFunction(int (* markerdetector_func)(const cv::Mat &in,int &nRotations) ) { + markerIdDetector_ptrfunc=markerdetector_func; + } + + /** Use an smaller version of the input image for marker detection. + * If your marker is small enough, you can employ an smaller image to perform the detection without noticeable reduction in the precision. + * Internally, we are performing a pyrdown operation + * + * @param level number of times the image size is divided by 2. Internally, we are performing a pyrdown. + */ + void pyrDown(unsigned int level){pyrdown_level=level;} + + ///------------------------------------------------- + /// Methods you may not need + /// Thesde methods do the hard work. They have been set public in case you want to do customizations + ///------------------------------------------------- + + /** + * Thesholds the passed image with the specified method. + */ + void thresHold(int method,const cv::Mat &grey,cv::Mat &thresImg,double param1=-1,double param2=-1)throw(cv::Exception); + /** + * Detection of candidates to be markers, i.e., rectangles. + * This function returns in candidates all the rectangles found in a thresolded image + */ + void detectRectangles(const cv::Mat &thresImg,vector > & candidates); + + /**Returns a list candidates to be markers (rectangles), for which no valid id was found after calling detectRectangles + */ + const vector > &getCandidates() { + return _candidates; + } + + /**Given the iput image with markers, creates an output image with it in the canonical position + * @param in input image + * @param out image with the marker + * @param size of out + * @param points 4 corners of the marker in the image in + * @return true if the operation succeed + */ + bool warp(cv::Mat &in,cv::Mat &out,cv::Size size, std::vector points)throw (cv::Exception); + + + + /** Refine MarkerCandidate Corner using LINES method + * @param candidate candidate to refine corners + */ + void refineCandidateLines(MarkerCandidate &candidate); + + + /**DEPRECATED!!! Use the member function in CameraParameters + * + * Given the intrinsic camera parameters returns the GL_PROJECTION matrix for opengl. + * PLease NOTE that when using OpenGL, it is assumed no camera distorsion! So, if it is not true, you should have + * undistor image + * + * @param CamMatrix arameters of the camera specified. + * @param orgImgSize size of the original image + * @param size of the image/window where to render (can be different from the real camera image). Please not that it must be related to CamMatrix + * @param proj_matrix output projection matrix to give to opengl + * @param gnear,gfar: visible rendering range + * @param invert: indicates if the output projection matrix has to yield a horizontally inverted image because image data has not been stored in the order of glDrawPixels: bottom-to-top. + */ + static void glGetProjectionMatrix( CameraParameters & CamMatrix,cv::Size orgImgSize, cv::Size size,double proj_matrix[16],double gnear,double gfar,bool invert=false )throw(cv::Exception); + +private: + + bool _enableCylinderWarp; + bool warp_cylinder ( cv::Mat &in,cv::Mat &out,cv::Size size, MarkerCandidate& mc ) throw ( cv::Exception ); + /** + * Detection of candidates to be markers, i.e., rectangles. + * This function returns in candidates all the rectangles found in a thresolded image + */ + void detectRectangles(const cv::Mat &thresImg,vector & candidates); +public: + //Current threshold method + ThresholdMethods _thresMethod; + //Threshold parameters + double _thresParam1,_thresParam2; + //Current corner method + CornerRefinementMethod _cornerMethod; + //minimum and maximum size of a contour lenght + float _minSize,_maxSize; + //Speed control + int _speed; + int _markerWarpSize; + bool _doErosion; + //vectr of candidates to be markers. This is a vector with a set of rectangles that have no valid id + vector > _candidates; + //level of image reduction + int pyrdown_level; + //Images + cv::Mat grey,thres,thres2,reduced; + //pointer to the function that analizes a rectangular region so as to detect its internal marker + int (* markerIdDetector_ptrfunc)(const cv::Mat &in,int &nRotations); +private: + /** + */ + bool isInto(cv::Mat &contour,std::vector &b); + /** + */ + int perimeter(std::vector &a); + + +// //GL routines +// +// static void argConvGLcpara2( double cparam[3][4], int width, int height, double gnear, double gfar, double m[16], bool invert )throw(cv::Exception); +// static int arParamDecompMat( double source[3][4], double cpara[3][4], double trans[3][4] )throw(cv::Exception); +// static double norm( double a, double b, double c ); +// static double dot( double a1, double a2, double a3, +// double b1, double b2, double b3 ); +// + + //detection of the + void findBestCornerInRegion_harris(const cv::Mat & grey,vector & Corners,int blockSize); + + + // auxiliar functions to perform LINES refinement + void interpolate2Dline( const vector< cv::Point > &inPoints, cv::Point3f &outLine); + cv::Point2f getCrossPoint(const cv::Point3f& line1, const cv::Point3f& line2); + + + /**Given a vector vinout with elements and a boolean vector indicating the lements from it to remove, + * this function remove the elements + * @param vinout + * @param toRemove + */ + template + void removeElements(vector & vinout,const vector &toRemove) + { + //remove the invalid ones by setting the valid in the positions left by the invalids + size_t indexValid=0; + for (size_t i=0;i &approxCurve ,cv::Scalar color); + void drawContour(cv::Mat &in,std::vector &contour,cv::Scalar ); + void drawAllContours(cv::Mat input, std::vector > &contours); + void draw(cv::Mat out,const std::vector &markers ); + +}; + + + + +} +#endif diff --git a/tracker-aruco/trans_calib.cpp b/tracker-aruco/trans_calib.cpp new file mode 100644 index 00000000..b5148efd --- /dev/null +++ b/tracker-aruco/trans_calib.cpp @@ -0,0 +1,41 @@ +/* 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. + */ + +#include "trans_calib.h" + +TranslationCalibrator::TranslationCalibrator() +{ + reset(); +} + +void TranslationCalibrator::reset() +{ + P = cv::Matx66f::zeros(); + y = cv::Vec6f(0,0,0, 0,0,0); +} + +void TranslationCalibrator::update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k) +{ + cv::Matx H_k_T = cv::Matx::zeros(); + for (int i=0; i<3; ++i) { + for (int j=0; j<3; ++j) { + H_k_T(i,j) = R_CM_k(j,i); + } + } + for (int i=0; i<3; ++i) + { + H_k_T(3+i,i) = 1.0; + } + P += H_k_T * H_k_T.t(); + y += H_k_T * t_CM_k; +} + +cv::Vec3f TranslationCalibrator::get_estimate() +{ + cv::Vec6f x = P.inv() * y; + return cv::Vec3f(x[0], x[1], x[2]); +} diff --git a/tracker-aruco/trans_calib.h b/tracker-aruco/trans_calib.h new file mode 100644 index 00000000..3d1e56fa --- /dev/null +++ b/tracker-aruco/trans_calib.h @@ -0,0 +1,39 @@ +/* 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. + */ + +#ifndef TRANSCALIB_H +#define TRANSCALIB_H + +#include + +//----------------------------------------------------------------------------- +// Calibrates the translation from head to model = t_MH +// by recursive least squares / +// kalman filter in information form with identity noise covariance +// measurement equation when head position = t_CH is fixed: +// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k + +class TranslationCalibrator +{ +public: + TranslationCalibrator(); + + // reset the calibration process + void reset(); + + // update the current estimate + void update(const cv::Matx33d& R_CM_k, const cv::Vec3d& t_CM_k); + + // get the current estimate for t_MH + cv::Vec3f get_estimate(); + +private: + cv::Matx66f P; // normalized precision matrix = inverse covariance + cv::Vec6f y; // P*(-t_MH, t_CH) +}; + +#endif //TRANSCALIB_H diff --git a/tracker-freepie-udp/CMakeLists.txt b/tracker-freepie-udp/CMakeLists.txt new file mode 100644 index 00000000..34cb2fdc --- /dev/null +++ b/tracker-freepie-udp/CMakeLists.txt @@ -0,0 +1 @@ +opentrack_boilerplate(opentrack-tracker-freepie-udp) diff --git a/tracker-freepie-udp/freepie-udp-controls.ui b/tracker-freepie-udp/freepie-udp-controls.ui new file mode 100644 index 00000000..74e5a6f1 --- /dev/null +++ b/tracker-freepie-udp/freepie-udp-controls.ui @@ -0,0 +1,285 @@ + + + UI_freepie_udp_dialog + + + Qt::NonModal + + + + 0 + 0 + 227 + 372 + + + + Tracker settings + + + + ../facetracknoir/images/facetracknoir.png../facetracknoir/images/facetracknoir.png + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 0 + 0 + + + + UDP port + + + + + + + 0 + + + 65535 + + + + + + + + + + Axis order + + + + + + output yaw + + + + + + + + input yaw + + + + + input pitch + + + + + input roll + + + + + + + + + input yaw + + + + + input pitch + + + + + input roll + + + + + + + + output pitch + + + + + + + + input yaw + + + + + input pitch + + + + + input roll + + + + + + + + output roll + + + + + + + + + + Add to axis + + + + + + yaw + + + + + + + + 0 + + + + + +90 + + + + + -90 + + + + + +180 + + + + + -180 + + + + + + + + pitch + + + + + + + roll + + + + + + + + 0 + + + + + +90 + + + + + -90 + + + + + +180 + + + + + -180 + + + + + + + + + 0 + + + + + +90 + + + + + -90 + + + + + +180 + + + + + -180 + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-freepie-udp/freepie-udp-res.qrc b/tracker-freepie-udp/freepie-udp-res.qrc new file mode 100644 index 00000000..3fd3edc4 --- /dev/null +++ b/tracker-freepie-udp/freepie-udp-res.qrc @@ -0,0 +1,5 @@ + + + glovepie.png + + diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp new file mode 100644 index 00000000..12cf9bca --- /dev/null +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.cpp @@ -0,0 +1,119 @@ +#include "ftnoir_tracker_freepie-udp.h" +#include "opentrack/plugin-api.hpp" + +#include +#include + +TrackerImpl::TrackerImpl() : pose { 0,0,0, 0,0,0 }, should_quit(false) +{ +} + +TrackerImpl::~TrackerImpl() +{ + should_quit = true; + wait(); +} + +template +static const t bound(t datum, t least, t max) +{ + if (datum < least) + return least; + if (datum > max) + return max; + return datum; +} + +void TrackerImpl::run() { +#pragma pack(push, 1) + struct { + uint8_t pad1; + uint8_t flags; + float fl[12]; + } data; +#pragma pack(pop) + enum F { + flag_Raw = 1 << 0, + flag_Orient = 1 << 1, + Mask = flag_Raw | flag_Orient + }; + + (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); + + while (!should_quit) { + int order[] = { + bound(s.idx_x, 0, 2), + bound(s.idx_y, 0, 2), + bound(s.idx_z, 0, 2) + }; + float orient[3]; + bool filled = false; + + while (sock.hasPendingDatagrams()) + { + using t = decltype(data); + t tmp {0,0, {0,0,0, 0,0,0, 0,0,0, 0,0,0}}; + (void) sock.readDatagram(reinterpret_cast(&tmp), sizeof(data)); + + int flags = tmp.flags & F::Mask; + + switch (flags) + { + //default: + case flag_Raw: + continue; + case flag_Raw | flag_Orient: + for (int i = 0; i < 3; i++) + orient[i] = tmp.fl[i+9]; + break; + case flag_Orient: + for (int i = 0; i < 3; i++) + orient[i] = tmp.fl[i]; + break; + } + + filled = true; + data = tmp; + } + + if (filled) + { + static const int add_cbx[] = { + 0, + 90, + -90, + 180, + -180, + }; + int indices[] = { s.add_yaw, s.add_pitch, s.add_roll }; + QMutexLocker foo(&mtx); + static constexpr double r2d = 57.295781; + for (int i = 0; i < 3; i++) + { + int val = 0; + int idx = indices[order[i]]; + if (idx >= 0 && idx < (int)(sizeof(add_cbx) / sizeof(*add_cbx))) + val = add_cbx[idx]; + pose[Yaw + i] = r2d * orient[order[i]] + val; + } + } + usleep(4000); + } +} + +void TrackerImpl::start_tracker(QFrame*) +{ + start(); + sock.moveToThread(this); +} + +void TrackerImpl::data(double *data) +{ + QMutexLocker foo(&mtx); + + data[Yaw] = pose[Yaw]; + data[Pitch] = pose[Pitch]; + data[Roll] = pose[Roll]; +} + +OPENTRACK_DECLARE_TRACKER(TrackerImpl, TrackerDialog, TrackerMeta) diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h new file mode 100644 index 00000000..7cff2ec9 --- /dev/null +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2014 Stanislaw Halik + * + * 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 +#include +#include +#include "ui_freepie-udp-controls.h" +#include "opentrack/plugin-api.hpp" +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value port, idx_x, idx_y, idx_z; + value add_yaw, add_pitch, add_roll; + settings() : + opts("freepie-udp-tracker"), + port(b, "port", 5555), + idx_x(b, "axis-index-x", 0), + idx_y(b, "axis-index-y", 1), + idx_z(b, "axis-index-z", 2), + add_yaw(b, "add-yaw-degrees", 0), + add_pitch(b, "add-pitch-degrees", 0), + add_roll(b, "add-roll-degrees", 0) + {} +}; + +class TrackerImpl : public ITracker, private QThread +{ +public: + TrackerImpl(); + ~TrackerImpl() override; + void start_tracker(QFrame *) override; + void data(double *data) override; +protected: + void run() override; +private: + double pose[6]; + QUdpSocket sock; + settings s; + QMutex mtx; + volatile bool should_quit; +}; + +class TrackerDialog : public ITrackerDialog +{ + Q_OBJECT +public: + TrackerDialog(); + void register_tracker(ITracker *) override {} + void unregister_tracker() override {} +private: + Ui::UI_freepie_udp_dialog ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class TrackerMeta : public Metadata +{ +public: + QString name() { return QString("FreePIE UDP receiver"); } + QIcon icon() { return QIcon(":/glovepie.png"); } +}; + diff --git a/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp b/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp new file mode 100644 index 00000000..55427d35 --- /dev/null +++ b/tracker-freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp @@ -0,0 +1,30 @@ +#include "ftnoir_tracker_freepie-udp.h" +#include "opentrack/plugin-api.hpp" + +TrackerDialog::TrackerDialog() +{ + ui.setupUi(this); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.port, ui.port); + tie_setting(s.idx_x, ui.input_x); + tie_setting(s.idx_y, ui.input_y); + tie_setting(s.idx_z, ui.input_z); + + tie_setting(s.add_yaw, ui.add_yaw); + tie_setting(s.add_pitch, ui.add_pitch); + tie_setting(s.add_roll, ui.add_roll); +} + +void TrackerDialog::doOK() { + s.b->save(); + this->close(); +} + +void TrackerDialog::doCancel() { + s.b->reload(); + this->close(); +} + diff --git a/tracker-freepie-udp/glovepie.png b/tracker-freepie-udp/glovepie.png new file mode 100644 index 00000000..2156b7af Binary files /dev/null and b/tracker-freepie-udp/glovepie.png differ diff --git a/tracker-hatire/CMakeLists.txt b/tracker-hatire/CMakeLists.txt new file mode 100644 index 00000000..e4c7b9d1 --- /dev/null +++ b/tracker-hatire/CMakeLists.txt @@ -0,0 +1,5 @@ +if(Qt5SerialPort_FOUND) + opentrack_boilerplate(opentrack-tracker-hatire) + target_link_libraries(opentrack-tracker-hatire ${Qt5SerialPort_LIBRARIES}) + target_include_directories(opentrack-tracker-hatire SYSTEM PUBLIC ${Qt5SerialPort_INCLUDE_DIRS}) +endif() diff --git a/tracker-hatire/ftnoir_arduino_type.h b/tracker-hatire/ftnoir_arduino_type.h new file mode 100644 index 00000000..57afed63 --- /dev/null +++ b/tracker-hatire/ftnoir_arduino_type.h @@ -0,0 +1,32 @@ +#ifndef FTNOIR_TARDUINO_TYPE_H +#define FTNOIR_TARDUINO_TYPE_H + +#include + +// Arduino trame structure +#pragma pack(push,2) +struct TArduinoData +{ + quint16 Begin; // Header trame 0xAAAA; + quint16 Code; // 0->999 Num Trame >=2000 Info >=3000 Init >=5000 Start Command >=9000 Error + float Rot[3]; + float Trans[3]; + quint16 End; // End trame 0x5555; +} ; +#pragma pack(pop) + + +inline QDataStream & operator >> ( QDataStream& in, TArduinoData& out ) +{ + in.setFloatingPointPrecision(QDataStream::SinglePrecision ); + + in >> out.Begin >> out.Code + >> out.Rot[0] >> out.Rot[1] >> out.Rot[2] + >> out.Trans[0] >> out.Trans[1] >> out.Trans[2] + >> out.End; + return in; +} + + + +#endif diff --git a/tracker-hatire/ftnoir_hat.qrc b/tracker-hatire/ftnoir_hat.qrc new file mode 100644 index 00000000..41d43617 --- /dev/null +++ b/tracker-hatire/ftnoir_hat.qrc @@ -0,0 +1,7 @@ + + + images/hat_logo.png + images/hat.ico + images/hat.png + + diff --git a/tracker-hatire/ftnoir_hatcontrols.ui b/tracker-hatire/ftnoir_hatcontrols.ui new file mode 100644 index 00000000..2d347f08 --- /dev/null +++ b/tracker-hatire/ftnoir_hatcontrols.ui @@ -0,0 +1,1253 @@ + + + UIHATControls + + + + 0 + 0 + 370 + 740 + + + + + 0 + 0 + + + + + 65536 + 65536 + + + + Qt::NoContextMenu + + + Head Arduino Tracker settings FaceTrackNoIR + + + + :/images/hat.png:/images/hat.png + + + 1.000000000000000 + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + + 80 + 25 + + + + + 80 + 25 + + + + Cancel + + + + + + + + 0 + 0 + + + + + 80 + 25 + + + + + 80 + 25 + + + + OK + + + + + + + + 0 + 0 + + + + + 65535 + 65535 + + + + 0 + + + + General + + + + + + + + + true + + + + 4 + + + + + + 0 + 0 + + + + + 65536 + 16777215 + + + + Serial port + + + + + + + + 0 + 0 + + + + + 65535 + 16777215 + + + + false + + + QComboBox::AdjustToMinimumContentsLength + + + 0 + + + + + + + + + + false + + + + 80 + 20 + + + + Zero + + + + + + + false + + + + 80 + 20 + + + + Center + + + + + + + false + + + + 80 + 20 + + + + Reset + + + + + + + Axis Configuration + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + Associate Axis + + + + RotX + + + + + RotY + + + + + RotZ + + + + + + + + + 20 + 16777215 + + + + Enable Axis + + + Qt::LeftToRight + + + + + + + + + + + 20 + 16777215 + + + + Enable Axis + + + Qt::LeftToRight + + + + + + + + + + Pitch: + + + + + + + Enable + + + + + + + + 20 + 16777215 + + + + Enable Axis + + + Qt::LeftToRight + + + + + + + + + + Yaw: + + + + + + + Invert + + + + + + + Y: + + + + + + + + 20 + 16777215 + + + + Invert Axis + + + Qt::LeftToRight + + + + + + + + + + + + + X: + + + + + + + + 20 + 16777215 + + + + Invert Axis + + + Qt::LeftToRight + + + + + + + + + + + + + + 20 + 16777215 + + + + Invert Axis + + + Qt::LeftToRight + + + + + + + + + + + + + Associate Axis + + + + X + + + + + Y + + + + + Z + + + + + + + + + 20 + 16777215 + + + + Enable Axis + + + Qt::LeftToRight + + + + + + + + + + Associate Axis + + + + X + + + + + Y + + + + + Z + + + + + + + + Roll: + + + + + + + + 20 + 16777215 + + + + Invert Axis + + + Qt::LeftToRight + + + + + + + + + + + + + Associate Axis + + + + X + + + + + Y + + + + + Z + + + + + + + + + 20 + 16777215 + + + + Invert Axis + + + Qt::LeftToRight + + + + + + + + + + + + + Z: + + + + + + + Associate Axis + + + + RotX + + + + + RotY + + + + + RotZ + + + + + + + + + 20 + 16777215 + + + + Enable Axis + + + Qt::LeftToRight + + + + + + + + + + + + + + 20 + 16777215 + + + + Enable Axis + + + Qt::LeftToRight + + + + + + + + + + + 20 + 16777215 + + + + Invert Axis + + + Qt::LeftToRight + + + + + + + + + + + + + Associate Axis + + + + RotX + + + + + RotY + + + + + RotZ + + + + + + + + Axis + + + + + + + + + + + 0 + 0 + + + + Status + + + false + + + + + + + 31 + 20 + + + + + 60 + 20 + + + + Trame per seconde + + + tps : + + + + + + + + 31 + 20 + + + + + 60 + 20 + + + + 0 + + + Qt::PlainText + + + + + + + + 0 + 20 + + + + + 60 + 20 + + + + Info : + + + + + + + + 170 + 20 + + + + + 60 + 20 + + + + HAT STOPPED + + + Qt::PlainText + + + + + + + + + + + Command + + + + + + Serial Parameters + + + + + + + + + + + + Flow control: + + + + + + + + + + + + + Stop bits: + + + + + + + Parity: + + + + + + + BaudRate: + + + + + + + + + + Data bits: + + + + + + + + + + Arduino Commands + + + + + + Delay Init + + + + + + + Init + + + + + + + Command for Initialising Arduino + + + + + + + Delay Start + + + + + + + Start: + + + + + + + Command for Start send sequence + + + + + + + Delay Sequence + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay after Start Command in ms</span></p></body></html> + + + 5000 + + + 50 + + + + + + + Stop: + + + + + + + Command for Stop send sequence + + + + + + + Center: + + + + + + + Command for read Center Gyro arduino + + + + + + + Zero: + + + + + + + Command for reset Center Gyro arduino + + + + + + + Reset: + + + + + + + Command for Reset Arduino + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Little or Big Endian for <span style=" font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;">the serialization of byte order</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;">Arduino is LittleEndian ( unchecked)</span></p></body></html> + + + Endian + + + + + + + + 60 + 16777215 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay before Init command in ms</span></p></body></html> + + + 5000 + + + 50 + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay after Init command in ms</span></p></body></html> + + + 5000 + + + 50 + + + + + + + + 51 + 19 + + + + <html><head/><body><p>Indicate at OpenTrack speed sketch FPS to adjust CPU </p></body></html> + + + 10 + + + 200 + + + + + + + + + + + About + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">FTNoIR HAT Plugin<br />by FuraX49</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://hatire.sourceforge.net/"><span style=" font-size:8pt; font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html> + + + true + + + + + + + false + + + + + + + :/images/hat_logo.png + + + + + 128 + 128 + + + + true + + + + + + + + Arial Black + 10 + 75 + true + true + + + + Version 1.0.0 + + + Qt::PlainText + + + true + + + + + + + + + + + + + + + + + Send + + + + + + + Qt::ActionsContextMenu + + + true + + + + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + 800 + + + false + + + + + + + Disable when not in use, will have a performance impact + + + Enable logging to diagnostic file + + + + + + + + + + + + 80 + 25 + + + + + 80 + 25 + + + + Save + + + + + + + btnOK + btnSave + btnCancel + cbSerialPort + btnZero + btnCenter + btnReset + chkEnableYaw + cb_yaw + chkInvertYaw + chkEnablePitch + cb_pitch + chkInvertPitch + chkEnableRoll + cb_roll + chkInvertRoll + chkEnableX + cb_x + chkInvertX + chkEnableY + cb_y + chkInvertY + chkEnableZ + cb_z + chkInvertZ + spb_BeforeInit + le_cmd_init + spb_BeforeStart + le_cmd_start + spb_AfterStart + le_cmd_stop + le_cmd_center + le_cmd_zero + le_cmd_reset + spb_Fps + cb_Endian + QCB_Serial_baudRate + QCB_Serial_dataBits + QCB_Serial_parity + QCB_Serial_stopBits + QCB_Serial_flowControl + lineSend + btnSend + pteINFO + tabWidget + btn_icone + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-hatire/ftnoir_tracker_hat.cpp b/tracker-hatire/ftnoir_tracker_hat.cpp new file mode 100644 index 00000000..eea1cbca --- /dev/null +++ b/tracker-hatire/ftnoir_tracker_hat.cpp @@ -0,0 +1,597 @@ +/* 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 +#include "ftnoir_tracker_hat.h" + +FTNoIR_Tracker::FTNoIR_Tracker() +{ + qDebug()<<"Tracker::HAT"; + + ComPort = NULL; + + HAT.Rot[0]=0; + HAT.Rot[1]=0; + HAT.Rot[2]=0; + HAT.Trans[0]=0; + HAT.Trans[1]=0; + HAT.Trans[2]=0; + + + // prepare & reserve QByteArray + dataRead.resize(4096); + dataRead.clear(); + Begin.append((char) 0xAA); + Begin.append((char) 0xAA); + End.append((char) 0x55); + End.append((char) 0x55); + + flDiagnostics.setFileName(QCoreApplication::applicationDirPath() + "/HATDiagnostics.txt"); + + settings.load_ini(); +} + +FTNoIR_Tracker::~FTNoIR_Tracker() +{ + qDebug()<<"Tracker::~HAT"; + if (ComPort!=NULL) { + if (ComPort->isOpen() ) { + +#ifdef OPENTRACK_API + QByteArray Msg; + Log("Tracker shut down"); + ComPort->write(sCmdStop); + if (!ComPort->waitForBytesWritten(1000)) { + emit sendMsgInfo("TimeOut in writing CMD"); + } else + { + Msg.append("\r\n"); + Msg.append("SEND '"); + Msg.append(sCmdStop); + Msg.append("'\r\n"); + } + emit sendMsgInfo(Msg); +#endif + ComPort->close(); + disconnect(ComPort,SIGNAL(readyRead()),0,0); + + } + delete ComPort; + ComPort=NULL; + } +} + + +//send ZERO to Arduino +bool FTNoIR_Tracker::notifyZeroed() { + qDebug() << " HAT send ZEROed "; + sendcmd(sCmdZero); + return true; +} + + + +//send RESET to Arduino +void FTNoIR_Tracker::reset() { + qDebug() << " HAT send RESET "; + sendcmd(sCmdReset); +} + + +// Info SerialPort +void FTNoIR_Tracker::SerialInfo() { + QByteArray Msg; + if (ComPort!=NULL) { + if (ComPort->isOpen() ) { + Msg.append("\r\n"); + Msg.append(ComPort->portName()); + Msg.append("\r\n"); + Msg.append("BAUDRATE :"); + Msg.append(QString::number(ComPort->baudRate())); + Msg.append("\r\n"); + Msg.append("DataBits :"); + Msg.append(QString::number(ComPort->dataBits())); + Msg.append("\r\n"); + Msg.append("Parity :"); + switch (ComPort->parity()) { + case 0: Msg.append("No parity"); + break; + case 2: Msg.append("Even parity"); + break; + case 3: Msg.append("Odd parity"); + break; + case 4: Msg.append("Space parity"); + break; + case 5: Msg.append("Mark parity"); + break; + default: Msg.append("Unknown parity"); + break; + } + Msg.append("\r\n"); + Msg.append("Stop Bits :"); + switch (ComPort->stopBits()) { + Msg.append(QString::number(ComPort->stopBits())); + case 1: Msg.append("1 stop bit."); + break; + case 2: Msg.append("2 stop bits."); + break; + case 3: Msg.append("1.5 stop bits."); + break; + default: Msg.append("Unknown number of stop bit."); + break; + } + Msg.append("\r\n"); + Msg.append("Flow Control :"); + switch (ComPort->flowControl()) { + case 0: Msg.append("No flow control"); + break; + case 1: Msg.append("Hardware flow control (RTS/CTS)"); + break; + case 2: Msg.append("Software flow control (XON/XOFF)"); + break; + default: Msg.append("Unknown flow control"); + break; + } + emit sendMsgInfo(Msg); + + } + } +} + + +//send command to Arduino +void FTNoIR_Tracker::sendcmd(const QByteArray &cmd) { + QByteArray Msg; + if (cmd.length()>0) { + if (ComPort->isOpen() ) + { + QString logMess; + logMess.append("SEND '"); + logMess.append(cmd); + logMess.append("'"); + Log(logMess); + ComPort->write(cmd); + if (!ComPort->waitForBytesWritten(1000)) { + emit sendMsgInfo("TimeOut in writing CMD"); + } else + { + Msg.append("\r\n"); + Msg.append("SEND '"); + Msg.append(cmd); + Msg.append("'\r\n"); + } + #if 0 // WaitForReadyRead isn't working well and there are some reports of it being a win32 issue. We can live without it anyway + if ( !ComPort->waitForReadyRead(1000)) { + emit sendMsgInfo("TimeOut in response to CMD") ; + } else { + emit sendMsgInfo(Msg); + } + #else + emit sendMsgInfo(Msg); + #endif + } else { + emit sendMsgInfo("ComPort not open") ; + } + } +} + + +// return FPS +void FTNoIR_Tracker::get_info( int *tps ){ + *tps=frame_cnt; + frame_cnt=0; +} + +void FTNoIR_Tracker::SerialRead() +{ + QMutexLocker lck(&mutex); + dataRead+=ComPort->readAll(); +} + +#ifndef OPENTRACK_API +void FTNoIR_Tracker::Initialize( QFrame *videoframe ) +{ + CptError=0; + dataRead.clear(); + frame_cnt=0; + + Log("INITIALISING HATIRE"); + + settings.load_ini(); + applysettings(settings); + ComPort = new QSerialPort(this); + ComPort->setPortName(sSerialPortName); + if (ComPort->open(QIODevice::ReadWrite ) == true) { + connect(ComPort, SIGNAL(readyRead()), this, SLOT(SerialRead())); + if ( + ComPort->setBaudRate((QSerialPort::BaudRate)iBaudRate) + && ComPort->setDataBits((QSerialPort::DataBits)iDataBits) + && ComPort->setParity((QSerialPort::Parity)iParity) + && ComPort->setStopBits((QSerialPort::StopBits)iStopBits) + && ComPort->setFlowControl((QSerialPort::FlowControl)iFlowControl) + && ComPort->clear(QSerialPort::AllDirections) + && ComPort->setDataErrorPolicy(QSerialPort::IgnorePolicy) + ) { + // Wait init arduino sequence + for (int i = 1; i <=iDelayInit; i+=50) { + if (ComPort->waitForReadyRead(50)) break; + } + sendcmd(sCmdInit); + // Wait init MPU sequence + for (int i = 1; i <=iDelayStart; i+=50) { + if (ComPort->waitForReadyRead(50)) break; + } + + } else { + QMessageBox::warning(0,"Error", ComPort->errorString(),QMessageBox::Ok,QMessageBox::NoButton); + } + } + else { + QMessageBox::warning(0,"Error", "Unable to open ComPort",QMessageBox::Ok,QMessageBox::NoButton); + delete ComPort; + ComPort = NULL; + } + return; +} + + + +void FTNoIR_Tracker::StartTracker(HWND parent_window) +{ + // Send START cmd to IMU + sendcmd(sCmdStart); + Log("Starting Tracker"); + // Wait start MPU sequence + for (int i = 1; i <=iDelaySeq; i+=50) { + if (ComPort->waitForReadyRead(50)) break; + } + return; +} + + +void FTNoIR_Tracker::StopTracker( bool exit ) +{ + QByteArray Msg; + + Log("Stopping tracker"); + if (sCmdStop.length()>0) { + if (ComPort->isOpen() ) + { + ComPort->write(sCmdStop); + if (!ComPort->waitForBytesWritten(1000)) { + emit sendMsgInfo("TimeOut in writing CMD"); + } else + { + Msg.append("\r\n"); + Msg.append("SEND '"); + Msg.append(sCmdStop); + Msg.append("'\r\n"); + } + emit sendMsgInfo(Msg); + } + } + // OK, the thread is not stopped, doing this. That might be dangerous anyway... + // + if (exit || !exit) return; + return; +} +//send CENTER to Arduino +void FTNoIR_Tracker::notifyCenter() { + sendcmd(sCmdCenter); +} + + +#else +void FTNoIR_Tracker::start_tracker(QFrame*) +{ + CptError=0; + dataRead.clear(); + frame_cnt=0; + new_frame=false; + settings.load_ini(); + applysettings(settings); + ComPort = new QSerialPort(this); + ComPort->setPortName(sSerialPortName); + Log("Starting Tracker"); + + if (ComPort->open(QIODevice::ReadWrite ) == true) { + connect(ComPort, SIGNAL(readyRead()), this, SLOT(SerialRead())); + Log("Port Open"); + if ( + ComPort->setBaudRate((QSerialPort::BaudRate)iBaudRate) + && ComPort->setDataBits((QSerialPort::DataBits)iDataBits) + && ComPort->setParity((QSerialPort::Parity)iParity) + && ComPort->setStopBits((QSerialPort::StopBits)iStopBits) + && ComPort->setFlowControl((QSerialPort::FlowControl)iFlowControl) + && ComPort->clear(QSerialPort::AllDirections) + && ComPort->setDataErrorPolicy(QSerialPort::IgnorePolicy) + ) { + Log("Port Parameters set"); + qDebug() << QTime::currentTime() << " HAT OPEN on " << ComPort->portName() << ComPort->baudRate() << ComPort->dataBits() << ComPort->parity() << ComPort->stopBits() << ComPort->flowControl(); + + if (ComPort->flowControl() == QSerialPort::HardwareControl) + { + // Raise DTR + Log("Raising DTR"); + if (!ComPort->setDataTerminalReady(true)) + Log("Couldn't set DTR"); + + // Raise RTS/CTS + Log("Raising RTS"); + if (!ComPort->setRequestToSend(true)) + Log("Couldn't set RTS"); + + } + // Wait init arduino sequence + for (int i = 1; i <=iDelayInit; i+=50) { + if (ComPort->waitForReadyRead(50)) break; + } + Log("Waiting on init"); + qDebug() << QTime::currentTime() << " HAT send INIT "; + sendcmd(sCmdInit); + // Wait init MPU sequence + for (int i = 1; i <=iDelayStart; i+=50) { + if (ComPort->waitForReadyRead(50)) break; + } + // Send START cmd to IMU + qDebug() << QTime::currentTime() << " HAT send START "; + sendcmd(sCmdStart); + + // Wait start MPU sequence + for (int i = 1; i <=iDelaySeq; i+=50) { + if (ComPort->waitForReadyRead(50)) break; + } + Log("Port setup, waiting for HAT frames to process"); + qDebug() << QTime::currentTime() << " HAT wait MPU "; + } else { + QMessageBox::warning(0,"Error", ComPort->errorString(),QMessageBox::Ok,QMessageBox::NoButton); + } + } + else { + QMessageBox::warning(0,"Error", "Unable to open ComPort: " + ComPort->errorString(), QMessageBox::Ok,QMessageBox::NoButton); + delete ComPort; + ComPort = NULL; + } + return; + +} + +//send CENTER to Arduino +void FTNoIR_Tracker::center() { + qDebug() << " HAT send CENTER "; + Log("Sending Centre Command"); + + sendcmd(sCmdCenter); +} + +//Return speed FPS sketch Arduino +int FTNoIR_Tracker::preferredHz() { + qDebug() << " HAT return Preferred FPS " << iFpsArduino; + return iFpsArduino; +} + +#endif + + +// +// Return 6DOF info +// +#ifdef OPENTRACK_API +void FTNoIR_Tracker::data(double *data) +#else +bool FTNoIR_Tracker::GiveHeadPoseData(THeadPoseData *data) +#endif +{ + QMutexLocker lck(&mutex); + while (dataRead.length()>=30) { + Log(dataRead.toHex()); + if ((dataRead.startsWith(Begin) && ( dataRead.mid(28,2)==End )) ) { // .Begin==0xAAAA .End==0x5555 + QDataStream datastream(dataRead.left(30)); + if (bBigEndian) datastream.setByteOrder(QDataStream::BigEndian ); + else datastream.setByteOrder(QDataStream::LittleEndian ); + datastream>>ArduinoData; + frame_cnt++; + if (ArduinoData.Code <= 1000) { + HAT=ArduinoData; + new_frame=true; + } else { + emit sendMsgInfo(dataRead.mid(4,24)) ; + } + dataRead.remove(0,30); + } else { + // resynchro trame + int index = dataRead.indexOf(Begin); + if (index==-1) { + index=dataRead.length(); + } + emit sendMsgInfo(dataRead.mid(0,index)) ; + dataRead.remove(0,index); + CptError++; + qDebug() << QTime::currentTime() << " HAT Resync-Frame, counter " << CptError; + } + } + + if (CptError>50) { + emit sendMsgInfo("Can't find HAT frame") ; + CptError=0; +#ifndef OPENTRACK_API + return false; +#endif + } + // Need to handle this differently in opentrack as opposed to tracknoir + //if (new_frame) { +#ifdef OPENTRACK_API + // in open track always populate the data, it seems opentrack always gives us a zeroed data structure to populate with pose data. + // if we have no new data, we don't populate it and so 0 pose gets handed back which is wrong. By always running the code below, if we + // have no new data, we will just give it the previous pose data which is the best thing we can do really. + if(1){ + + if (bEnableYaw) { + if (bInvertYaw ) data[Yaw] = HAT.Rot[iYawAxe] * -1.0f; + else data[Yaw] = HAT.Rot[iYawAxe]; + + } else data[Yaw] =0; + + if (bEnablePitch) { + if (bInvertPitch) data[Pitch] = HAT.Rot[iPitchAxe] * -1.0f; + else data[Pitch] = HAT.Rot[iPitchAxe]; + } else data[Pitch] = 0; + + if (bEnableRoll) { + if (bInvertRoll) data[Roll] = HAT.Rot[iRollAxe] * -1.0f; + else data[Roll] = HAT.Rot[iRollAxe]; + } else data[Roll] =0; + + if (bEnableX) { + if (bInvertX) data[TX] = HAT.Trans[iXAxe]* -1.0f; + else data[TX] = HAT.Trans[iXAxe]; + } else data[TX] =0; + + if (bEnableY) { + if (bInvertY) data[TY] = HAT.Trans[iYAxe]* -1.0f; + else data[TY] = HAT.Trans[iYAxe]; + } else data[TY] =0; + + if (bEnableZ) { + if (bInvertZ) data[TZ] = HAT.Trans[iZAxe]* -1.0f; + else data[TZ] = HAT.Trans[iZAxe]; + } else data[TZ] =0; +#else + if (new_frame) { // treat frame handling as it was for TrackNoIR. + if (bEnableYaw) { + if (bInvertYaw ) data->yaw = (double) HAT.Rot[iYawAxe] * -1.0f; + else data->yaw = (double) HAT.Rot[iYawAxe]; + } + + if (bEnablePitch) { + if (bInvertPitch)data->pitch = (double) HAT.Rot[iPitchAxe] * -1.0f; + else data->pitch = (double) HAT.Rot[iPitchAxe]; + } + + if (bEnableRoll) { + if (bInvertRoll) data->roll = (double) HAT.Rot[iRollAxe] * -1.0f; + else data->roll = (double) HAT.Rot[iRollAxe]; + } + + if (bEnableX) { + if (bInvertX) data->x = (double) HAT.Trans[iXAxe]* -1.0f; + else data->x = (double) HAT.Trans[iXAxe]; + } + + if (bEnableY) { + if (bInvertY) data->y = (double) HAT.Trans[iYAxe]* -1.0f; + else data->y = (double) HAT.Trans[iYAxe]; + } + + if (bEnableZ) { + if (bInvertZ) data->z = (double) HAT.Trans[iZAxe]* -1.0f; + else data->z = (double) HAT.Trans[iZAxe]; + } + return true; +#endif + new_frame=false; + // For debug + //data->x=dataRead.length(); + //data->y=CptError; + } +} + + + +// +// Apply modification Settings +// +void FTNoIR_Tracker::applysettings(const TrackerSettings& settings){ + QMutexLocker lck(&mutex); + sSerialPortName= settings.SerialPortName; + + bEnableRoll = settings.EnableRoll; + bEnablePitch = settings.EnablePitch; + bEnableYaw = settings.EnableYaw; + bEnableX = settings.EnableX; + bEnableY = settings.EnableY; + bEnableZ = settings.EnableZ; + + bInvertRoll = settings.InvertRoll; + bInvertPitch = settings.InvertPitch; + bInvertYaw = settings.InvertYaw; + bInvertX = settings.InvertX; + bInvertY = settings.InvertY; + bInvertZ = settings.InvertZ; + bEnableLogging = settings.EnableLogging; + + iRollAxe= settings.RollAxe; + iPitchAxe= settings.PitchAxe; + iYawAxe= settings.YawAxe; + iXAxe= settings.XAxe; + iYAxe= settings.YAxe; + iZAxe= settings.ZAxe; + + iBaudRate=settings.pBaudRate; + iDataBits=settings.pDataBits; + iParity=settings.pParity; + iStopBits=settings.pStopBits; + iFlowControl=settings.pFlowControl; + + sCmdStart= settings.CmdStart.toLatin1(); + sCmdStop= settings.CmdStop.toLatin1(); + sCmdInit= settings.CmdInit.toLatin1(); + sCmdReset= settings.CmdReset.toLatin1(); + sCmdCenter= settings.CmdCenter.toLatin1(); + sCmdZero= settings.CmdZero.toLatin1(); + + iDelayInit=settings.DelayInit; + iDelayStart=settings.DelayStart; + iDelaySeq=settings.DelaySeq; + + bBigEndian=settings.BigEndian; +#ifdef OPENTRACK_API + iFpsArduino=settings.FPSArduino; +#endif +} + +void FTNoIR_Tracker::Log(QString message) +{ + // Drop out immediately if logging is off. Yes, there is still some overhead because of passing strings around for no reason. + // that's unfortunate and I'll monitor the impact and see if it needs a more involved fix. + if (!bEnableLogging) return; + QString logMessage; + + if (flDiagnostics.open(QIODevice::ReadWrite | QIODevice::Append)) + { + QTextStream out(&flDiagnostics); + QString milliSeconds; + milliSeconds = QString("%1").arg(QTime::currentTime().msec(), 3, 10, QChar('0')); + // We have a file + out << QTime::currentTime().toString() << "." << milliSeconds << ": " << message << "\r\n"; + flDiagnostics.close(); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Factory function that creates instances if the Tracker object. + +// Export both decorated and undecorated names. +// GetTracker - Undecorated name, which can be easily used with GetProcAddress +// Win32 API function. +// _GetTracker@0 - Common name decoration for __stdcall functions in C language. +//////////////////////////////////////////////////////////////////////////////// +#ifdef OPENTRACK_API +#include "ftnoir_tracker_hat_dialog.h" +OPENTRACK_DECLARE_TRACKER(FTNoIR_Tracker, TrackerControls, TrackerDll) +#else +#pragma comment(linker, "/export:GetTracker=_GetTracker@0") +FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker() +{ + return new FTNoIR_Tracker; +} +#endif + diff --git a/tracker-hatire/ftnoir_tracker_hat.h b/tracker-hatire/ftnoir_tracker_hat.h new file mode 100644 index 00000000..2472428b --- /dev/null +++ b/tracker-hatire/ftnoir_tracker_hat.h @@ -0,0 +1,157 @@ +#ifndef FTNOIR_TRACKER_HAT_H +#define FTNOIR_TRACKER_HAT_H + +#ifdef OPENTRACK_API +# include "opentrack/plugin-support.hpp" +#else +# include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#endif +#include "ftnoir_tracker_hat_settings.h" +#include "ftnoir_arduino_type.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VER_FILEVERSION_STR "Version 2.1.1\0" + +class FTNoIR_Tracker : public QObject, public ITracker +{ + Q_OBJECT +public: + FTNoIR_Tracker(); + ~FTNoIR_Tracker(); + +#ifdef OPENTRACK_API + void start_tracker(QFrame*); + void data(double *data); + int preferredHz(); // unused + void center(); // unused +#else + void Initialize( QFrame *videoframe ); + void StartTracker(HWND parent_window); + void StopTracker(bool exit); + bool GiveHeadPoseData(THeadPoseData *data); + void notifyCenter(); +#endif + void applysettings(const TrackerSettings& settings); + bool notifyZeroed(); + void reset(); + void SerialInfo(); + void sendcmd(const QByteArray &cmd); + void get_info( int *tps ); + +private Q_SLOTS: + void SerialRead(); + void Log(QString message); + +signals: + void sendMsgInfo(const QByteArray &MsgInfo); + + +private: + QSerialPort *ComPort; + TArduinoData ArduinoData, HAT ; // Trame from Arduino + QByteArray dataRead; + QByteArray dataToSend; + QByteArray Begin; + QByteArray End; + QMutex mutex; + int frame_cnt; + bool new_frame; + + TrackerSettings settings; + + bool bEnableRoll; + bool bEnablePitch; + bool bEnableYaw; + bool bEnableX; + bool bEnableY; + bool bEnableZ; + + bool bInvertRoll; + bool bInvertPitch; + bool bInvertYaw; + bool bInvertX; + bool bInvertY; + bool bInvertZ; + bool bEnableLogging; + + int iRollAxe; + int iPitchAxe; + int iYawAxe; + int iXAxe; + int iYAxe; + int iZAxe; + + QByteArray sCmdStart; + QByteArray sCmdStop; + QByteArray sCmdInit; + QByteArray sCmdReset; + QByteArray sCmdCenter; + QByteArray sCmdZero; + + int iDelayInit; + int iDelayStart; + int iDelaySeq; + + bool bBigEndian; + + QString sSerialPortName; + QSerialPort::BaudRate iBaudRate; + QSerialPort::DataBits iDataBits; + QSerialPort::Parity iParity; + QSerialPort::StopBits iStopBits; + QSerialPort::FlowControl iFlowControl; + + QFile flDiagnostics; +#ifdef OPENTRACK_API + int iFpsArduino; +#endif + int CptError; + + +}; + + +//******************************************************************************************************* +// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker +//******************************************************************************************************* +#if defined(OPENTRACK_API) +class TrackerDll : public Metadata +{ + QString name() { return QString("Hatire Arduino"); } + QIcon icon() { return QIcon(":/images/hat.png"); } +}; +#else +class TrackerDll : +public Metadata +public ITrackerDll +{ +public: + TrackerDll(); + ~TrackerDll(); + + void Initialize(); + + QString name(); + QIcon icon(); + void getFullName(QString *strToBeFilled); + void getShortName(QString *strToBeFilled); + void getDescription(QString *strToBeFilled); + void getIcon(QIcon *icon); + +private: + QString trackerFullName; // Trackers' name and description + QString trackerShortName; + QString trackerDescription; +}; +#endif + +#endif // FTNOIR_TRACKER_HAT_H diff --git a/tracker-hatire/ftnoir_tracker_hat_dialog.cpp b/tracker-hatire/ftnoir_tracker_hat_dialog.cpp new file mode 100644 index 00000000..3ef1a764 --- /dev/null +++ b/tracker-hatire/ftnoir_tracker_hat_dialog.cpp @@ -0,0 +1,411 @@ +/* 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_tracker_hat.h" +#include "ftnoir_tracker_hat_dialog.h" + +#include + +//******************************************************************************************************* +// FaceTrackNoIR Client Settings-dialog. +//******************************************************************************************************* + +// +// Constructor for server-settings-dialog +// +TrackerControls::TrackerControls() : theTracker(NULL), settingsDirty(false), timer(this) +{ + + ui.setupUi( this ); + settings.load_ini(); + + ui.label_version->setText(VER_FILEVERSION_STR); + + // make SerialPort list + ui.cbSerialPort->clear(); + foreach (QSerialPortInfo PortInfo , QSerialPortInfo::availablePorts() ) { + ui.cbSerialPort->addItem(PortInfo.portName()); + } + + + // Stop if no SerialPort dispo + if (ui.cbSerialPort->count()<1) { + QMessageBox::critical(this,"Error", "No SerialPort avaible"); + } else { + + int indxport =ui.cbSerialPort->findText(settings.SerialPortName,Qt::MatchExactly ); + if (indxport!=-1) { + ui.cbSerialPort->setCurrentIndex(indxport); + } else { + if (settings.SerialPortName != "") + QMessageBox::warning(this,"Error", "Selected SerialPort modified"); + ui.cbSerialPort-> setCurrentIndex(indxport); + } + } + // Serial config + ui.QCB_Serial_baudRate->clear(); + ui.QCB_Serial_baudRate->addItem(QLatin1String("9600"),QSerialPort::Baud9600); + ui.QCB_Serial_baudRate->addItem(QLatin1String("19200"),QSerialPort::Baud19200); + ui.QCB_Serial_baudRate->addItem(QLatin1String("38400"),QSerialPort::Baud38400); + ui.QCB_Serial_baudRate->addItem(QLatin1String("57600"),QSerialPort:: Baud57600); + ui.QCB_Serial_baudRate->addItem(QLatin1String("115200"),QSerialPort::Baud115200); + ui.QCB_Serial_baudRate->setCurrentIndex(ui.QCB_Serial_baudRate->findData(settings.pBaudRate)); + + ui.QCB_Serial_dataBits->clear(); + ui.QCB_Serial_dataBits->addItem(QLatin1String("5"), QSerialPort::Data5); + ui.QCB_Serial_dataBits->addItem(QLatin1String("6"), QSerialPort::Data6); + ui.QCB_Serial_dataBits->addItem(QLatin1String("7"), QSerialPort::Data7); + ui.QCB_Serial_dataBits->addItem(QLatin1String("8"), QSerialPort::Data8); + ui.QCB_Serial_dataBits->setCurrentIndex(ui.QCB_Serial_dataBits->findData(settings.pDataBits)); + + ui.QCB_Serial_parity->clear(); + ui.QCB_Serial_parity->addItem(QLatin1String("None"), QSerialPort::NoParity); + ui.QCB_Serial_parity->addItem(QLatin1String("Even"), QSerialPort::EvenParity); + ui.QCB_Serial_parity->addItem(QLatin1String("Odd"), QSerialPort::OddParity); + ui.QCB_Serial_parity->addItem(QLatin1String("Space"), QSerialPort::SpaceParity); + ui.QCB_Serial_parity->addItem(QLatin1String("Mark"), QSerialPort::MarkParity); + ui.QCB_Serial_parity->setCurrentIndex(ui.QCB_Serial_parity->findData(settings.pParity)); + + ui.QCB_Serial_stopBits->clear(); + ui.QCB_Serial_stopBits->addItem(QLatin1String("1"), QSerialPort::OneStop); + ui.QCB_Serial_stopBits->addItem(QLatin1String("1.5"), QSerialPort::OneAndHalfStop); + ui.QCB_Serial_stopBits->addItem(QLatin1String("2"), QSerialPort::TwoStop); + ui.QCB_Serial_stopBits->setCurrentIndex(ui.QCB_Serial_stopBits->findData(settings.pStopBits)); + + + ui.QCB_Serial_flowControl->clear(); + ui.QCB_Serial_flowControl->addItem(QLatin1String("None"), QSerialPort::NoFlowControl); + ui.QCB_Serial_flowControl->addItem(QLatin1String("RTS/CTS"), QSerialPort::HardwareControl); + ui.QCB_Serial_flowControl->addItem(QLatin1String("XON/XOFF"), QSerialPort::SoftwareControl); + ui.QCB_Serial_flowControl->setCurrentIndex(ui.QCB_Serial_flowControl->findData(settings.pFlowControl)); + + + ui.chkEnableRoll->setChecked(settings.EnableRoll); + ui.chkEnablePitch->setChecked(settings.EnablePitch); + ui.chkEnableYaw->setChecked(settings.EnableYaw); + ui.chkEnableX->setChecked(settings.EnableX); + ui.chkEnableY->setChecked(settings.EnableY); + ui.chkEnableZ->setChecked(settings.EnableZ); + + ui.chkInvertRoll->setChecked(settings.InvertRoll); + ui.chkInvertPitch->setChecked(settings.InvertPitch); + ui.chkInvertYaw->setChecked(settings.InvertYaw); + ui.chkInvertX->setChecked(settings.InvertX); + ui.chkInvertY->setChecked(settings.InvertY); + ui.chkInvertZ->setChecked(settings.InvertZ); + + ui.chkEnableLogging->setChecked(settings.EnableLogging); + + + ui.cb_roll->setCurrentIndex(settings.RollAxe); + ui.cb_pitch->setCurrentIndex(settings.PitchAxe); + ui.cb_yaw->setCurrentIndex(settings.YawAxe); + ui.cb_x->setCurrentIndex(settings.XAxe); + ui.cb_y->setCurrentIndex(settings.YAxe); + ui.cb_z->setCurrentIndex(settings.ZAxe); + + ui.le_cmd_start->setText(settings.CmdStart); + ui.le_cmd_stop->setText(settings.CmdStop); + ui.le_cmd_init->setText(settings.CmdInit); + ui.le_cmd_reset->setText(settings.CmdReset); + ui.le_cmd_center->setText(settings.CmdCenter); + ui.le_cmd_zero->setText(settings.CmdZero); + + ui.spb_BeforeInit->setValue(settings.DelayInit); + ui.spb_BeforeStart->setValue(settings.DelayStart); + ui.spb_AfterStart->setValue(settings.DelaySeq); + + ui.cb_Endian->setChecked(settings.BigEndian); + +#ifdef OPENTRACK_API + ui.spb_Fps->setValue(settings.FPSArduino); + connect(ui.spb_Fps, SIGNAL(valueChanged ( int )), this,SLOT(set_Fps(int))); +#endif + + // Connect Qt signals to member-functions + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); + connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(doSave())); + + + connect(ui.cbSerialPort, SIGNAL(currentIndexChanged(QString)), this,SLOT(set_mod_port(QString)) ); + + connect( ui.chkEnableRoll,SIGNAL(toggled(bool)), this,SLOT(set_ena_roll(bool)) ); + connect( ui.chkEnablePitch,SIGNAL(toggled(bool)), this,SLOT(set_ena_pitch(bool)) ); + connect( ui.chkEnableYaw,SIGNAL(toggled(bool)), this,SLOT(set_ena_yaw(bool)) ); + connect( ui.chkEnableX,SIGNAL(toggled(bool)), this,SLOT(set_ena_x(bool)) ); + connect( ui.chkEnableY,SIGNAL(toggled(bool)), this,SLOT(set_ena_y(bool)) ); + connect( ui.chkEnableZ,SIGNAL(toggled(bool)), this,SLOT(set_ena_z(bool)) ); + + connect( ui.chkInvertRoll,SIGNAL(toggled(bool)), this,SLOT(set_inv_roll(bool)) ); + connect( ui.chkInvertPitch,SIGNAL(toggled(bool)), this,SLOT(set_inv_pitch(bool)) ); + connect( ui.chkInvertYaw,SIGNAL(toggled(bool)), this,SLOT(set_inv_yaw(bool)) ); + connect( ui.chkInvertX,SIGNAL(toggled(bool)), this,SLOT(set_inv_x(bool)) ); + connect( ui.chkInvertY,SIGNAL(toggled(bool)), this,SLOT(set_inv_y(bool)) ); + connect( ui.chkInvertZ,SIGNAL(toggled(bool)), this,SLOT(set_inv_z(bool)) ); + connect( ui.chkEnableLogging,SIGNAL(toggled(bool)), this,SLOT(set_diag_logging(bool)) ); + + connect(ui.cb_roll, SIGNAL(currentIndexChanged(int)), this,SLOT(set_rot_roll(int))); + connect(ui.cb_pitch, SIGNAL(currentIndexChanged(int)),this,SLOT(set_rot_pitch(int))); + connect(ui.cb_yaw, SIGNAL(currentIndexChanged(int)), this,SLOT(set_rot_yaw(int))); + connect(ui.cb_x, SIGNAL(currentIndexChanged(int)), this,SLOT(set_acc_x(int))); + connect(ui.cb_y, SIGNAL(currentIndexChanged(int)), this,SLOT(set_acc_y(int))); + connect(ui.cb_z, SIGNAL(currentIndexChanged(int)), this,SLOT(set_acc_z(int))); + + connect(ui.le_cmd_start, SIGNAL(textEdited (QString )), this,SLOT(set_cmd_start(QString))); + connect(ui.le_cmd_stop, SIGNAL(textEdited ( QString )), this,SLOT(set_cmd_stop(QString))); + connect(ui.le_cmd_init, SIGNAL(textChanged ( QString )), this,SLOT(set_cmd_init(QString))); + connect(ui.le_cmd_reset, SIGNAL(textChanged ( QString )), this,SLOT(set_cmd_reset(QString))); + connect(ui.le_cmd_center, SIGNAL(textChanged ( QString )),this,SLOT(set_cmd_center(QString))); + connect(ui.le_cmd_zero, SIGNAL(textChanged ( QString )),this,SLOT(set_cmd_zero(QString))); + + connect(ui.spb_BeforeInit, SIGNAL(valueChanged ( int )), this,SLOT(set_DelayInit(int))); + connect(ui.spb_BeforeStart, SIGNAL(valueChanged ( int )), this,SLOT(set_DelayStart(int))); + connect(ui.spb_AfterStart, SIGNAL(valueChanged ( int )), this,SLOT(set_DelaySeq(int))); + + connect( ui.cb_Endian,SIGNAL(toggled(bool)), this,SLOT(set_endian(bool)) ); + + + connect(ui.QCB_Serial_baudRate, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_baud(int)) ); + connect(ui.QCB_Serial_dataBits, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_dataBits(int)) ); + connect(ui.QCB_Serial_parity, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_parity(int)) ); + connect(ui.QCB_Serial_stopBits, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_stopBits(int)) ); + connect(ui.QCB_Serial_flowControl, SIGNAL(currentIndexChanged(int)), this,SLOT(set_mod_flowControl(int)) ); + + connect(ui.btnReset, SIGNAL(clicked()), this, SLOT(doReset())); + connect(ui.btnCenter, SIGNAL(clicked()), this, SLOT(doCenter())); + connect(ui.btnZero, SIGNAL(clicked()), this, SLOT(doZero())); + connect(ui.btnSend, SIGNAL(clicked()), this, SLOT(doSend())); + + connect(ui.btn_icone, SIGNAL(clicked()), this, SLOT(doSerialInfo())); + + connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info())); + + // can't connect slot, keyPressEvent takes QKeyPressEvent as argument + //connect(ui.lineSend,SIGNAL(keyPressEvent),this,SLOT(on_lineSend_returnPressed()) ); +} + +// +// Destructor for server-dialog +// +TrackerControls::~TrackerControls() { +} + +// +// Initialize tracker-client-dialog +// +void TrackerControls::Initialize(QWidget *parent) { + QPoint offsetpos(100, 100); + if (parent) { + this->move(parent->pos() + offsetpos); + } + show(); +} + + + +// +// Apply online settings to tracker +// +void TrackerControls::settings_changed() +{ + settingsDirty = true; + if (theTracker) theTracker->applysettings(settings); +} + + +// +// Center asked to ARDUINO +// +void TrackerControls::doCenter() { +#ifdef OPENTRACK_API + if (theTracker) theTracker->center(); +#else + if (theTracker) theTracker->notifyCenter(); +#endif +} + + +// +// Zero asked to ARDUINO +// +void TrackerControls::doZero() { + if (theTracker) theTracker->notifyZeroed(); +} + + +// +// Reset asked to ARDUINO +// +void TrackerControls::doReset() { + if (theTracker) theTracker->reset(); +} + + +// +// Serial Info debug +// +void TrackerControls::doSerialInfo() { + if (theTracker) theTracker->SerialInfo(); +} + + +// +// Send command to ARDUINO +// +void TrackerControls::doSend() { + if (theTracker) { + if (!ui.lineSend->text().isEmpty()) { + theTracker->sendcmd(ui.lineSend->text().toLatin1()); + } + } +} + + +// +// Enter on lineSend for send to ARDUINO +// +void TrackerControls::on_lineSend_returnPressed() +{ + this->doSend(); + +} + + +// +// Display FPS of Arduino. +// +void TrackerControls::poll_tracker_info() +{ + if (theTracker) + { + int nb_trame; + + theTracker->get_info(&nb_trame); + ui.lab_vtps->setText(QString::number(nb_trame*(1000/last_time.elapsed()))); + last_time.restart(); + } + +} + + +void TrackerControls::WriteMsgInfo(const QByteArray &MsgInfo) +{ + QApplication::beep(); + ui.pteINFO->moveCursor(QTextCursor::End); + ui.pteINFO->insertPlainText(QString(MsgInfo)); + QScrollBar *bar = ui.pteINFO->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + + + +void TrackerControls::doSave() { + settingsDirty=false; + settings.save_ini(); +} + + +// +// OK clicked on server-dialog +// +void TrackerControls::doOK() { + settingsDirty=false; + settings.save_ini(); + this->close(); +} + +// +// Cancel clicked on server-dialog +// +void TrackerControls::doCancel() { + // + // Ask if changed Settings should be saved + // + if (settingsDirty) { + int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); + switch (ret) { + case QMessageBox::Save: + settings.save_ini(); + close(); + break; + case QMessageBox::Discard: + close(); + break; + case QMessageBox::Cancel: + // Cancel was clicked + break; + default: + // should never be reached + break; + } + } + else { + close(); + } +} + +#ifdef OPENTRACK_API +void TrackerControls::register_tracker(ITracker *tracker) +#else +void TrackerControls::registerTracker(ITracker *tracker) +#endif +{ + theTracker = static_cast(tracker); + connect(theTracker, SIGNAL(sendMsgInfo(QByteArray)),this , SLOT(WriteMsgInfo(QByteArray))); + + if (isVisible() && settingsDirty) theTracker->applysettings(settings); + + ui.cbSerialPort->setEnabled(false); + ui.btnZero->setEnabled(true); + ui.btnCenter->setEnabled(true); + ui.btnReset->setEnabled(true); + ui.pteINFO->clear(); + ui.lab_vstatus->setText("HAT START"); + last_time.start(); + timer.start(250); + +} + +#ifdef OPENTRACK_API +void TrackerControls::unregister_tracker() +#else +void TrackerControls::unRegisterTracker() +#endif +{ + timer.stop(); + theTracker=NULL; + ui.cbSerialPort->setEnabled(true); + ui.btnZero->setEnabled(false); + ui.btnCenter->setEnabled(false); + ui.btnReset->setEnabled(false); + ui.lab_vstatus->setText("HAT STOPPED"); + ui.lab_vtps->setText(""); +} + + + + +//////////////////////////////////////////////////////////////////////////////// +// Factory function that creates instances if the Tracker-settings dialog object. + +// Export both decorated and undecorated names. +// GetTrackerDialog - Undecorated name, which can be easily used with GetProcAddress +// Win32 API function. +// _GetTrackerDialog@0 - Common name decoration for __stdcall functions in C language. +#ifdef OPENTRACK_API +#else +#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") +FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( ) +{ + return new TrackerControls; +} +#endif + diff --git a/tracker-hatire/ftnoir_tracker_hat_dialog.h b/tracker-hatire/ftnoir_tracker_hat_dialog.h new file mode 100644 index 00000000..ebaffc6d --- /dev/null +++ b/tracker-hatire/ftnoir_tracker_hat_dialog.h @@ -0,0 +1,116 @@ +#ifndef FTNOIR_TRACKER_HAT_DIALOG_H +#define FTNOIR_TRACKER_HAT_DIALOG_H + +#ifdef OPENTRACK_API +#include "opentrack/plugin-api.hpp" +#else +#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#endif +#include "ftnoir_tracker_hat_settings.h" +#include "ftnoir_tracker_hat.h" +#include "ui_ftnoir_hatcontrols.h" +#include +#include +#include +#include +#include +#include + +// Widget that has controls for FTNoIR protocol client-settings. +#ifdef OPENTRACK_API +class TrackerControls: public ITrackerDialog + #else +class TrackerControls: public QWidget, public ITrackerDialog + #endif +{ + Q_OBJECT +public: + explicit TrackerControls(); + ~TrackerControls() override; +#ifdef OPENTRACK_API + void Initialize(QWidget *parent) ; // unused + void register_tracker(ITracker *tracker); + void unregister_tracker(); +#else + void Initialize(QWidget *parent) ; + void registerTracker(ITracker *tracker) ; + void unRegisterTracker() ; +#endif + +private: + Ui::UIHATControls ui; + FTNoIR_Tracker *theTracker; + QTime last_time; + +public slots: + void WriteMsgInfo(const QByteArray &MsgInfo); + +protected slots: + void set_mod_port(const QString & val) { settings.SerialPortName =val; settings_changed(); } + void set_ena_roll(bool val) { settings.EnableRoll = val; settings_changed(); } + void set_ena_pitch(bool val) { settings.EnablePitch = val; settings_changed(); } + void set_ena_yaw(bool val) { settings.EnableYaw = val; settings_changed(); } + void set_ena_x(bool val) { settings.EnableX = val; settings_changed(); } + void set_ena_y(bool val) { settings.EnableY = val; settings_changed(); } + void set_ena_z(bool val) { settings.EnableZ = val; settings_changed(); } + + void set_inv_roll(bool val) { settings.InvertRoll = val; settings_changed(); } + void set_inv_pitch(bool val) { settings.InvertPitch = val; settings_changed(); } + void set_inv_yaw(bool val) { settings.InvertYaw = val; settings_changed(); } + void set_inv_x(bool val) { settings.InvertX = val; settings_changed(); } + void set_inv_y(bool val) { settings.InvertY = val; settings_changed(); } + void set_inv_z(bool val) { settings.InvertZ = val; settings_changed(); } + + void set_diag_logging(bool val) { settings.EnableLogging = val; settings_changed(); } + + + void set_rot_roll(int val) { settings.RollAxe = val; settings_changed(); } + void set_rot_pitch(int val) { settings.PitchAxe = val; settings_changed(); } + void set_rot_yaw(int val) { settings.YawAxe = val; settings_changed(); } + void set_acc_x(int val) { settings.XAxe = val; settings_changed(); } + void set_acc_y(int val) { settings.YAxe = val; settings_changed(); } + void set_acc_z(int val) { settings.ZAxe = val; settings_changed(); } + + void set_cmd_start(const QString &val) { settings.CmdStart = val; settings_changed(); } + void set_cmd_stop(const QString &val) { settings.CmdStop = val; settings_changed(); } + void set_cmd_init(const QString &val) { settings.CmdInit = val; settings_changed(); } + void set_cmd_reset(const QString &val) { settings.CmdReset = val; settings_changed(); } + void set_cmd_center(const QString &val) { settings.CmdCenter = val; settings_changed(); } + void set_cmd_zero(const QString &val) { settings.CmdZero = val; settings_changed(); } + + void set_DelayInit(int val) { settings.DelayInit = val; settings_changed(); } + void set_DelayStart(int val) { settings.DelayStart = val; settings_changed(); } + void set_DelaySeq(int val) { settings.DelaySeq = val; settings_changed(); } + + void set_endian(bool val) { settings.BigEndian = val; settings_changed(); } +#ifdef OPENTRACK_API + void set_Fps(int val) { settings.FPSArduino = val; settings_changed(); } +#endif + + void set_mod_baud(int val) { settings.pBaudRate = static_cast(ui.QCB_Serial_baudRate->itemData(val).toInt()) ; settings_changed(); } + void set_mod_dataBits(int val) { settings.pDataBits = static_cast(ui.QCB_Serial_dataBits->itemData(val).toInt()) ; settings_changed(); } + void set_mod_parity(int val) { settings.pParity = static_cast(ui.QCB_Serial_parity->itemData(val).toInt()) ; settings_changed(); } + void set_mod_stopBits(int val) { settings.pStopBits = static_cast(ui.QCB_Serial_stopBits->itemData(val).toInt()); settings_changed(); } + void set_mod_flowControl(int val) { settings.pFlowControl = static_cast(ui.QCB_Serial_flowControl->itemData(val).toInt()) ; settings_changed(); } + + void doOK(); + void doCancel(); + void doSave(); + void doReset(); + void doCenter(); + void doZero(); + void doSend(); + void poll_tracker_info(); + void doSerialInfo(); + +protected: + bool settingsDirty; + void settings_changed(); + TrackerSettings settings; + QTimer timer; + +private slots: + void on_lineSend_returnPressed(); +}; + +#endif //FTNOIR_TRACKER_HAT_DIALOG_H diff --git a/tracker-hatire/ftnoir_tracker_hat_settings.cpp b/tracker-hatire/ftnoir_tracker_hat_settings.cpp new file mode 100644 index 00000000..e6b32047 --- /dev/null +++ b/tracker-hatire/ftnoir_tracker_hat_settings.cpp @@ -0,0 +1,146 @@ +/* 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 +#include +#include + +#include "ftnoir_tracker_hat_settings.h" +#ifdef OPENTRACK_API +#include "opentrack/options.hpp" +#endif + +void TrackerSettings::load_ini() +{ +#ifndef OPENTRACK_API + QSettings settings(OPENTRACK_ORG); // Registry settings (in HK_USER) + QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); +#else + QString currentFile = options::group::ini_pathname(); +#endif + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup( "HAT" ); + + SerialPortName=iniFile.value ( "PortName" ).toString(); + + EnableRoll = iniFile.value( "EnableRoll", 1 ).toBool(); + EnablePitch = iniFile.value( "EnablePitch", 1 ).toBool(); + EnableYaw = iniFile.value( "EnableYaw", 1 ).toBool(); + EnableX = iniFile.value( "EnableX", 0 ).toBool(); + EnableY = iniFile.value( "EnableY", 0 ).toBool(); + EnableZ = iniFile.value( "EnableZ", 0 ).toBool(); + EnableLogging = iniFile.value( "EnableLogging", 0).toBool(); + + InvertRoll = iniFile.value( "InvertRoll", 1 ).toBool(); + InvertPitch = iniFile.value( "InvertPitch", 1 ).toBool(); + InvertYaw = iniFile.value( "InvertYaw", 1 ).toBool(); + InvertX = iniFile.value( "InvertX", 0 ).toBool(); + InvertY = iniFile.value( "InvertY", 0 ).toBool(); + InvertZ = iniFile.value( "InvertZ", 0 ).toBool(); + + + RollAxe=iniFile.value("RollAxe",1).toInt(); + PitchAxe=iniFile.value("PitchAxe",2).toInt(); + YawAxe=iniFile.value("YawAxe",0).toInt(); + XAxe=iniFile.value("XAxe",1).toInt(); + YAxe=iniFile.value("YAxe",2).toInt(); + ZAxe=iniFile.value("ZAxe",0).toInt(); + + + CmdStart=iniFile.value ( "CmdStart").toString(); + CmdStop=iniFile.value ( "CmdStop" ).toString(); + CmdInit=iniFile.value ( "CmdInit" ).toString(); + CmdReset=iniFile.value ( "CmdReset" ).toString(); + CmdCenter=iniFile.value ( "CmdCenter" ).toString(); + CmdZero=iniFile.value ( "CmdZero" ).toString(); + + DelayInit=iniFile.value("DelayInit",0).toInt(); + DelayStart=iniFile.value("DelayStart",0).toInt(); + DelaySeq=iniFile.value("DelaySeq",0).toInt(); + +#ifdef OPENTRACK_API + FPSArduino=iniFile.value("FPSArduino",30).toInt(); +#endif + BigEndian=iniFile.value("BigEndian",0).toBool(); + + + pBaudRate=static_cast(iniFile.value("BaudRate",QSerialPort::Baud115200).toInt()); + pDataBits=static_cast(iniFile.value("DataBits",QSerialPort::Data8).toInt()); + pParity=static_cast(iniFile.value("Parity",QSerialPort::NoParity).toInt()); + pStopBits=static_cast(iniFile.value("StopBits",QSerialPort::OneStop).toInt()); + pFlowControl=static_cast(iniFile.value("FlowControl",QSerialPort::HardwareControl).toInt()); + + iniFile.endGroup(); +} + +void TrackerSettings::save_ini() const +{ + +#ifndef OPENTRACK_API + QSettings settings(OPENTRACK_ORG); // Registry settings (in HK_USER) + QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); +#else + QString currentFile = options::group::ini_pathname(); +#endif + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup ( "HAT" ); + + iniFile.setValue ( "PortName",SerialPortName ); + + iniFile.setValue( "EnableRoll", EnableRoll ); + iniFile.setValue( "EnablePitch", EnablePitch ); + iniFile.setValue( "EnableYaw", EnableYaw ); + iniFile.setValue( "EnableX", EnableX ); + iniFile.setValue( "EnableY", EnableY ); + iniFile.setValue( "EnableZ", EnableZ ); + iniFile.setValue( "EnableLogging", EnableLogging ); + + iniFile.setValue( "InvertRoll", InvertRoll ); + iniFile.setValue( "InvertPitch", InvertPitch ); + iniFile.setValue( "InvertYaw", InvertYaw ); + iniFile.setValue( "InvertX", InvertX ); + iniFile.setValue( "InvertY", InvertY ); + iniFile.setValue( "InvertZ", InvertZ ); + + iniFile.setValue ( "RollAxe", RollAxe ); + iniFile.setValue ( "PitchAxe", PitchAxe ); + iniFile.setValue ( "YawAxe",YawAxe ); + iniFile.setValue ( "XAxe", XAxe ); + iniFile.setValue ( "YAxe", YAxe ); + iniFile.setValue ( "ZAxe", ZAxe ); + + iniFile.setValue ( "CmdStart",CmdStart.toLatin1()); + iniFile.setValue ( "CmdStop",CmdStop.toLatin1()); + iniFile.setValue ( "CmdInit",CmdInit.toLatin1()); + iniFile.setValue ( "CmdReset",CmdReset.toLatin1()); + iniFile.setValue ( "CmdCenter",CmdCenter.toLatin1() ); + iniFile.setValue ( "CmdZero",CmdZero.toLatin1() ); + + iniFile.setValue ( "DelayInit",DelayInit); + iniFile.setValue ( "DelayStart",DelayStart); + iniFile.setValue ( "DelaySeq",DelaySeq); + +#ifdef OPENTRACK_API + iniFile.setValue ( "FPSArduino", FPSArduino ); +#endif + iniFile.setValue("BigEndian",BigEndian); + + iniFile.setValue("BaudRate",pBaudRate); + iniFile.setValue("DataBits",pDataBits); + iniFile.setValue("Parity",pParity); + iniFile.setValue("StopBits",pStopBits); + iniFile.setValue("FlowControl",pFlowControl); + + + iniFile.endGroup(); +} + diff --git a/tracker-hatire/ftnoir_tracker_hat_settings.h b/tracker-hatire/ftnoir_tracker_hat_settings.h new file mode 100644 index 00000000..ade46d54 --- /dev/null +++ b/tracker-hatire/ftnoir_tracker_hat_settings.h @@ -0,0 +1,68 @@ +/* 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. + */ + +#ifndef FTNOIR_TRACKER_HAT_SETTINGS_H +#define FTNOIR_TRACKER_HAT_SETTINGS_H + +#include + +//----------------------------------------------------------------------------- +struct TrackerSettings +{ + void load_ini(); + void save_ini() const; + + bool EnableRoll; + bool EnablePitch; + bool EnableYaw; + bool EnableX; + bool EnableY; + bool EnableZ; + + bool InvertRoll; + bool InvertPitch; + bool InvertYaw; + bool InvertX; + bool InvertY; + bool InvertZ; + + + int RollAxe; + int PitchAxe; + int YawAxe; + int XAxe; + int YAxe; + int ZAxe; + + QString CmdStart; + QString CmdStop; + QString CmdInit; + QString CmdReset; + QString CmdCenter; + QString CmdZero; + + int DelayInit; + int DelayStart; + int DelaySeq; + + bool BigEndian; + bool EnableLogging; + + QString SerialPortName; + QSerialPort::BaudRate pBaudRate; + QSerialPort::DataBits pDataBits; + QSerialPort::Parity pParity; + QSerialPort::StopBits pStopBits; + QSerialPort::FlowControl pFlowControl; + +#ifdef OPENTRACK_API + int FPSArduino; +#endif +}; + + +#endif //FTNOIR_TRACKER_HAT_SETTINGS_H diff --git a/tracker-hatire/images/hat.ico b/tracker-hatire/images/hat.ico new file mode 100644 index 00000000..d8f5aac4 Binary files /dev/null and b/tracker-hatire/images/hat.ico differ diff --git a/tracker-hatire/images/hat.png b/tracker-hatire/images/hat.png new file mode 100644 index 00000000..a5f7852f Binary files /dev/null and b/tracker-hatire/images/hat.png differ diff --git a/tracker-hatire/images/hat_logo.png b/tracker-hatire/images/hat_logo.png new file mode 100644 index 00000000..c3a92b1b Binary files /dev/null and b/tracker-hatire/images/hat_logo.png differ diff --git a/tracker-ht/CMakeLists.txt b/tracker-ht/CMakeLists.txt new file mode 100644 index 00000000..74fd9056 --- /dev/null +++ b/tracker-ht/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SDK_HT "" CACHE FILEPATH "Path to headtracker library") +set(SDK_HT_FLANDMARK "" CACHE FILEPATH "Path to flandmark library for headtracker") +find_package(OpenCV 3.0) +if(OpenCV_FOUND) + if(SDK_HT AND SDK_HT_FLANDMARK) + opentrack_boilerplate(opentrack-tracker-ht) + target_link_libraries(opentrack-tracker-ht ${SDK_HT} ${SDK_HT_FLANDMARK} ${OpenCV_LIBS}) + link_with_dinput8(opentrack-tracker-ht) + target_include_directories(opentrack-tracker-ht SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) + endif() +endif() diff --git a/tracker-ht/ftnoir_tracker_ht.cpp b/tracker-ht/ftnoir_tracker_ht.cpp new file mode 100644 index 00000000..cc9d2ba1 --- /dev/null +++ b/tracker-ht/ftnoir_tracker_ht.cpp @@ -0,0 +1,225 @@ +#include "headtracker-ftnoir.h" +#include "ftnoir_tracker_ht.h" +#include "ui_ht-trackercontrols.h" +#include "opentrack/plugin-api.hpp" +#include +#include "opentrack/camera-names.hpp" +#include "opentrack-compat/sleep.hpp" + +typedef struct { + int width; + int height; +} resolution_tuple; + +static resolution_tuple resolution_choices[] = { + { 640, 480 }, + { 320, 240 }, + { 320, 200 }, + { 0, 0 } +}; + +void Tracker::load_settings(ht_config_t* config) +{ + int nframes = 0; + switch (static_cast(s.fps)) + { + default: + case 0: + nframes = 0; + break; + case 1: + nframes = 30; + break; + case 2: + nframes = 60; + break; + case 3: + nframes = 120; + break; + case 4: + nframes = 180; + break; + } + + config->classification_delay = 500; + config->field_of_view = s.fov; + config->max_keypoints = 150; + config->keypoint_distance = 3.5; + config->force_fps = nframes; + config->camera_index = camera_name_to_index(s.camera_name); + + config->ransac_max_reprojection_error = 25; + config->ransac_max_inlier_error = config->ransac_max_reprojection_error; + + 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 = 1; + config->ransac_min_features = 0.95; + 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 = 50; + for (int i = 0; i < 5; i++) + config->dist_coeffs[i] = 0; +} + +Tracker::Tracker() : + ht(nullptr), + ypr {0,0,0, 0,0,0}, + videoWidget(nullptr), + layout(nullptr), + should_stop(false) +{ +} + +Tracker::~Tracker() +{ + should_stop = true; + wait(); + ht_free_context(ht); + if (layout) + delete layout; + if (videoWidget) + delete videoWidget; +} + +void Tracker::start_tracker(QFrame* videoframe) +{ + videoframe->show(); + videoWidget = new HTVideoWidget(videoframe); + QHBoxLayout* layout = new QHBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(videoWidget); + if (videoframe->layout()) + delete videoframe->layout(); + videoframe->setLayout(layout); + videoWidget->show(); + this->layout = layout; + + 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(y, x); + const cv::Scalar elt2 = static_cast(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; + } + } + } + // give opencv time to exit camera threads, etc. + portable::sleep(500); +} + +void Tracker::data(double* data) +{ + { + QMutexLocker l(&frame_mtx); + + if (frame.width > 0) + { + videoWidget->update_image(frame.frame, frame.width, frame.height); + frame.width = 0; + } + } + + { + QMutexLocker l(&ypr_mtx); + + for (int i = 0; i < 6; i++) + data[i] = ypr[i]; + } +} + +TrackerControls::TrackerControls() : tracker(nullptr) +{ + ui.setupUi(this); + ui.cameraName->clear(); + QList names = get_camera_names(); + names.prepend("Any available"); + ui.cameraName->addItems(names); + tie_setting(s.camera_name, ui.cameraName); + tie_setting(s.fps, ui.cameraFPS); + tie_setting(s.fov, ui.cameraFOV); + tie_setting(s.resolution, ui.resolution); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings())); +} + +void TrackerControls::doOK() +{ + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() +{ + s.b->reload(); + this->close(); +} + +void TrackerControls::camera_settings() +{ + 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); +} + +OPENTRACK_DECLARE_TRACKER(Tracker, TrackerControls, TrackerDll) diff --git a/tracker-ht/ftnoir_tracker_ht.h b/tracker-ht/ftnoir_tracker_ht.h new file mode 100644 index 00000000..1e364456 --- /dev/null +++ b/tracker-ht/ftnoir_tracker_ht.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2013 Stanislaw Halik + * + * 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 "headtracker-ftnoir.h" +#include "ui_ht-trackercontrols.h" +#include "ht_video_widget.h" +#include "opentrack-compat/shm.h" +#include +#include "opentrack/options.hpp" +#include "opentrack/plugin-api.hpp" +#include "opentrack/opencv-camera-dialog.hpp" + +#include +#include +#include +#include +#include + +using namespace options; + +struct settings : opts { + value fov; + value camera_name; + value fps, resolution; + settings() : + opts("HT-Tracker"), + fov(b, "fov", 56), + camera_name(b, "camera-name", ""), + fps(b, "fps", 0), + resolution(b, "resolution", 0) + {} +}; + +class Tracker : public QThread, public ITracker +{ + Q_OBJECT +public: + Tracker(); + ~Tracker() override; + void run() override; + void start_tracker(QFrame* frame) override; + void data(double *data) override; + void load_settings(ht_config_t* config); + headtracker_t* ht; + QMutex camera_mtx; +private: + double ypr[6]; + settings s; + ht_config_t conf; + HTVideoWidget* videoWidget; + QHBoxLayout* layout; + QMutex ypr_mtx, frame_mtx; + ht_video_t frame; + volatile bool should_stop; +}; + +class TrackerControls : public ITrackerDialog, protected camera_dialog +{ + Q_OBJECT +public: + TrackerControls(); + void register_tracker(ITracker * t) override + { + tracker = static_cast(t); + } + void unregister_tracker() override + { + tracker = nullptr; + } +private: + Ui::Form ui; + settings s; + Tracker* tracker; +private slots: + void doOK(); + void doCancel(); + void camera_settings(); +}; + +class TrackerDll : public Metadata +{ + QString name() { return QString("ht -- face tracker"); } + QIcon icon() { return QIcon(":/images/ht.png"); } +}; diff --git a/tracker-ht/headtracker-ftnoir.h b/tracker-ht/headtracker-ftnoir.h new file mode 100644 index 00000000..9a343bae --- /dev/null +++ b/tracker-ht/headtracker-ftnoir.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include "ht-api.h" + +#define HT_SHM_NAME "ftnoir-tracker-ht-shm" +#define HT_MUTEX_NAME "ftnoir-tracker-ht-mutex" + +#define HT_MAX_VIDEO_WIDTH 640 +#define HT_MAX_VIDEO_HEIGHT 480 +#define HT_MAX_VIDEO_CHANNELS 3 + +typedef struct { + int width, height, channels; + unsigned char frame[HT_MAX_VIDEO_WIDTH * HT_MAX_VIDEO_HEIGHT * HT_MAX_VIDEO_CHANNELS]; +} ht_video_t; + +typedef struct { + ht_video_t frame; + ht_config_t config; + ht_result_t result; + volatile int timer; + volatile bool pause, terminate, running; +} ht_shm_t; diff --git a/tracker-ht/ht-api.h b/tracker-ht/ht-api.h new file mode 100644 index 00000000..4629a00b --- /dev/null +++ b/tracker-ht/ht-api.h @@ -0,0 +1,51 @@ +#pragma once +#ifndef HT_API +# if defined(_WIN32) && !defined(MINGW) +# define HT_API(t) __declspec(dllexport) t __stdcall +# else +# define HT_API(t) t +# endif +#endif +#if !defined(_WIN32) && !defined(_isnan) +# define _isnan isnan +#endif +#include +#include +struct ht_context; +typedef struct ht_context headtracker_t; + +typedef struct ht_config { + float field_of_view; + float classification_delay; + int pyrlk_pyramids; + int pyrlk_win_size_w; + int pyrlk_win_size_h; + float ransac_max_inlier_error; + float ransac_max_reprojection_error; + int max_keypoints; + float keypoint_distance; + int force_width; + int force_height; + int force_fps; + int camera_index; + bool debug; + int ransac_num_iters; + float ransac_min_features; + float ransac_max_mean_error; + float ransac_abs_max_mean_error; + float flandmark_delay; + double dist_coeffs[5]; +} ht_config_t; + +typedef struct { + double rotx, roty, rotz; + double tx, ty, tz; + bool filled; +} ht_result_t; + +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(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/tracker-ht/ht-tracker.qrc b/tracker-ht/ht-tracker.qrc new file mode 100644 index 00000000..b6af7a18 --- /dev/null +++ b/tracker-ht/ht-tracker.qrc @@ -0,0 +1,5 @@ + + + images/ht.png + + diff --git a/tracker-ht/ht-trackercontrols.ui b/tracker-ht/ht-trackercontrols.ui new file mode 100644 index 00000000..29b80c8d --- /dev/null +++ b/tracker-ht/ht-trackercontrols.ui @@ -0,0 +1,157 @@ + + + Form + + + Qt::NonModal + + + + 0 + 0 + 354 + 179 + + + + + 0 + 0 + + + + + 750 + 280 + + + + HT tracker settings + + + + + + Frames per second + + + + + + + + + + 35.000000000000000 + + + 180.000000000000000 + + + 52.000000000000000 + + + + + + + Diagonal FOV + + + + + + + + Default + + + + + 30 + + + + + 60 + + + + + 120 + + + + + 180 + + + + + + + + + + + + 640x480 + + + + + 320x240 + + + + + 320x200 + + + + + Default (not recommended!) + + + + + + + + Resolution + + + + + + + Camera name + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Camera settings + + + + + + + Open + + + + + + + + diff --git a/tracker-ht/ht_video_widget.cpp b/tracker-ht/ht_video_widget.cpp new file mode 100644 index 00000000..02fe71d1 --- /dev/null +++ b/tracker-ht/ht_video_widget.cpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2014 Stanislaw Halik + * + * 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 "ht_video_widget.h" + +void HTVideoWidget::update_image(unsigned char *frame, int width, int height) +{ + QMutexLocker foo(&mtx); + if (!fresh) + { + memcpy(fb, frame, width * height * 3); + this->width = width; + this->height = height; + fresh = true; + } +} + +void HTVideoWidget::update_and_repaint() +{ + QImage qframe; + { + QMutexLocker foo(&mtx); + if (width*height <= 0 || !fresh) + return; + fresh = false; + qframe = QImage(width, height, QImage::Format_RGB888); + uchar* data = qframe.bits(); + const int pitch = qframe.bytesPerLine(); + for (int y = 0; y < height; y++) + { + const int part = y*width; + for (int x = 0; x < width; x++) + { + const int pos = 3 * (part + x); + const int x_ = x * 3; + data[x_ + 0] = fb[pos + 2]; + data[x_ + 1] = fb[pos + 1]; + data[x_ + 2] = fb[pos + 0]; + } + data += pitch; + } + } + qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); + { + QMutexLocker foo(&mtx); + texture = qframe; + } + update(); +} diff --git a/tracker-ht/ht_video_widget.h b/tracker-ht/ht_video_widget.h new file mode 100644 index 00000000..054b2cf4 --- /dev/null +++ b/tracker-ht/ht_video_widget.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2014 Stanislaw Halik + * + * 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 +#include +#include +#include +#include +#include + +class HTVideoWidget : public QWidget +{ + Q_OBJECT +public: + HTVideoWidget(QWidget *parent) : QWidget(parent), fb(), width(0), height(0), fresh(false) { + connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); + timer.start(60); + } + void update_image(unsigned char* frame, int width, int height); +protected slots: + void paintEvent( QPaintEvent* e ) { + QMutexLocker foo(&mtx); + QPainter painter(this); + painter.drawImage(e->rect(), texture); + } + void update_and_repaint(); +private: + QMutex mtx; + QImage texture; + QTimer timer; + unsigned char fb[2048*2048*3]; + int width,height; + bool fresh; +}; diff --git a/tracker-ht/images/ht.png b/tracker-ht/images/ht.png new file mode 100644 index 00000000..19c73d21 Binary files /dev/null and b/tracker-ht/images/ht.png differ diff --git a/tracker-hydra/CMakeLists.txt b/tracker-hydra/CMakeLists.txt new file mode 100644 index 00000000..6a4a7cfe --- /dev/null +++ b/tracker-hydra/CMakeLists.txt @@ -0,0 +1,44 @@ +SET(SDK_HYDRA "" CACHE PATH "libSixense path for Razer Hydra") +SET(SDK_HYDRA_AMD64 FALSE CACHE BOOL "whether libSixense is amd64 (else ia-32)") +if(SDK_HYDRA) + opentrack_boilerplate(opentrack-tracker-hydra) + target_include_directories(opentrack-tracker-hydra SYSTEM PUBLIC ${SDK_HYDRA}/include ${SDK_HYDRA}/include/sixense_utils) + if(WIN32) + if(MSVC) + set(dir lib) + set(ext lib) + else() + set(dir bin) + set(ext dll) + endif() + target_link_libraries(opentrack-tracker-hydra + "${SDK_HYDRA}/${dir}/win32/release_dll/sixense.${ext}" + #"${SDK_HYDRA}/${dir}/win32/release_dll/sixense_utils.${ext}" + ) + install(FILES "${SDK_HYDRA}/bin/win32/release_dll/sixense.dll" + #"${SDK_HYDRA}/bin/win32/release_dll/sixense_utils.dll" + DESTINATION . ${opentrack-perms}) + else() + if(SDK_HYDRA_AMD64) + set(six4 _x64) + else() + set(six4) + endif() + if(APPLE) + set(under-dll _dll) + set(soext dylib) + set(plat osx) + else() + set(under-dll) + set(soext so) + set(plat linux) + endif() + install(FILES + "${SDK_HYDRA}/lib/${plat}${six4}/release${under-dll}/libsixense${six4}.${soext}" + DESTINATION . + ) + target_link_libraries(opentrack-tracker-hydra + "${SDK_HYDRA}/lib/${plat}${six4}/release${under-dll}/libsixense${six4}.${soext}" + ) + endif() +endif() diff --git a/tracker-hydra/ftnoir_hydra_clientcontrols.ui b/tracker-hydra/ftnoir_hydra_clientcontrols.ui new file mode 100644 index 00000000..7cfac075 --- /dev/null +++ b/tracker-hydra/ftnoir_hydra_clientcontrols.ui @@ -0,0 +1,53 @@ + + + UIHydraControls + + + Qt::NonModal + + + + 0 + 0 + 190 + 62 + + + + Sixense Hydra tracker settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + None whatsoever + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-hydra/ftnoir_tracker_hydra.cpp b/tracker-hydra/ftnoir_tracker_hydra.cpp new file mode 100644 index 00000000..8d0e6832 --- /dev/null +++ b/tracker-hydra/ftnoir_tracker_hydra.cpp @@ -0,0 +1,46 @@ +/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ +#include "ftnoir_tracker_hydra.h" +#include "opentrack/plugin-api.hpp" +#include +#ifdef _WIN32 +# define SIXENSE_STATIC_LIB +# define SIXENSE_UTILS_STATIC_LIB +#endif +#include + +Hydra_Tracker::Hydra_Tracker() : should_quit(false) {} + +#include + +Hydra_Tracker::~Hydra_Tracker() +{ + + sixenseExit(); +} + +void Hydra_Tracker::start_tracker(QFrame*) +{ + sixenseInit(); +} + +void Hydra_Tracker::data(double *data) +{ + + sixenseSetActiveBase(0); + sixenseAllControllerData acd; + sixenseGetAllNewestData( &acd ); + sixenseMath::Matrix4 mat = sixenseMath::Matrix4(acd.controllers[0].rot_mat); + + float ypr[3]; + + mat.getEulerAngles().fill(ypr); + data[TX] = acd.controllers[0].pos[0]/50.0; + data[TY] = acd.controllers[0].pos[1]/50.0; + data[TZ] = acd.controllers[0].pos[2]/50.0; + static constexpr double r2d = 57.295781; + data[Yaw] = ypr[0] * r2d; + data[Pitch] = ypr[1] * r2d; + data[Roll] = ypr[2] * r2d; +} + +OPENTRACK_DECLARE_TRACKER(Hydra_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/tracker-hydra/ftnoir_tracker_hydra.h b/tracker-hydra/ftnoir_tracker_hydra.h new file mode 100644 index 00000000..47a1eb9a --- /dev/null +++ b/tracker-hydra/ftnoir_tracker_hydra.h @@ -0,0 +1,46 @@ +#include "ui_ftnoir_hydra_clientcontrols.h" +#include "opentrack/plugin-api.hpp" +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + settings() : + opts("tracker-hydra") + {} +}; + +class Hydra_Tracker : public ITracker +{ +public: + Hydra_Tracker(); + ~Hydra_Tracker(); + void start_tracker(QFrame *) override; + void data(double *data) override; + volatile bool should_quit; +private: + settings s; + QMutex mutex; +}; + +class TrackerControls: public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + void register_tracker(ITracker *) {} + void unregister_tracker() {} +private: + settings s; + Ui::UIHydraControls ui; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + QString name() { return QString("Razer Hydra -- inertial device"); } + QIcon icon() { return QIcon(":/images/facetracknoir.png"); } +}; + diff --git a/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp b/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp new file mode 100644 index 00000000..2c23ee46 --- /dev/null +++ b/tracker-hydra/ftnoir_tracker_hydra_dialog.cpp @@ -0,0 +1,22 @@ +#include "ftnoir_tracker_hydra.h" +#include "opentrack/plugin-api.hpp" + +TrackerControls::TrackerControls() +{ + ui.setupUi( this ); + + // Connect Qt signals to member-functions + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); +} + +void TrackerControls::doOK() { + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->reload(); + close(); +} + diff --git a/tracker-joystick/CMakeLists.txt b/tracker-joystick/CMakeLists.txt new file mode 100644 index 00000000..c8d2d218 --- /dev/null +++ b/tracker-joystick/CMakeLists.txt @@ -0,0 +1,4 @@ +if(WIN32) + opentrack_boilerplate(opentrack-tracker-joystick) + link_with_dinput8(opentrack-tracker-joystick) +endif() diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp new file mode 100644 index 00000000..77fd7241 --- /dev/null +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -0,0 +1,253 @@ +/* Copyright (c) 2013 Stanislaw Halik + * + * 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_tracker_joystick.h" +#include "opentrack/plugin-api.hpp" +#include + +FTNoIR_Tracker::FTNoIR_Tracker() : + g_pDI(nullptr), + g_pJoystick(nullptr), + mtx(QMutex::Recursive), + iter(-1) +{ +} + +void FTNoIR_Tracker::reload() +{ + s.b->reload(); + QMutexLocker foo(&mtx); + if (g_pJoystick) + { + g_pJoystick->Unacquire(); + g_pJoystick->Release(); + } + if (g_pDI) + g_pDI->Release(); + + g_pJoystick = nullptr; + g_pDI = nullptr; + + start_tracker(frame); +} + +FTNoIR_Tracker::~FTNoIR_Tracker() +{ + if (g_pJoystick) + { + g_pJoystick->Unacquire(); + g_pJoystick->Release(); + } + if (g_pDI) + { + g_pDI->Release(); + } +} + +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + auto self = (FTNoIR_Tracker*) pContext; + + if( pdidoi->dwType & DIDFT_AXIS ) + { + DIPROPRANGE diprg = {0}; + diprg.diph.dwSize = sizeof( DIPROPRANGE ); + diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; + diprg.lMax = FTNoIR_Tracker::AXIS_MAX; + diprg.lMin = -FTNoIR_Tracker::AXIS_MAX; + + if( FAILED( self->g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) + return DIENUM_STOP; + + self->iter++; + } + + return self->iter == 8 ? DIENUM_STOP : DIENUM_CONTINUE; +} + +static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) +{ + auto self = reinterpret_cast(pContext); + bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid; + + if (stop) + { + if (self->guid_to_check.size()) + { + QString guid = guid_to_string(pdidInstance->guidInstance); + if (guid != self->guid_to_check) + { + return DIENUM_CONTINUE; + } + else + qDebug() << "guid ok" << self->guid_to_check; + } + + (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL); + qDebug() << "device" << static_cast(self->s.joyid); + } + + return stop ? DIENUM_STOP : DIENUM_CONTINUE; +} + +void FTNoIR_Tracker::start_tracker(QFrame* frame) +{ + QMutexLocker foo(&mtx); + this->frame = frame; + iter = 0; + auto hr = CoInitialize( nullptr ); + + if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, + IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) + { + qDebug() << "create"; + goto fail; + } + + guid_to_check = s.guid; + + if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "enum1"; + goto fail; + } + + if (!g_pJoystick && guid_to_check.size()) + { + guid_to_check = ""; + + if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "enum2"; + goto fail; + } + } + + if (!g_pJoystick) + { + qDebug() << "ENODEV"; + goto fail; + } + + if (FAILED(g_pJoystick->SetDataFormat(&c_dfDIJoystick))) + { + qDebug() << "format"; + goto fail; + } + + if (FAILED(g_pJoystick->SetCooperativeLevel((HWND) frame->window()->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + goto fail; + } + + iter = 0; + + if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback, + ( VOID* )this, DIDFT_ALL ))) + { + qDebug() << "enum axes"; + goto fail; + } + + return; + +fail: + if (g_pJoystick) + g_pJoystick->Release(); + if (g_pDI) + g_pDI->Release(); + g_pJoystick = nullptr; + g_pDI = nullptr; + + qDebug() << "joy init failure"; +} + +void FTNoIR_Tracker::data(double *data) +{ + QMutexLocker foo(&mtx); + DIJOYSTATE js = {0}; + + if( !g_pDI || !g_pJoystick) + return; + + bool ok = false; + + for (int i = 0; i < 100; i++) + { + if (!FAILED(g_pJoystick->Poll())) + { + ok = true; + break; + } + if (g_pJoystick->Acquire() != DI_OK) + continue; + else + ok = true; + break; + } + + if (!ok) + return; + + HRESULT hr = 0; + + if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof( js ), &js ) ) ) + return; + + const LONG values[] = { + js.lX, + js.lY, + js.lZ, + js.lRx, + js.lRy, + js.lRz, + js.rglSlider[0], + js.rglSlider[1] + }; + + int map[6] = { + s.joy_1 - 1, + s.joy_2 - 1, + s.joy_3 - 1, + s.joy_4 - 1, + s.joy_5 - 1, + s.joy_6 - 1, + }; + + const double limits[] = { + 100, + 100, + 100, + 180, + 180, + 180 + }; + + for (int i = 0; i < 6; i++) + { + int k = map[i] - 1; + if (k < 0 || k >= 8) + data[i] = 0; + else + data[i] = values[k] * limits[i] / AXIS_MAX; + } +} + +OPENTRACK_DECLARE_TRACKER(FTNoIR_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h new file mode 100644 index 00000000..75305f07 --- /dev/null +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2013 Stanislaw Halik + * + * 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 "ui_ftnoir_tracker_joystick_controls.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +#endif +#include +#include +#include +#include +#include +#include + +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value joyid, guid; + value joy_1, joy_2, joy_3, joy_4, joy_5, joy_6; + settings() : + opts("tracker-joystick"), + joyid(b, "joy-id", ""), + guid(b, "joy-guid", ""), + joy_1(b, "axis-map-1", 1), + joy_2(b, "axis-map-2", 2), + joy_3(b, "axis-map-3", 3), + joy_4(b, "axis-map-4", 4), + joy_5(b, "axis-map-5", 5), + joy_6(b, "axis-map-6", 6) + {} +}; + +template +QString guid_to_string(const GUID guid) +{ + char buf[40] = {0}; + wchar_t szGuidW[40] = {0}; + + StringFromGUID2(guid, szGuidW, 40); + WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); + + return QString(buf); +} + +class FTNoIR_Tracker : public ITracker +{ +public: + FTNoIR_Tracker(); + ~FTNoIR_Tracker(); + void start_tracker(QFrame *frame); + void data(double *data); + void reload(); + LPDIRECTINPUT8 g_pDI; + LPDIRECTINPUTDEVICE8 g_pJoystick; + QMutex mtx; + QFrame* frame; + DIDEVICEINSTANCE def; + int iter; // XXX bad style + settings s; + QString guid_to_check; + static constexpr int AXIS_MAX = 65535; +}; + +class TrackerControls: public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + void register_tracker(ITracker *) {} + void unregister_tracker() {} + Ui::UIJoystickControls ui; + FTNoIR_Tracker* tracker; + settings s; + struct joys { + QString name; + QString guid; + }; + QList _joys; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + QString name() { return QString("Joystick input"); } + QIcon icon() { return QIcon(":/images/facetracknoir.png"); } +}; + diff --git a/tracker-joystick/ftnoir_tracker_joystick_controls.ui b/tracker-joystick/ftnoir_tracker_joystick_controls.ui new file mode 100644 index 00000000..88737023 --- /dev/null +++ b/tracker-joystick/ftnoir_tracker_joystick_controls.ui @@ -0,0 +1,492 @@ + + + UIJoystickControls + + + Qt::NonModal + + + + 0 + 0 + 498 + 303 + + + + Tracker settings + + + + ../facetracknoir/images/facetracknoir.png../facetracknoir/images/facetracknoir.png + + + + 12 + + + 6 + + + 12 + + + 6 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + + + + + 0 + 0 + + + + Device + + + + + + + + 0 + 0 + + + + + + + + + + + Mapping + + + + + + + 0 + 0 + + + + 1 + + + + Disabled + + + + + Joystick axis #1 + + + + + Joystick axis #2 + + + + + Joystick axis #3 + + + + + Joystick axis #4 + + + + + Joystick axis #5 + + + + + Joystick axis #6 + + + + + Joystick axis #7 + + + + + Joystick axis #8 + + + + + + + + + 0 + 0 + + + + 2 + + + + Disabled + + + + + Joystick axis #1 + + + + + Joystick axis #2 + + + + + Joystick axis #3 + + + + + Joystick axis #4 + + + + + Joystick axis #5 + + + + + Joystick axis #6 + + + + + Joystick axis #7 + + + + + Joystick axis #8 + + + + + + + + + 0 + 0 + + + + 3 + + + + Disabled + + + + + Joystick axis #1 + + + + + Joystick axis #2 + + + + + Joystick axis #3 + + + + + Joystick axis #4 + + + + + Joystick axis #5 + + + + + Joystick axis #6 + + + + + Joystick axis #7 + + + + + Joystick axis #8 + + + + + + + + + 0 + 0 + + + + 4 + + + + Disabled + + + + + Joystick axis #1 + + + + + Joystick axis #2 + + + + + Joystick axis #3 + + + + + Joystick axis #4 + + + + + Joystick axis #5 + + + + + Joystick axis #6 + + + + + Joystick axis #7 + + + + + Joystick axis #8 + + + + + + + + + 0 + 0 + + + + 5 + + + + Disabled + + + + + Joystick axis #1 + + + + + Joystick axis #2 + + + + + Joystick axis #3 + + + + + Joystick axis #4 + + + + + Joystick axis #5 + + + + + Joystick axis #6 + + + + + Joystick axis #7 + + + + + Joystick axis #8 + + + + + + + + + 0 + 0 + + + + 6 + + + + Disabled + + + + + Joystick axis #1 + + + + + Joystick axis #2 + + + + + Joystick axis #3 + + + + + Joystick axis #4 + + + + + Joystick axis #5 + + + + + Joystick axis #6 + + + + + Joystick axis #7 + + + + + Joystick axis #8 + + + + + + + + X + + + + + + + Y + + + + + + + Z + + + + + + + Yaw + + + + + + + Pitch + + + + + + + Roll + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp new file mode 100644 index 00000000..0463933f --- /dev/null +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -0,0 +1,69 @@ +#include "ftnoir_tracker_joystick.h" +#include "opentrack/plugin-api.hpp" + +static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) +{ + auto self = ( TrackerControls* )pContext; + auto name = QString(pdidInstance->tszInstanceName); + auto guid = guid_to_string(pdidInstance->guidInstance); + TrackerControls::joys cur { name, guid }; + self->_joys.append(cur); + + self->ui.joylist->addItem(name + " " + guid); + + return DIENUM_CONTINUE; +} + +TrackerControls::TrackerControls() : tracker(nullptr) +{ + ui.setupUi( this ); + + // Connect Qt signals to member-functions + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + { + auto hr = CoInitialize( nullptr ); + LPDIRECTINPUT8 g_pDI = nullptr; + + if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION, + IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) ) + goto fin; + + if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY ))) + goto fin; + +fin: + if (g_pDI) + g_pDI->Release(); + } + + tie_setting(s.joy_1, ui.joy_1); + tie_setting(s.joy_2, ui.joy_2); + tie_setting(s.joy_3, ui.joy_3); + tie_setting(s.joy_4, ui.joy_4); + tie_setting(s.joy_5, ui.joy_5); + tie_setting(s.joy_6, ui.joy_6); +} + +void TrackerControls::doOK() { + int idx = ui.joylist->currentIndex(); + joys def { "", "" }; + auto val = _joys.value(idx, def); + s.guid = val.guid; + s.joyid = val.name; + s.b->save(); + if (tracker) + tracker->reload(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->reload(); + this->close(); +} + + diff --git a/tracker-pt/CMakeLists.txt b/tracker-pt/CMakeLists.txt new file mode 100644 index 00000000..94b04437 --- /dev/null +++ b/tracker-pt/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(OpenCV 3.0) +opentrack_boilerplate(opentrack-tracker-pt) +target_link_libraries(opentrack-tracker-pt ${OpenCV_LIBS}) +target_include_directories(opentrack-tracker-pt SYSTEM PUBLIC ${OpenCV_INCLUDE_DIRS}) +link_with_dinput8(opentrack-tracker-pt) diff --git a/tracker-pt/FTNoIR_PT_Controls.ui b/tracker-pt/FTNoIR_PT_Controls.ui new file mode 100644 index 00000000..88575644 --- /dev/null +++ b/tracker-pt/FTNoIR_PT_Controls.ui @@ -0,0 +1,1220 @@ + + + UICPTClientControls + + + Qt::NonModal + + + + 0 + 0 + 424 + 579 + + + + + 0 + 0 + + + + PointTracker Settings + + + + :/Resources/Logo_IR.png:/Resources/Logo_IR.png + + + Qt::LeftToRight + + + false + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + 0 + + + + Camera + + + + + + Camera settings + + + + + + + 0 + 0 + + + + FPS + + + fps_spin + + + + + + + + 0 + 0 + + + + Desired capture height + + + px + + + 2000 + + + 10 + + + + + + + + 0 + 0 + + + + Diagonal field of view + + + + + + + + 0 + 0 + + + + Width + + + + + + + ° + + + + + + 10 + + + 90 + + + + + + + + + + + + + + + 0 + 0 + + + + Dynamic pose resolution + + + + + + + Dynamic pose timeout + + + + + + + + 0 + 0 + + + + Desired capture framerate + + + Hz + + + 2000 + + + + + + + ms + + + 1 + + + 10000 + + + + + + + + 0 + 0 + + + + Height + + + + + + + + 0 + 0 + + + + Desired capture width + + + px + + + 2000 + + + 10 + + + + + + + + 0 + 0 + + + + 10 + + + + + + + + 0 + 0 + + + + Device + + + camdevice_combo + + + + + + + Camera settings dialog + + + + + + + + 0 + 0 + + + + Open + + + + + + + + + + Point extraction + + + + + + Max size + + + maxdiam_spin + + + + + + + Threshold + + + threshold_slider + + + + + + + Min size + + + mindiam_spin + + + + + + + Intensity threshold for point extraction + + + 255 + + + 1 + + + 127 + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + 25 + + + + + + + Automatic threshold + + + + + + + Enable, slider sets point size + + + + + + + Maximum point diameter + + + px + + + 1 + + + 0.100000000000000 + + + + + + + Minimum point diameter + + + px + + + 1 + + + 0.100000000000000 + + + + + + + + + + + Model + + + + + + + 0 + 0 + + + + QTabWidget::Rounded + + + 0 + + + false + + + false + + + false + + + + Clip + + + + + + + 0 + 0 + + + + + 331 + 208 + + + + Model Dimensions + + + + + 70 + 35 + 100 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + 150 + 130 + 100 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + 65 + 55 + 71 + 111 + + + + + + + :/Resources/clip_side.png + + + + + + 20 + 40 + 46 + 13 + + + + Side + + + + + + 50 + 160 + 100 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + 150 + 70 + 100 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + 290 + 40 + 46 + 13 + + + + Front + + + + + + 300 + 70 + 21 + 111 + + + + + + + :/Resources/clip_front.png + + + + + + + + + Cap + + + + + + + 331 + 208 + + + + Model Dimensions + + + + + 100 + 60 + 111 + 81 + + + + + + + :/Resources/cap_side.png + + + + + + 20 + 40 + 46 + 13 + + + + Side + + + + + + 90 + 40 + 101 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + 220 + 100 + 81 + 81 + + + + + + + :/Resources/cap_front.png + + + + + + 240 + 70 + 81 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + 240 + 40 + 46 + 13 + + + + Front + + + + + + 20 + 90 + 81 + 22 + + + + mm + + + -65535 + + + 65535 + + + + + + + + + Custom + + + + + + Model Dimensions + + + + + + + 0 + 0 + + + + z: + + + + + + + mm + + + -65535 + + + 65535 + + + + + + + + 0 + 0 + + + + x: + + + + + + + mm + + + -65535 + + + 65535 + + + + + + + mm + + + -65535 + + + 65535 + + + + + + + mm + + + -65535 + + + 65535 + + + + + + + mm + + + -65535 + + + 65535 + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html> + + + + + + + mm + + + -65535 + + + 65535 + + + + + + + + 0 + 0 + + + + y: + + + + + + + + 0 + 0 + + + + x: + + + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html> + + + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html> + + + + + + + + 0 + 0 + + + + z: + + + + + + + + 0 + 0 + + + + y: + + + + + + + + + + + + + + + 0 + 0 + + + + Model position + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 0 + 0 + + + + x: + + + + + + + mm + + + -65535 + + + 65536 + + + + + + + + 0 + 0 + + + + y: + + + + + + + mm + + + -65535 + + + 65536 + + + + + + + + 0 + 0 + + + + z: + + + + + + + mm + + + -65535 + + + 65536 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + <html><head/><body><p><a href="https://github.com/opentrack/opentrack/wiki/model-calibration-for-PT-and-Aruco-trackers"><span style=" text-decoration: underline; color:#0000ff;">Instructions on the opentrack wiki</span></a></p></body></html> + + + true + + + + + + + false + + + Toggle calibration + + + true + + + + + + + + + + + + + + About + + + + + + <html><head/><body><p><span style=" font-weight:600;">FTNoIR PointTracker Plugin<br/>Version 1.1</span></p><p><span style=" font-weight:600;">by Patrick Ruoff</span></p><p><a href="http://ftnoirpt.sourceforge.net/"><span style=" font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + :/Resources/Logo_IR.png + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + Status + + + + + + Extracted Points: + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Camera Info: + + + + + + + + 50 + 0 + + + + + + + + + + + + 0 + 0 + + + + + 120 + 0 + + + + + + + + + + + + + + tabWidget + camdevice_combo + res_x_spin + res_y_spin + fps_spin + fov + threshold_slider + model_tabs + clip_tlength_spin + clip_theight_spin + clip_bheight_spin + clip_blength_spin + cap_length_spin + cap_width_spin + cap_height_spin + m1x_spin + m1y_spin + m1z_spin + m2x_spin + m2y_spin + m2z_spin + tx_spin + ty_spin + tz_spin + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-pt/Resources/Logo_IR.png b/tracker-pt/Resources/Logo_IR.png new file mode 100644 index 00000000..95032a25 Binary files /dev/null and b/tracker-pt/Resources/Logo_IR.png differ diff --git a/tracker-pt/Resources/cap_front.png b/tracker-pt/Resources/cap_front.png new file mode 100644 index 00000000..14207a67 Binary files /dev/null and b/tracker-pt/Resources/cap_front.png differ diff --git a/tracker-pt/Resources/cap_side.png b/tracker-pt/Resources/cap_side.png new file mode 100644 index 00000000..5ad4ee65 Binary files /dev/null and b/tracker-pt/Resources/cap_side.png differ diff --git a/tracker-pt/Resources/clip_front.png b/tracker-pt/Resources/clip_front.png new file mode 100644 index 00000000..04880138 Binary files /dev/null and b/tracker-pt/Resources/clip_front.png differ diff --git a/tracker-pt/Resources/clip_side.png b/tracker-pt/Resources/clip_side.png new file mode 100644 index 00000000..72667ac7 Binary files /dev/null and b/tracker-pt/Resources/clip_side.png differ diff --git a/tracker-pt/camera.cpp b/tracker-pt/camera.cpp new file mode 100644 index 00000000..63b401a8 --- /dev/null +++ b/tracker-pt/camera.cpp @@ -0,0 +1,145 @@ +/* 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. + */ + +#include "camera.h" +#include +#include +#include "opentrack-compat/sleep.hpp" + +void Camera::set_device_index(int index) +{ + if (desired_index != index) + { + desired_index = index; + _set_device_index(); + + // reset fps + dt_valid = 0; + dt_mean = 0; + active_index = index; + } +} + +void Camera::set_fps(int fps) +{ + if (cam_desired.fps != fps) + { + cam_desired.fps = fps; + _set_fps(); + } +} + +void Camera::set_res(int x_res, int y_res) +{ + if (cam_desired.res_x != x_res || cam_desired.res_y != y_res) + { + cam_desired.res_x = x_res; + cam_desired.res_y = y_res; + _set_res(); + } +} + +bool Camera::get_info(CamInfo& ret) +{ + if (cam_info.res_x == 0 || cam_info.res_y == 0) + { + return false; + } + ret = cam_info; + return true; +} + +bool Camera::get_frame(float dt, cv::Mat* frame) +{ + bool new_frame = _get_frame(frame); + // measure fps of valid frames + const float dt_smoothing_const = 0.95; + dt_valid += dt; + if (new_frame) + { + dt_mean = dt_smoothing_const * dt_mean + (1.0 - dt_smoothing_const) * dt_valid; + cam_info.fps = dt_mean > 1e-3 ? 1.0 / dt_mean : 0; + dt_valid = 0; + } + else + qDebug() << "pt camera: can't get frame"; + return new_frame; +} + +void CVCamera::start() +{ + stop(); + cap = new cv::VideoCapture(desired_index); + _set_res(); + _set_fps(); + // extract camera info + if (cap->isOpened()) + { + active_index = desired_index; + cam_info.res_x = 0; + cam_info.res_y = 0; + } else { + stop(); + } +} + +void CVCamera::stop() +{ + if (cap) + { + const bool opened = cap->isOpened(); + if (opened) + { + qDebug() << "pt: freeing camera"; + cap->release(); + } + delete cap; + cap = nullptr; + // give opencv time to exit camera threads, etc. + if (opened) + portable::sleep(500); + qDebug() << "pt camera: assuming stopped"; + } +} + +bool CVCamera::_get_frame(cv::Mat* frame) +{ + if (cap && cap->isOpened()) + { + cv::Mat img; + for (int i = 0; i < 100 && !cap->read(img); i++) + ;; + + if (img.empty()) + return false; + + *frame = img; + cam_info.res_x = img.cols; + cam_info.res_y = img.rows; + return true; + } + return false; +} + +void CVCamera::_set_fps() +{ + if (cap) cap->set(CV_CAP_PROP_FPS, cam_desired.fps); +} + +void CVCamera::_set_res() +{ + if (cap) + { + cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x); + cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y); + } +} +void CVCamera::_set_device_index() +{ + if (desired_index != active_index) + stop(); +} diff --git a/tracker-pt/camera.h b/tracker-pt/camera.h new file mode 100644 index 00000000..e73d9dff --- /dev/null +++ b/tracker-pt/camera.h @@ -0,0 +1,95 @@ +/* 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 +#include +#include +#include + +struct CamInfo +{ + CamInfo() : res_x(0), res_y(0), fps(0) {} + + int res_x; + int res_y; + int fps; +}; + +// ---------------------------------------------------------------------------- +// Base class for cameras, calculates the frame rate +class Camera +{ +public: + Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1) {} + virtual ~Camera() = 0; + + // start/stop capturing + virtual void start() = 0; + virtual void stop() = 0; + void restart() { stop(); start(); } + + // calls corresponding template methods and reinitializes frame rate calculation + void set_device_index(int index); + void set_fps(int fps); + void set_res(int x_res, int y_res); + + // gets a frame from the camera, dt: time since last call in seconds + bool get_frame(float dt, cv::Mat* frame); + + // WARNING: returned references are valid as long as object + bool get_info(CamInfo &ret); + CamInfo get_desired() const { return cam_desired; } + +protected: + // get a frame from the camera + virtual bool _get_frame(cv::Mat* frame) = 0; + + // update the camera using cam_desired, write res and f to cam_info if successful + virtual void _set_device_index() = 0; + virtual void _set_fps() = 0; + virtual void _set_res() = 0; +private: + float dt_valid; + float dt_mean; +protected: + int desired_index; + int active_index; + CamInfo cam_info; + CamInfo cam_desired; +}; +inline Camera::~Camera() {} + +// ---------------------------------------------------------------------------- +// camera based on OpenCV's videoCapture +class CVCamera : public Camera +{ +public: + CVCamera() : cap(NULL) {} + ~CVCamera() { stop(); } + + void start() override; + void stop() override; + + operator cv::VideoCapture*() { return cap; } + +protected: + bool _get_frame(cv::Mat* frame) override; + void _set_fps() override; + void _set_res() override; + void _set_device_index() override; +private: + cv::VideoCapture* cap; +}; + +enum RotationType +{ + CLOCKWISE = 0, + ZERO = 1, + COUNTER_CLOCKWISE = 2 +}; diff --git a/tracker-pt/doc/index.htm b/tracker-pt/doc/index.htm new file mode 100644 index 00000000..87b7356f --- /dev/null +++ b/tracker-pt/doc/index.htm @@ -0,0 +1,262 @@ + + + + + FTNoIR PointTracker Help + + + + + + + + + + + + + + +
+

FaceTrackNoIR PointTracker Plugin

PointTracker Plugin Logo
+ + +

About

+
+

+PointTracker is a plugin for the free head tracking software FaceTrackNoIR +which introduces the capability to track a (typically IR-) point model comprising 3 bright points to FaceTrackNoIR, +much like the popular free tracking software Freetrack does.
+It was created as a stable modular alternative to Freetrack, which has some stability issues with newer systems and seems to be no longer actively developped. +

+
+ + +

Settings

+
+

+This section desribes the various settings of the PointTracker plugin in detail. +

+ +Settings Pane 1 +
+
Show VideoWidget
Whether the video widget is updated or not. It may save some performance to turn this off when not needed
+
Sleep time
Time the tracking thread sleeps after each processed image. It's inverse should be below the framefrate you want to achieve. +(check the framerate in the status region when tracker is active, in case the sleep time is too high, the framerate will decrease). +Low values will result in more CPU-load.
+
Dynamic Pose Resolution
Whether the point correspondence and pose ambiquity is resolved using a more sophisticated dynamic algorithm (constant velocity prediction) or a simple static resolution. +Dynamic pose resolution can capture more extreme poses but may occasionally get stuck in a wrong pose estimates so that a reset of the internal state becomes neccessary.
+
Auto-reset time
If no valid tracking result can be found when using dynamic pose resolution, the tracker will automatically reset its internal state (used for resolving the pose ambiguity and point correspondence) +and return to a fail-safe initialization phase that assumes a neutral pose after this time. +Decrease this time, if you get stuck in a wrong pose too often.
+
Reset
Manually reset the trackers internal state used for dynamic pose resolution and return to a fail-safe initialization phase that assumes a neutral pose. +You may use this in case you get stuck in a wrong pose.
+
Enable Axis ...
Which axis to use for FTNoIR.
+
+ +Settings Pane 2 +
+
Device
The camera used for tracking.
+
Resolution
The desired capture resolution. If your camera does not support the entered resolution the true output resolution may be different or even invalid. +You may check the true capture resolution in the status area while the tracker is running. A higher resolution results in more accurate point positions and will increase the +stability of the tracking result, as long as the signal/noise ratio is sufficiently high.
+
FPS
The desired capture framerate. Again, if your camera does not support the entered framerate, the true caputre framerate may be different or invalid. +You may check the true processing framerate in the status area while the tracker is running.
+
F/W
The focal length of the camera divided by the sensor width (of course in the same units). +In case you don't have access to your camera's specifications, you can measure this yourself by placing a plane object of known width (for example a piece of cardboard) in front of the camera until it fills the whole image width. +Then measure the distance between the object and the camera and divide by the object width.
+
VideoWidget
Shows a resizable stand-alone video widget that shows the same content as the integrated video widget in FTNoIR. +Update rate is only 10 fps and may lag behind a bit. Mainly useful during calibration of the point extraction. Same as for the integrated wiget, to save resources, this widget should only be shown when needed.
+
Roll Pitch Yaw...
The orientation of the camera relative to the reference frame. +If these angles are setup properly, the direction of translations may not be correct. +Roll is treated in a special way since it is implemented as a frame rotation by +/- 90 deg that is transparent to the rest of the processing pipeline. +
+
Threshold
The threshold for point recognition. Areas above the threshold are shown in blue in the VideoWidget. +Since point accuracy is best if the points are as big as possible in pixels, the theshold should be chosen as low as possible (stop before the contour of the points becomes "noisy"). +If small reflections are being falsely classified as points, increasing the minimum point diameter (see below) may help.
+
Min Diameter
Minimum diameter of blobs to be classified as a pointmodel-point.
+
Max Diameter
Maximum diameter of blobs to be classified as a pointmodel-point.
+
Status
The tracker's status is shown in this area while the tracker is running. +The FPS shown here correspond to the framerate of the whole tracker processing chain and may be lower than what your camera is able to provide, when
+1. The processing gets not enough CPU time
+2. The sleep time of the tracking thread is set too high
+
+ +Settings Pane 3 +
+
Model Selection and Dimensions ...
+First select your model type (point, clip, custom), then enter the dimensions of your model in milimeters here.
+For the custom setting, the coordinates of the two remaining model points have to be entered (reference point M0 is at (0,0,0)) in a pose where the model roughly faces the camera. +For orientation, the coordinates for the standard Freetrack clip are (0,40,-30), (0,-70,-80) and the ones for the cap (40,-60,-100), (-40,-60,-100).
+When using a custom point-model configuration, the following restrictions should be observed:
+The plane in which the 3 points lie should never be parallel to the image plane, M0-M1 and M0-M2 should be roughly perpendicular.
+ +
Model Position
The vector from the model to the center of the head in the model frame. Can be calibrated automatically.
+
Calibrate
In order to automatically calibrate the model-head offset, do the following:
Press the Calibrate button, then look around while not moving your shoulder. (i.e. only rotation, no translation). +Do not stay in one pose for too long. The current translation estimate will be updated in real time. As soon as the values stabilized sufficiently, press the Calibrate button again to stop the calibration process.
+
+
+ + +

Filter Setup

+
+

+This section desribes how the FTNoIR filter work and what the recommended settings for PointTracker are. +

+

+Filtering is always a tradeoff between stability, accuracy and responsiveness. +

+

+The Smoothing filter in FTNoIR is just a simple average over the last n samples. +Since this filter produces input lag no matter how fast the head-movements are, it is recommended to turn it off by setting samples to 1. +

+

+In the filter tab, it is recommended to select Accela Filter Mk2. +Accela is a non-linear filter that works as follows:
+It looks at the difference between the new raw values new_val from the tracker and the last filtered value old_val +and maps this difference via the customizable response function f via:
+

+

+new_val = old_val + f(new_val - old_val) / reduction_factor +

+

+So by setting f(x) = reduction_factor * x, one will get no filtering at all.
+If you set lower values for small x, small deviations (usually noise) will get dampened. +This results in a dynamic dead-zone around the current position. +

+

+The last two points are used by accela to extrapolate for large deviations. +So in order to get a fast unfiltered response for large deviations, the line connecting the last two points should have a slope >= reduction_factor. +

+

+More aggressive accela settings than the default FTNoIR accela settings are recommended in order to decrease the filtering lag and fully use the potential of point tracking.
+My current settings are: +

+

+[Accela]
+Reduction=20
+
+[Curves-Accela-Scaling-Rotation]
+point-count=4
+point-0-x=0.1
+point-0-y=0
+point-1-x=1.43
+point-1-y=2.45
+point-2-x=2.0
+point-2-y=5.44
+point-3-x=2.06
+point-3-y=6
+
+

+The curve is not too different from the standard one (except that I like a small dynamic dead zone for steady aiming, that's why the curve has a slope of 0 at the beginning).
+However, the reduction factor is decreased to a value of 20 (compared to the standard value of 100). This implies that each value of the curve is effectively 5 times higher than in standard FTNoIR (see formula above), which means higher responsiveness but can also lead to jitter/shaking.
+Keep in mind that there are no best filter settings. Since filtering is always a compromise it's a matter of personal taste and +playing around with the filter settings is highly recommended. +

+
+ + +

Support

+
+

+For questions/feedback about the plugin, post to the FTNoIR-Forum.
+In case you like this plugin and would like to support the author, you may consider making a donation. +

+
+
+
+ + + + +
+
+
+
+ + +

ChangeLog

+
+

1.1

+
    +
  • Added camera yaw and roll correction (intended for vertically mounted cameras)
  • +
  • Improved point extraction algorithm, thanks to Michael Welter
  • +
  • UI improvements: Select camera by device name, different VideoWidget architecture
  • +
  • Bugfixes: Removed 99 FPS limitation
  • +
+ +

1.0

+
    +
  • Added camera pitch correction
  • +
  • Better communication with FTNoIR: output axis configuration, status report
  • +
+ +

1.0 beta

+
    +
  • Switchted to videoInput library for capture. Desired capture resolution and fps can now be customized
  • +
  • Introduced dynamic point-correspondence and POSIT-ambiguity resolution, which allows for the reconstruction of more extreme poses
  • +
  • More convenient freetrack-like model dimension GUI
  • +
  • Bugfixes: VideoWidget skipping frames, Timer resolution too low for accurate FPS measurement
  • +
+
+ + +

Build Instructions

+
+

+This section describes what you need to do in order to build PointTracker yourself.
+You can find the sources at the project site +or as part of the FTNoIR sources. +

+

The project was created with Visual Studio.

+ +

Dependencies

+
    +
  • Qt 4.8.2 library
  • +
  • Qt plugin for Visual studio
  • +
  • OpenCV 2.4 prebuilt for Windows
  • +
  • Boost 1.47
  • +
+ +

Details

+
+

Common

+
    +
  • setup environment variable "QTDIR" (example value "D:\Devel\Libs\Qt\4.8.2")
  • +
  • add "%QTDIR%\bin" to PATH
  • +
  • setup environment variable "BOOST_DIR" (example value "D:\Devel\Libs\boost_1_47_0")
  • +
  • setup environment variable "OPENCV_DIR" (example value "D:\Devel\Libs\opencv\build")
  • +
+

Debug

+

opencv linked dynamically:

+
    +
  • add "%OPENCV_DIR%\x86\vc9\bin" to PATH
  • +
+

(in case of different Visual studio, change PATH and linker dependencies accordingly)

+

Release

+

opencv linked statically:

+
    +
  • custom build a statically linked version of opencv with the buil-option BUILD_WITH_STATIC_CRT set to OFF!
  • +
  • copy resulting libaries to "%OPENCV_DIR%\x86\vc9\static_lib"
  • +
+

(in case of different Visual studio, change PATH and linker dependencies accordingly)

+
+
+ +
+ + + \ No newline at end of file diff --git a/tracker-pt/doc/logo.png b/tracker-pt/doc/logo.png new file mode 100644 index 00000000..95032a25 Binary files /dev/null and b/tracker-pt/doc/logo.png differ diff --git a/tracker-pt/doc/ptrack.ico b/tracker-pt/doc/ptrack.ico new file mode 100644 index 00000000..c4b2aedc Binary files /dev/null and b/tracker-pt/doc/ptrack.ico differ diff --git a/tracker-pt/doc/settings1.png b/tracker-pt/doc/settings1.png new file mode 100644 index 00000000..35b84c5c Binary files /dev/null and b/tracker-pt/doc/settings1.png differ diff --git a/tracker-pt/doc/settings2.png b/tracker-pt/doc/settings2.png new file mode 100644 index 00000000..c6cfd1f3 Binary files /dev/null and b/tracker-pt/doc/settings2.png differ diff --git a/tracker-pt/doc/settings3.png b/tracker-pt/doc/settings3.png new file mode 100644 index 00000000..5922403d Binary files /dev/null and b/tracker-pt/doc/settings3.png differ diff --git a/tracker-pt/doc/style.css b/tracker-pt/doc/style.css new file mode 100644 index 00000000..0c3d29a6 --- /dev/null +++ b/tracker-pt/doc/style.css @@ -0,0 +1,131 @@ +body { + width: 1000px; + font-size: 13px; + color: #000000; + padding: 0; + margin: 0 auto; + background: #444444; + font-family: verdana,arial; +} + +table { + border-width: 3px; + border-color: #0000FF; + border-style: ridge; + margin-top: 5px; + background-color: #E0E0FF; +} + +table.blind { + border: none; + background-color: #E6E6E6; +} + +fieldset.blind { + border: none; +} + +h1 { font-size: 160%; } +h2 { font-size: 140%; } +h3 { font-size: 115%; } + +.indent { + margin-left: 25px; +} + +p +{ + margin-left: 10px; +} + +li +{ + margin: 10px; +} + + +dl +{ + /*width: 80%;*/ + border-bottom: 1px solid #999; +} + +dt +{ + padding-top: 5px; + font-weight: bold; + border-top: 1px solid #999; +} + +dd +{ + padding: 5px; +} + + +hr { + color: #688938; +} + +a:link, a:visited { + color: #0000BF; +} +a:hover { + color: #0000FF; +} + +a.nav { + position: relative; + top: -30px; + display: block; + visibility: hidden; +} + +#navbar { + width: 1000px; + height: 30px; + background-color:#1a1a1b; + position: fixed; + margin: 0 auto; + padding: 0; +} + +#navbar ul +{ + list-style-type: none; + margin: 0 auto; + padding: 0; + overflow: hidden; +} + +#navbar li +{ + margin: 0 auto; + padding: 5px; + float:left; +} + +#navbar a:link,a:visited +{ + display:block; + width:150px; + font-weight:bold; + color:#e85d02; + text-align:center; + /*padding:4px;*/ + text-decoration:none; + /*text-transform:uppercase;*/ +} + +#navbar a:hover,a:active +{ + color:#ffffff; +} + +#content { + background-color:#ffffff; + padding: 15px; + padding-top: 40px; + padding-right: 40px; + margin: 0 auto; +} diff --git a/tracker-pt/ftnoir_tracker_pt.cpp b/tracker-pt/ftnoir_tracker_pt.cpp new file mode 100644 index 00000000..15a60962 --- /dev/null +++ b/tracker-pt/ftnoir_tracker_pt.cpp @@ -0,0 +1,219 @@ +/* Copyright (c) 2012 Patrick Ruoff + * Copyright (c) 2014-2015 Stanislaw Halik + * + * 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_tracker_pt.h" +#include +#include +#include +#include +#include +#include "opentrack/camera-names.hpp" + +//#define PT_PERF_LOG //log performance + +//----------------------------------------------------------------------------- +Tracker_PT::Tracker_PT() + : mutex(QMutex::Recursive), + commands(0), + video_widget(NULL), + video_frame(NULL), + ever_success(false) +{ + connect(s.b.get(), SIGNAL(saving()), this, SLOT(apply_settings())); +} + +Tracker_PT::~Tracker_PT() +{ + set_command(ABORT); + wait(); + delete video_widget; + video_widget = NULL; + if (video_frame->layout()) delete video_frame->layout(); + camera.stop(); +} + +void Tracker_PT::set_command(Command command) +{ + //QMutexLocker lock(&mutex); + commands |= command; +} + +void Tracker_PT::reset_command(Command command) +{ + //QMutexLocker lock(&mutex); + commands &= ~command; +} + +bool Tracker_PT::get_focal_length(float& ret) +{ + QMutexLocker l(&camera_mtx); + CamInfo info; + const bool res = camera.get_info(info); + if (res) + { + static constexpr double pi = 3.14159265359; + const int w = info.res_x, h = info.res_y; + const double diag = sqrt(1. + h/(double)w * h/(double)w); + const double diag_fov = static_cast(s.fov) * pi / 180.; + const double fov = 2.*atan(tan(diag_fov/2.0)/diag); + ret = .5 / tan(.5 * fov); + return true; + } + return false; +} + +void Tracker_PT::run() +{ +#ifdef PT_PERF_LOG + QFile log_file(QCoreApplication::applicationDirPath() + "/PointTrackerPerformance.txt"); + if (!log_file.open(QIODevice::WriteOnly | QIODevice::Text)) return; + QTextStream log_stream(&log_file); +#endif + + apply_settings(); + + while((commands & ABORT) == 0) + { + const double dt = time.elapsed() * 1e-9; + time.start(); + cv::Mat frame; + bool new_frame; + + { + QMutexLocker l(&camera_mtx); + new_frame = camera.get_frame(dt, &frame); + } + + if (new_frame && !frame.empty()) + { + QMutexLocker lock(&mutex); + + std::vector points = point_extractor.extract_points(frame); + + // blobs are sorted in order of circularity + if (points.size() > PointModel::N_POINTS) + points.resize(PointModel::N_POINTS); + + bool success = points.size() == PointModel::N_POINTS; + + float fx; + if (!get_focal_length(fx)) + continue; + + if (success) + { + point_tracker.track(points, PointModel(s), fx, s.dynamic_pose, s.init_phase_timeout); + } + + Affine X_CM = pose(); + + ever_success |= success; + + { + Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); // just copy pasted these lines from below + Affine X_GH = X_CM * X_MH; + cv::Vec3f p = X_GH.t; // head (center?) position in global space + cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx); // projected to screen + points.push_back(p_); + } + + for (unsigned i = 0; i < points.size(); i++) + { + auto& p = points[i]; + auto p2 = cv::Point(p[0] * frame.cols + frame.cols/2, -p[1] * frame.cols + frame.rows/2); + cv::Scalar color(0, 255, 0); + if (i == points.size()-1) + color = cv::Scalar(0, 0, 255); + cv::line(frame, + cv::Point(p2.x - 20, p2.y), + cv::Point(p2.x + 20, p2.y), + color, + 4); + cv::line(frame, + cv::Point(p2.x, p2.y - 20), + cv::Point(p2.x, p2.y + 20), + color, + 4); + } + + video_widget->update_image(frame); + } +#ifdef PT_PERF_LOG + log_stream<<"dt: "<video_frame = parent_window; + video_frame->setAttribute(Qt::WA_NativeWindow); + video_frame->show(); + video_widget = new PTVideoWidget(video_frame); + QHBoxLayout* video_layout = new QHBoxLayout(parent_window); + video_layout->setContentsMargins(0, 0, 0, 0); + video_layout->addWidget(video_widget); + video_frame->setLayout(video_layout); + video_widget->resize(video_frame->width(), video_frame->height()); + start(); +} + +void Tracker_PT::data(double *data) +{ + if (ever_success) + { + Affine X_CM = pose(); + + Affine X_MH(cv::Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z)); + Affine X_GH = X_CM * X_MH; + + cv::Matx33f R = X_GH.R; + cv::Vec3f t = X_GH.t; + + // translate rotation matrix from opengl (G) to roll-pitch-yaw (E) frame + // -z -> x, y -> z, x -> -y + cv::Matx33f R_EG(0, 0,-1, + -1, 0, 0, + 0, 1, 0); + R = R_EG * R * R_EG.t(); + + // extract rotation angles + float alpha, beta, gamma; + beta = atan2( -R(2,0), sqrt(R(2,1)*R(2,1) + R(2,2)*R(2,2)) ); + alpha = atan2( R(1,0), R(0,0)); + gamma = atan2( R(2,1), R(2,2)); + + // extract rotation angles + data[Yaw] = rad2deg * alpha; + data[Pitch] = -rad2deg * beta; + data[Roll] = rad2deg * gamma; + // get translation(s) + data[TX] = t[0] / 10.0; // convert to cm + data[TY] = t[1] / 10.0; + data[TZ] = t[2] / 10.0; + } +} + +#include "ftnoir_tracker_pt_dialog.h" +OPENTRACK_DECLARE_TRACKER(Tracker_PT, TrackerDialog_PT, TrackerDll) + diff --git a/tracker-pt/ftnoir_tracker_pt.h b/tracker-pt/ftnoir_tracker_pt.h new file mode 100644 index 00000000..f73d106b --- /dev/null +++ b/tracker-pt/ftnoir_tracker_pt.h @@ -0,0 +1,86 @@ +/* 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. + */ + +#ifndef FTNOIR_TRACKER_PT_H +#define FTNOIR_TRACKER_PT_H + +#include "opentrack/plugin-api.hpp" +#include "ftnoir_tracker_pt_settings.h" +#include "camera.h" +#include "point_extractor.h" +#include "point_tracker.h" +#include "pt_video_widget.h" +#include "opentrack-compat/timer.hpp" +#include "opentrack/opencv-camera-dialog.hpp" + +#include +#include +#include +#include +#include +#include +#include + +class TrackerDialog_PT; + +//----------------------------------------------------------------------------- +// Constantly processes the tracking chain in a separate thread +class Tracker_PT : public QThread, public ITracker +{ + Q_OBJECT + friend class camera_dialog; + friend class TrackerDialog_PT; +public: + Tracker_PT(); + ~Tracker_PT() override; + void start_tracker(QFrame* parent_window) override; + void data(double* data) override; + + Affine pose() { QMutexLocker lock(&mutex); return point_tracker.pose(); } + int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); } + bool get_cam_info(CamInfo* info) { QMutexLocker lock(&camera_mtx); return camera.get_info(*info); } +public slots: + void apply_settings(); +protected: + void run() override; +private: + QMutex mutex; + // thread commands + enum Command { + ABORT = 1<<0 + }; + void set_command(Command command); + void reset_command(Command command); + + bool get_focal_length(float &ret); + + volatile int commands; + + QMutex camera_mtx; + CVCamera camera; + PointExtractor point_extractor; + PointTracker point_tracker; + + PTVideoWidget* video_widget; + QFrame* video_frame; + + settings_pt s; + Timer time; + + volatile bool ever_success; + + static constexpr double rad2deg = 180.0/3.14159265; + static constexpr double deg2rad = 3.14159265/180.0; +}; + +class TrackerDll : public Metadata +{ + QString name() { return QString("PointTracker 1.1"); } + QIcon icon() { return QIcon(":/Resources/Logo_IR.png"); } +}; + +#endif // FTNOIR_TRACKER_PT_H diff --git a/tracker-pt/ftnoir_tracker_pt.qrc b/tracker-pt/ftnoir_tracker_pt.qrc new file mode 100644 index 00000000..a8f9a1af --- /dev/null +++ b/tracker-pt/ftnoir_tracker_pt.qrc @@ -0,0 +1,9 @@ + + + Resources/cap_front.png + Resources/cap_side.png + Resources/clip_front.png + Resources/clip_side.png + Resources/Logo_IR.png + + diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.cpp b/tracker-pt/ftnoir_tracker_pt_dialog.cpp new file mode 100644 index 00000000..b1ae2238 --- /dev/null +++ b/tracker-pt/ftnoir_tracker_pt_dialog.cpp @@ -0,0 +1,182 @@ +/* Copyright (c) 2012 Patrick Ruoff + * Copyright (c) 2014-2015 Stanislaw Halik + * + * 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_tracker_pt_dialog.h" + +#include +#include +#include +#include +#include "opentrack/camera-names.hpp" +#include + +//----------------------------------------------------------------------------- +TrackerDialog_PT::TrackerDialog_PT() + : tracker(NULL), + timer(this), + trans_calib_running(false) +{ + ui.setupUi( this ); + + ui.camdevice_combo->addItems(get_camera_names()); + + tie_setting(s.camera_name, ui.camdevice_combo); + tie_setting(s.cam_res_x, ui.res_x_spin); + tie_setting(s.cam_res_y, ui.res_y_spin); + tie_setting(s.cam_fps, ui.fps_spin); + + tie_setting(s.threshold, ui.threshold_slider); + + tie_setting(s.min_point_size, ui.mindiam_spin); + tie_setting(s.max_point_size, ui.maxdiam_spin); + + tie_setting(s.clip_by, ui.clip_bheight_spin); + tie_setting(s.clip_bz, ui.clip_blength_spin); + tie_setting(s.clip_ty, ui.clip_theight_spin); + tie_setting(s.clip_tz, ui.clip_tlength_spin); + + tie_setting(s.cap_x, ui.cap_width_spin); + tie_setting(s.cap_y, ui.cap_height_spin); + tie_setting(s.cap_z, ui.cap_length_spin); + + tie_setting(s.m01_x, ui.m1x_spin); + tie_setting(s.m01_y, ui.m1y_spin); + tie_setting(s.m01_z, ui.m1z_spin); + + tie_setting(s.m02_x, ui.m2x_spin); + tie_setting(s.m02_y, ui.m2y_spin); + tie_setting(s.m02_z, ui.m2z_spin); + + tie_setting(s.t_MH_x, ui.tx_spin); + tie_setting(s.t_MH_y, ui.ty_spin); + tie_setting(s.t_MH_z, ui.tz_spin); + + tie_setting(s.fov, ui.fov); + + tie_setting(s.active_model_panel, ui.model_tabs); + + tie_setting(s.dynamic_pose, ui.dynamic_pose); + tie_setting(s.init_phase_timeout, ui.init_phase_timeout); + + tie_setting(s.auto_threshold, ui.auto_threshold); + + connect( ui.tcalib_button,SIGNAL(toggled(bool)), this,SLOT(startstop_trans_calib(bool)) ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info())); + connect(ui.camera_settings, SIGNAL(pressed()), this, SLOT(camera_settings())); + timer.start(100); +} + +void TrackerDialog_PT::camera_settings() +{ + if (tracker) + open_camera_settings(static_cast(tracker->camera), s.camera_name, &tracker->camera_mtx); + else + open_camera_settings(nullptr, s.camera_name, nullptr); +} + +void TrackerDialog_PT::startstop_trans_calib(bool start) +{ + if (start) + { + qDebug()<<"TrackerDialog:: Starting translation calibration"; + trans_calib.reset(); + trans_calib_running = true; + s.t_MH_x = 0; + s.t_MH_y = 0; + s.t_MH_z = 0; + } + else + { + qDebug()<<"TrackerDialog:: Stopping translation calibration"; + trans_calib_running = false; + { + auto tmp = trans_calib.get_estimate(); + s.t_MH_x = tmp[0]; + s.t_MH_y = tmp[1]; + s.t_MH_z = tmp[2]; + } + } +} + +void TrackerDialog_PT::poll_tracker_info() +{ + CamInfo info; + if (tracker && tracker->get_cam_info(&info)) + { + QString to_print; + { + // display caminfo + to_print = QString::number(info.res_x)+"x"+QString::number(info.res_y)+" @ "+QString::number(info.fps)+" FPS"; + } + ui.caminfo_label->setText(to_print); + + // display pointinfo + int n_points = tracker->get_n_points(); + to_print = QString::number(n_points); + if (n_points == 3) + to_print += " OK!"; + else + to_print += " BAD!"; + ui.pointinfo_label->setText(to_print); + + // update calibration + if (trans_calib_running) trans_calib_step(); + } + else + { + ui.caminfo_label->setText("Tracker offline"); + ui.pointinfo_label->setText(""); + } +} + +void TrackerDialog_PT::trans_calib_step() +{ + if (tracker) + { + Affine X_CM = tracker->pose(); + trans_calib.update(X_CM.R, X_CM.t); + } +} + +void TrackerDialog_PT::save() +{ + s.b->save(); +} + +void TrackerDialog_PT::doOK() +{ + save(); + close(); +} + +void TrackerDialog_PT::doCancel() +{ + s.b->reload(); + close(); +} + +void TrackerDialog_PT::register_tracker(ITracker *t) +{ + qDebug()<<"TrackerDialog:: Tracker registered"; + tracker = static_cast(t); + ui.tcalib_button->setEnabled(true); + //ui.center_button->setEnabled(true); +} + +void TrackerDialog_PT::unregister_tracker() +{ + qDebug()<<"TrackerDialog:: Tracker un-registered"; + tracker = NULL; + ui.tcalib_button->setEnabled(false); + //ui.center_button->setEnabled(false); +} + diff --git a/tracker-pt/ftnoir_tracker_pt_dialog.h b/tracker-pt/ftnoir_tracker_pt_dialog.h new file mode 100644 index 00000000..3502e227 --- /dev/null +++ b/tracker-pt/ftnoir_tracker_pt_dialog.h @@ -0,0 +1,51 @@ +/* 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. + */ + +#ifndef FTNOIR_TRACKER_PT_DIALOG_H +#define FTNOIR_TRACKER_PT_DIALOG_H + +#include "opentrack/plugin-api.hpp" +#include "ftnoir_tracker_pt_settings.h" +#include "ftnoir_tracker_pt.h" +#include "trans_calib.h" +#include "pt_video_widget.h" +#include "ui_FTNoIR_PT_Controls.h" +#include "opentrack/opencv-camera-dialog.hpp" + +#include + +//----------------------------------------------------------------------------- +// The dialog that shows up when the user presses "Settings" +class TrackerDialog_PT : public ITrackerDialog, protected camera_dialog +{ + Q_OBJECT +public: + TrackerDialog_PT(); + void register_tracker(ITracker *tracker) override; + void unregister_tracker() override; + void save(); + void trans_calib_step(); + +public slots: + void doOK(); + void doCancel(); + + void startstop_trans_calib(bool start); + void poll_tracker_info(); + void camera_settings(); +private: + settings_pt s; + Tracker_PT* tracker; + QTimer timer; + + TranslationCalibrator trans_calib; + bool trans_calib_running; + + Ui::UICPTClientControls ui; +}; + +#endif //FTNOIR_TRACKER_PT_DIALOG_H diff --git a/tracker-pt/ftnoir_tracker_pt_settings.h b/tracker-pt/ftnoir_tracker_pt_settings.h new file mode 100644 index 00000000..85eec8f9 --- /dev/null +++ b/tracker-pt/ftnoir_tracker_pt_settings.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2012 Patrick Ruoff + * Copyright (c) 2014-2015 Stanislaw Halik + * + * 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. + */ + +#ifndef FTNOIR_TRACKER_PT_SETTINGS_H +#define FTNOIR_TRACKER_PT_SETTINGS_H + +#include "opentrack/options.hpp" +using namespace options; + +struct settings_pt : opts +{ + value camera_name; + value cam_res_x, + cam_res_y, + cam_fps, + threshold; + value min_point_size, max_point_size; + + value m01_x, m01_y, m01_z; + value m02_x, m02_y, m02_z; + + value t_MH_x, t_MH_y, t_MH_z; + + value clip_ty, clip_tz, clip_by, clip_bz; + value active_model_panel, cap_x, cap_y, cap_z; + + value fov; + + value dynamic_pose; + value init_phase_timeout; + value auto_threshold; + + settings_pt() : + opts("tracker-pt"), + camera_name(b, "camera-name", ""), + cam_res_x(b, "camera-res-width", 640), + cam_res_y(b, "camera-res-height", 480), + cam_fps(b, "camera-fps", 30), + threshold(b, "threshold-primary", 128), + min_point_size(b, "min-point-size", 1), + max_point_size(b, "max-point-size", 50), + m01_x(b, "m_01-x", 0), + m01_y(b, "m_01-y", 0), + m01_z(b, "m_01-z", 0), + m02_x(b, "m_02-x", 0), + m02_y(b, "m_02-y", 0), + m02_z(b, "m_02-z", 0), + t_MH_x(b, "model-centroid-x", 0), + t_MH_y(b, "model-centroid-y", 0), + t_MH_z(b, "model-centroid-z", 0), + clip_ty(b, "clip-ty", 40), + clip_tz(b, "clip-tz", 30), + clip_by(b, "clip-by", 70), + clip_bz(b, "clip-bz", 80), + active_model_panel(b, "active-model-panel", 0), + cap_x(b, "cap-x", 40), + cap_y(b, "cap-y", 60), + cap_z(b, "cap-z", 100), + fov(b, "camera-fov", 56), + dynamic_pose(b, "dynamic-pose-resolution", true), + init_phase_timeout(b, "init-phase-timeout", 500), + auto_threshold(b, "automatic-threshold", false) + {} +}; + +#endif //FTNOIR_TRACKER_PT_SETTINGS_H diff --git a/tracker-pt/point_extractor.cpp b/tracker-pt/point_extractor.cpp new file mode 100644 index 00000000..ec37dd00 --- /dev/null +++ b/tracker-pt/point_extractor.cpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2012 Patrick Ruoff + * Copyright (c) 2014-2015 Stanislaw Halik + * + * 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 "point_extractor.h" +#include + +#ifdef DEBUG_EXTRACTION +# include "opentrack-compat/timer.hpp" +#endif + +PointExtractor::PointExtractor(){ + //if (!AllocConsole()){} + //else SetConsoleTitle("debug"); + //freopen("CON", "w", stdout); + //freopen("CON", "w", stderr); +} +// ---------------------------------------------------------------------------- +std::vector PointExtractor::extract_points(cv::Mat& frame) +{ + const int W = frame.cols; + const int H = frame.rows; + + // convert to grayscale + cv::Mat frame_gray; + cv::cvtColor(frame, frame_gray, cv::COLOR_RGB2GRAY); + + const double region_size_min = s.min_point_size; + const double region_size_max = s.max_point_size; + + struct blob + { + double radius; + cv::Vec2d pos; + double confid; + bool taken; + double area; + blob(double radius, const cv::Vec2d& pos, double confid, double area) : radius(radius), pos(pos), confid(confid), taken(false), area(area) + { + //qDebug() << "radius" << radius << "pos" << pos[0] << pos[1] << "confid" << confid; + } + bool inside(const blob& other) + { + cv::Vec2d tmp = pos - other.pos; + return sqrt(tmp.dot(tmp)) < radius; + } + }; + + // mask for everything that passes the threshold (or: the upper threshold of the hysteresis) + cv::Mat frame_bin = cv::Mat::zeros(H, W, CV_8U); + + std::vector blobs; + std::vector> contours; + + const int thres = s.threshold; + if (!s.auto_threshold) + { + cv::Mat frame_bin_; + cv::threshold(frame_gray, frame_bin_, thres, 255, cv::THRESH_BINARY); + frame_bin.setTo(170, frame_bin_); + cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + } + else + { + cv::Mat hist; + cv::calcHist(std::vector { frame_gray }, + std::vector { 0 }, + cv::Mat(), + hist, + std::vector { 256 }, + std::vector { 0, 256 }, + false); + const int sz = hist.rows*hist.cols; + int val = 0; + int cnt = 0; + constexpr int min_pixels = 250; + const auto pixels_to_include = std::max(0, min_pixels * s.threshold/100.); + for (int i = sz-1; i >= 0; i--) + { + cnt += hist.at(i); + if (cnt >= pixels_to_include) + { + val = i; + break; + } + } + val *= 240./256.; + //qDebug() << "val" << val; + + cv::Mat frame_bin_; + cv::threshold(frame_gray, frame_bin_, val, 255, CV_THRESH_BINARY); + frame_bin.setTo(170, frame_bin_); + cv::findContours(frame_bin_, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); + } + + int cnt = 0; + + for (auto& c : contours) + { + if (cnt++ > 30) + break; + + const auto m = cv::moments(cv::Mat(c)); + const double area = m.m00; + if (area == 0.) + continue; + const cv::Vec2d pos(m.m10 / m.m00, m.m01 / m.m00); + + double radius; +// following based on OpenCV SimpleBlobDetector + { + std::vector dists; + for (auto& k : c) + { + dists.push_back(cv::norm(pos - cv::Vec2d(k.x, k.y))); + } + std::sort(dists.begin(), dists.end()); + radius = (dists[(dists.size() - 1)/2] + dists[dists.size()/2])/2; + } + + if (radius < region_size_min || radius > region_size_max) + continue; + + double confid = 1; + { + double denominator = std::sqrt(std::pow(2 * m.mu11, 2) + std::pow(m.mu20 - m.mu02, 2)); + const double eps = 1e-2; + if (denominator > eps) + { + double cosmin = (m.mu20 - m.mu02) / denominator; + double sinmin = 2 * m.mu11 / denominator; + double cosmax = -cosmin; + double sinmax = -sinmin; + + double imin = 0.5 * (m.mu20 + m.mu02) - 0.5 * (m.mu20 - m.mu02) * cosmin - m.mu11 * sinmin; + double imax = 0.5 * (m.mu20 + m.mu02) - 0.5 * (m.mu20 - m.mu02) * cosmax - m.mu11 * sinmax; + confid = imin / imax; + } + } +// end SimpleBlobDetector + + { + char buf[64]; + sprintf(buf, "%.2fpx %.2fc", radius, confid); + cv::putText(frame, buf, cv::Point(pos[0]+30, pos[1]+20), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 255), 1); + } + + blobs.push_back(blob(radius, pos, confid, area)); + } + + // clear old points + points.clear(); + + using b = const blob; + std::sort(blobs.begin(), blobs.end(), [](b& b1, b& b2) {return b1.confid > b2.confid;}); + + for (auto& b : blobs) + { + cv::Vec2f p((b.pos[0] - W/2)/W, -(b.pos[1] - H/2)/W); + points.push_back(p); + } + + // draw output image + std::vector channels_; + cv::split(frame, channels_); + std::vector channels; + { + cv::Mat frame_bin__ = frame_bin * .5; + channels.push_back(channels_[0] + frame_bin__); + channels.push_back(channels_[1] - frame_bin__); + channels.push_back(channels_[2] - frame_bin__); + cv::merge(channels, frame); + } + + return points; +} diff --git a/tracker-pt/point_extractor.h b/tracker-pt/point_extractor.h new file mode 100644 index 00000000..b9368ab6 --- /dev/null +++ b/tracker-pt/point_extractor.h @@ -0,0 +1,33 @@ +/* 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. + */ + +#ifndef POINTEXTRACTOR_H +#define POINTEXTRACTOR_H + +#include +#include + +#include "ftnoir_tracker_pt_settings.h" + +// ---------------------------------------------------------------------------- +// Extracts points from an opencv image +class PointExtractor +{ +public: + // extracts points from frame and draws some processing info into frame, if draw_output is set + // dt: time since last call in seconds + // WARNING: returned reference is valid as long as object + std::vector extract_points(cv::Mat &frame); + const std::vector& get_points() { return points; } + PointExtractor(); + + settings_pt s; +private: + std::vector points; +}; + +#endif //POINTEXTRACTOR_H diff --git a/tracker-pt/point_tracker.cpp b/tracker-pt/point_tracker.cpp new file mode 100644 index 00000000..924b75de --- /dev/null +++ b/tracker-pt/point_tracker.cpp @@ -0,0 +1,267 @@ +/* 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. + */ + +#include "point_tracker.h" + +#include +#include +#include + +#include + +const float PI = 3.14159265358979323846f; + +static void get_row(const cv::Matx33f& m, int i, cv::Vec3f& v) +{ + v[0] = m(i,0); + v[1] = m(i,1); + v[2] = m(i,2); +} + +static void set_row(cv::Matx33f& m, int i, const cv::Vec3f& v) +{ + m(i,0) = v[0]; + m(i,1) = v[1]; + m(i,2) = v[2]; +} + +static bool d_vals_sort(const std::pair a, const std::pair b) +{ + return a.first < b.first; +} + +void PointModel::get_d_order(const std::vector& points, int d_order[], cv::Vec2f d) const +{ + // fit line to orthographically projected points + std::vector> d_vals; + // get sort indices with respect to d scalar product + for (unsigned i = 0; i(d.dot(points[i]), i)); + + std::sort(d_vals.begin(), + d_vals.end(), + d_vals_sort + ); + + for (unsigned i = 0; i& points, const PointModel& model, float f) +{ + PointTracker::PointOrder p; + p.points[0] = project(cv::Vec3f(0,0,0), f); + p.points[1] = project(model.M01, f); + p.points[2] = project(model.M02, f); + + // set correspondences by minimum distance to projected model point + bool point_taken[PointModel::N_POINTS]; + for (int i=0; i& points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout) +{ + PointOrder order; + + if (t.elapsed_ms() > init_phase_timeout) + { + t.start(); + init_phase = true; + } + + if (!dynamic_pose || init_phase) + order = find_correspondences(points, model); + else + order = find_correspondences_previous(points, model, f); + + POSIT(model, order, f); + init_phase = false; + t.start(); +} + +PointTracker::PointOrder PointTracker::find_correspondences(const std::vector& points, const PointModel& model) +{ + // We do a simple freetrack-like sorting in the init phase... + // sort points + int point_d_order[PointModel::N_POINTS]; + int model_d_order[PointModel::N_POINTS]; + cv::Vec2f d(model.M01[0]-model.M02[0], model.M01[1]-model.M02[1]); + model.get_d_order(points, point_d_order, d); + // calculate d and d_order for simple freetrack-like point correspondence + model.get_d_order(std::vector { + cv::Vec2f{0,0}, + cv::Vec2f(model.M01[0], model.M01[1]), + cv::Vec2f(model.M02[0], model.M02[1]) + }, + model_d_order, + d); + // set correspondences + PointOrder p; + for (int i=0; i and + cv::Vec2f I0_M0i(order[1][0]*(1.0 + epsilon_1) - order[0][0], + order[2][0]*(1.0 + epsilon_2) - order[0][0]); + cv::Vec2f J0_M0i(order[1][1]*(1.0 + epsilon_1) - order[0][1], + order[2][1]*(1.0 + epsilon_2) - order[0][1]); + + // construct projection of I, J onto M0i plane: I0 and J0 + I0_coeff = model.P * I0_M0i; + J0_coeff = model.P * J0_M0i; + I0 = I0_coeff[0]*model.M01 + I0_coeff[1]*model.M02; + J0 = J0_coeff[0]*model.M01 + J0_coeff[1]*model.M02; + + // calculate u component of I, J + float II0 = I0.dot(I0); + float IJ0 = I0.dot(J0); + float JJ0 = J0.dot(J0); + float rho, theta; + if (JJ0 == II0) { + rho = std::sqrt(std::abs(2*IJ0)); + theta = -PI/4; + if (IJ0<0) theta *= -1; + } + else { + rho = sqrt(sqrt( (JJ0-II0)*(JJ0-II0) + 4*IJ0*IJ0 )); + theta = atan( -2*IJ0 / (JJ0-II0) ); + if (JJ0 - II0 < 0) theta += PI; + theta /= 2; + } + + // construct the two solutions + I_1 = I0 + rho*cos(theta)*model.u; + I_2 = I0 - rho*cos(theta)*model.u; + + J_1 = J0 + rho*sin(theta)*model.u; + J_2 = J0 - rho*sin(theta)*model.u; + + float norm_const = 1.0/cv::norm(I_1); // all have the same norm + + // create rotation matrices + I_1 *= norm_const; J_1 *= norm_const; + I_2 *= norm_const; J_2 *= norm_const; + + set_row(R_1, 0, I_1); + set_row(R_1, 1, J_1); + set_row(R_1, 2, I_1.cross(J_1)); + + set_row(R_2, 0, I_2); + set_row(R_2, 1, J_2); + set_row(R_2, 2, I_2.cross(J_2)); + + // the single translation solution + Z0 = norm_const * focal_length; + + // pick the rotation solution closer to the expected one + // in simple metric d(A,B) = || I - A * B^T || + float R_1_deviation = cv::norm(cv::Matx33f::eye() - R_expected * R_1.t()); + float R_2_deviation = cv::norm(cv::Matx33f::eye() - R_expected * R_2.t()); + + if (R_1_deviation < R_2_deviation) + R_current = &R_1; + else + R_current = &R_2; + + get_row(*R_current, 2, k); + + // check for convergence condition + if (std::abs(epsilon_1 - old_epsilon_1) + std::abs(epsilon_2 - old_epsilon_2) < EPS_THRESHOLD) + break; + old_epsilon_1 = epsilon_1; + old_epsilon_2 = epsilon_2; + } + + // apply results + X_CM.R = *R_current; + X_CM.t[0] = order[0][0] * Z0/focal_length; + X_CM.t[1] = order[0][1] * Z0/focal_length; + X_CM.t[2] = Z0; + + //qDebug() << "iter:" << i; + + return i; +} + +cv::Vec2f PointTracker::project(const cv::Vec3f& v_M, float f) +{ + cv::Vec3f v_C = X_CM * v_M; + return cv::Vec2f(f*v_C[0]/v_C[2], f*v_C[1]/v_C[2]); +} diff --git a/tracker-pt/point_tracker.h b/tracker-pt/point_tracker.h new file mode 100644 index 00000000..fd002948 --- /dev/null +++ b/tracker-pt/point_tracker.h @@ -0,0 +1,147 @@ +/* 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. + */ + +#ifndef POINTTRACKER_H +#define POINTTRACKER_H + +#include +#include +#include +#include "opentrack-compat/timer.hpp" +#include "ftnoir_tracker_pt_settings.h" + +#include + +// ---------------------------------------------------------------------------- +// Affine frame trafo +class Affine +{ +public: + Affine() : R(cv::Matx33f::eye()), t(0,0,0) {} + Affine(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {} + + cv::Matx33f R; + cv::Vec3f t; +}; + +inline Affine operator*(const Affine& X, const Affine& Y) +{ + return Affine(X.R*Y.R, X.R*Y.t + X.t); +} + +inline Affine operator*(const cv::Matx33f& X, const Affine& Y) +{ + return Affine(X*Y.R, X*Y.t); +} + +inline Affine operator*(const Affine& X, const cv::Matx33f& Y) +{ + return Affine(X.R*Y, X.t); +} + +inline cv::Vec3f operator*(const Affine& X, const cv::Vec3f& v) +{ + return X.R*v + X.t; +} + + +// ---------------------------------------------------------------------------- +// Describes a 3-point model +// nomenclature as in +// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] +class PointModel +{ + friend class PointTracker; +public: + static constexpr int N_POINTS = 3; + + cv::Vec3f M01; // M01 in model frame + cv::Vec3f M02; // M02 in model frame + + cv::Vec3f u; // unit vector perpendicular to M01,M02-plane + + cv::Matx22f P; + + enum Model { Clip = 0, Cap = 1, Custom = 2 }; + + PointModel(settings_pt& s) + { + set_model(s); + // calculate u + u = M01.cross(M02); + u /= norm(u); + + // calculate projection matrix on M01,M02 plane + float s11 = M01.dot(M01); + float s12 = M01.dot(M02); + float s22 = M02.dot(M02); + P = 1.0/(s11*s22-s12*s12) * cv::Matx22f(s22, -s12, -s12, s11); + } + + void set_model(settings_pt& s) + { + switch (s.active_model_panel) + { + case Clip: + M01 = cv::Vec3f(0, static_cast(s.clip_ty), -static_cast(s.clip_tz)); + M02 = cv::Vec3f(0, -static_cast(s.clip_by), -static_cast(s.clip_bz)); + break; + case Cap: + M01 = cv::Vec3f(-static_cast(s.cap_x), -static_cast(s.cap_y), -static_cast(s.cap_z)); + M02 = cv::Vec3f(static_cast(s.cap_x), -static_cast(s.cap_y), -static_cast(s.cap_z)); + break; + case Custom: + M01 = cv::Vec3f(s.m01_x, s.m01_y, s.m01_z); + M02 = cv::Vec3f(s.m02_x, s.m02_y, s.m02_z); + break; + } + } + + void get_d_order(const std::vector& points, int* d_order, cv::Vec2f d) const; +}; + +// ---------------------------------------------------------------------------- +// Tracks a 3-point model +// implementing the POSIT algorithm for coplanar points as presented in +// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] +class PointTracker +{ +public: + PointTracker(); + // track the pose using the set of normalized point coordinates (x pos in range -0.5:0.5) + // f : (focal length)/(sensor width) + // dt : time since last call + void track(const std::vector& projected_points, const PointModel& model, float f, bool dynamic_pose, int init_phase_timeout); + Affine pose() const { return X_CM; } + cv::Vec2f project(const cv::Vec3f& v_M, float f); + void reset(const Affine& pose) + { + X_CM = pose; + } +private: + // the points in model order + struct PointOrder + { + cv::Vec2f points[PointModel::N_POINTS]; + PointOrder() + { + for (int i = 0; i < PointModel::N_POINTS; i++) + points[i] = cv::Vec2f(0, 0); + } + }; + + PointOrder find_correspondences(const std::vector& projected_points, const PointModel &model); + PointOrder find_correspondences_previous(const std::vector& points, const PointModel &model, float f); + int POSIT(const PointModel& point_model, const PointOrder& order, float focal_length); // The POSIT algorithm, returns the number of iterations + + Affine X_CM; // trafo from model to camera + + Timer t; + bool init_phase; +}; + +#endif //POINTTRACKER_H diff --git a/tracker-pt/pt_video_widget.cpp b/tracker-pt/pt_video_widget.cpp new file mode 100644 index 00000000..cbb7c268 --- /dev/null +++ b/tracker-pt/pt_video_widget.cpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2012 Patrick Ruoff + * Copyright (c) 2015 Stanislaw Halik + * + * 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. + * + * 20130312, WVR: Add 7 lines to resizeGL after resize_frame. This should lower CPU-load. + */ + +#include "pt_video_widget.h" + +void PTVideoWidget::update_image(const cv::Mat& frame) +{ + QMutexLocker foo(&mtx); + + if (!freshp) + { + _frame = frame.clone(); + freshp = true; + } +} + +void PTVideoWidget::update_and_repaint() +{ + QImage qframe; + { + QMutexLocker foo(&mtx); + if (_frame.empty() || !freshp) + return; + qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888); + freshp = false; + uchar* data = qframe.bits(); + const int pitch = qframe.bytesPerLine(); + unsigned char *input = (unsigned char*) _frame.data; + const int chans = _frame.channels(); + for (int y = 0; y < _frame.rows; y++) + { + const int step = y * _frame.step; + const int pitch_ = y * pitch; + for (int x = 0; x < _frame.cols; x++) + { + data[pitch_ + x * 3 + 0] = input[step + x * chans + 2]; + data[pitch_ + x * 3 + 1] = input[step + x * chans + 1]; + data[pitch_ + x * 3 + 2] = input[step + x * chans + 0]; + } + } + } + qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation); + { + QMutexLocker foo(&mtx); + texture = qframe; + } + update(); +} diff --git a/tracker-pt/pt_video_widget.h b/tracker-pt/pt_video_widget.h new file mode 100644 index 00000000..af1d60fd --- /dev/null +++ b/tracker-pt/pt_video_widget.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2012 Patrick Ruoff + * Copyright (c) 2014 Stanislaw Halik + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +class PTVideoWidget : public QWidget +{ + Q_OBJECT + +public: + PTVideoWidget(QWidget *parent) : + QWidget(parent), + freshp(false) + { + connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint())); + timer.start(40); + } + void update_image(const cv::Mat &frame); +protected slots: + void paintEvent( QPaintEvent* e ) { + QMutexLocker foo(&mtx); + QPainter painter(this); + painter.drawImage(e->rect(), texture); + } + void update_and_repaint(); +private: + QMutex mtx; + QImage texture; + QTimer timer; + cv::Mat _frame; + bool freshp; +}; diff --git a/tracker-pt/trans_calib.cpp b/tracker-pt/trans_calib.cpp new file mode 100644 index 00000000..a1a4b641 --- /dev/null +++ b/tracker-pt/trans_calib.cpp @@ -0,0 +1,41 @@ +/* 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. + */ + +#include "trans_calib.h" + +TranslationCalibrator::TranslationCalibrator() +{ + reset(); +} + +void TranslationCalibrator::reset() +{ + P = cv::Matx66f::zeros(); + y = cv::Vec6f(0,0,0, 0,0,0); +} + +void TranslationCalibrator::update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k) +{ + cv::Matx H_k_T = cv::Matx::zeros(); + for (int i=0; i<3; ++i) { + for (int j=0; j<3; ++j) { + H_k_T(i,j) = R_CM_k(j,i); + } + } + for (int i=0; i<3; ++i) + { + H_k_T(3+i,i) = 1.0; + } + P += H_k_T * H_k_T.t(); + y += H_k_T * t_CM_k; +} + +cv::Vec3f TranslationCalibrator::get_estimate() +{ + cv::Vec6f x = P.inv() * y; + return cv::Vec3f(-x[0], -x[1], -x[2]); +} diff --git a/tracker-pt/trans_calib.h b/tracker-pt/trans_calib.h new file mode 100644 index 00000000..e20fc767 --- /dev/null +++ b/tracker-pt/trans_calib.h @@ -0,0 +1,39 @@ +/* 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. + */ + +#ifndef TRANSCALIB_H +#define TRANSCALIB_H + +#include + +//----------------------------------------------------------------------------- +// Calibrates the translation from head to model = t_MH +// by recursive least squares / +// kalman filter in information form with identity noise covariance +// measurement equation when head position = t_CH is fixed: +// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k + +class TranslationCalibrator +{ +public: + TranslationCalibrator(); + + // reset the calibration process + void reset(); + + // update the current estimate + void update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k); + + // get the current estimate for t_MH + cv::Vec3f get_estimate(); + +private: + cv::Matx66f P; // normalized precision matrix = inverse covariance + cv::Vec6f y; // P*(-t_MH, t_CH) +}; + +#endif //TRANSCALIB_H diff --git a/tracker-rift-025/CMakeLists.txt b/tracker-rift-025/CMakeLists.txt new file mode 100644 index 00000000..7891ad4d --- /dev/null +++ b/tracker-rift-025/CMakeLists.txt @@ -0,0 +1,3 @@ +include(opentrack-rift) +opentrack_rift_boilerplate(opentrack-tracker-rift-025 SDK_RIFT_025) +SET(SDK_RIFT_025 "" CACHE PATH "libOVR 0.2.5 path for Oculus Rift") diff --git a/tracker-rift-025/ftnoir_rift_025.qrc b/tracker-rift-025/ftnoir_rift_025.qrc new file mode 100644 index 00000000..cd174fc4 --- /dev/null +++ b/tracker-rift-025/ftnoir_rift_025.qrc @@ -0,0 +1,7 @@ + + + images/rift_medium.png + images/rift_small.png + images/rift_tiny.png + + diff --git a/tracker-rift-025/ftnoir_rift_clientcontrols_025.ui b/tracker-rift-025/ftnoir_rift_clientcontrols_025.ui new file mode 100644 index 00000000..20c8f00b --- /dev/null +++ b/tracker-rift-025/ftnoir_rift_clientcontrols_025.ui @@ -0,0 +1,176 @@ + + + UIRiftControls + + + Qt::NonModal + + + + 0 + 0 + 218 + 200 + + + + + 0 + 0 + + + + Oculus Rift tracker settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + Yaw spring + + + + + + Enable + + + + + + + Persistence + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.900000000000000 + + + 1.000000000000000 + + + 0.001000000000000 + + + + + + + Constant drift + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.000100000000000 + + + 0.100000000000000 + + + 0.001000000000000 + + + + + + + Deadzone + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.cpp b/tracker-rift-025/ftnoir_tracker_rift_025.cpp new file mode 100644 index 00000000..9588aaf8 --- /dev/null +++ b/tracker-rift-025/ftnoir_tracker_rift_025.cpp @@ -0,0 +1,92 @@ +/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ +#include "ftnoir_tracker_rift_025.h" +#include "opentrack/plugin-api.hpp" +#include "OVR.h" +#include + +using namespace OVR; + +Rift_Tracker::Rift_Tracker() +{ + pManager = NULL; + pSensor = NULL; + pSFusion = NULL; + old_yaw = 0; +} + +Rift_Tracker::~Rift_Tracker() +{ + if (pSensor) + pSensor->Release(); + if (pSFusion) + delete pSFusion; + if (pManager) + pManager->Release(); + System::Destroy(); +} + +void Rift_Tracker::start_tracker(QFrame*) +{ + System::Init(Log::ConfigureDefaultLog(LogMask_All)); + pManager = DeviceManager::Create(); + if (pManager != NULL) + { + DeviceEnumerator enumerator = pManager->EnumerateDevices(); + if (enumerator.IsAvailable()) + { + pSensor = enumerator.CreateDevice(); + + if (pSensor) + { + pSFusion = new OVR::SensorFusion(); + pSFusion->Reset(); + pSFusion->AttachToSensor(pSensor); + } + else + { + QMessageBox::warning(0,"Error", "Unable to create Rift sensor",QMessageBox::Ok,QMessageBox::NoButton); + } + + } + else + { + QMessageBox::warning(0,"Error", "Unable to enumerate Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); + } + } + else + { + QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); + } +} + + +void Rift_Tracker::data(double *data) +{ + if (pSFusion != NULL && pSensor != NULL) + { + Quatf hmdOrient = pSFusion->GetOrientation(); + double newHeadPose[6]; + + float yaw = 0.0f; + float pitch = 0.0f; + float roll = 0.0f; + hmdOrient.GetEulerAngles(&yaw, &pitch , &roll); + newHeadPose[Pitch] = pitch; + newHeadPose[Roll] = roll; + newHeadPose[Yaw] = yaw; + if (s.useYawSpring) + { + newHeadPose[Yaw] = old_yaw*s.persistence + (yaw-old_yaw); + if(newHeadPose[Yaw] > s.deadzone) + newHeadPose[Yaw] -= s.constant_drift; + if(newHeadPose[Yaw] < -s.deadzone) + newHeadPose[Yaw] += s.constant_drift; + old_yaw=yaw; + } + data[Yaw] = newHeadPose[Yaw] * 57.295781f; + data[Pitch] = newHeadPose[Pitch] * 57.295781f; + data[Roll] = newHeadPose[Roll] * 57.295781f; + } +} + +OPENTRACK_DECLARE_TRACKER(Rift_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/tracker-rift-025/ftnoir_tracker_rift_025.h b/tracker-rift-025/ftnoir_tracker_rift_025.h new file mode 100644 index 00000000..2bd5024b --- /dev/null +++ b/tracker-rift-025/ftnoir_tracker_rift_025.h @@ -0,0 +1,63 @@ +#pragma once +#include "ui_ftnoir_rift_clientcontrols_025.h" +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "OVR.h" +#include +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value useYawSpring; + value constant_drift, persistence, deadzone; + settings() : + opts("Rift-025"), + useYawSpring(b, "yaw-spring", false), + constant_drift(b, "constant-drift", 0.000005), + persistence(b, "persistence", 0.99999), + deadzone(b, "deadzone", 0.02) + {} +}; + +class Rift_Tracker : public ITracker +{ +public: + Rift_Tracker(); + virtual ~Rift_Tracker() override; + void start_tracker(QFrame *) override; + void data(double *data) override; +private: + double old_yaw; + settings s; + static bool isInitialised; + OVR::DeviceManager* pManager; + OVR::SensorDevice* pSensor; + OVR::SensorFusion* pSFusion; +}; + +class TrackerControls: public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + + void register_tracker(ITracker *) {} + void unregister_tracker() {} + +private: + Ui::UIRiftControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + QString name() { return QString("Oculus Rift runtime 0.2.5 -- HMD"); } + QIcon icon() { return QIcon(":/images/rift_tiny.png"); } +}; + diff --git a/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp b/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp new file mode 100644 index 00000000..8100e362 --- /dev/null +++ b/tracker-rift-025/ftnoir_tracker_rift_dialog_025.cpp @@ -0,0 +1,26 @@ +#include "ftnoir_tracker_rift_025.h" +#include "opentrack/plugin-api.hpp" + +TrackerControls::TrackerControls() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.constant_drift, ui.constantDrift); + tie_setting(s.deadzone, ui.deadzone); + tie_setting(s.persistence, ui.persistence); + tie_setting(s.useYawSpring, ui.yawSpring); +} + +void TrackerControls::doOK() { + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->reload(); + close(); +} + diff --git a/tracker-rift-025/images/medium.png b/tracker-rift-025/images/medium.png new file mode 100644 index 00000000..a5ba49e7 Binary files /dev/null and b/tracker-rift-025/images/medium.png differ diff --git a/tracker-rift-025/images/rift_medium.png b/tracker-rift-025/images/rift_medium.png new file mode 100644 index 00000000..a5ba49e7 Binary files /dev/null and b/tracker-rift-025/images/rift_medium.png differ diff --git a/tracker-rift-025/images/rift_small.png b/tracker-rift-025/images/rift_small.png new file mode 100644 index 00000000..3f18080c Binary files /dev/null and b/tracker-rift-025/images/rift_small.png differ diff --git a/tracker-rift-025/images/rift_tiny.png b/tracker-rift-025/images/rift_tiny.png new file mode 100644 index 00000000..76fe0f58 Binary files /dev/null and b/tracker-rift-025/images/rift_tiny.png differ diff --git a/tracker-rift-025/images/small.png b/tracker-rift-025/images/small.png new file mode 100644 index 00000000..3f18080c Binary files /dev/null and b/tracker-rift-025/images/small.png differ diff --git a/tracker-rift-025/images/tiny.png b/tracker-rift-025/images/tiny.png new file mode 100644 index 00000000..76fe0f58 Binary files /dev/null and b/tracker-rift-025/images/tiny.png differ diff --git a/tracker-rift-042/CMakeLists.txt b/tracker-rift-042/CMakeLists.txt new file mode 100644 index 00000000..9d444cd0 --- /dev/null +++ b/tracker-rift-042/CMakeLists.txt @@ -0,0 +1,3 @@ +include(opentrack-rift) +opentrack_rift_boilerplate(opentrack-tracker-rift-042 SDK_RIFT_042) +SET(SDK_RIFT_042 "" CACHE PATH "libOVR 0.4.2 path for Oculus Rift") diff --git a/tracker-rift-042/ftnoir_rift_042.qrc b/tracker-rift-042/ftnoir_rift_042.qrc new file mode 100644 index 00000000..cd174fc4 --- /dev/null +++ b/tracker-rift-042/ftnoir_rift_042.qrc @@ -0,0 +1,7 @@ + + + images/rift_medium.png + images/rift_small.png + images/rift_tiny.png + + diff --git a/tracker-rift-042/ftnoir_rift_clientcontrols_042.ui b/tracker-rift-042/ftnoir_rift_clientcontrols_042.ui new file mode 100644 index 00000000..20c8f00b --- /dev/null +++ b/tracker-rift-042/ftnoir_rift_clientcontrols_042.ui @@ -0,0 +1,176 @@ + + + UIRiftControls + + + Qt::NonModal + + + + 0 + 0 + 218 + 200 + + + + + 0 + 0 + + + + Oculus Rift tracker settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + Yaw spring + + + + + + Enable + + + + + + + Persistence + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.900000000000000 + + + 1.000000000000000 + + + 0.001000000000000 + + + + + + + Constant drift + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.000100000000000 + + + 0.100000000000000 + + + 0.001000000000000 + + + + + + + Deadzone + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.cpp b/tracker-rift-042/ftnoir_tracker_rift_042.cpp new file mode 100644 index 00000000..deea4a08 --- /dev/null +++ b/tracker-rift-042/ftnoir_tracker_rift_042.cpp @@ -0,0 +1,71 @@ +/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ +#include "ftnoir_tracker_rift_042.h" +#include "opentrack/plugin-api.hpp" +#include "OVR_CAPI.h" +#include "Kernel/OVR_Math.h" +#include + +using namespace OVR; + +Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr) +{ +} + +Rift_Tracker::~Rift_Tracker() +{ + ovrHmd_Destroy(hmd); + ovr_Shutdown(); +} + +void Rift_Tracker::start_tracker(QFrame*) +{ + ovr_Initialize(); + hmd = ovrHmd_Create(0); + if (hmd) + { + ovrHmd_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation); + } + else + { + // XXX need change ITracker et al api to allow for failure reporting + // this qmessagebox doesn't give any relevant details either -sh 20141012 + QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); + } +} + + +void Rift_Tracker::data(double *data) +{ + if (hmd) + { + ovrHSWDisplayState hsw; + if (ovrHmd_GetHSWDisplayState(hmd, &hsw), hsw.Displayed) + ovrHmd_DismissHSWDisplay(hmd); + ovrTrackingState ss = ovrHmd_GetTrackingState(hmd, 0); + if(ss.StatusFlags & ovrStatus_OrientationTracked) { + auto pose = ss.HeadPose.ThePose; + Quatf quat = pose.Orientation; + float yaw, pitch, roll; + quat.GetEulerAngles(&yaw, &pitch, &roll); + // XXX TODO move to core + if (s.useYawSpring) + { + yaw = old_yaw*s.persistence + (yaw-old_yaw); + if(yaw > s.deadzone) + yaw -= s.constant_drift; + if(yaw < -s.deadzone) + yaw += s.constant_drift; + old_yaw=yaw; + } + constexpr double d2r = 57.295781; + data[Yaw] = yaw * -d2r; + data[Pitch] = pitch * d2r; + data[Roll] = roll * d2r; + data[TX] = pose.Position.x * -1e2; + data[TY] = pose.Position.y * 1e2; + data[TZ] = pose.Position.z * 1e2; + } + } +} + +OPENTRACK_DECLARE_TRACKER(Rift_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/tracker-rift-042/ftnoir_tracker_rift_042.h b/tracker-rift-042/ftnoir_tracker_rift_042.h new file mode 100644 index 00000000..437a2a39 --- /dev/null +++ b/tracker-rift-042/ftnoir_tracker_rift_042.h @@ -0,0 +1,60 @@ +#pragma once +#include "ui_ftnoir_rift_clientcontrols_042.h" +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "OVR.h" +#include +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value useYawSpring; + value constant_drift, persistence, deadzone; + settings() : + opts("Rift"), + useYawSpring(b, "yaw-spring", false), + constant_drift(b, "constant-drift", 0.000005), + persistence(b, "persistence", 0.99999), + deadzone(b, "deadzone", 0.02) + {} +}; + +class Rift_Tracker : public ITracker +{ +public: + Rift_Tracker(); + virtual ~Rift_Tracker() override; + void start_tracker(QFrame *) override; + void data(double *data) override; +private: + double old_yaw; + ovrHmd hmd; + settings s; +}; + +class TrackerControls: public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + + void register_tracker(ITracker *) {} + void unregister_tracker() {} + +private: + Ui::UIRiftControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + QString name() { return QString("Oculus Rift runtime 0.4.2 -- HMD"); } + QIcon icon() { return QIcon(":/images/rift_tiny.png"); } +}; + diff --git a/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp b/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp new file mode 100644 index 00000000..9a8b7549 --- /dev/null +++ b/tracker-rift-042/ftnoir_tracker_rift_dialog_042.cpp @@ -0,0 +1,26 @@ +#include "ftnoir_tracker_rift_042.h" +#include "opentrack/plugin-api.hpp" + +TrackerControls::TrackerControls() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.constant_drift, ui.constantDrift); + tie_setting(s.deadzone, ui.deadzone); + tie_setting(s.persistence, ui.persistence); + tie_setting(s.useYawSpring, ui.yawSpring); +} + +void TrackerControls::doOK() { + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->reload(); + close(); +} + diff --git a/tracker-rift-042/images/medium.png b/tracker-rift-042/images/medium.png new file mode 100644 index 00000000..a5ba49e7 Binary files /dev/null and b/tracker-rift-042/images/medium.png differ diff --git a/tracker-rift-042/images/rift_medium.png b/tracker-rift-042/images/rift_medium.png new file mode 100644 index 00000000..a5ba49e7 Binary files /dev/null and b/tracker-rift-042/images/rift_medium.png differ diff --git a/tracker-rift-042/images/rift_small.png b/tracker-rift-042/images/rift_small.png new file mode 100644 index 00000000..3f18080c Binary files /dev/null and b/tracker-rift-042/images/rift_small.png differ diff --git a/tracker-rift-042/images/rift_tiny.png b/tracker-rift-042/images/rift_tiny.png new file mode 100644 index 00000000..76fe0f58 Binary files /dev/null and b/tracker-rift-042/images/rift_tiny.png differ diff --git a/tracker-rift-042/images/small.png b/tracker-rift-042/images/small.png new file mode 100644 index 00000000..3f18080c Binary files /dev/null and b/tracker-rift-042/images/small.png differ diff --git a/tracker-rift-042/images/tiny.png b/tracker-rift-042/images/tiny.png new file mode 100644 index 00000000..76fe0f58 Binary files /dev/null and b/tracker-rift-042/images/tiny.png differ diff --git a/tracker-rift-080/CMakeLists.txt b/tracker-rift-080/CMakeLists.txt new file mode 100644 index 00000000..e59e9fdc --- /dev/null +++ b/tracker-rift-080/CMakeLists.txt @@ -0,0 +1,3 @@ +include(opentrack-rift) +opentrack_rift_boilerplate(opentrack-tracker-rift-080 SDK_RIFT_080) +SET(SDK_RIFT_080 "" CACHE PATH "libOVR 0.8.0 path for Oculus Rift") diff --git a/tracker-rift-080/ftnoir_rift_080.qrc b/tracker-rift-080/ftnoir_rift_080.qrc new file mode 100644 index 00000000..cd174fc4 --- /dev/null +++ b/tracker-rift-080/ftnoir_rift_080.qrc @@ -0,0 +1,7 @@ + + + images/rift_medium.png + images/rift_small.png + images/rift_tiny.png + + diff --git a/tracker-rift-080/ftnoir_rift_clientcontrols_080.ui b/tracker-rift-080/ftnoir_rift_clientcontrols_080.ui new file mode 100644 index 00000000..20c8f00b --- /dev/null +++ b/tracker-rift-080/ftnoir_rift_clientcontrols_080.ui @@ -0,0 +1,176 @@ + + + UIRiftControls + + + Qt::NonModal + + + + 0 + 0 + 218 + 200 + + + + + 0 + 0 + + + + Oculus Rift tracker settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + Yaw spring + + + + + + Enable + + + + + + + Persistence + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.900000000000000 + + + 1.000000000000000 + + + 0.001000000000000 + + + + + + + Constant drift + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.000100000000000 + + + 0.100000000000000 + + + 0.001000000000000 + + + + + + + Deadzone + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + 5 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_080.cpp new file mode 100644 index 00000000..889ac8c3 --- /dev/null +++ b/tracker-rift-080/ftnoir_tracker_rift_080.cpp @@ -0,0 +1,75 @@ +/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ +#include "ftnoir_tracker_rift_080.h" +#include "opentrack/plugin-api.hpp" +#include "OVR_CAPI.h" +#include "Extras/OVR_Math.h" +#include "OVR_CAPI_0_8_0.h" +#include + +using namespace OVR; + +Rift_Tracker::Rift_Tracker() : old_yaw(0), hmd(nullptr) +{ +} + +Rift_Tracker::~Rift_Tracker() +{ + if (hmd) + ovr_Destroy(hmd); + ovr_Shutdown(); +} + +void Rift_Tracker::start_tracker(QFrame*) +{ + { + ovrInitParams args = {0}; + if (!OVR_SUCCESS(ovr_Initialize(&args))) + goto error; + } + { + ovrGraphicsLuid luid = {0}; + ovrResult res = ovr_Create(&hmd, &luid); + if (OVR_SUCCESS(res)) + { + ovr_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation); + } + else + goto error; + } + return; +error: + QMessageBox::warning(0,"Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); +} + +void Rift_Tracker::data(double *data) +{ + if (hmd) + { + ovrTrackingState ss = ovr_GetTrackingState(hmd, 0, false); + if(ss.StatusFlags & ovrStatus_OrientationTracked) { + auto pose = ss.HeadPose.ThePose; + Quatf quat = pose.Orientation; + float yaw, pitch, roll; + quat.GetEulerAngles(&yaw, &pitch, &roll); + // XXX TODO move to core + if (s.useYawSpring) + { + yaw = old_yaw*s.persistence + (yaw-old_yaw); + if(yaw > s.deadzone) + yaw -= s.constant_drift; + if(yaw < -s.deadzone) + yaw += s.constant_drift; + old_yaw=yaw; + } + constexpr double d2r = 57.295781; + data[Yaw] = yaw * -d2r; + data[Pitch] = pitch * d2r; + data[Roll] = roll * d2r; + data[TX] = pose.Position.x * -1e2; + data[TY] = pose.Position.y * 1e2; + data[TZ] = pose.Position.z * 1e2; + } + } +} + +OPENTRACK_DECLARE_TRACKER(Rift_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/tracker-rift-080/ftnoir_tracker_rift_080.h b/tracker-rift-080/ftnoir_tracker_rift_080.h new file mode 100644 index 00000000..08684dd2 --- /dev/null +++ b/tracker-rift-080/ftnoir_tracker_rift_080.h @@ -0,0 +1,60 @@ +#pragma once +#include "ui_ftnoir_rift_clientcontrols_080.h" +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "OVR.h" +#include +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value useYawSpring; + value constant_drift, persistence, deadzone; + settings() : + opts("Rift"), + useYawSpring(b, "yaw-spring", false), + constant_drift(b, "constant-drift", 0.000005), + persistence(b, "persistence", 0.99999), + deadzone(b, "deadzone", 0.02) + {} +}; + +class Rift_Tracker : public ITracker +{ +public: + Rift_Tracker(); + ~Rift_Tracker() override; + void start_tracker(QFrame *) override; + void data(double *data) override; +private: + double old_yaw; + ovrSession hmd; + settings s; +}; + +class TrackerControls: public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + + void register_tracker(ITracker *) {} + void unregister_tracker() {} + +private: + Ui::UIRiftControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + QString name() { return QString("Oculus Rift runtime 0.8.0 -- HMD"); } + QIcon icon() { return QIcon(":/images/rift_tiny.png"); } +}; + diff --git a/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp b/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp new file mode 100644 index 00000000..0bf797be --- /dev/null +++ b/tracker-rift-080/ftnoir_tracker_rift_dialog_080.cpp @@ -0,0 +1,26 @@ +#include "ftnoir_tracker_rift_080.h" +#include "opentrack/plugin-api.hpp" + +TrackerControls::TrackerControls() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.constant_drift, ui.constantDrift); + tie_setting(s.deadzone, ui.deadzone); + tie_setting(s.persistence, ui.persistence); + tie_setting(s.useYawSpring, ui.yawSpring); +} + +void TrackerControls::doOK() { + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->reload(); + close(); +} + diff --git a/tracker-rift-080/images/medium.png b/tracker-rift-080/images/medium.png new file mode 100644 index 00000000..a5ba49e7 Binary files /dev/null and b/tracker-rift-080/images/medium.png differ diff --git a/tracker-rift-080/images/rift_medium.png b/tracker-rift-080/images/rift_medium.png new file mode 100644 index 00000000..a5ba49e7 Binary files /dev/null and b/tracker-rift-080/images/rift_medium.png differ diff --git a/tracker-rift-080/images/rift_small.png b/tracker-rift-080/images/rift_small.png new file mode 100644 index 00000000..3f18080c Binary files /dev/null and b/tracker-rift-080/images/rift_small.png differ diff --git a/tracker-rift-080/images/rift_tiny.png b/tracker-rift-080/images/rift_tiny.png new file mode 100644 index 00000000..76fe0f58 Binary files /dev/null and b/tracker-rift-080/images/rift_tiny.png differ diff --git a/tracker-rift-080/images/small.png b/tracker-rift-080/images/small.png new file mode 100644 index 00000000..3f18080c Binary files /dev/null and b/tracker-rift-080/images/small.png differ diff --git a/tracker-rift-080/images/tiny.png b/tracker-rift-080/images/tiny.png new file mode 100644 index 00000000..76fe0f58 Binary files /dev/null and b/tracker-rift-080/images/tiny.png differ diff --git a/tracker-rs/CMakeLists.txt b/tracker-rs/CMakeLists.txt new file mode 100644 index 00000000..f4f6d4b9 --- /dev/null +++ b/tracker-rs/CMakeLists.txt @@ -0,0 +1,5 @@ +if(WIN32) + opentrack_boilerplate(opentrack-tracker-rs) + install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe" DESTINATION . ${opentrack-perms}) + install(FILES "${CMAKE_SOURCE_DIR}/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe" DESTINATION ./contrib/ ${opentrack-perms}) +endif() diff --git a/tracker-rs/README.md b/tracker-rs/README.md new file mode 100644 index 00000000..5fca4392 --- /dev/null +++ b/tracker-rs/README.md @@ -0,0 +1,16 @@ +# Intel® RealSense™ plugin for opentrack +This is a tracker providing markerless 3D head tracking using the Intel® RealSense™ SDK and the Intel® RealSense™ front-facing cameras. + +More information on RealSense can be found on [Intel.com](http://www.intel.com/content/www/us/en/architecture-and-technology/realsense-overview.html) + +This tracker uses a separate process that gets data from the SDK. Its sources are under rs_impl and can be recompiled by calling build.bat, which depends on +Microsoft Visual C++ Compiler and the [Intel® RealSense™ SDK R4](https://software.intel.com/en-us/intel-realsense-sdk) + +# ISC License +Copyright (c) 2015, Intel Corporation + + Author: Xavier Hallade + +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. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/tracker-rs/ftnoir_tracker_rs.cpp b/tracker-rs/ftnoir_tracker_rs.cpp new file mode 100644 index 00000000..3e9b23c8 --- /dev/null +++ b/tracker-rs/ftnoir_tracker_rs.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ftnoir_tracker_rs.h" +#include "ftnoir_tracker_rs_controls.h" + +#include "opentrack/plugin-api.hpp" +#include + +RSTracker::RSTracker() : mPose{ 0,0,0, 0,0,0 } { + mThread.setObjectName("RSTrackerWorkerThread"); + + mRealSenseImplProcess.moveToThread(&mThread); + mSocket.moveToThread(&mThread); + + connect(&mRealSenseImplProcess, SIGNAL(finished(int)), + this, SLOT(rsImplProcessFinished(int)), Qt::QueuedConnection); + + qRegisterMetaType("QProcess::ProcessError"); + connect(&mRealSenseImplProcess, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(rsImplProcessError(QProcess::ProcessError)), Qt::QueuedConnection); + + connect(&mSocket, SIGNAL(readyRead()), + this, SLOT(readPendingUdpPoseData()), Qt::DirectConnection); + + connect(&mThread, &QThread::started, + &mThread, [this]{ + mSocket.bind(QHostAddress::LocalHost, 4242, QUdpSocket::DontShareAddress); + mRealSenseImplProcess.start("opentrack-tracker-rs-impl.exe", QProcess::NotOpen); + }, Qt::DirectConnection); + + connect(&mThread, &QThread::finished, + &mThread, [this]{ + mRealSenseImplProcess.kill(); + mRealSenseImplProcess.waitForFinished(); + }, Qt::DirectConnection); +} + +void RSTracker::start_tracker(QFrame*) +{ + mThread.start(); +} + +void RSTracker::readPendingUdpPoseData(){ + double pose[6]; + + while(mSocket.hasPendingDatagrams()) { + mSocket.readDatagram((char*)pose, sizeof(pose)); + QMutexLocker foo(&mMutex); + memcpy(mPose, pose, sizeof(pose)); + } +} + +void RSTracker::rsImplProcessError(QProcess::ProcessError error){ + if(error == QProcess::FailedToStart){ + QMessageBox::warning(NULL, "RealSense Tracking Error", "Couldn't start the RealSense tracking module.\nMaybe opentrack-tracker-rs-impl.exe is missing.", QMessageBox::Ok); + } + else if(error == QProcess::Crashed){ + QMessageBox::warning(NULL, "RealSense Tracking Error", "The RealSense tracking module has crashed.", QMessageBox::Ok); + } +} + + +void RSTracker::rsImplProcessFinished(int exitCode){ + if(exitCode!=0){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); + msgBox.setText("RealSense Tracking Error"); + if(exitCode==-101){ //The implementation got an invalid handle from the RealSense SDK session/modules + msgBox.setInformativeText("Couldn't initialize RealSense tracking. Please install SDK Runtime R4."); + } + else { + msgBox.setInformativeText("Status code: " + QString::number(exitCode) + ".\n\nNote that you need the latest camera drivers and the SDK runtime R4 to be installed."); + } + QPushButton* triggerSdkInstallation = msgBox.addButton("Install Runtime", QMessageBox::ActionRole); + msgBox.addButton(QMessageBox::Ok); + msgBox.exec(); + + if(msgBox.clickedButton() == triggerSdkInstallation){ + bool pStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); + if(!pStarted){ + QMessageBox::warning(0, "Intel® RealSense™ Runtime Installation", "Installation process failed to start.", QMessageBox::Ok); + } + } + } +} + +void RSTracker::data(double *data) +{ + QMutexLocker foo(&mMutex); + memcpy(data, mPose, sizeof(mPose)); +} + +RSTracker::~RSTracker() { + mThread.quit(); + mThread.wait(); +} + +QString RSTrackerMetaData::name() { + return QString("Intel® RealSense™ Technology"); +} + +QIcon RSTrackerMetaData::icon() { + return QIcon(":/images/intel-16x16.png"); +} + +OPENTRACK_DECLARE_TRACKER(RSTracker, RSTrackerControls, RSTrackerMetaData) diff --git a/tracker-rs/ftnoir_tracker_rs.h b/tracker-rs/ftnoir_tracker_rs.h new file mode 100644 index 00000000..7cda7370 --- /dev/null +++ b/tracker-rs/ftnoir_tracker_rs.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "ui_ftnoir_tracker_rs_controls.h" +#include "opentrack/plugin-api.hpp" +#include +#include +#include +#include + +class RSTracker : protected QObject, public ITracker +{ + Q_OBJECT + +public: + RSTracker(); + ~RSTracker(); + void start_tracker(QFrame *) override; + void data(double *data) override; + +private: + QMutex mMutex; + QThread mThread; + QProcess mRealSenseImplProcess; + QUdpSocket mSocket; + double mPose[6]; + +private slots: + void rsImplProcessError(QProcess::ProcessError); + void rsImplProcessFinished(int); + void readPendingUdpPoseData(); + +}; + +class RSTrackerMetaData : public Metadata +{ +public: + QString name(); + QIcon icon(); +}; diff --git a/tracker-rs/ftnoir_tracker_rs_controls.cpp b/tracker-rs/ftnoir_tracker_rs_controls.cpp new file mode 100644 index 00000000..6c71d58f --- /dev/null +++ b/tracker-rs/ftnoir_tracker_rs_controls.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ftnoir_tracker_rs_controls.h" + +#include +#include + +RSTrackerControls::RSTrackerControls() +{ + ui.setupUi(this); + connect(ui.triggerSDKInstallButton, SIGNAL(clicked(bool)), this, SLOT(doInstallRSRuntime())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); +} + +void RSTrackerControls::doInstallRSRuntime() +{ + bool processStarted = QProcess::startDetached("contrib\\intel_rs_sdk_runtime_websetup_6.0.21.6598.exe --finstall=core,face3d --fnone=all"); + if(processStarted){ + this->close(); + } + else{ + QMessageBox::warning(0, "Intel® RealSenseTM Runtime Installation", "Installation process failed to start.", QMessageBox::Ok); + } +} + +void RSTrackerControls::doOK() +{ + this->close(); +} + +void RSTrackerControls::doCancel() +{ + this->close(); +} diff --git a/tracker-rs/ftnoir_tracker_rs_controls.h b/tracker-rs/ftnoir_tracker_rs_controls.h new file mode 100644 index 00000000..010dac99 --- /dev/null +++ b/tracker-rs/ftnoir_tracker_rs_controls.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ftnoir_tracker_rs.h" + +class RSTrackerControls : public ITrackerDialog +{ + Q_OBJECT +public: + RSTrackerControls(); + void register_tracker(ITracker *) {} + void unregister_tracker() {} +private: + Ui::UIRSControls ui; + private slots: + void doOK(); + void doCancel(); + void doInstallRSRuntime(); +}; diff --git a/tracker-rs/ftnoir_tracker_rs_controls.ui b/tracker-rs/ftnoir_tracker_rs_controls.ui new file mode 100644 index 00000000..834803d1 --- /dev/null +++ b/tracker-rs/ftnoir_tracker_rs_controls.ui @@ -0,0 +1,67 @@ + + + UIRSControls + + + Qt::NonModal + + + + 0 + 0 + 378 + 193 + + + + RealSense 3D Tracker settings + + + + images/RS.pngimages/RS.png + + + Qt::LeftToRight + + + false + + + + + + There is no configuration available at the moment. + +The application will activate your camera for face tracking by the +Intel® RealSense™ SDK. By design, the application has no direct access +to any camera images. + +In order to use this tracker, you need a PC equipped with +an Intel® RealSense™ R200 camera and the RealSense™ SDK R4 runtime. + + + + + + + Install SDK Runtime R4 + + + + + + + QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-rs/images/RS.png b/tracker-rs/images/RS.png new file mode 100644 index 00000000..4ca11aac Binary files /dev/null and b/tracker-rs/images/RS.png differ diff --git a/tracker-rs/images/intel-16x16.png b/tracker-rs/images/intel-16x16.png new file mode 100644 index 00000000..e985ace1 Binary files /dev/null and b/tracker-rs/images/intel-16x16.png differ diff --git a/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe new file mode 100644 index 00000000..34ecc9df Binary files /dev/null and b/tracker-rs/redist/intel_rs_sdk_runtime_websetup_6.0.21.6598.exe differ diff --git a/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe new file mode 100644 index 00000000..1e2a57f1 Binary files /dev/null and b/tracker-rs/rs_impl/bin/opentrack-tracker-rs-impl.exe differ diff --git a/tracker-rs/rs_impl/build.bat b/tracker-rs/rs_impl/build.bat new file mode 100644 index 00000000..15206431 --- /dev/null +++ b/tracker-rs/rs_impl/build.bat @@ -0,0 +1,2 @@ +cd "%VS120COMNTOOLS%\..\..\VC" +vcvarsall x64 && cd %~dp0 && CL /nologo /Ox /DUNICODE /D_UNICODE /MT /I"%RSSDK_DIR%\opensource\include" ftnoir_tracker_rs_impl.cpp udp_sender.cpp "%RSSDK_DIR%\opensource\src\libpxc\libpxc.cpp" /link ADVAPI32.LIB Ws2_32.lib /SUBSYSTEM:CONSOLE /OUT:bin\opentrack-tracker-rs-impl.exe \ No newline at end of file diff --git a/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp b/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp new file mode 100644 index 00000000..c1ba5c75 --- /dev/null +++ b/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ftnoir_tracker_rs_impl.h" +#include +#include + +PXCSenseManager* g_senseManager = NULL; +PXCFaceData* g_faceData = NULL; + +pxcStatus rs_tracker_set_configuration(PXCFaceModule *faceModule){ + pxcStatus retStatus; + PXCFaceConfiguration *faceConfig = NULL; + + if (faceModule == NULL) + return PXC_STATUS_HANDLE_INVALID; + + faceConfig = faceModule->CreateActiveConfiguration(); + if (faceConfig == NULL){ + return PXC_STATUS_HANDLE_INVALID; + } + + faceConfig->pose.isEnabled = true; + faceConfig->pose.maxTrackedFaces = 1; + faceConfig->pose.smoothingLevel = PXCFaceConfiguration::SmoothingLevelType::SMOOTHING_DISABLED; + faceConfig->strategy = PXCFaceConfiguration::STRATEGY_CLOSEST_TO_FARTHEST; + faceConfig->detection.isEnabled = false; + faceConfig->landmarks.isEnabled = false; + faceConfig->DisableAllAlerts(); + faceConfig->SetTrackingMode(PXCFaceConfiguration::FACE_MODE_COLOR_PLUS_DEPTH); + + retStatus = faceConfig->ApplyChanges(); + if (retStatus != PXC_STATUS_NO_ERROR){ + faceConfig->Release(); + return retStatus; + } + + faceConfig->Release(); + return PXC_STATUS_NO_ERROR; +} + +int rs_tracker_impl_start(){ + pxcStatus retStatus; + PXCFaceModule *faceModule = NULL; + + g_senseManager = PXCSenseManager::CreateInstance(); + if (g_senseManager == NULL){ + rs_tracker_impl_end(); + return PXC_STATUS_HANDLE_INVALID; + } + + retStatus = g_senseManager->EnableFace(); + if (retStatus != PXC_STATUS_NO_ERROR){ + rs_tracker_impl_end(); + return retStatus; + } + + faceModule = g_senseManager->QueryFace(); + if (faceModule == NULL){ + rs_tracker_impl_end(); + return PXC_STATUS_HANDLE_INVALID; + } + + retStatus = rs_tracker_set_configuration(faceModule); + if (retStatus != PXC_STATUS_NO_ERROR){ + rs_tracker_impl_end(); + return PXC_STATUS_HANDLE_INVALID; + } + + retStatus = g_senseManager->Init(); + if (retStatus != PXC_STATUS_NO_ERROR){ + rs_tracker_impl_end(); + return retStatus; + } + + g_faceData = faceModule->CreateOutput(); + if (g_faceData == NULL){ + rs_tracker_impl_end(); + return PXC_STATUS_HANDLE_INVALID; + } + + return PXC_STATUS_NO_ERROR; +} + +int rs_tracker_impl_update_pose(double *data){ + pxcStatus retStatus; + PXCFaceData::PoseEulerAngles angles; + PXCFaceData::HeadPosition headPosition; + PXCFaceData::Face *face = NULL; + PXCFaceData::PoseData *pose = NULL; + bool poseAnglesAvailable = false; + bool headPositionAvailable = false; + + if (g_senseManager != NULL && g_faceData != NULL + && (retStatus = g_senseManager->AcquireFrame(true, 16)) == PXC_STATUS_NO_ERROR){ + + retStatus = g_faceData->Update(); + if (retStatus != PXC_STATUS_NO_ERROR){ + rs_tracker_impl_end(); + return retStatus; + } + + pxcI32 numberOfDetectedFaces = g_faceData->QueryNumberOfDetectedFaces(); + for (pxcI32 i = 0; i < numberOfDetectedFaces; ++i) { + face = g_faceData->QueryFaceByIndex(0); + if (face == NULL) continue; + + pose = face->QueryPose(); + if (pose == NULL) continue; + + poseAnglesAvailable = pose->QueryPoseAngles(&angles); + if (!poseAnglesAvailable) continue; + + headPositionAvailable = pose->QueryHeadPosition(&headPosition); + if (!headPositionAvailable) continue; + + //TODO: use pxcI32 pose->QueryConfidence(); ? for data[6] or to filter here ? + + //x, y, z: cm + data[0] = headPosition.headCenter.x / 10.; + data[1] = headPosition.headCenter.y / 10.; + data[2] = headPosition.headCenter.z / 10.; + + //yaw, pitch, roll: degrees + data[3] = -angles.yaw; + data[4] = angles.pitch; + data[5] = -angles.roll; + } + + g_senseManager->ReleaseFrame(); + } + + return retStatus; +} + +int rs_tracker_impl_end(){ + if (g_faceData != NULL){ + g_faceData->Release(); + g_faceData = NULL; + } + + if (g_senseManager != NULL){ + g_senseManager->Release(); + g_senseManager = NULL; + } + return PXC_STATUS_NO_ERROR; +} diff --git a/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.h b/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.h new file mode 100644 index 00000000..0e4073d0 --- /dev/null +++ b/tracker-rs/rs_impl/ftnoir_tracker_rs_impl.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once +#ifdef EXPORT_RS_IMPL +#define RSTRACKERIMPL_VISIBILITY __declspec( dllexport ) +#else +#define RSTRACKERIMPL_VISIBILITY +#endif + +extern "C" { + RSTRACKERIMPL_VISIBILITY int rs_tracker_impl_start(); + RSTRACKERIMPL_VISIBILITY int rs_tracker_impl_update_pose(double *pose); + RSTRACKERIMPL_VISIBILITY int rs_tracker_impl_end(); +} diff --git a/tracker-rs/rs_impl/udp_sender.cpp b/tracker-rs/rs_impl/udp_sender.cpp new file mode 100644 index 00000000..095edd8f --- /dev/null +++ b/tracker-rs/rs_impl/udp_sender.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015, Intel Corporation + * Author: Xavier Hallade + * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ftnoir_tracker_rs_impl.h" +#include +#include +#include +#include + +#define UDP_PORT 4242 + +int main(){ + double pose[6] = { 0., 0., 0., 0., 0., 0. }; + struct sockaddr_in socketInfo; + SOCKET s = 0; + WSADATA wsa; + + int retStatus = rs_tracker_impl_start(); + if (retStatus != 0){ + exit(retStatus); + } + + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) //init winsocketapi + exit(EXIT_FAILURE); + + memset(&socketInfo, 0, sizeof(socketInfo)); + socketInfo.sin_family = AF_INET; + socketInfo.sin_port = htons(UDP_PORT); + InetPton(AF_INET, L"127.0.0.1", &socketInfo.sin_addr.S_un.S_addr); + + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) //create UDP socket + exit(EXIT_FAILURE); + + for(;;) { + retStatus = rs_tracker_impl_update_pose(pose); + if(retStatus == 0){ //no error + if (sendto(s, (char*)&pose, sizeof(pose), 0, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) == SOCKET_ERROR) //send new data + exit(EXIT_FAILURE); + } + + if(retStatus != 0 && retStatus != -303)// -303=timeout and 0 are ok, else we've got to stop. + break; + } + + closesocket(s); + WSACleanup(); + + return retStatus; +} diff --git a/tracker-rs/rs_tracker.qrc b/tracker-rs/rs_tracker.qrc new file mode 100644 index 00000000..155a5bd1 --- /dev/null +++ b/tracker-rs/rs_tracker.qrc @@ -0,0 +1,6 @@ + + + images/RS.png + images/intel-16x16.png + + diff --git a/tracker-udp/CMakeLists.txt b/tracker-udp/CMakeLists.txt new file mode 100644 index 00000000..51e96773 --- /dev/null +++ b/tracker-udp/CMakeLists.txt @@ -0,0 +1 @@ +opentrack_boilerplate(opentrack-tracker-udp) diff --git a/tracker-udp/ftnoir_ftnclientcontrols.ui b/tracker-udp/ftnoir_ftnclientcontrols.ui new file mode 100644 index 00000000..cb9362ca --- /dev/null +++ b/tracker-udp/ftnoir_ftnclientcontrols.ui @@ -0,0 +1,208 @@ + + + UICFTNClientControls + + + Qt::NonModal + + + + 0 + 0 + 195 + 224 + + + + UDP tracker settings + + + + ../facetracknoir/images/facetracknoir.png../facetracknoir/images/facetracknoir.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + + + + + + + Port + + + + + + + 0 + + + 65535 + + + + + + + + + + Add to axis + + + + + + yaw + + + + + + + + 0 + + + + + +90 + + + + + -90 + + + + + +180 + + + + + -180 + + + + + + + + pitch + + + + + + + roll + + + + + + + + 0 + + + + + +90 + + + + + -90 + + + + + +180 + + + + + -180 + + + + + + + + + 0 + + + + + +90 + + + + + -90 + + + + + +180 + + + + + -180 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-udp/ftnoir_tracker_udp.cpp b/tracker-udp/ftnoir_tracker_udp.cpp new file mode 100644 index 00000000..1610f917 --- /dev/null +++ b/tracker-udp/ftnoir_tracker_udp.cpp @@ -0,0 +1,70 @@ +/* Copyright (c) 2014, Stanislaw Halik + + * 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_tracker_udp.h" +#include "opentrack/plugin-api.hpp" + +FTNoIR_Tracker::FTNoIR_Tracker() : last_recv_pose { 0,0,0, 0,0,0 }, should_quit(false) {} + +FTNoIR_Tracker::~FTNoIR_Tracker() +{ + should_quit = true; + wait(); +} + +void FTNoIR_Tracker::run() { + QByteArray datagram; + datagram.resize(sizeof(last_recv_pose)); + (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); + for (;;) { + if (should_quit) + break; + { + QMutexLocker foo(&mutex); + while (sock.hasPendingDatagrams()) { + sock.readDatagram((char * ) last_recv_pose, sizeof(double[6])); + } + } + msleep(1); + } +} + +void FTNoIR_Tracker::start_tracker(QFrame*) +{ + start(); + sock.moveToThread(this); +} + +void FTNoIR_Tracker::data(double *data) +{ + QMutexLocker foo(&mutex); + for (int i = 0; i < 6; i++) + data[i] = last_recv_pose[i]; + + int values[] = { + 0, + 90, + -90, + 180, + -180, + }; + int indices[] = { + s.add_yaw, + s.add_pitch, + s.add_roll, + }; + + for (int i = 0; i < 3; i++) + { + int k = std::min(sizeof(values)/sizeof(values[0]), std::max(0, indices[i])); + data[Yaw + i] += values[k]; + } +} + + +OPENTRACK_DECLARE_TRACKER(FTNoIR_Tracker, TrackerControls, FTNoIR_TrackerDll) diff --git a/tracker-udp/ftnoir_tracker_udp.h b/tracker-udp/ftnoir_tracker_udp.h new file mode 100644 index 00000000..6de5b295 --- /dev/null +++ b/tracker-udp/ftnoir_tracker_udp.h @@ -0,0 +1,60 @@ +#pragma once +#include "ui_ftnoir_ftnclientcontrols.h" +#include +#include +#include +#include "opentrack/plugin-api.hpp" +#include "opentrack/options.hpp" +using namespace options; + +struct settings : opts { + value port; + value add_yaw, add_pitch, add_roll; + settings() : + opts("udp-tracker"), + port(b, "port", 4242), + add_yaw(b, "add-yaw", 0), + add_pitch(b, "add-pitch", 0), + add_roll(b, "add-roll", 0) + {} +}; + +class FTNoIR_Tracker : public ITracker, protected QThread +{ +public: + FTNoIR_Tracker(); + ~FTNoIR_Tracker() override; + void start_tracker(QFrame *) override; + void data(double *data) override; +protected: + void run() override; +private: + QUdpSocket sock; + double last_recv_pose[6]; + QMutex mutex; + settings s; + volatile bool should_quit; +}; + +class TrackerControls: public ITrackerDialog +{ + Q_OBJECT +public: + TrackerControls(); + void register_tracker(ITracker *) override {} + void unregister_tracker() override {} +private: + Ui::UICFTNClientControls ui; + settings s; +private slots: + void doOK(); + void doCancel(); +}; + +class FTNoIR_TrackerDll : public Metadata +{ +public: + QString name() { return QString("UDP sender"); } + QIcon icon() { return QIcon(":/images/facetracknoir.png"); } +}; + diff --git a/tracker-udp/ftnoir_tracker_udp_dialog.cpp b/tracker-udp/ftnoir_tracker_udp_dialog.cpp new file mode 100644 index 00000000..5e7d5437 --- /dev/null +++ b/tracker-udp/ftnoir_tracker_udp_dialog.cpp @@ -0,0 +1,26 @@ +#include "ftnoir_tracker_udp.h" +#include "opentrack/plugin-api.hpp" + +TrackerControls::TrackerControls() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.port, ui.spinPortNumber); + tie_setting(s.add_yaw, ui.add_yaw); + tie_setting(s.add_pitch, ui.add_pitch); + tie_setting(s.add_roll, ui.add_roll); +} + +void TrackerControls::doOK() { + s.b->save(); + this->close(); +} + +void TrackerControls::doCancel() { + s.b->reload(); + this->close(); +} + diff --git a/x-plane-plugin/CMakeLists.txt b/x-plane-plugin/CMakeLists.txt new file mode 100644 index 00000000..de42b5a5 --- /dev/null +++ b/x-plane-plugin/CMakeLists.txt @@ -0,0 +1,29 @@ +opentrack_boilerplate(opentrack-xplane-plugin NO-LIBRARY) + +if(LINUX OR APPLE) + set(SDK_XPLANE "" CACHE PATH "Path to X-Plane SDK") + if(SDK_XPLANE) + # probably librt already included + add_library(opentrack-xplane-plugin SHARED ${opentrack-xplane-plugin-c}) + target_include_directories(opentrack-xplane-plugin SYSTEM PUBLIC ${SDK_XPLANE}/CHeaders ${SDK_XPLANE}/CHeaders/XPLM) + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC AND NOT APPLE) + SET_TARGET_PROPERTIES(opentrack-xplane-plugin + PROPERTIES LINK_FLAGS + "-Wl,--version-script=${CMAKE_SOURCE_DIR}/x-plane-plugin/version-script.txt -shared -rdynamic -nodefaultlibs -undefined_warning -fPIC" + COMPILE_FLAGS "-Wall -O2 -pipe -fPIC -DLIN -DXPLM200 -DXPLM210" + LIBRARY_OUTPUT_NAME "opentrack.xpl" + PREFIX "" SUFFIX "") + endif() + if(APPLE) + SET_TARGET_PROPERTIES(opentrack-xplane-plugin PROPERTIES + COMPILE_FLAGS "-iframework ${SDK_XPLANE}/Libraries/Mac/ -DAPL -DXPLM200 -DXPLM210 -framework XPLM -framework XPWidgets" + LINK_FLAGS "-F${SDK_XPLANE}/Libraries/Mac/ -framework XPLM -framework XPWidgets" + LIBRARY_OUTPUT_NAME "opentrack.xpl" + PREFIX "" SUFFIX "") + endif() + if(UNIX AND NOT APPLE) + target_link_libraries(opentrack-xplane-plugin rt) + endif() + install(TARGETS opentrack-xplane-plugin RUNTIME DESTINATION . LIBRARY DESTINATION . ) + endif() +endif() -- cgit v1.2.3 From 2160e39a4f3d5198eafbb483671583a5a0b51eaa Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 30 Oct 2015 08:34:40 +0100 Subject: rename gui directory --- CMakeLists.txt | 2 +- facetracknoir/CMakeLists.txt | 62 -- facetracknoir/curve-config.cpp | 81 --- facetracknoir/curve-config.h | 18 - facetracknoir/facetracknoir.ico | Bin 67134 -> 0 bytes facetracknoir/facetracknoir.rc | 2 - facetracknoir/images/curves.png | Bin 3457 -> 0 bytes facetracknoir/images/facetracknoir.png | Bin 29485 -> 0 bytes facetracknoir/images/filter-16.png | Bin 642 -> 0 bytes facetracknoir/images/no-feed.png | Bin 4471 -> 0 bytes facetracknoir/images/settings16.png | Bin 711 -> 0 bytes facetracknoir/images/tools.png | Bin 3053 -> 0 bytes facetracknoir/keyboard.h | 50 -- facetracknoir/keyboard_listener.ui | 37 - facetracknoir/main.cpp | 71 -- facetracknoir/main.ui | 1255 -------------------------------- facetracknoir/mapping.ui | 391 ---------- facetracknoir/new_config.ui | 45 -- facetracknoir/new_file_dialog.h | 50 -- facetracknoir/options-dialog.cpp | 96 --- facetracknoir/options-dialog.hpp | 23 - facetracknoir/process_detector.cpp | 211 ------ facetracknoir/process_detector.h | 86 --- facetracknoir/process_widget.ui | 121 --- facetracknoir/settings.ui | 1109 ---------------------------- facetracknoir/ui-res.qrc | 10 - facetracknoir/ui.cpp | 567 --------------- facetracknoir/ui.h | 113 --- gui/CMakeLists.txt | 62 ++ gui/curve-config.cpp | 81 +++ gui/curve-config.h | 18 + gui/facetracknoir.ico | Bin 0 -> 67134 bytes gui/facetracknoir.rc | 2 + gui/images/curves.png | Bin 0 -> 3457 bytes gui/images/facetracknoir.png | Bin 0 -> 29485 bytes gui/images/filter-16.png | Bin 0 -> 642 bytes gui/images/no-feed.png | Bin 0 -> 4471 bytes gui/images/settings16.png | Bin 0 -> 711 bytes gui/images/tools.png | Bin 0 -> 3053 bytes gui/keyboard.h | 50 ++ gui/keyboard_listener.ui | 37 + gui/main.cpp | 71 ++ gui/main.ui | 1255 ++++++++++++++++++++++++++++++++ gui/mapping.ui | 391 ++++++++++ gui/new_config.ui | 45 ++ gui/new_file_dialog.h | 50 ++ gui/options-dialog.cpp | 96 +++ gui/options-dialog.hpp | 23 + gui/process_detector.cpp | 211 ++++++ gui/process_detector.h | 86 +++ gui/process_widget.ui | 121 +++ gui/settings.ui | 1109 ++++++++++++++++++++++++++++ gui/ui-res.qrc | 10 + gui/ui.cpp | 567 +++++++++++++++ gui/ui.h | 113 +++ 55 files changed, 4399 insertions(+), 4399 deletions(-) delete mode 100644 facetracknoir/CMakeLists.txt delete mode 100644 facetracknoir/curve-config.cpp delete mode 100644 facetracknoir/curve-config.h delete mode 100644 facetracknoir/facetracknoir.ico delete mode 100644 facetracknoir/facetracknoir.rc delete mode 100644 facetracknoir/images/curves.png delete mode 100644 facetracknoir/images/facetracknoir.png delete mode 100644 facetracknoir/images/filter-16.png delete mode 100644 facetracknoir/images/no-feed.png delete mode 100644 facetracknoir/images/settings16.png delete mode 100644 facetracknoir/images/tools.png delete mode 100644 facetracknoir/keyboard.h delete mode 100644 facetracknoir/keyboard_listener.ui delete mode 100644 facetracknoir/main.cpp delete mode 100644 facetracknoir/main.ui delete mode 100644 facetracknoir/mapping.ui delete mode 100644 facetracknoir/new_config.ui delete mode 100644 facetracknoir/new_file_dialog.h delete mode 100644 facetracknoir/options-dialog.cpp delete mode 100644 facetracknoir/options-dialog.hpp delete mode 100644 facetracknoir/process_detector.cpp delete mode 100644 facetracknoir/process_detector.h delete mode 100644 facetracknoir/process_widget.ui delete mode 100644 facetracknoir/settings.ui delete mode 100644 facetracknoir/ui-res.qrc delete mode 100644 facetracknoir/ui.cpp delete mode 100644 facetracknoir/ui.h create mode 100644 gui/CMakeLists.txt create mode 100644 gui/curve-config.cpp create mode 100644 gui/curve-config.h create mode 100644 gui/facetracknoir.ico create mode 100644 gui/facetracknoir.rc create mode 100644 gui/images/curves.png create mode 100644 gui/images/facetracknoir.png create mode 100644 gui/images/filter-16.png create mode 100644 gui/images/no-feed.png create mode 100644 gui/images/settings16.png create mode 100644 gui/images/tools.png create mode 100644 gui/keyboard.h create mode 100644 gui/keyboard_listener.ui create mode 100644 gui/main.cpp create mode 100644 gui/main.ui create mode 100644 gui/mapping.ui create mode 100644 gui/new_config.ui create mode 100644 gui/new_file_dialog.h create mode 100644 gui/options-dialog.cpp create mode 100644 gui/options-dialog.hpp create mode 100644 gui/process_detector.cpp create mode 100644 gui/process_detector.h create mode 100644 gui/process_widget.ui create mode 100644 gui/settings.ui create mode 100644 gui/ui-res.qrc create mode 100644 gui/ui.cpp create mode 100644 gui/ui.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b43189c..06634b06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ file(GLOB opentrack-subprojects "protocol-*/${C}" "filter-*/${C}" "opentrack*/${C}" - "facetracknoir/${C}" + "gui/${C}" "x-plane-plugin/${C}" "csv/${C}" "pose-widget/${C}" diff --git a/facetracknoir/CMakeLists.txt b/facetracknoir/CMakeLists.txt deleted file mode 100644 index 51d0cea3..00000000 --- a/facetracknoir/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -opentrack_boilerplate(opentrack NO-LIBRARY) - -if(UNIX OR APPLE) - target_include_directories(opentrack "${CMAKE_SOURCE_DIR}/qxt-mini") - if(APPLE) - set(qxt-plat mac) - else() - set(qxt-plat x11) - endif() - file(GLOB qxt-mini-c - ${CMAKE_SOURCE_DIR}/qxt-mini/*.h - ${CMAKE_SOURCE_DIR}/qxt-mini/qxtglobalshortcut.cpp - ${CMAKE_SOURCE_DIR}/qxt-mini/plat/qxtglobalshortcut_${qxt-plat}.cpp - ) - opentrack_qt(qxt-mini) - add_library(opentrack-qxt-mini STATIC ${qxt-mini-all}) - target_link_libraries(opentrack-qxt-mini ${MY_QT_LIBS}) - if(NOT APPLE) - target_link_libraries(opentrack-qxt-mini X11) - endif() -endif() - -if(WIN32) - SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console window visible at runtime") -endif() - -if(WIN32 AND NOT SDK_CONSOLE_DEBUG) - set(opentrack-win32-executable WIN32) -else() - set(opentrack-win32-executable "") -endif() - -if(UNIX OR APPLE) - list(APPEND opentrack-c ${CMAKE_SOURCE_DIR}/qxt-mini/qxtglobalshortcut.h) -endif() -opentrack_qt(opentrack) -add_executable(opentrack ${opentrack-win32-executable} ${opentrack-all}) -opentrack_compat(opentrack) -if(NOT WIN32) - set_target_properties(opentrack PROPERTIES SUFFIX ".bin") -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() -if(UNIX OR APPLE) - target_link_libraries(opentrack opentrack-qxt-mini) -endif() -link_with_dinput8(opentrack) -target_link_libraries(opentrack ${MY_QT_LIBS}) - -if(APPLE) - # for process detector - target_link_libraries(opentrack proc) -endif() - -if(LINUX) - # for process detector - target_link_libraries(opentrack procps) -endif() - -install(TARGETS opentrack DESTINATION .) diff --git a/facetracknoir/curve-config.cpp b/facetracknoir/curve-config.cpp deleted file mode 100644 index 2e9065b4..00000000 --- a/facetracknoir/curve-config.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2014-2015, Stanislaw Halik - - * 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 "curve-config.h" -#include "opentrack/main-settings.hpp" -MapWidget::MapWidget(Mappings& m, main_settings& s) : - m(m) -{ - ui.setupUi( this ); - - // rest of mapping settings taken care of by options::value - m.load_mappings(); - - { - struct { - QFunctionConfigurator* qfc; - Axis axis; - QCheckBox* checkbox; - bool altp; - } qfcs[] = - { - { ui.rxconfig, Yaw, nullptr, false }, - { ui.ryconfig, Pitch, nullptr, false }, - { ui.rzconfig, Roll, nullptr, false }, - { ui.txconfig, TX, nullptr, false }, - { ui.tyconfig, TY, nullptr, false }, - { ui.tzconfig, TZ, nullptr, false }, - - { ui.rxconfig_alt, Yaw, ui.rx_altp, true }, - { ui.ryconfig_alt, Pitch, ui.ry_altp, true }, - { ui.rzconfig_alt, Roll, ui.rz_altp, true }, - { ui.txconfig_alt, TX, ui.tx_altp, true }, - { ui.tyconfig_alt, TY, ui.ty_altp, true }, - { ui.tzconfig_alt, TZ, ui.tz_altp, true }, - { nullptr, Yaw, nullptr, false } - }; - - for (int i = 0; qfcs[i].qfc; i++) - { - const bool altp = qfcs[i].altp; - Mapping& axis = m(qfcs[i].axis); - Map* conf = altp ? &axis.curveAlt : &axis.curve; - const auto& name = qfcs[i].altp ? axis.name2 : axis.name1; - if (altp) - { - QFunctionConfigurator& qfc = *qfcs[i].qfc; - connect(qfcs[i].checkbox, &QCheckBox::toggled, - [&](bool f) -> void {qfc.setEnabled(f); qfc.force_redraw();}); - qfc.setEnabled(qfcs[i].checkbox->isChecked()); - qfc.force_redraw(); - } - qfcs[i].qfc->setConfig(conf, name); - } - } - - setFont(qApp->font()); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.a_x.altp, ui.tx_altp); - tie_setting(s.a_y.altp, ui.ty_altp); - tie_setting(s.a_z.altp, ui.tz_altp); - tie_setting(s.a_yaw.altp, ui.rx_altp); - tie_setting(s.a_pitch.altp, ui.ry_altp); - tie_setting(s.a_roll.altp, ui.rz_altp); -} - -void MapWidget::doOK() { - m.save_mappings(); - this->close(); -} - -void MapWidget::doCancel() { - m.invalidate_unsaved(); - this->close(); -} diff --git a/facetracknoir/curve-config.h b/facetracknoir/curve-config.h deleted file mode 100644 index 0cbc7055..00000000 --- a/facetracknoir/curve-config.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include "opentrack/mappings.hpp" -#include "ui_mapping.h" - -class MapWidget: public QWidget -{ - Q_OBJECT -public: - MapWidget(Mappings &m, main_settings &s); -private: - Ui::UICCurveConfigurationDialog ui; - Mappings& m; - void closeEvent(QCloseEvent *) override { doCancel(); } -private slots: - void doOK(); - void doCancel(); -}; diff --git a/facetracknoir/facetracknoir.ico b/facetracknoir/facetracknoir.ico deleted file mode 100644 index 5cac8da1..00000000 Binary files a/facetracknoir/facetracknoir.ico and /dev/null differ diff --git a/facetracknoir/facetracknoir.rc b/facetracknoir/facetracknoir.rc deleted file mode 100644 index 020ffe97..00000000 --- a/facetracknoir/facetracknoir.rc +++ /dev/null @@ -1,2 +0,0 @@ -#include -IDI_ICON1 ICON "facetracknoir.ico" diff --git a/facetracknoir/images/curves.png b/facetracknoir/images/curves.png deleted file mode 100644 index 3f953a0a..00000000 Binary files a/facetracknoir/images/curves.png and /dev/null differ diff --git a/facetracknoir/images/facetracknoir.png b/facetracknoir/images/facetracknoir.png deleted file mode 100644 index 85c06df6..00000000 Binary files a/facetracknoir/images/facetracknoir.png and /dev/null differ diff --git a/facetracknoir/images/filter-16.png b/facetracknoir/images/filter-16.png deleted file mode 100644 index ecde6a10..00000000 Binary files a/facetracknoir/images/filter-16.png and /dev/null differ diff --git a/facetracknoir/images/no-feed.png b/facetracknoir/images/no-feed.png deleted file mode 100644 index 02aa227a..00000000 Binary files a/facetracknoir/images/no-feed.png and /dev/null differ diff --git a/facetracknoir/images/settings16.png b/facetracknoir/images/settings16.png deleted file mode 100644 index 3b31623b..00000000 Binary files a/facetracknoir/images/settings16.png and /dev/null differ diff --git a/facetracknoir/images/tools.png b/facetracknoir/images/tools.png deleted file mode 100644 index 2da8f9f5..00000000 Binary files a/facetracknoir/images/tools.png and /dev/null differ diff --git a/facetracknoir/keyboard.h b/facetracknoir/keyboard.h deleted file mode 100644 index 62a9ce20..00000000 --- a/facetracknoir/keyboard.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#include "ui_keyboard_listener.h" -#ifdef _WIN32 -#include "opentrack/win32-shortcuts.h" -#include "opentrack/shortcuts.h" -#endif -#include -#include -#include - -class KeyboardListener : public QLabel -{ - Q_OBJECT - Ui_keyboard_listener ui; -#ifdef _WIN32 - KeybindingWorker w; -#endif -public: - KeyboardListener(QWidget* parent = nullptr) : QLabel(parent) -#ifdef _WIN32 - , w([&](Key& k) - { - Qt::KeyboardModifiers m; - QKeySequence k_; - if (win_key::to_qt(k, k_, m)) - key_pressed(static_cast(k_).toInt() | m); - }, this->winId()) -#endif - { - ui.setupUi(this); - setFocusPolicy(Qt::StrongFocus); -#ifdef _WIN32 - w.start(); -#endif - } -#ifndef _WIN32 - void keyPressEvent(QKeyEvent* event) override - { - //qDebug() << "k" << (event->key() | event->modifiers()); - switch (event->key() | event->modifiers()) - { - default: - emit key_pressed(QKeySequence(event->key() | event->modifiers())); - break; - } - } -#endif -signals: - void key_pressed(QKeySequence k); -}; diff --git a/facetracknoir/keyboard_listener.ui b/facetracknoir/keyboard_listener.ui deleted file mode 100644 index b6977df0..00000000 --- a/facetracknoir/keyboard_listener.ui +++ /dev/null @@ -1,37 +0,0 @@ - - - keyboard_listener - - - Qt::ApplicationModal - - - - 0 - 0 - 224 - 33 - - - - - 0 - 0 - - - - Bind a shortcut - - - <html><head/><body><p>Press a key or close this window to remove the keybinding.</p></body></html> - - - Qt::RichText - - - 10 - - - - - diff --git a/facetracknoir/main.cpp b/facetracknoir/main.cpp deleted file mode 100644 index a63fe54a..00000000 --- a/facetracknoir/main.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifdef _WIN32 -# include -#endif - -#include "ui.h" -#include "opentrack/options.hpp" -using namespace options; -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -// workaround QTBUG-38598, allow for launching from another directory -static void add_program_library_path() -{ - char* p = _pgmptr; - char path[MAX_PATH+1]; - strcpy(path, p); - char* ptr = strrchr(path, '\\'); - if (ptr) - { - *ptr = '\0'; - QCoreApplication::addLibraryPath(path); - } -} -#endif - -int main(int argc, char** argv) -{ -#ifdef _WIN32 - add_program_library_path(); -#elif !defined(__linux) - // workaround QTBUG-38598 - QCoreApplication::addLibraryPath("."); -#endif - -#if defined(_WIN32) || defined(__APPLE__) - // qt5 designer-made controls look like shit on 'doze -sh 20140921 - // also our OSX look leaves a lot to be desired -sh 20150726 - { - const QStringList preferred { "fusion", "windowsvista", "macintosh", "windowsxp" }; - for (const auto& style_name : preferred) - { - QStyle* s = QStyleFactory::create(style_name); - if (s) - { - QApplication::setStyle(s); - break; - } - } - } -#endif - - QApplication::setAttribute(Qt::AA_X11InitThreads, true); - QApplication app(argc, argv); - - auto w = std::make_shared(); - - w->show(); - app.exec(); - - // on MSVC crashes in atexit -#ifdef _MSC_VER - TerminateProcess(GetCurrentProcess(), 0); -#endif - return 0; -} diff --git a/facetracknoir/main.ui b/facetracknoir/main.ui deleted file mode 100644 index ab63e832..00000000 --- a/facetracknoir/main.ui +++ /dev/null @@ -1,1255 +0,0 @@ - - - Lovecraftian Octopus - OpentrackUI - - - - 0 - 0 - 707 - 494 - - - - - :/images/facetracknoir.png:/images/facetracknoir.png - - - #video_feed { border: 0; } - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - 0 - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 480 - 360 - - - - - 480 - 360 - - - - - - 0 - 0 - 480 - 360 - - - - - 0 - 0 - - - - - - 0 - 0 - 480 - 360 - - - - - 0 - 0 - - - - - 480 - 360 - - - - - 480 - 360 - - - - - - - - - - - - - QFrame::NoFrame - - - 0 - - - - 12 - - - 6 - - - 12 - - - 8 - - - 4 - - - - - - 0 - 0 - - - - - 80 - 90 - - - - - - - - - 0 - 0 - - - - Raw tracker data - - - - 0 - - - 0 - - - 0 - - - 0 - - - 3 - - - 2 - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - yaw - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - roll - - - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TZ - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - pitch - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - TX - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 1 - - - true - - - 4 - - - QLCDNumber::Outline - - - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TY - - - - - - - - - - - 0 - 0 - - - - Game data - - - - 0 - - - 0 - - - 0 - - - 0 - - - 3 - - - 2 - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TY - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - pitch - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - yaw - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - roll - - - - - - - true - - - - 0 - 0 - - - - false - - - QFrame::Raised - - - TZ - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - TX - - - - - - - true - - - - 0 - 0 - - - - QFrame::NoFrame - - - true - - - 4 - - - QLCDNumber::Flat - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 4 - - - 8 - - - 10 - - - 0 - - - 4 - - - 0 - - - - - - 4 - 0 - - - - Settings - - - true - - - - 3 - - - 4 - - - 2 - - - 0 - - - 6 - - - - - - 0 - 2 - - - - - 0 - - - 0 - - - 2 - - - 2 - - - - - true - - - - 0 - 0 - - - - Profile - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextBesideIcon - - - true - - - Qt::DownArrow - - - - - - - - 0 - 0 - - - - 20 - - - - - - - - - - - 0 - 3 - - - - Mapping - - - - :/images/curves.png:/images/curves.png - - - - 80 - 24 - - - - - - - - - 0 - 3 - - - - Options - - - - :/images/tools.png:/images/tools.png - - - - 80 - 24 - - - - - - - - - - - - 3 - 0 - - - - Controls - - - true - - - - 8 - - - 0 - - - 8 - - - 0 - - - 9 - - - - - - 0 - 0 - - - - Start - - - - - - - false - - - - 0 - 0 - - - - Stop - - - - - - - - - - - 4 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 2 - - - 3 - - - 2 - - - 3 - - - 8 - - - - - Tracker - - - - 4 - - - 0 - - - 4 - - - 0 - - - 3 - - - 0 - - - - - - - - true - - - ... - - - false - - - - - - - - - - Protocol - - - - 4 - - - 0 - - - 4 - - - 0 - - - 3 - - - 0 - - - - - - - - true - - - ... - - - false - - - - - - - - - - Filter - - - - 4 - - - 0 - - - 4 - - - 0 - - - 3 - - - 0 - - - - - - - - true - - - ... - - - false - - - - - - - - - - - - - - - - - - - - - GLWidget - QWidget -
pose-widget/glwidget.h
-
-
- - btnStartTracker - btnStopTracker - iconcomboTrackerSource - btnShowEngineControls - iconcomboProtocol - btnShowServerControls - iconcomboFilter - btnShowFilterControls - profile_button - iconcomboProfile - btnEditCurves - btnShortcuts - - - - - -
diff --git a/facetracknoir/mapping.ui b/facetracknoir/mapping.ui deleted file mode 100644 index 75c32e27..00000000 --- a/facetracknoir/mapping.ui +++ /dev/null @@ -1,391 +0,0 @@ - - - UICCurveConfigurationDialog - - - - 0 - 0 - 970 - 664 - - - - - 0 - 0 - - - - - 970 - 664 - - - - - 970 - 664 - - - - Mapping properties - - - - images/facetracknoir.pngimages/facetracknoir.png - - - Qt::LeftToRight - - - background-color: #ccc; - - - - - - - - - QTabWidget::North - - - 0 - - - - Yaw - - - - - - - 255 - 0 - 0 - - - - - 240 - 240 - 240 - - - - - - - - Asymmetric mapping below - - - - - - - - 255 - 0 - 0 - - - - - 255 - 255 - 255 - - - - - - - - - Pitch - - - - - - - 0 - 255 - 0 - - - - - 240 - 240 - 240 - - - - - - - - Asymmetric mapping below - - - - - - - - 0 - 255 - 0 - - - - - 240 - 240 - 240 - - - - - - - - - Roll - - - - - - - 0 - 0 - 255 - - - - - 240 - 240 - 240 - - - - - - - - Asymmetric mapping below - - - - - - - - 0 - 0 - 255 - - - - - 240 - 240 - 240 - - - - - - - - - X - - - - - - - 255 - 0 - 255 - - - - - 240 - 240 - 240 - - - - - - - - Asymmetric mapping below - - - - - - - - 255 - 0 - 255 - - - - - 240 - 240 - 240 - - - - - - - - - Y - - - - - - - 255 - 255 - 0 - - - - - 240 - 240 - 240 - - - - - - - - Asymmetric mapping below - - - - - - - - 255 - 255 - 0 - - - - - 240 - 240 - 240 - - - - - - - - - Z - - - - - - - 0 - 255 - 255 - - - - - 240 - 240 - 240 - - - - - - - - Asymmetric mapping below - - - - - - - - 0 - 255 - 255 - - - - - 240 - 240 - 240 - - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - QFunctionConfigurator - QWidget -
spline-widget/qfunctionconfigurator.h
-
-
- - ry_altp - rz_altp - tx_altp - ty_altp - tz_altp - tabWidget - buttonBox - rx_altp - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - -
diff --git a/facetracknoir/new_config.ui b/facetracknoir/new_config.ui deleted file mode 100644 index 27dce0f8..00000000 --- a/facetracknoir/new_config.ui +++ /dev/null @@ -1,45 +0,0 @@ - - - UI_new_config - - - Qt::ApplicationModal - - - - 0 - 0 - 269 - 67 - - - - Config filename - - - - images/facetracknoir.pngimages/facetracknoir.png - - - - - - New file name: - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - diff --git a/facetracknoir/new_file_dialog.h b/facetracknoir/new_file_dialog.h deleted file mode 100644 index 3a35cf71..00000000 --- a/facetracknoir/new_file_dialog.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "ui_new_config.h" -#include "opentrack/options.hpp" -#include -#include -#include -#include - -class new_file_dialog : public QDialog -{ - Q_OBJECT -public: - new_file_dialog(QWidget* parent = 0) : QDialog(parent), ok(false) - { - ui.setupUi(this); - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(ok_clicked())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(cancel_clicked())); - setFixedSize(size()); - } - bool is_ok(QString& name_) - { - name_ = name; - return ok; - } -private: - Ui::UI_new_config ui; - bool ok; - QString name; -private slots: - void cancel_clicked() { close(); } - void ok_clicked() - { - QString text = ui.lineEdit->text(); - text = text.replace('/', ""); - text = text.replace('\\', ""); - if (text != "" && !text.endsWith(".ini")) - text += ".ini"; - if (text == "" || text == ".ini" || QFile(options::group::ini_directory() + "/" + text).exists()) - { - QMessageBox::warning(this, - "File exists", "This file already exists. Pick another name.", - QMessageBox::Ok, QMessageBox::NoButton); - return; - } - ok = true; - close(); - name = text; - } -}; diff --git a/facetracknoir/options-dialog.cpp b/facetracknoir/options-dialog.cpp deleted file mode 100644 index fef2b0ca..00000000 --- a/facetracknoir/options-dialog.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2015, Stanislaw Halik - - * 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 "options-dialog.hpp" -#include "keyboard.h" -#include -#include - -OptionsDialog::OptionsDialog() -{ - ui.setupUi( this ); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - - tie_setting(s.s_main.tray_enabled, ui.trayp); - - tie_setting(s.s_main.center_at_startup, ui.center_at_startup); - - tie_setting(s.s_main.tcomp_p, ui.tcomp_enable); - tie_setting(s.s_main.tcomp_tz, ui.tcomp_rz); - - tie_setting(s.s_main.a_x.zero, ui.pos_tx); - tie_setting(s.s_main.a_y.zero, ui.pos_ty); - tie_setting(s.s_main.a_z.zero, ui.pos_tz); - tie_setting(s.s_main.a_yaw.zero, ui.pos_rx); - tie_setting(s.s_main.a_pitch.zero, ui.pos_ry); - tie_setting(s.s_main.a_roll.zero, ui.pos_rz); - - tie_setting(s.s_main.a_yaw.invert, ui.invert_yaw); - tie_setting(s.s_main.a_pitch.invert, ui.invert_pitch); - tie_setting(s.s_main.a_roll.invert, ui.invert_roll); - tie_setting(s.s_main.a_x.invert, ui.invert_x); - tie_setting(s.s_main.a_y.invert, ui.invert_y); - tie_setting(s.s_main.a_z.invert, ui.invert_z); - - tie_setting(s.s_main.a_yaw.src, ui.src_yaw); - tie_setting(s.s_main.a_pitch.src, ui.src_pitch); - tie_setting(s.s_main.a_roll.src, ui.src_roll); - tie_setting(s.s_main.a_x.src, ui.src_x); - tie_setting(s.s_main.a_y.src, ui.src_y); - tie_setting(s.s_main.a_z.src, ui.src_z); - - tie_setting(s.s_main.camera_yaw, ui.camera_yaw); - tie_setting(s.s_main.camera_pitch, ui.camera_pitch); - tie_setting(s.s_main.camera_roll, ui.camera_roll); - - tie_setting(s.s_main.center_method, ui.center_method); - - connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center.keycode, ui.center_text); }); - connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero.keycode, ui.zero_text); }); - connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle.keycode, ui.toggle_text); }); - - ui.center_text->setText(s.center.keycode == "" ? "None" : static_cast(s.center.keycode)); - ui.toggle_text->setText(s.toggle.keycode == "" ? "None" : static_cast(s.toggle.keycode)); - ui.zero_text->setText(s.zero.keycode == "" ? "None" : static_cast(s.zero.keycode)); -} - -void OptionsDialog::bind_key(value& ret, QLabel* label) -{ - ret = ""; - QDialog d; - auto l = new QHBoxLayout; - l->setMargin(0); - auto k = new KeyboardListener; - l->addWidget(k); - d.setLayout(l); - d.setFixedSize(QSize(500, 300)); - d.setWindowFlags(Qt::Dialog); - connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { ret = s.toString(QKeySequence::PortableText); d.close(); }); - d.exec(); - label->setText(ret == "" ? "None" : static_cast(ret)); - delete k; - delete l; -} - -void OptionsDialog::doOK() { - s.b->save(); - s.s_main.b->save(); - ui.game_detector->save(); - this->close(); - emit reload(); -} - -void OptionsDialog::doCancel() { - s.b->reload(); - s.s_main.b->reload(); - ui.game_detector->revert(); - close(); -} - diff --git a/facetracknoir/options-dialog.hpp b/facetracknoir/options-dialog.hpp deleted file mode 100644 index 3ef99d06..00000000 --- a/facetracknoir/options-dialog.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include -#include "ui_settings.h" -#include "opentrack/shortcuts.h" - -class OptionsDialog: public QWidget -{ - Q_OBJECT -signals: - void reload(); -public: - OptionsDialog(); -private: - Ui::UI_Settings ui; - Shortcuts::settings s; - void closeEvent(QCloseEvent *) override { doCancel(); } -private slots: - void doOK(); - void doCancel(); - void bind_key(value& ret, QLabel* label); -}; diff --git a/facetracknoir/process_detector.cpp b/facetracknoir/process_detector.cpp deleted file mode 100644 index 59a40f03..00000000 --- a/facetracknoir/process_detector.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (c) 2015, Stanislaw Halik - - * 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 "process_detector.h" -#include "facetracknoir/ui.h" -#include "opentrack-compat/process-list.hpp" -#include -#include -#include -#include -#include -#include - -void settings::set_game_list(const QString &game_list) -{ - QSettings settings(OPENTRACK_ORG); - settings.setValue("executable-list", game_list); -} - -QString settings::get_game_list() -{ - QSettings settings(OPENTRACK_ORG); - return settings.value("executable-list").toString(); -} - -bool settings::is_enabled() -{ - QSettings settings(OPENTRACK_ORG); - return settings.value("executable-detector-enabled", false).toBool(); -} - -void settings::set_is_enabled(bool enabled) -{ - QSettings settings(OPENTRACK_ORG); - settings.setValue("executable-detector-enabled", enabled); -} - -QHash settings::split_process_names() -{ - QHash ret; - QString str = get_game_list(); - QStringList pairs = str.split('|'); - for (auto pair : pairs) - { - QList tmp = pair.split(':'); - if (tmp.count() != 2) - continue; - ret[tmp[0]] = tmp[1]; - } - return ret; -} - -void BrowseButton::browse() -{ - QFileDialog dialog(this); - dialog.setFileMode(QFileDialog::ExistingFile); - QString dir_path = QFileInfo(group::ini_pathname()).absolutePath(); - QString filename = dialog.getOpenFileName( - this, - tr("Set executable name"), - dir_path, - tr("Executable (*.exe);;All Files (*)")); - MainWindow::set_working_directory(); - filename = QFileInfo(filename).fileName(); - if (!filename.isNull()) - twi->setText(filename); -} - -int process_detector::add_row(QString exe_name, QString profile) -{ - int i = ui.tableWidget->rowCount(); - ui.tableWidget->insertRow(i); - - QComboBox* cb = new QComboBox(); - cb->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); - cb->addItem(""); - cb->addItems(group::ini_list()); - ui.tableWidget->setCellWidget(i, 1, cb); - - QTableWidgetItem* twi = new QTableWidgetItem(exe_name); - ui.tableWidget->setItem(i, 0, twi); - - { - BrowseButton* b = new BrowseButton(twi); - b->setText("..."); - QObject::connect(b, SIGNAL(pressed()), b, SLOT(browse())); - ui.tableWidget->setCellWidget(i, 2, b); - } - - cb->setCurrentText(profile); - - return i; -} - -void process_detector::add_items() -{ - auto names = s.split_process_names(); - ui.tableWidget->clearContents(); - auto keys = names.keys(); - qSort(keys); - for (auto n : keys) - add_row(n, names[n]); -} - -process_detector::process_detector(QWidget* parent) : QWidget(parent) -{ - ui.setupUi(this); - setFixedSize(size()); - connect(ui.add, SIGNAL(pressed()), this, SLOT(add())); - connect(ui.remove, SIGNAL(pressed()), this, SLOT(remove())); - - add_items(); - - QResizeEvent e(ui.tableWidget->size(), ui.tableWidget->size()); - ui.tableWidget->resizeEvent(&e); - - settings s; - - ui.enabled->setChecked(s.is_enabled()); -} - -void process_detector::save() -{ - QString str; - - for (int i = 0; i < ui.tableWidget->rowCount(); i++) - { - auto exe = ui.tableWidget->item(i, 0)->text(); - auto profile = reinterpret_cast(ui.tableWidget->cellWidget(i, 1))->currentText(); - str += "|" + exe + ":" + profile; - } - - s.set_game_list(str); - s.set_is_enabled(ui.enabled->isChecked()); -} - -void process_detector::revert() -{ -} - -void process_detector::add() -{ - add_row(); -} - -void process_detector::remove() -{ - int r = ui.tableWidget->currentRow(); - if (r != -1) - ui.tableWidget->removeRow(r); -} - -bool process_detector_worker::should_stop() -{ - if (last_exe_name == "") - return false; - - settings s; - - if (!s.is_enabled()) - { - last_exe_name = ""; - return false; - } - - QStringList exe_list = get_all_executable_names(); - - if (exe_list.contains(last_exe_name)) - return false; - - last_exe_name = ""; - - return true; -} - -bool process_detector_worker::config_to_start(QString& str) -{ - settings s; - if (!s.is_enabled()) - { - last_exe_name = ""; - return false; - } - - auto filenames = s.split_process_names(); - QStringList exe_list = get_all_executable_names(); - - // assuming manual stop by user button click. - // don't automatically start again while the same process is running. - if (last_exe_name != "" && exe_list.contains(last_exe_name)) - return false; - // it's gone, we can start automatically again - last_exe_name = ""; - - for (auto& name : exe_list) - { - if (filenames.contains(name)) - { - last_exe_name = name; - str = filenames[name]; - return str != ""; - } - } - - return false; -} diff --git a/facetracknoir/process_detector.h b/facetracknoir/process_detector.h deleted file mode 100644 index f6497c90..00000000 --- a/facetracknoir/process_detector.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (c) 2015, Stanislaw Halik - - * 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 -#include -#include -#include - -#include "opentrack/options.hpp" -using namespace options; - -class FancyTable : public QTableWidget -{ - Q_OBJECT -public: - void resizeEvent(QResizeEvent* e) override - { - QTableView::resizeEvent(e); - int w = width(); - setColumnWidth(2, 32); - w -= 48; - setColumnWidth(0, w / 2); - setColumnWidth(1, w / 2); - } -public: - FancyTable(QWidget* parent = nullptr) : QTableWidget(parent) {} -}; - -struct settings -{ - QHash split_process_names(); - QString get_game_list(); - void set_game_list(const QString& game_list); - bool is_enabled(); - void set_is_enabled(bool enabled); -}; - -#include "ui_process_widget.h" - -class process_detector : public QWidget -{ - Q_OBJECT - - Ui_Dialog ui; - settings s; - - int add_row(QString exe_name = "...", QString profile = ""); - void add_items(); -public: - process_detector(QWidget* parent = nullptr); -public slots: - void save(); - void revert(); -private slots: - void add(); - void remove(); -}; - -class BrowseButton : public QPushButton -{ - Q_OBJECT - QTableWidgetItem* twi; -public: - BrowseButton(QTableWidgetItem* twi) : twi(twi) - {} -public slots: - void browse(); -}; - -class process_detector_worker : QObject -{ - Q_OBJECT - settings s; - QString last_exe_name; -public: - bool config_to_start(QString& s); - bool should_stop(); -}; - diff --git a/facetracknoir/process_widget.ui b/facetracknoir/process_widget.ui deleted file mode 100644 index 19fe39da..00000000 --- a/facetracknoir/process_widget.ui +++ /dev/null @@ -1,121 +0,0 @@ - - - Dialog - - - - 0 - 0 - 302 - 325 - - - - Game detector - - - - - - - 0 - 0 - - - - - Executable - - - - - Profile - - - - - - - - - - - - - - 0 - 0 - - - - border: 0; - - - - - - - 5 - - - - - - 0 - 0 - - - - - 14 - 75 - true - - - - + - - - - - - - - 0 - 0 - - - - - 14 - 75 - true - - - - - - - - - - - - - - - Start profiles from game executable names in this list - - - - - - - - FancyTable - QTableWidget -
facetracknoir/process_detector.h
-
-
- - -
diff --git a/facetracknoir/settings.ui b/facetracknoir/settings.ui deleted file mode 100644 index 92d275b6..00000000 --- a/facetracknoir/settings.ui +++ /dev/null @@ -1,1109 +0,0 @@ - - - UI_Settings - - - - 0 - 0 - 348 - 548 - - - - Options - - - - images/facetracknoir.pngimages/facetracknoir.png - - - Qt::LeftToRight - - - false - - - - - - 0 - - - - Shortcuts - - - - - - Global shortcuts - - - - - - - 0 - 0 - - - - <html><head/><body><p><span style=" font-weight:600;">Center</span> - use current pose as looking perfectly forward.<br/><span style=" font-weight:600;">Toggle</span> - keep looking at same spot until toggle keypress.<br/><span style=" font-weight:600;">Zero</span> - keep looking forward while the key is pressed.<br/></p></body></html> - - - true - - - - - - - QGroupBox { border: 0; } - - - - - - - - - - - - - Center - - - false - - - - - - - - - - - - - - - - - - - - - Toggle - - - false - - - - - - - Zero - - - false - - - - - - - Bind - - - - - - - Bind - - - - - - - Bind - - - - - - - - - - - - - Centering method - - - - - - Method - - - - - - - - Relative (inertial device) - - - - - Absolute (camera device) - - - - - - - - Try changing this if centering doesn't perform correctly for your input device. - - - true - - - - - - - - - - Center at startup - - - - - - - Minimize to tray - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Camera - - - - - - Camera offset - - - - - - <html><head/><body><p>Specify an angle for off-center camera as a basis for which direction is which, avoiding axis interconnect. Also see <a href="https://github.com/opentrack/opentrack/wiki/choosing-camera-offset"><span style=" text-decoration: underline; color:#0000ff;">description on wiki</span></a>.</p></body></html> - - - Qt::AlignJustify|Qt::AlignVCenter - - - true - - - 2 - - - true - - - - - - - QGroupBox -{ - border: 0; -} - - - - - - Roll - - - - - - - - 80 - 0 - - - - -180 - - - 180 - - - - - - - - 80 - 0 - - - - -180 - - - 180 - - - - - - - Pitch - - - - - - - - 80 - 0 - - - - -180 - - - 180 - - - - - - - Yaw - - - - - - - - - - - - - Center pose offset - - - - - - Alter the centered position sent to games by a fixed amount. - - - true - - - 2 - - - - - - - QGroupBox { - border: 0; -} - - - - - - Qt::AlignCenter - - - false - - - false - - - - - - deg. - - - 3 - - - -180.000000000000000 - - - 180.000000000000000 - - - - - - - cm - - - 3 - - - -100.000000000000000 - - - 100.000000000000000 - - - - - - - TX - - - - - - - cm - - - 3 - - - -100.000000000000000 - - - 100.000000000000000 - - - - - - - RY - - - - - - - TY - - - - - - - deg. - - - 3 - - - -180.000000000000000 - - - 180.000000000000000 - - - - - - - TZ - - - - - - - RZ - - - - - - - cm - - - 3 - - - -100.000000000000000 - - - 100.000000000000000 - - - - - - - RX - - - - - - - deg. - - - 3 - - - -180.000000000000000 - - - 180.000000000000000 - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Output - - - - - - - 0 - 0 - - - - - - - Translation compensation - - - false - - - - - - With compensation on, translation is applied after rotation. For example, rotating +180 degrees yaw and moving backwards results in moving forward as a result of that rotation. - - - Qt::AlignJustify|Qt::AlignVCenter - - - true - - - 2 - - - - - - - - - - Enable - - - - - - - - - - Disable Z axis compensation - - - - - - - - - - - 65536 - 65536 - - - - - true - - - - Output remap - - - Qt::AlignCenter - - - false - - - false - - - - QLayout::SetMinAndMaxSize - - - 6 - - - - - Assign input axis to output axis. - - - Qt::AlignJustify|Qt::AlignVCenter - - - true - - - - - - - QGroupBox -{ - border: 0; -} - - - - - - - - - - - - - Roll - - - - - - - X - - - - - - - Invert - - - - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - Disabled - - - - - - - - Pitch - - - - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - Disabled - - - - - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - Disabled - - - - - - - - - - - - - - - Y - - - - - - - Destination - - - - - - - - - - - - - - Yaw - - - - - - - - - - - - - - Source - - - - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - Disabled - - - - - - - - - - - - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - Disabled - - - - - - - - Z - - - - - - - - X - - - - - Y - - - - - Z - - - - - Yaw - - - - - Pitch - - - - - Roll - - - - - Disabled - - - - - - - - - - - - - label_15 - label_13 - label_14 - src_yaw - invert_yaw - label_7 - src_pitch - label_8 - invert_pitch - label_9 - src_roll - invert_roll - label_10 - src_x - invert_x - label_11 - src_y - invert_y - label_12 - src_z - invert_z - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Game detection - - - - - - Game detection - - - - - - - - - - 0 - 0 - - - - Start tracking automatically when a game starts with selected profile, and stop when the game exits. - - - true - - - - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - process_detector - QWidget -
facetracknoir/process_detector.h
-
-
- - tabWidget - center_at_startup - trayp - camera_yaw - camera_pitch - camera_roll - pos_rx - pos_ry - pos_rz - pos_tx - pos_ty - pos_tz - tcomp_enable - tcomp_rz - src_yaw - invert_yaw - src_pitch - invert_pitch - src_roll - invert_roll - src_x - invert_x - src_y - invert_y - src_z - invert_z - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - -
diff --git a/facetracknoir/ui-res.qrc b/facetracknoir/ui-res.qrc deleted file mode 100644 index 030a6153..00000000 --- a/facetracknoir/ui-res.qrc +++ /dev/null @@ -1,10 +0,0 @@ - - - images/tools.png - images/settings16.png - images/curves.png - images/facetracknoir.png - images/no-feed.png - images/filter-16.png - - diff --git a/facetracknoir/ui.cpp b/facetracknoir/ui.cpp deleted file mode 100644 index d0a5e93c..00000000 --- a/facetracknoir/ui.cpp +++ /dev/null @@ -1,567 +0,0 @@ -/* Copyright (c) 2013-2015, Stanislaw Halik - - * 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 "ui.h" -#include "opentrack/tracker.h" -#include "opentrack/options.hpp" -#include "facetracknoir/new_file_dialog.h" -#include -#include - -#ifndef _WIN32 -# include -#else -# include -#endif - -MainWindow::MainWindow() : - pose_update_timer(this), - kbd_quit(QKeySequence("Ctrl+Q"), this), - no_feed_pixmap(":/images/no-feed.png"), - is_refreshing_profiles(false) -{ - ui.setupUi(this); - - setFixedSize(size()); - - updateButtonState(false, false); - ui.video_frame_label->setPixmap(no_feed_pixmap); - - connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration())); - connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(show_options_dialog())); - connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings())); - connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showProtocolSettings())); - connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterSettings())); - - modules.filters().push_front(std::make_shared("", dylib::Filter)); - - for (auto x : modules.trackers()) - ui.iconcomboTrackerSource->addItem(x->icon, x->name); - - for (auto x : modules.protocols()) - ui.iconcomboProtocol->addItem(x->icon, x->name); - - for (auto x : modules.filters()) - ui.iconcomboFilter->addItem(x->icon, x->name); - - refresh_config_list(); - connect(&config_list_timer, SIGNAL(timeout()), this, SLOT(refresh_config_list())); - config_list_timer.start(1000 * 3); - - tie_setting(s.tracker_dll, ui.iconcomboTrackerSource); - tie_setting(s.protocol_dll, ui.iconcomboProtocol); - tie_setting(s.filter_dll, ui.iconcomboFilter); - - connect(ui.iconcomboTrackerSource, - &QComboBox::currentTextChanged, - [&](QString) -> void { if (pTrackerDialog) pTrackerDialog = nullptr; save(); }); - - connect(ui.iconcomboProtocol, - &QComboBox::currentTextChanged, - [&](QString) -> void { if (pProtocolDialog) pProtocolDialog = nullptr; save(); }); - - connect(ui.iconcomboFilter, - &QComboBox::currentTextChanged, - [&](QString) -> void { if (pFilterDialog) pFilterDialog = nullptr; save(); }); - - connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker())); - connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker())); - connect(ui.iconcomboProfile, SIGNAL(currentTextChanged(QString)), this, SLOT(profileSelected(QString))); - - connect(&pose_update_timer, SIGNAL(timeout()), this, SLOT(showHeadPose())); - connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit())); - - save_timer.setSingleShot(true); - connect(&save_timer, SIGNAL(timeout()), this, SLOT(_save())); - - profile_menu.addAction("Create new empty config", this, SLOT(make_empty_config())); - profile_menu.addAction("Create new copied config", this, SLOT(make_copied_config())); - profile_menu.addAction("Open configuration directory", this, SLOT(open_config_directory())); - ui.profile_button->setMenu(&profile_menu); - - kbd_quit.setEnabled(true); - - connect(&det_timer, SIGNAL(timeout()), this, SLOT(maybe_start_profile_from_executable())); - det_timer.start(1000); - - ensure_tray(); - set_working_directory(); - - if (!QFile(group::ini_pathname()).exists()) - { - set_profile(OPENTRACK_DEFAULT_CONFIG); - const auto pathname = group::ini_pathname(); - if (!QFile(pathname).exists()) - { - QFile file(pathname); - (void) file.open(QFile::ReadWrite); - } - } - - if (group::ini_directory() == "") - QMessageBox::warning(this, - "Configuration not saved.", - "Can't create configuration directory! Expect major malfunction.", - QMessageBox::Ok, QMessageBox::NoButton); - - ui.btnStartTracker->setFocus(); -} - -bool MainWindow::get_new_config_name_from_dialog(QString& ret) -{ - new_file_dialog dlg; - dlg.exec(); - return dlg.is_ok(ret); -} - -MainWindow::~MainWindow() -{ - maybe_save(); - - if (tray) - tray->hide(); - stopTracker(); -} - -void MainWindow::set_working_directory() -{ - QDir::setCurrent(QCoreApplication::applicationDirPath()); -} - -void MainWindow::save_mappings() { - pose.save_mappings(); -} - -void MainWindow::save() -{ - save_timer.stop(); - save_timer.start(5000); -} - -void MainWindow::maybe_save() -{ - if (save_timer.isActive()) - { - save_timer.stop(); - _save(); - } -} - -void MainWindow::_save() { - s.b->save(); - save_mappings(); - mem settings = group::ini_file(); - settings->sync(); - -#if defined(__unix) || defined(__linux) - QString currentFile = group::ini_pathname(); - QByteArray bytes = QFile::encodeName(currentFile); - const char* filename_as_asciiz = bytes.constData(); - - if (access(filename_as_asciiz, R_OK | W_OK)) - { - QMessageBox::warning(this, "Something went wrong", "Check permissions and ownership for your .ini file!", QMessageBox::Ok, QMessageBox::NoButton); - } -#endif -} - -void MainWindow::load_mappings() { - pose.load_mappings(); -} - -void MainWindow::load_settings() { - s.b->reload(); - load_mappings(); -} - -void MainWindow::make_empty_config() -{ - QString name; - const QString dir = group::ini_directory(); - if (dir != "" && get_new_config_name_from_dialog(name)) - { - QFile filename(dir + "/" + name); - (void) filename.open(QFile::ReadWrite); - refresh_config_list(); - ui.iconcomboProfile->setCurrentText(name); - } -} - -void MainWindow::make_copied_config() -{ - const QString dir = group::ini_directory(); - const QString cur = group::ini_pathname(); - QString name; - if (cur != "" && dir != "" && get_new_config_name_from_dialog(name)) - { - const QString new_name = dir + "/" + name; - (void) QFile::remove(new_name); - (void) QFile::copy(cur, new_name); - refresh_config_list(); - ui.iconcomboProfile->setCurrentText(name); - } -} - -void MainWindow::open_config_directory() -{ - const QString path = group::ini_directory(); - if (path != "") - { - QDesktopServices::openUrl("file:///" + QDir::toNativeSeparators(path)); - } -} - -extern "C" const char* opentrack_version; - -void MainWindow::refresh_config_list() -{ - if (work) - return; - - if (group::ini_list().size() == 0) - { - QFile filename(group::ini_directory() + "/" OPENTRACK_DEFAULT_CONFIG); - (void) filename.open(QFile::ReadWrite); - } - - QStringList ini_list = group::ini_list(); - set_title(); - QString current = group::ini_filename(); - is_refreshing_profiles = true; - ui.iconcomboProfile->clear(); - for (auto x : ini_list) - ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), x); - is_refreshing_profiles = false; - ui.iconcomboProfile->setCurrentText(current); -} - -void MainWindow::updateButtonState(bool running, bool inertialp) -{ - bool not_running = !running; - ui.iconcomboProfile->setEnabled ( not_running ); - ui.btnStartTracker->setEnabled ( not_running ); - ui.btnStopTracker->setEnabled ( running ); - ui.iconcomboProtocol->setEnabled ( not_running ); - ui.iconcomboFilter->setEnabled ( not_running ); - ui.iconcomboTrackerSource->setEnabled(not_running); - ui.video_frame_label->setVisible(not_running || inertialp); - ui.profile_button->setEnabled(not_running); -} - -void MainWindow::reload_options() -{ - if (work) - work->reload_shortcuts(); - ensure_tray(); -} - -void MainWindow::startTracker() { - // tracker dtor needs run first - work = nullptr; - - libs = SelectedLibraries(ui.video_frame, current_tracker(), current_protocol(), current_filter()); - - { - double p[6] = {0,0,0, 0,0,0}; - display_pose(p, p); - } - - if (!libs.correct) - { - QMessageBox::warning(this, "Library load error", - "One of libraries failed to load. Check installation.", - QMessageBox::Ok, - QMessageBox::NoButton); - libs = SelectedLibraries(); - return; - } - - work = std::make_shared(s, pose, libs, this, winId()); - - reload_options(); - - if (pTrackerDialog) - pTrackerDialog->register_tracker(libs.pTracker.get()); - - if (pFilterDialog) - pFilterDialog->register_filter(libs.pFilter.get()); - - if (pProtocolDialog) - pProtocolDialog->register_protocol(libs.pProtocol.get()); - - pose_update_timer.start(50); - - // NB check valid since SelectedLibraries ctor called - // trackers take care of layout state updates - const bool is_inertial = ui.video_frame->layout() == nullptr; - updateButtonState(true, is_inertial); - - maybe_save(); - - ui.btnStopTracker->setFocus(); -} - -void MainWindow::stopTracker( ) { - //ui.game_name->setText("Not connected"); - - pose_update_timer.stop(); - ui.pose_display->rotateBy(0, 0, 0, 0, 0, 0); - - if (pTrackerDialog) - pTrackerDialog->unregister_tracker(); - - if (pProtocolDialog) - pProtocolDialog->unregister_protocol(); - - if (pFilterDialog) - pFilterDialog->unregister_filter(); - - maybe_save(); - - work = nullptr; - libs = SelectedLibraries(); - - { - double p[6] = {0,0,0, 0,0,0}; - display_pose(p, p); - } - updateButtonState(false, false); - - set_title(); - - ui.btnStartTracker->setFocus(); -} - -void MainWindow::display_pose(const double *mapped, const double *raw) -{ - ui.pose_display->rotateBy(mapped[Yaw], mapped[Pitch], mapped[Roll], - mapped[TX], mapped[TY], mapped[TZ]); - - if (mapping_widget) - mapping_widget->update(); - - double mapped_[6], raw_[6]; - - for (int i = 0; i < 6; i++) - { - mapped_[i] = (int) mapped[i]; - raw_[i] = (int) raw[i]; - } - - ui.raw_x->display(raw_[TX]); - ui.raw_y->display(raw_[TY]); - ui.raw_z->display(raw_[TZ]); - ui.raw_yaw->display(raw_[Yaw]); - ui.raw_pitch->display(raw_[Pitch]); - ui.raw_roll->display(raw_[Roll]); - - ui.pose_x->display(mapped_[TX]); - ui.pose_y->display(mapped_[TY]); - ui.pose_z->display(mapped_[TZ]); - ui.pose_yaw->display(mapped_[Yaw]); - ui.pose_pitch->display(mapped_[Pitch]); - ui.pose_roll->display(mapped_[Roll]); - - QString game_title; - if (libs.pProtocol) - game_title = libs.pProtocol->game_name(); - set_title(game_title); -} - -void MainWindow::set_title(const QString& game_title_) -{ - QString game_title; - if (game_title_ != "") - game_title = " :: " + game_title_; - QString current = group::ini_filename(); - setWindowTitle(opentrack_version + QStringLiteral(" :: ") + current + game_title); -} - -void MainWindow::showHeadPose() -{ - double mapped[6], raw[6]; - - work->tracker->get_raw_and_mapped_poses(mapped, raw); - - display_pose(mapped, raw); -} - -template -bool mk_dialog(mem lib, mem& orig) -{ - if (orig && orig->isVisible()) - { - orig->show(); - orig->raise(); - return false; - } - - if (lib && lib->Dialog) - { - auto dialog = mem(reinterpret_cast(lib->Dialog())); - dialog->setWindowFlags(Qt::Dialog); - dialog->setFixedSize(dialog->size()); - - orig = dialog; - dialog->show(); - dialog->raise(); - - QObject::connect(dialog.get(), &BaseDialog::closing, [&]() -> void { orig = nullptr; }); - - return true; - } - - return false; -} - -void MainWindow::showTrackerSettings() -{ - if (mk_dialog(current_tracker(), pTrackerDialog) && libs.pTracker) - pTrackerDialog->register_tracker(libs.pTracker.get()); -} - -void MainWindow::showProtocolSettings() { - if (mk_dialog(current_protocol(), pProtocolDialog) && libs.pProtocol) - pProtocolDialog->register_protocol(libs.pProtocol.get()); -} - -void MainWindow::showFilterSettings() { - if (mk_dialog(current_filter(), pFilterDialog) && libs.pFilter) - pFilterDialog->register_filter(libs.pFilter.get()); -} - -template -bool mk_window(mem* place, Args... params) -{ - if (*place && (*place)->isVisible()) - { - (*place)->show(); - (*place)->raise(); - return false; - } - else - { - *place = std::make_shared(params...); - (*place)->setWindowFlags(Qt::Dialog); - (*place)->show(); - (*place)->raise(); - return true; - } -} - -void MainWindow::show_options_dialog() { - if (mk_window(&options_widget)) - connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options())); -} - -void MainWindow::showCurveConfiguration() { - mk_window(&mapping_widget, pose, s); -} - -void MainWindow::exit() { - QCoreApplication::exit(0); -} - -void MainWindow::profileSelected(QString name) -{ - if (name == "" || is_refreshing_profiles) - return; - - const auto old_name = group::ini_filename(); - const auto new_name = name; - - if (old_name != new_name) - { - save(); - - { - QSettings settings(OPENTRACK_ORG); - settings.setValue (OPENTRACK_CONFIG_FILENAME_KEY, new_name); - } - - set_title(); - load_settings(); - } -} - -void MainWindow::shortcutRecentered() -{ - qDebug() << "Center"; - if (work) - work->tracker->center(); -} - -void MainWindow::shortcutToggled() -{ - qDebug() << "Toggle"; - if (work) - work->tracker->toggle_enabled(); -} - -void MainWindow::shortcutZeroed() -{ - qDebug() << "Zero"; - if (work) - work->tracker->zero(); -} - -void MainWindow::ensure_tray() -{ - if (tray) - tray->hide(); - tray = nullptr; - if (s.tray_enabled) - { - tray = std::make_shared(this); - tray->setIcon(QIcon(":/images/facetracknoir.png")); - tray->show(); - connect(tray.get(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - this, SLOT(restore_from_tray(QSystemTrayIcon::ActivationReason))); - } -} - -void MainWindow::restore_from_tray(QSystemTrayIcon::ActivationReason) -{ - show(); - setWindowState(Qt::WindowNoState); -} - -void MainWindow::changeEvent(QEvent* e) -{ - if (s.tray_enabled && e->type() == QEvent::WindowStateChange && (windowState() & Qt::WindowMinimized)) - { - if (!tray) - ensure_tray(); - hide(); - } - QMainWindow::changeEvent(e); -} - -void MainWindow::maybe_start_profile_from_executable() -{ - if (!work) - { - QString prof; - if (det.config_to_start(prof)) - { - ui.iconcomboProfile->setCurrentText(prof); - startTracker(); - } - } - else - { - if (det.should_stop()) - stopTracker(); - } -} - -void MainWindow::set_profile(const QString &profile) -{ - QSettings settings(OPENTRACK_ORG); - settings.setValue(OPENTRACK_CONFIG_FILENAME_KEY, profile); -} diff --git a/facetracknoir/ui.h b/facetracknoir/ui.h deleted file mode 100644 index 91e4ebbf..00000000 --- a/facetracknoir/ui.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (c) 2014-2015, Stanislaw Halik - - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "ui_main.h" - -#include "opentrack/options.hpp" -#include "opentrack/main-settings.hpp" -#include "opentrack/plugin-support.hpp" -#include "opentrack/tracker.h" -#include "opentrack/shortcuts.h" -#include "opentrack/work.hpp" -#include "opentrack/state.hpp" -#include "curve-config.h" -#include "options-dialog.hpp" -#include "process_detector.h" - -using namespace options; - -class MainWindow : public QMainWindow, private State -{ - Q_OBJECT - - Ui::OpentrackUI ui; - mem tray; - QTimer pose_update_timer; - QTimer det_timer; - QTimer config_list_timer; - mem options_widget; - mem mapping_widget; - QShortcut kbd_quit; - QPixmap no_feed_pixmap; - mem pFilterDialog; - mem pProtocolDialog; - mem pTrackerDialog; - process_detector_worker det; - QMenu profile_menu; - bool is_refreshing_profiles; - QTimer save_timer; - - mem current_tracker() - { - return modules.trackers().value(ui.iconcomboTrackerSource->currentIndex(), nullptr); - } - mem current_protocol() - { - return modules.protocols().value(ui.iconcomboProtocol->currentIndex(), nullptr); - } - mem current_filter() - { - return modules.filters().value(ui.iconcomboFilter->currentIndex(), nullptr); - } - - void changeEvent(QEvent* e) override; - - void load_settings(); - void updateButtonState(bool running, bool inertialp); - void display_pose(const double* mapped, const double* raw); - void ensure_tray(); - void set_title(const QString& game_title = QStringLiteral("")); - static bool get_new_config_name_from_dialog(QString &ret); - void set_profile(const QString& profile); - void maybe_save(); -private slots: - void _save(); - void save(); - void exit(); - void profileSelected(QString name); - - void showTrackerSettings(); - void showProtocolSettings(); - void showFilterSettings(); - void show_options_dialog(); - void showCurveConfiguration(); - void showHeadPose(); - - void restore_from_tray(QSystemTrayIcon::ActivationReason); - void maybe_start_profile_from_executable(); - - void make_empty_config(); - void make_copied_config(); - void open_config_directory(); - void refresh_config_list(); - - void startTracker(); - void stopTracker(); - void reload_options(); -public slots: - void shortcutRecentered(); - void shortcutToggled(); - void shortcutZeroed(); -public: - MainWindow(); - ~MainWindow(); - void save_mappings(); - void load_mappings(); - static void set_working_directory(); -}; diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt new file mode 100644 index 00000000..51d0cea3 --- /dev/null +++ b/gui/CMakeLists.txt @@ -0,0 +1,62 @@ +opentrack_boilerplate(opentrack NO-LIBRARY) + +if(UNIX OR APPLE) + target_include_directories(opentrack "${CMAKE_SOURCE_DIR}/qxt-mini") + if(APPLE) + set(qxt-plat mac) + else() + set(qxt-plat x11) + endif() + file(GLOB qxt-mini-c + ${CMAKE_SOURCE_DIR}/qxt-mini/*.h + ${CMAKE_SOURCE_DIR}/qxt-mini/qxtglobalshortcut.cpp + ${CMAKE_SOURCE_DIR}/qxt-mini/plat/qxtglobalshortcut_${qxt-plat}.cpp + ) + opentrack_qt(qxt-mini) + add_library(opentrack-qxt-mini STATIC ${qxt-mini-all}) + target_link_libraries(opentrack-qxt-mini ${MY_QT_LIBS}) + if(NOT APPLE) + target_link_libraries(opentrack-qxt-mini X11) + endif() +endif() + +if(WIN32) + SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console window visible at runtime") +endif() + +if(WIN32 AND NOT SDK_CONSOLE_DEBUG) + set(opentrack-win32-executable WIN32) +else() + set(opentrack-win32-executable "") +endif() + +if(UNIX OR APPLE) + list(APPEND opentrack-c ${CMAKE_SOURCE_DIR}/qxt-mini/qxtglobalshortcut.h) +endif() +opentrack_qt(opentrack) +add_executable(opentrack ${opentrack-win32-executable} ${opentrack-all}) +opentrack_compat(opentrack) +if(NOT WIN32) + set_target_properties(opentrack PROPERTIES SUFFIX ".bin") +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() +if(UNIX OR APPLE) + target_link_libraries(opentrack opentrack-qxt-mini) +endif() +link_with_dinput8(opentrack) +target_link_libraries(opentrack ${MY_QT_LIBS}) + +if(APPLE) + # for process detector + target_link_libraries(opentrack proc) +endif() + +if(LINUX) + # for process detector + target_link_libraries(opentrack procps) +endif() + +install(TARGETS opentrack DESTINATION .) diff --git a/gui/curve-config.cpp b/gui/curve-config.cpp new file mode 100644 index 00000000..2e9065b4 --- /dev/null +++ b/gui/curve-config.cpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik + + * 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 "curve-config.h" +#include "opentrack/main-settings.hpp" +MapWidget::MapWidget(Mappings& m, main_settings& s) : + m(m) +{ + ui.setupUi( this ); + + // rest of mapping settings taken care of by options::value + m.load_mappings(); + + { + struct { + QFunctionConfigurator* qfc; + Axis axis; + QCheckBox* checkbox; + bool altp; + } qfcs[] = + { + { ui.rxconfig, Yaw, nullptr, false }, + { ui.ryconfig, Pitch, nullptr, false }, + { ui.rzconfig, Roll, nullptr, false }, + { ui.txconfig, TX, nullptr, false }, + { ui.tyconfig, TY, nullptr, false }, + { ui.tzconfig, TZ, nullptr, false }, + + { ui.rxconfig_alt, Yaw, ui.rx_altp, true }, + { ui.ryconfig_alt, Pitch, ui.ry_altp, true }, + { ui.rzconfig_alt, Roll, ui.rz_altp, true }, + { ui.txconfig_alt, TX, ui.tx_altp, true }, + { ui.tyconfig_alt, TY, ui.ty_altp, true }, + { ui.tzconfig_alt, TZ, ui.tz_altp, true }, + { nullptr, Yaw, nullptr, false } + }; + + for (int i = 0; qfcs[i].qfc; i++) + { + const bool altp = qfcs[i].altp; + Mapping& axis = m(qfcs[i].axis); + Map* conf = altp ? &axis.curveAlt : &axis.curve; + const auto& name = qfcs[i].altp ? axis.name2 : axis.name1; + if (altp) + { + QFunctionConfigurator& qfc = *qfcs[i].qfc; + connect(qfcs[i].checkbox, &QCheckBox::toggled, + [&](bool f) -> void {qfc.setEnabled(f); qfc.force_redraw();}); + qfc.setEnabled(qfcs[i].checkbox->isChecked()); + qfc.force_redraw(); + } + qfcs[i].qfc->setConfig(conf, name); + } + } + + setFont(qApp->font()); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.a_x.altp, ui.tx_altp); + tie_setting(s.a_y.altp, ui.ty_altp); + tie_setting(s.a_z.altp, ui.tz_altp); + tie_setting(s.a_yaw.altp, ui.rx_altp); + tie_setting(s.a_pitch.altp, ui.ry_altp); + tie_setting(s.a_roll.altp, ui.rz_altp); +} + +void MapWidget::doOK() { + m.save_mappings(); + this->close(); +} + +void MapWidget::doCancel() { + m.invalidate_unsaved(); + this->close(); +} diff --git a/gui/curve-config.h b/gui/curve-config.h new file mode 100644 index 00000000..0cbc7055 --- /dev/null +++ b/gui/curve-config.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include "opentrack/mappings.hpp" +#include "ui_mapping.h" + +class MapWidget: public QWidget +{ + Q_OBJECT +public: + MapWidget(Mappings &m, main_settings &s); +private: + Ui::UICCurveConfigurationDialog ui; + Mappings& m; + void closeEvent(QCloseEvent *) override { doCancel(); } +private slots: + void doOK(); + void doCancel(); +}; diff --git a/gui/facetracknoir.ico b/gui/facetracknoir.ico new file mode 100644 index 00000000..5cac8da1 Binary files /dev/null and b/gui/facetracknoir.ico differ diff --git a/gui/facetracknoir.rc b/gui/facetracknoir.rc new file mode 100644 index 00000000..020ffe97 --- /dev/null +++ b/gui/facetracknoir.rc @@ -0,0 +1,2 @@ +#include +IDI_ICON1 ICON "facetracknoir.ico" diff --git a/gui/images/curves.png b/gui/images/curves.png new file mode 100644 index 00000000..3f953a0a Binary files /dev/null and b/gui/images/curves.png differ diff --git a/gui/images/facetracknoir.png b/gui/images/facetracknoir.png new file mode 100644 index 00000000..85c06df6 Binary files /dev/null and b/gui/images/facetracknoir.png differ diff --git a/gui/images/filter-16.png b/gui/images/filter-16.png new file mode 100644 index 00000000..ecde6a10 Binary files /dev/null and b/gui/images/filter-16.png differ diff --git a/gui/images/no-feed.png b/gui/images/no-feed.png new file mode 100644 index 00000000..02aa227a Binary files /dev/null and b/gui/images/no-feed.png differ diff --git a/gui/images/settings16.png b/gui/images/settings16.png new file mode 100644 index 00000000..3b31623b Binary files /dev/null and b/gui/images/settings16.png differ diff --git a/gui/images/tools.png b/gui/images/tools.png new file mode 100644 index 00000000..2da8f9f5 Binary files /dev/null and b/gui/images/tools.png differ diff --git a/gui/keyboard.h b/gui/keyboard.h new file mode 100644 index 00000000..62a9ce20 --- /dev/null +++ b/gui/keyboard.h @@ -0,0 +1,50 @@ +#pragma once +#include "ui_keyboard_listener.h" +#ifdef _WIN32 +#include "opentrack/win32-shortcuts.h" +#include "opentrack/shortcuts.h" +#endif +#include +#include +#include + +class KeyboardListener : public QLabel +{ + Q_OBJECT + Ui_keyboard_listener ui; +#ifdef _WIN32 + KeybindingWorker w; +#endif +public: + KeyboardListener(QWidget* parent = nullptr) : QLabel(parent) +#ifdef _WIN32 + , w([&](Key& k) + { + Qt::KeyboardModifiers m; + QKeySequence k_; + if (win_key::to_qt(k, k_, m)) + key_pressed(static_cast(k_).toInt() | m); + }, this->winId()) +#endif + { + ui.setupUi(this); + setFocusPolicy(Qt::StrongFocus); +#ifdef _WIN32 + w.start(); +#endif + } +#ifndef _WIN32 + void keyPressEvent(QKeyEvent* event) override + { + //qDebug() << "k" << (event->key() | event->modifiers()); + switch (event->key() | event->modifiers()) + { + default: + emit key_pressed(QKeySequence(event->key() | event->modifiers())); + break; + } + } +#endif +signals: + void key_pressed(QKeySequence k); +}; diff --git a/gui/keyboard_listener.ui b/gui/keyboard_listener.ui new file mode 100644 index 00000000..b6977df0 --- /dev/null +++ b/gui/keyboard_listener.ui @@ -0,0 +1,37 @@ + + + keyboard_listener + + + Qt::ApplicationModal + + + + 0 + 0 + 224 + 33 + + + + + 0 + 0 + + + + Bind a shortcut + + + <html><head/><body><p>Press a key or close this window to remove the keybinding.</p></body></html> + + + Qt::RichText + + + 10 + + + + + diff --git a/gui/main.cpp b/gui/main.cpp new file mode 100644 index 00000000..a63fe54a --- /dev/null +++ b/gui/main.cpp @@ -0,0 +1,71 @@ +#ifdef _WIN32 +# include +#endif + +#include "ui.h" +#include "opentrack/options.hpp" +using namespace options; +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +// workaround QTBUG-38598, allow for launching from another directory +static void add_program_library_path() +{ + char* p = _pgmptr; + char path[MAX_PATH+1]; + strcpy(path, p); + char* ptr = strrchr(path, '\\'); + if (ptr) + { + *ptr = '\0'; + QCoreApplication::addLibraryPath(path); + } +} +#endif + +int main(int argc, char** argv) +{ +#ifdef _WIN32 + add_program_library_path(); +#elif !defined(__linux) + // workaround QTBUG-38598 + QCoreApplication::addLibraryPath("."); +#endif + +#if defined(_WIN32) || defined(__APPLE__) + // qt5 designer-made controls look like shit on 'doze -sh 20140921 + // also our OSX look leaves a lot to be desired -sh 20150726 + { + const QStringList preferred { "fusion", "windowsvista", "macintosh", "windowsxp" }; + for (const auto& style_name : preferred) + { + QStyle* s = QStyleFactory::create(style_name); + if (s) + { + QApplication::setStyle(s); + break; + } + } + } +#endif + + QApplication::setAttribute(Qt::AA_X11InitThreads, true); + QApplication app(argc, argv); + + auto w = std::make_shared(); + + w->show(); + app.exec(); + + // on MSVC crashes in atexit +#ifdef _MSC_VER + TerminateProcess(GetCurrentProcess(), 0); +#endif + return 0; +} diff --git a/gui/main.ui b/gui/main.ui new file mode 100644 index 00000000..ab63e832 --- /dev/null +++ b/gui/main.ui @@ -0,0 +1,1255 @@ + + + Lovecraftian Octopus + OpentrackUI + + + + 0 + 0 + 707 + 494 + + + + + :/images/facetracknoir.png:/images/facetracknoir.png + + + #video_feed { border: 0; } + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 480 + 360 + + + + + 480 + 360 + + + + + + 0 + 0 + 480 + 360 + + + + + 0 + 0 + + + + + + 0 + 0 + 480 + 360 + + + + + 0 + 0 + + + + + 480 + 360 + + + + + 480 + 360 + + + + + + + + + + + + + QFrame::NoFrame + + + 0 + + + + 12 + + + 6 + + + 12 + + + 8 + + + 4 + + + + + + 0 + 0 + + + + + 80 + 90 + + + + + + + + + 0 + 0 + + + + Raw tracker data + + + + 0 + + + 0 + + + 0 + + + 0 + + + 3 + + + 2 + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + yaw + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + roll + + + + + + + true + + + + 0 + 0 + + + + false + + + QFrame::Raised + + + TZ + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + pitch + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + TX + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + true + + + 4 + + + QLCDNumber::Outline + + + + + + + true + + + + 0 + 0 + + + + false + + + QFrame::Raised + + + TY + + + + + + + + + + + 0 + 0 + + + + Game data + + + + 0 + + + 0 + + + 0 + + + 0 + + + 3 + + + 2 + + + + + true + + + + 0 + 0 + + + + false + + + QFrame::Raised + + + TY + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + pitch + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + yaw + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + roll + + + + + + + true + + + + 0 + 0 + + + + false + + + QFrame::Raised + + + TZ + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + TX + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + true + + + 4 + + + QLCDNumber::Flat + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 4 + + + 8 + + + 10 + + + 0 + + + 4 + + + 0 + + + + + + 4 + 0 + + + + Settings + + + true + + + + 3 + + + 4 + + + 2 + + + 0 + + + 6 + + + + + + 0 + 2 + + + + + 0 + + + 0 + + + 2 + + + 2 + + + + + true + + + + 0 + 0 + + + + Profile + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + Qt::DownArrow + + + + + + + + 0 + 0 + + + + 20 + + + + + + + + + + + 0 + 3 + + + + Mapping + + + + :/images/curves.png:/images/curves.png + + + + 80 + 24 + + + + + + + + + 0 + 3 + + + + Options + + + + :/images/tools.png:/images/tools.png + + + + 80 + 24 + + + + + + + + + + + + 3 + 0 + + + + Controls + + + true + + + + 8 + + + 0 + + + 8 + + + 0 + + + 9 + + + + + + 0 + 0 + + + + Start + + + + + + + false + + + + 0 + 0 + + + + Stop + + + + + + + + + + + 4 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 2 + + + 3 + + + 2 + + + 3 + + + 8 + + + + + Tracker + + + + 4 + + + 0 + + + 4 + + + 0 + + + 3 + + + 0 + + + + + + + + true + + + ... + + + false + + + + + + + + + + Protocol + + + + 4 + + + 0 + + + 4 + + + 0 + + + 3 + + + 0 + + + + + + + + true + + + ... + + + false + + + + + + + + + + Filter + + + + 4 + + + 0 + + + 4 + + + 0 + + + 3 + + + 0 + + + + + + + + true + + + ... + + + false + + + + + + + + + + + + + + + + + + + + + GLWidget + QWidget +
pose-widget/glwidget.h
+
+
+ + btnStartTracker + btnStopTracker + iconcomboTrackerSource + btnShowEngineControls + iconcomboProtocol + btnShowServerControls + iconcomboFilter + btnShowFilterControls + profile_button + iconcomboProfile + btnEditCurves + btnShortcuts + + + + + +
diff --git a/gui/mapping.ui b/gui/mapping.ui new file mode 100644 index 00000000..75c32e27 --- /dev/null +++ b/gui/mapping.ui @@ -0,0 +1,391 @@ + + + UICCurveConfigurationDialog + + + + 0 + 0 + 970 + 664 + + + + + 0 + 0 + + + + + 970 + 664 + + + + + 970 + 664 + + + + Mapping properties + + + + images/facetracknoir.pngimages/facetracknoir.png + + + Qt::LeftToRight + + + background-color: #ccc; + + + + + + + + + QTabWidget::North + + + 0 + + + + Yaw + + + + + + + 255 + 0 + 0 + + + + + 240 + 240 + 240 + + + + + + + + Asymmetric mapping below + + + + + + + + 255 + 0 + 0 + + + + + 255 + 255 + 255 + + + + + + + + + Pitch + + + + + + + 0 + 255 + 0 + + + + + 240 + 240 + 240 + + + + + + + + Asymmetric mapping below + + + + + + + + 0 + 255 + 0 + + + + + 240 + 240 + 240 + + + + + + + + + Roll + + + + + + + 0 + 0 + 255 + + + + + 240 + 240 + 240 + + + + + + + + Asymmetric mapping below + + + + + + + + 0 + 0 + 255 + + + + + 240 + 240 + 240 + + + + + + + + + X + + + + + + + 255 + 0 + 255 + + + + + 240 + 240 + 240 + + + + + + + + Asymmetric mapping below + + + + + + + + 255 + 0 + 255 + + + + + 240 + 240 + 240 + + + + + + + + + Y + + + + + + + 255 + 255 + 0 + + + + + 240 + 240 + 240 + + + + + + + + Asymmetric mapping below + + + + + + + + 255 + 255 + 0 + + + + + 240 + 240 + 240 + + + + + + + + + Z + + + + + + + 0 + 255 + 255 + + + + + 240 + 240 + 240 + + + + + + + + Asymmetric mapping below + + + + + + + + 0 + 255 + 255 + + + + + 240 + 240 + 240 + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + QFunctionConfigurator + QWidget +
spline-widget/qfunctionconfigurator.h
+
+
+ + ry_altp + rz_altp + tx_altp + ty_altp + tz_altp + tabWidget + buttonBox + rx_altp + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + +
diff --git a/gui/new_config.ui b/gui/new_config.ui new file mode 100644 index 00000000..27dce0f8 --- /dev/null +++ b/gui/new_config.ui @@ -0,0 +1,45 @@ + + + UI_new_config + + + Qt::ApplicationModal + + + + 0 + 0 + 269 + 67 + + + + Config filename + + + + images/facetracknoir.pngimages/facetracknoir.png + + + + + + New file name: + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + diff --git a/gui/new_file_dialog.h b/gui/new_file_dialog.h new file mode 100644 index 00000000..3a35cf71 --- /dev/null +++ b/gui/new_file_dialog.h @@ -0,0 +1,50 @@ +#pragma once + +#include "ui_new_config.h" +#include "opentrack/options.hpp" +#include +#include +#include +#include + +class new_file_dialog : public QDialog +{ + Q_OBJECT +public: + new_file_dialog(QWidget* parent = 0) : QDialog(parent), ok(false) + { + ui.setupUi(this); + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(ok_clicked())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(cancel_clicked())); + setFixedSize(size()); + } + bool is_ok(QString& name_) + { + name_ = name; + return ok; + } +private: + Ui::UI_new_config ui; + bool ok; + QString name; +private slots: + void cancel_clicked() { close(); } + void ok_clicked() + { + QString text = ui.lineEdit->text(); + text = text.replace('/', ""); + text = text.replace('\\', ""); + if (text != "" && !text.endsWith(".ini")) + text += ".ini"; + if (text == "" || text == ".ini" || QFile(options::group::ini_directory() + "/" + text).exists()) + { + QMessageBox::warning(this, + "File exists", "This file already exists. Pick another name.", + QMessageBox::Ok, QMessageBox::NoButton); + return; + } + ok = true; + close(); + name = text; + } +}; diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp new file mode 100644 index 00000000..fef2b0ca --- /dev/null +++ b/gui/options-dialog.cpp @@ -0,0 +1,96 @@ +/* Copyright (c) 2015, Stanislaw Halik + + * 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 "options-dialog.hpp" +#include "keyboard.h" +#include +#include + +OptionsDialog::OptionsDialog() +{ + ui.setupUi( this ); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); + + tie_setting(s.s_main.tray_enabled, ui.trayp); + + tie_setting(s.s_main.center_at_startup, ui.center_at_startup); + + tie_setting(s.s_main.tcomp_p, ui.tcomp_enable); + tie_setting(s.s_main.tcomp_tz, ui.tcomp_rz); + + tie_setting(s.s_main.a_x.zero, ui.pos_tx); + tie_setting(s.s_main.a_y.zero, ui.pos_ty); + tie_setting(s.s_main.a_z.zero, ui.pos_tz); + tie_setting(s.s_main.a_yaw.zero, ui.pos_rx); + tie_setting(s.s_main.a_pitch.zero, ui.pos_ry); + tie_setting(s.s_main.a_roll.zero, ui.pos_rz); + + tie_setting(s.s_main.a_yaw.invert, ui.invert_yaw); + tie_setting(s.s_main.a_pitch.invert, ui.invert_pitch); + tie_setting(s.s_main.a_roll.invert, ui.invert_roll); + tie_setting(s.s_main.a_x.invert, ui.invert_x); + tie_setting(s.s_main.a_y.invert, ui.invert_y); + tie_setting(s.s_main.a_z.invert, ui.invert_z); + + tie_setting(s.s_main.a_yaw.src, ui.src_yaw); + tie_setting(s.s_main.a_pitch.src, ui.src_pitch); + tie_setting(s.s_main.a_roll.src, ui.src_roll); + tie_setting(s.s_main.a_x.src, ui.src_x); + tie_setting(s.s_main.a_y.src, ui.src_y); + tie_setting(s.s_main.a_z.src, ui.src_z); + + tie_setting(s.s_main.camera_yaw, ui.camera_yaw); + tie_setting(s.s_main.camera_pitch, ui.camera_pitch); + tie_setting(s.s_main.camera_roll, ui.camera_roll); + + tie_setting(s.s_main.center_method, ui.center_method); + + connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center.keycode, ui.center_text); }); + connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero.keycode, ui.zero_text); }); + connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle.keycode, ui.toggle_text); }); + + ui.center_text->setText(s.center.keycode == "" ? "None" : static_cast(s.center.keycode)); + ui.toggle_text->setText(s.toggle.keycode == "" ? "None" : static_cast(s.toggle.keycode)); + ui.zero_text->setText(s.zero.keycode == "" ? "None" : static_cast(s.zero.keycode)); +} + +void OptionsDialog::bind_key(value& ret, QLabel* label) +{ + ret = ""; + QDialog d; + auto l = new QHBoxLayout; + l->setMargin(0); + auto k = new KeyboardListener; + l->addWidget(k); + d.setLayout(l); + d.setFixedSize(QSize(500, 300)); + d.setWindowFlags(Qt::Dialog); + connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { ret = s.toString(QKeySequence::PortableText); d.close(); }); + d.exec(); + label->setText(ret == "" ? "None" : static_cast(ret)); + delete k; + delete l; +} + +void OptionsDialog::doOK() { + s.b->save(); + s.s_main.b->save(); + ui.game_detector->save(); + this->close(); + emit reload(); +} + +void OptionsDialog::doCancel() { + s.b->reload(); + s.s_main.b->reload(); + ui.game_detector->revert(); + close(); +} + diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp new file mode 100644 index 00000000..3ef99d06 --- /dev/null +++ b/gui/options-dialog.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include "ui_settings.h" +#include "opentrack/shortcuts.h" + +class OptionsDialog: public QWidget +{ + Q_OBJECT +signals: + void reload(); +public: + OptionsDialog(); +private: + Ui::UI_Settings ui; + Shortcuts::settings s; + void closeEvent(QCloseEvent *) override { doCancel(); } +private slots: + void doOK(); + void doCancel(); + void bind_key(value& ret, QLabel* label); +}; diff --git a/gui/process_detector.cpp b/gui/process_detector.cpp new file mode 100644 index 00000000..f9fa4b59 --- /dev/null +++ b/gui/process_detector.cpp @@ -0,0 +1,211 @@ +/* Copyright (c) 2015, Stanislaw Halik + + * 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 "process_detector.h" +#include "ui.h" +#include "opentrack-compat/process-list.hpp" +#include +#include +#include +#include +#include +#include + +void settings::set_game_list(const QString &game_list) +{ + QSettings settings(OPENTRACK_ORG); + settings.setValue("executable-list", game_list); +} + +QString settings::get_game_list() +{ + QSettings settings(OPENTRACK_ORG); + return settings.value("executable-list").toString(); +} + +bool settings::is_enabled() +{ + QSettings settings(OPENTRACK_ORG); + return settings.value("executable-detector-enabled", false).toBool(); +} + +void settings::set_is_enabled(bool enabled) +{ + QSettings settings(OPENTRACK_ORG); + settings.setValue("executable-detector-enabled", enabled); +} + +QHash settings::split_process_names() +{ + QHash ret; + QString str = get_game_list(); + QStringList pairs = str.split('|'); + for (auto pair : pairs) + { + QList tmp = pair.split(':'); + if (tmp.count() != 2) + continue; + ret[tmp[0]] = tmp[1]; + } + return ret; +} + +void BrowseButton::browse() +{ + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::ExistingFile); + QString dir_path = QFileInfo(group::ini_pathname()).absolutePath(); + QString filename = dialog.getOpenFileName( + this, + tr("Set executable name"), + dir_path, + tr("Executable (*.exe);;All Files (*)")); + MainWindow::set_working_directory(); + filename = QFileInfo(filename).fileName(); + if (!filename.isNull()) + twi->setText(filename); +} + +int process_detector::add_row(QString exe_name, QString profile) +{ + int i = ui.tableWidget->rowCount(); + ui.tableWidget->insertRow(i); + + QComboBox* cb = new QComboBox(); + cb->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + cb->addItem(""); + cb->addItems(group::ini_list()); + ui.tableWidget->setCellWidget(i, 1, cb); + + QTableWidgetItem* twi = new QTableWidgetItem(exe_name); + ui.tableWidget->setItem(i, 0, twi); + + { + BrowseButton* b = new BrowseButton(twi); + b->setText("..."); + QObject::connect(b, SIGNAL(pressed()), b, SLOT(browse())); + ui.tableWidget->setCellWidget(i, 2, b); + } + + cb->setCurrentText(profile); + + return i; +} + +void process_detector::add_items() +{ + auto names = s.split_process_names(); + ui.tableWidget->clearContents(); + auto keys = names.keys(); + qSort(keys); + for (auto n : keys) + add_row(n, names[n]); +} + +process_detector::process_detector(QWidget* parent) : QWidget(parent) +{ + ui.setupUi(this); + setFixedSize(size()); + connect(ui.add, SIGNAL(pressed()), this, SLOT(add())); + connect(ui.remove, SIGNAL(pressed()), this, SLOT(remove())); + + add_items(); + + QResizeEvent e(ui.tableWidget->size(), ui.tableWidget->size()); + ui.tableWidget->resizeEvent(&e); + + settings s; + + ui.enabled->setChecked(s.is_enabled()); +} + +void process_detector::save() +{ + QString str; + + for (int i = 0; i < ui.tableWidget->rowCount(); i++) + { + auto exe = ui.tableWidget->item(i, 0)->text(); + auto profile = reinterpret_cast(ui.tableWidget->cellWidget(i, 1))->currentText(); + str += "|" + exe + ":" + profile; + } + + s.set_game_list(str); + s.set_is_enabled(ui.enabled->isChecked()); +} + +void process_detector::revert() +{ +} + +void process_detector::add() +{ + add_row(); +} + +void process_detector::remove() +{ + int r = ui.tableWidget->currentRow(); + if (r != -1) + ui.tableWidget->removeRow(r); +} + +bool process_detector_worker::should_stop() +{ + if (last_exe_name == "") + return false; + + settings s; + + if (!s.is_enabled()) + { + last_exe_name = ""; + return false; + } + + QStringList exe_list = get_all_executable_names(); + + if (exe_list.contains(last_exe_name)) + return false; + + last_exe_name = ""; + + return true; +} + +bool process_detector_worker::config_to_start(QString& str) +{ + settings s; + if (!s.is_enabled()) + { + last_exe_name = ""; + return false; + } + + auto filenames = s.split_process_names(); + QStringList exe_list = get_all_executable_names(); + + // assuming manual stop by user button click. + // don't automatically start again while the same process is running. + if (last_exe_name != "" && exe_list.contains(last_exe_name)) + return false; + // it's gone, we can start automatically again + last_exe_name = ""; + + for (auto& name : exe_list) + { + if (filenames.contains(name)) + { + last_exe_name = name; + str = filenames[name]; + return str != ""; + } + } + + return false; +} diff --git a/gui/process_detector.h b/gui/process_detector.h new file mode 100644 index 00000000..f6497c90 --- /dev/null +++ b/gui/process_detector.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2015, Stanislaw Halik + + * 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 +#include +#include +#include + +#include "opentrack/options.hpp" +using namespace options; + +class FancyTable : public QTableWidget +{ + Q_OBJECT +public: + void resizeEvent(QResizeEvent* e) override + { + QTableView::resizeEvent(e); + int w = width(); + setColumnWidth(2, 32); + w -= 48; + setColumnWidth(0, w / 2); + setColumnWidth(1, w / 2); + } +public: + FancyTable(QWidget* parent = nullptr) : QTableWidget(parent) {} +}; + +struct settings +{ + QHash split_process_names(); + QString get_game_list(); + void set_game_list(const QString& game_list); + bool is_enabled(); + void set_is_enabled(bool enabled); +}; + +#include "ui_process_widget.h" + +class process_detector : public QWidget +{ + Q_OBJECT + + Ui_Dialog ui; + settings s; + + int add_row(QString exe_name = "...", QString profile = ""); + void add_items(); +public: + process_detector(QWidget* parent = nullptr); +public slots: + void save(); + void revert(); +private slots: + void add(); + void remove(); +}; + +class BrowseButton : public QPushButton +{ + Q_OBJECT + QTableWidgetItem* twi; +public: + BrowseButton(QTableWidgetItem* twi) : twi(twi) + {} +public slots: + void browse(); +}; + +class process_detector_worker : QObject +{ + Q_OBJECT + settings s; + QString last_exe_name; +public: + bool config_to_start(QString& s); + bool should_stop(); +}; + diff --git a/gui/process_widget.ui b/gui/process_widget.ui new file mode 100644 index 00000000..63ad9472 --- /dev/null +++ b/gui/process_widget.ui @@ -0,0 +1,121 @@ + + + Dialog + + + + 0 + 0 + 302 + 325 + + + + Game detector + + + + + + + 0 + 0 + + + + + Executable + + + + + Profile + + + + + + + + + + + + + + 0 + 0 + + + + border: 0; + + + + + + + 5 + + + + + + 0 + 0 + + + + + 14 + 75 + true + + + + + + + + + + + + + 0 + 0 + + + + + 14 + 75 + true + + + + - + + + + + + + + + + Start profiles from game executable names in this list + + + + + + + + FancyTable + QTableWidget +
process_detector.h
+
+
+ + +
diff --git a/gui/settings.ui b/gui/settings.ui new file mode 100644 index 00000000..e277b5d8 --- /dev/null +++ b/gui/settings.ui @@ -0,0 +1,1109 @@ + + + UI_Settings + + + + 0 + 0 + 348 + 548 + + + + Options + + + + images/facetracknoir.pngimages/facetracknoir.png + + + Qt::LeftToRight + + + false + + + + + + 0 + + + + Shortcuts + + + + + + Global shortcuts + + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-weight:600;">Center</span> - use current pose as looking perfectly forward.<br/><span style=" font-weight:600;">Toggle</span> - keep looking at same spot until toggle keypress.<br/><span style=" font-weight:600;">Zero</span> - keep looking forward while the key is pressed.<br/></p></body></html> + + + true + + + + + + + QGroupBox { border: 0; } + + + + + + + + + + + + + Center + + + false + + + + + + + + + + + + + + + + + + + + + Toggle + + + false + + + + + + + Zero + + + false + + + + + + + Bind + + + + + + + Bind + + + + + + + Bind + + + + + + + + + + + + + Centering method + + + + + + Method + + + + + + + + Relative (inertial device) + + + + + Absolute (camera device) + + + + + + + + Try changing this if centering doesn't perform correctly for your input device. + + + true + + + + + + + + + + Center at startup + + + + + + + Minimize to tray + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Camera + + + + + + Camera offset + + + + + + <html><head/><body><p>Specify an angle for off-center camera as a basis for which direction is which, avoiding axis interconnect. Also see <a href="https://github.com/opentrack/opentrack/wiki/choosing-camera-offset"><span style=" text-decoration: underline; color:#0000ff;">description on wiki</span></a>.</p></body></html> + + + Qt::AlignJustify|Qt::AlignVCenter + + + true + + + 2 + + + true + + + + + + + QGroupBox +{ + border: 0; +} + + + + + + Roll + + + + + + + + 80 + 0 + + + + -180 + + + 180 + + + + + + + + 80 + 0 + + + + -180 + + + 180 + + + + + + + Pitch + + + + + + + + 80 + 0 + + + + -180 + + + 180 + + + + + + + Yaw + + + + + + + + + + + + + Center pose offset + + + + + + Alter the centered position sent to games by a fixed amount. + + + true + + + 2 + + + + + + + QGroupBox { + border: 0; +} + + + + + + Qt::AlignCenter + + + false + + + false + + + + + + deg. + + + 3 + + + -180.000000000000000 + + + 180.000000000000000 + + + + + + + cm + + + 3 + + + -100.000000000000000 + + + 100.000000000000000 + + + + + + + TX + + + + + + + cm + + + 3 + + + -100.000000000000000 + + + 100.000000000000000 + + + + + + + RY + + + + + + + TY + + + + + + + deg. + + + 3 + + + -180.000000000000000 + + + 180.000000000000000 + + + + + + + TZ + + + + + + + RZ + + + + + + + cm + + + 3 + + + -100.000000000000000 + + + 100.000000000000000 + + + + + + + RX + + + + + + + deg. + + + 3 + + + -180.000000000000000 + + + 180.000000000000000 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Output + + + + + + + 0 + 0 + + + + + + + Translation compensation + + + false + + + + + + With compensation on, translation is applied after rotation. For example, rotating +180 degrees yaw and moving backwards results in moving forward as a result of that rotation. + + + Qt::AlignJustify|Qt::AlignVCenter + + + true + + + 2 + + + + + + + + + + Enable + + + + + + + + + + Disable Z axis compensation + + + + + + + + + + + 65536 + 65536 + + + + + true + + + + Output remap + + + Qt::AlignCenter + + + false + + + false + + + + QLayout::SetMinAndMaxSize + + + 6 + + + + + Assign input axis to output axis. + + + Qt::AlignJustify|Qt::AlignVCenter + + + true + + + + + + + QGroupBox +{ + border: 0; +} + + + + + + + + + + + + + Roll + + + + + + + X + + + + + + + Invert + + + + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + Disabled + + + + + + + + Pitch + + + + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + Disabled + + + + + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + Disabled + + + + + + + + + + + + + + + Y + + + + + + + Destination + + + + + + + + + + + + + + Yaw + + + + + + + + + + + + + + Source + + + + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + Disabled + + + + + + + + + + + + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + Disabled + + + + + + + + Z + + + + + + + + X + + + + + Y + + + + + Z + + + + + Yaw + + + + + Pitch + + + + + Roll + + + + + Disabled + + + + + + + + + + + + + label_15 + label_13 + label_14 + src_yaw + invert_yaw + label_7 + src_pitch + label_8 + invert_pitch + label_9 + src_roll + invert_roll + label_10 + src_x + invert_x + label_11 + src_y + invert_y + label_12 + src_z + invert_z + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Game detection + + + + + + Game detection + + + + + + + + + + 0 + 0 + + + + Start tracking automatically when a game starts with selected profile, and stop when the game exits. + + + true + + + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + process_detector + QWidget +
process_detector.h
+
+
+ + tabWidget + center_at_startup + trayp + camera_yaw + camera_pitch + camera_roll + pos_rx + pos_ry + pos_rz + pos_tx + pos_ty + pos_tz + tcomp_enable + tcomp_rz + src_yaw + invert_yaw + src_pitch + invert_pitch + src_roll + invert_roll + src_x + invert_x + src_y + invert_y + src_z + invert_z + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + +
diff --git a/gui/ui-res.qrc b/gui/ui-res.qrc new file mode 100644 index 00000000..030a6153 --- /dev/null +++ b/gui/ui-res.qrc @@ -0,0 +1,10 @@ + + + images/tools.png + images/settings16.png + images/curves.png + images/facetracknoir.png + images/no-feed.png + images/filter-16.png + + diff --git a/gui/ui.cpp b/gui/ui.cpp new file mode 100644 index 00000000..5ea5dbfa --- /dev/null +++ b/gui/ui.cpp @@ -0,0 +1,567 @@ +/* Copyright (c) 2013-2015, Stanislaw Halik + + * 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 "ui.h" +#include "opentrack/tracker.h" +#include "opentrack/options.hpp" +#include "new_file_dialog.h" +#include +#include + +#ifndef _WIN32 +# include +#else +# include +#endif + +MainWindow::MainWindow() : + pose_update_timer(this), + kbd_quit(QKeySequence("Ctrl+Q"), this), + no_feed_pixmap(":/images/no-feed.png"), + is_refreshing_profiles(false) +{ + ui.setupUi(this); + + setFixedSize(size()); + + updateButtonState(false, false); + ui.video_frame_label->setPixmap(no_feed_pixmap); + + connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration())); + connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(show_options_dialog())); + connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings())); + connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showProtocolSettings())); + connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterSettings())); + + modules.filters().push_front(std::make_shared("", dylib::Filter)); + + for (auto x : modules.trackers()) + ui.iconcomboTrackerSource->addItem(x->icon, x->name); + + for (auto x : modules.protocols()) + ui.iconcomboProtocol->addItem(x->icon, x->name); + + for (auto x : modules.filters()) + ui.iconcomboFilter->addItem(x->icon, x->name); + + refresh_config_list(); + connect(&config_list_timer, SIGNAL(timeout()), this, SLOT(refresh_config_list())); + config_list_timer.start(1000 * 3); + + tie_setting(s.tracker_dll, ui.iconcomboTrackerSource); + tie_setting(s.protocol_dll, ui.iconcomboProtocol); + tie_setting(s.filter_dll, ui.iconcomboFilter); + + connect(ui.iconcomboTrackerSource, + &QComboBox::currentTextChanged, + [&](QString) -> void { if (pTrackerDialog) pTrackerDialog = nullptr; save(); }); + + connect(ui.iconcomboProtocol, + &QComboBox::currentTextChanged, + [&](QString) -> void { if (pProtocolDialog) pProtocolDialog = nullptr; save(); }); + + connect(ui.iconcomboFilter, + &QComboBox::currentTextChanged, + [&](QString) -> void { if (pFilterDialog) pFilterDialog = nullptr; save(); }); + + connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker())); + connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker())); + connect(ui.iconcomboProfile, SIGNAL(currentTextChanged(QString)), this, SLOT(profileSelected(QString))); + + connect(&pose_update_timer, SIGNAL(timeout()), this, SLOT(showHeadPose())); + connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit())); + + save_timer.setSingleShot(true); + connect(&save_timer, SIGNAL(timeout()), this, SLOT(_save())); + + profile_menu.addAction("Create new empty config", this, SLOT(make_empty_config())); + profile_menu.addAction("Create new copied config", this, SLOT(make_copied_config())); + profile_menu.addAction("Open configuration directory", this, SLOT(open_config_directory())); + ui.profile_button->setMenu(&profile_menu); + + kbd_quit.setEnabled(true); + + connect(&det_timer, SIGNAL(timeout()), this, SLOT(maybe_start_profile_from_executable())); + det_timer.start(1000); + + ensure_tray(); + set_working_directory(); + + if (!QFile(group::ini_pathname()).exists()) + { + set_profile(OPENTRACK_DEFAULT_CONFIG); + const auto pathname = group::ini_pathname(); + if (!QFile(pathname).exists()) + { + QFile file(pathname); + (void) file.open(QFile::ReadWrite); + } + } + + if (group::ini_directory() == "") + QMessageBox::warning(this, + "Configuration not saved.", + "Can't create configuration directory! Expect major malfunction.", + QMessageBox::Ok, QMessageBox::NoButton); + + ui.btnStartTracker->setFocus(); +} + +bool MainWindow::get_new_config_name_from_dialog(QString& ret) +{ + new_file_dialog dlg; + dlg.exec(); + return dlg.is_ok(ret); +} + +MainWindow::~MainWindow() +{ + maybe_save(); + + if (tray) + tray->hide(); + stopTracker(); +} + +void MainWindow::set_working_directory() +{ + QDir::setCurrent(QCoreApplication::applicationDirPath()); +} + +void MainWindow::save_mappings() { + pose.save_mappings(); +} + +void MainWindow::save() +{ + save_timer.stop(); + save_timer.start(5000); +} + +void MainWindow::maybe_save() +{ + if (save_timer.isActive()) + { + save_timer.stop(); + _save(); + } +} + +void MainWindow::_save() { + s.b->save(); + save_mappings(); + mem settings = group::ini_file(); + settings->sync(); + +#if defined(__unix) || defined(__linux) + QString currentFile = group::ini_pathname(); + QByteArray bytes = QFile::encodeName(currentFile); + const char* filename_as_asciiz = bytes.constData(); + + if (access(filename_as_asciiz, R_OK | W_OK)) + { + QMessageBox::warning(this, "Something went wrong", "Check permissions and ownership for your .ini file!", QMessageBox::Ok, QMessageBox::NoButton); + } +#endif +} + +void MainWindow::load_mappings() { + pose.load_mappings(); +} + +void MainWindow::load_settings() { + s.b->reload(); + load_mappings(); +} + +void MainWindow::make_empty_config() +{ + QString name; + const QString dir = group::ini_directory(); + if (dir != "" && get_new_config_name_from_dialog(name)) + { + QFile filename(dir + "/" + name); + (void) filename.open(QFile::ReadWrite); + refresh_config_list(); + ui.iconcomboProfile->setCurrentText(name); + } +} + +void MainWindow::make_copied_config() +{ + const QString dir = group::ini_directory(); + const QString cur = group::ini_pathname(); + QString name; + if (cur != "" && dir != "" && get_new_config_name_from_dialog(name)) + { + const QString new_name = dir + "/" + name; + (void) QFile::remove(new_name); + (void) QFile::copy(cur, new_name); + refresh_config_list(); + ui.iconcomboProfile->setCurrentText(name); + } +} + +void MainWindow::open_config_directory() +{ + const QString path = group::ini_directory(); + if (path != "") + { + QDesktopServices::openUrl("file:///" + QDir::toNativeSeparators(path)); + } +} + +extern "C" const char* opentrack_version; + +void MainWindow::refresh_config_list() +{ + if (work) + return; + + if (group::ini_list().size() == 0) + { + QFile filename(group::ini_directory() + "/" OPENTRACK_DEFAULT_CONFIG); + (void) filename.open(QFile::ReadWrite); + } + + QStringList ini_list = group::ini_list(); + set_title(); + QString current = group::ini_filename(); + is_refreshing_profiles = true; + ui.iconcomboProfile->clear(); + for (auto x : ini_list) + ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), x); + is_refreshing_profiles = false; + ui.iconcomboProfile->setCurrentText(current); +} + +void MainWindow::updateButtonState(bool running, bool inertialp) +{ + bool not_running = !running; + ui.iconcomboProfile->setEnabled ( not_running ); + ui.btnStartTracker->setEnabled ( not_running ); + ui.btnStopTracker->setEnabled ( running ); + ui.iconcomboProtocol->setEnabled ( not_running ); + ui.iconcomboFilter->setEnabled ( not_running ); + ui.iconcomboTrackerSource->setEnabled(not_running); + ui.video_frame_label->setVisible(not_running || inertialp); + ui.profile_button->setEnabled(not_running); +} + +void MainWindow::reload_options() +{ + if (work) + work->reload_shortcuts(); + ensure_tray(); +} + +void MainWindow::startTracker() { + // tracker dtor needs run first + work = nullptr; + + libs = SelectedLibraries(ui.video_frame, current_tracker(), current_protocol(), current_filter()); + + { + double p[6] = {0,0,0, 0,0,0}; + display_pose(p, p); + } + + if (!libs.correct) + { + QMessageBox::warning(this, "Library load error", + "One of libraries failed to load. Check installation.", + QMessageBox::Ok, + QMessageBox::NoButton); + libs = SelectedLibraries(); + return; + } + + work = std::make_shared(s, pose, libs, this, winId()); + + reload_options(); + + if (pTrackerDialog) + pTrackerDialog->register_tracker(libs.pTracker.get()); + + if (pFilterDialog) + pFilterDialog->register_filter(libs.pFilter.get()); + + if (pProtocolDialog) + pProtocolDialog->register_protocol(libs.pProtocol.get()); + + pose_update_timer.start(50); + + // NB check valid since SelectedLibraries ctor called + // trackers take care of layout state updates + const bool is_inertial = ui.video_frame->layout() == nullptr; + updateButtonState(true, is_inertial); + + maybe_save(); + + ui.btnStopTracker->setFocus(); +} + +void MainWindow::stopTracker( ) { + //ui.game_name->setText("Not connected"); + + pose_update_timer.stop(); + ui.pose_display->rotateBy(0, 0, 0, 0, 0, 0); + + if (pTrackerDialog) + pTrackerDialog->unregister_tracker(); + + if (pProtocolDialog) + pProtocolDialog->unregister_protocol(); + + if (pFilterDialog) + pFilterDialog->unregister_filter(); + + maybe_save(); + + work = nullptr; + libs = SelectedLibraries(); + + { + double p[6] = {0,0,0, 0,0,0}; + display_pose(p, p); + } + updateButtonState(false, false); + + set_title(); + + ui.btnStartTracker->setFocus(); +} + +void MainWindow::display_pose(const double *mapped, const double *raw) +{ + ui.pose_display->rotateBy(mapped[Yaw], mapped[Pitch], mapped[Roll], + mapped[TX], mapped[TY], mapped[TZ]); + + if (mapping_widget) + mapping_widget->update(); + + double mapped_[6], raw_[6]; + + for (int i = 0; i < 6; i++) + { + mapped_[i] = (int) mapped[i]; + raw_[i] = (int) raw[i]; + } + + ui.raw_x->display(raw_[TX]); + ui.raw_y->display(raw_[TY]); + ui.raw_z->display(raw_[TZ]); + ui.raw_yaw->display(raw_[Yaw]); + ui.raw_pitch->display(raw_[Pitch]); + ui.raw_roll->display(raw_[Roll]); + + ui.pose_x->display(mapped_[TX]); + ui.pose_y->display(mapped_[TY]); + ui.pose_z->display(mapped_[TZ]); + ui.pose_yaw->display(mapped_[Yaw]); + ui.pose_pitch->display(mapped_[Pitch]); + ui.pose_roll->display(mapped_[Roll]); + + QString game_title; + if (libs.pProtocol) + game_title = libs.pProtocol->game_name(); + set_title(game_title); +} + +void MainWindow::set_title(const QString& game_title_) +{ + QString game_title; + if (game_title_ != "") + game_title = " :: " + game_title_; + QString current = group::ini_filename(); + setWindowTitle(opentrack_version + QStringLiteral(" :: ") + current + game_title); +} + +void MainWindow::showHeadPose() +{ + double mapped[6], raw[6]; + + work->tracker->get_raw_and_mapped_poses(mapped, raw); + + display_pose(mapped, raw); +} + +template +bool mk_dialog(mem lib, mem& orig) +{ + if (orig && orig->isVisible()) + { + orig->show(); + orig->raise(); + return false; + } + + if (lib && lib->Dialog) + { + auto dialog = mem(reinterpret_cast(lib->Dialog())); + dialog->setWindowFlags(Qt::Dialog); + dialog->setFixedSize(dialog->size()); + + orig = dialog; + dialog->show(); + dialog->raise(); + + QObject::connect(dialog.get(), &BaseDialog::closing, [&]() -> void { orig = nullptr; }); + + return true; + } + + return false; +} + +void MainWindow::showTrackerSettings() +{ + if (mk_dialog(current_tracker(), pTrackerDialog) && libs.pTracker) + pTrackerDialog->register_tracker(libs.pTracker.get()); +} + +void MainWindow::showProtocolSettings() { + if (mk_dialog(current_protocol(), pProtocolDialog) && libs.pProtocol) + pProtocolDialog->register_protocol(libs.pProtocol.get()); +} + +void MainWindow::showFilterSettings() { + if (mk_dialog(current_filter(), pFilterDialog) && libs.pFilter) + pFilterDialog->register_filter(libs.pFilter.get()); +} + +template +bool mk_window(mem* place, Args... params) +{ + if (*place && (*place)->isVisible()) + { + (*place)->show(); + (*place)->raise(); + return false; + } + else + { + *place = std::make_shared(params...); + (*place)->setWindowFlags(Qt::Dialog); + (*place)->show(); + (*place)->raise(); + return true; + } +} + +void MainWindow::show_options_dialog() { + if (mk_window(&options_widget)) + connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options())); +} + +void MainWindow::showCurveConfiguration() { + mk_window(&mapping_widget, pose, s); +} + +void MainWindow::exit() { + QCoreApplication::exit(0); +} + +void MainWindow::profileSelected(QString name) +{ + if (name == "" || is_refreshing_profiles) + return; + + const auto old_name = group::ini_filename(); + const auto new_name = name; + + if (old_name != new_name) + { + save(); + + { + QSettings settings(OPENTRACK_ORG); + settings.setValue (OPENTRACK_CONFIG_FILENAME_KEY, new_name); + } + + set_title(); + load_settings(); + } +} + +void MainWindow::shortcutRecentered() +{ + qDebug() << "Center"; + if (work) + work->tracker->center(); +} + +void MainWindow::shortcutToggled() +{ + qDebug() << "Toggle"; + if (work) + work->tracker->toggle_enabled(); +} + +void MainWindow::shortcutZeroed() +{ + qDebug() << "Zero"; + if (work) + work->tracker->zero(); +} + +void MainWindow::ensure_tray() +{ + if (tray) + tray->hide(); + tray = nullptr; + if (s.tray_enabled) + { + tray = std::make_shared(this); + tray->setIcon(QIcon(":/images/facetracknoir.png")); + tray->show(); + connect(tray.get(), SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(restore_from_tray(QSystemTrayIcon::ActivationReason))); + } +} + +void MainWindow::restore_from_tray(QSystemTrayIcon::ActivationReason) +{ + show(); + setWindowState(Qt::WindowNoState); +} + +void MainWindow::changeEvent(QEvent* e) +{ + if (s.tray_enabled && e->type() == QEvent::WindowStateChange && (windowState() & Qt::WindowMinimized)) + { + if (!tray) + ensure_tray(); + hide(); + } + QMainWindow::changeEvent(e); +} + +void MainWindow::maybe_start_profile_from_executable() +{ + if (!work) + { + QString prof; + if (det.config_to_start(prof)) + { + ui.iconcomboProfile->setCurrentText(prof); + startTracker(); + } + } + else + { + if (det.should_stop()) + stopTracker(); + } +} + +void MainWindow::set_profile(const QString &profile) +{ + QSettings settings(OPENTRACK_ORG); + settings.setValue(OPENTRACK_CONFIG_FILENAME_KEY, profile); +} diff --git a/gui/ui.h b/gui/ui.h new file mode 100644 index 00000000..91e4ebbf --- /dev/null +++ b/gui/ui.h @@ -0,0 +1,113 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik + + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "ui_main.h" + +#include "opentrack/options.hpp" +#include "opentrack/main-settings.hpp" +#include "opentrack/plugin-support.hpp" +#include "opentrack/tracker.h" +#include "opentrack/shortcuts.h" +#include "opentrack/work.hpp" +#include "opentrack/state.hpp" +#include "curve-config.h" +#include "options-dialog.hpp" +#include "process_detector.h" + +using namespace options; + +class MainWindow : public QMainWindow, private State +{ + Q_OBJECT + + Ui::OpentrackUI ui; + mem tray; + QTimer pose_update_timer; + QTimer det_timer; + QTimer config_list_timer; + mem options_widget; + mem mapping_widget; + QShortcut kbd_quit; + QPixmap no_feed_pixmap; + mem pFilterDialog; + mem pProtocolDialog; + mem pTrackerDialog; + process_detector_worker det; + QMenu profile_menu; + bool is_refreshing_profiles; + QTimer save_timer; + + mem current_tracker() + { + return modules.trackers().value(ui.iconcomboTrackerSource->currentIndex(), nullptr); + } + mem current_protocol() + { + return modules.protocols().value(ui.iconcomboProtocol->currentIndex(), nullptr); + } + mem current_filter() + { + return modules.filters().value(ui.iconcomboFilter->currentIndex(), nullptr); + } + + void changeEvent(QEvent* e) override; + + void load_settings(); + void updateButtonState(bool running, bool inertialp); + void display_pose(const double* mapped, const double* raw); + void ensure_tray(); + void set_title(const QString& game_title = QStringLiteral("")); + static bool get_new_config_name_from_dialog(QString &ret); + void set_profile(const QString& profile); + void maybe_save(); +private slots: + void _save(); + void save(); + void exit(); + void profileSelected(QString name); + + void showTrackerSettings(); + void showProtocolSettings(); + void showFilterSettings(); + void show_options_dialog(); + void showCurveConfiguration(); + void showHeadPose(); + + void restore_from_tray(QSystemTrayIcon::ActivationReason); + void maybe_start_profile_from_executable(); + + void make_empty_config(); + void make_copied_config(); + void open_config_directory(); + void refresh_config_list(); + + void startTracker(); + void stopTracker(); + void reload_options(); +public slots: + void shortcutRecentered(); + void shortcutToggled(); + void shortcutZeroed(); +public: + MainWindow(); + ~MainWindow(); + void save_mappings(); + void load_mappings(); + static void set_working_directory(); +}; -- cgit v1.2.3 From 9b736d361bcde7a2ddaf3fe54b471c0e658e94f4 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 30 Oct 2015 08:43:22 +0100 Subject: cmake: cleanup hydra --- tracker-hydra/CMakeLists.txt | 48 ++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/tracker-hydra/CMakeLists.txt b/tracker-hydra/CMakeLists.txt index 6a4a7cfe..2c90e285 100644 --- a/tracker-hydra/CMakeLists.txt +++ b/tracker-hydra/CMakeLists.txt @@ -11,34 +11,24 @@ if(SDK_HYDRA) set(dir bin) set(ext dll) endif() - target_link_libraries(opentrack-tracker-hydra - "${SDK_HYDRA}/${dir}/win32/release_dll/sixense.${ext}" - #"${SDK_HYDRA}/${dir}/win32/release_dll/sixense_utils.${ext}" - ) - install(FILES "${SDK_HYDRA}/bin/win32/release_dll/sixense.dll" - #"${SDK_HYDRA}/bin/win32/release_dll/sixense_utils.dll" - DESTINATION . ${opentrack-perms}) - else() - if(SDK_HYDRA_AMD64) - set(six4 _x64) - else() - set(six4) - endif() - if(APPLE) - set(under-dll _dll) - set(soext dylib) - set(plat osx) - else() - set(under-dll) - set(soext so) - set(plat linux) - endif() - install(FILES - "${SDK_HYDRA}/lib/${plat}${six4}/release${under-dll}/libsixense${six4}.${soext}" - DESTINATION . - ) - target_link_libraries(opentrack-tracker-hydra - "${SDK_HYDRA}/lib/${plat}${six4}/release${under-dll}/libsixense${six4}.${soext}" - ) + target_link_libraries(opentrack-tracker-hydra "${SDK_HYDRA}/${dir}/win32/release_dll/sixense.${ext}") + install(FILES "${SDK_HYDRA}/bin/win32/release_dll/sixense.dll" DESTINATION . ${opentrack-perms}) + else() + if(SDK_HYDRA_AMD64) + set(six4 _x64) + else() + set(six4) + endif() + if(APPLE) + set(under-dll _dll) + set(soext dylib) + set(plat osx) + else() + set(under-dll) + set(soext so) + set(plat linux) + endif() + install(FILES "${SDK_HYDRA}/lib/${plat}${six4}/release${under-dll}/libsixense${six4}.${soext}" DESTINATION .) + target_link_libraries(opentrack-tracker-hydra "${SDK_HYDRA}/lib/${plat}${six4}/release${under-dll}/libsixense${six4}.${soext}") endif() endif() -- cgit v1.2.3