summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitmodules0
-rw-r--r--CMakeLists.txt87
-rw-r--r--README.md57
-rwxr-xr-xbin/freetrackclient.dllbin0 -> 41472 bytes
-rw-r--r--clientfiles/FlightGear/Protocol/headtracker.xml (renamed from facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml)0
-rw-r--r--clientfiles/FlightGear/readme.txt (renamed from facetracknoir/clientfiles/FlightGear/readme.txt)0
-rw-r--r--clientfiles/Tir4Fun/npclient.dll (renamed from facetracknoir/clientfiles/Tir4Fun/npclient.dll)bin53248 -> 53248 bytes
-rw-r--r--clientfiles/Tir4Fun/readme.txt (renamed from facetracknoir/clientfiles/Tir4Fun/readme.txt)0
-rw-r--r--clientfiles/Tir4Fun/tir4fun.exe (renamed from facetracknoir/clientfiles/Tir4Fun/tir4fun.exe)bin36864 -> 36864 bytes
-rw-r--r--clientfiles/aruco/aruco_create_marker.exe (renamed from facetracknoir/clientfiles/aruco/aruco_create_marker.exe)bin826368 -> 826368 bytes
-rw-r--r--clientfiles/aruco/test3.jpg (renamed from facetracknoir/clientfiles/aruco/test3.jpg)bin2145 -> 2145 bytes
-rw-r--r--clientfiles/cfs3/readme.txt (renamed from facetracknoir/clientfiles/cfs3/readme.txt)0
-rw-r--r--clientfiles/cfs3/tirviews.dll (renamed from facetracknoir/clientfiles/cfs3/tirviews.dll)bin109568 -> 109568 bytes
-rw-r--r--clientfiles/cute-octopus-vector-material_15-1831.jpg (renamed from facetracknoir/clientfiles/cute-octopus-vector-material_15-1831.jpg)bin71514 -> 71514 bytes
-rw-r--r--clientfiles/freepie-udp/com.freepie.android.imu.apkbin0 -> 167822 bytes
-rw-r--r--clientfiles/freetracktest/freetracktest.exe (renamed from facetracknoir/clientfiles/freetracktest/freetracktest.exe)bin398848 -> 398848 bytes
-rw-r--r--clientfiles/freetracktest/readme.txt (renamed from facetracknoir/clientfiles/freetracktest/readme.txt)0
-rw-r--r--clientfiles/fs2002 and fs2004/fsuipc.dll (renamed from facetracknoir/clientfiles/fs2002 and fs2004/fsuipc.dll)bin210880 -> 210880 bytes
-rw-r--r--clientfiles/glovepie/facetracknoir2trackir.pie (renamed from facetracknoir/clientfiles/glovepie/facetracknoir2trackir.pie)0
-rw-r--r--clientfiles/glovepie/readme.txt (renamed from facetracknoir/clientfiles/glovepie/readme.txt)0
-rwxr-xr-xclientfiles/make-csv.pl (renamed from facetracknoir/clientfiles/make-csv.pl)0
-rw-r--r--clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg (renamed from facetracknoir/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg)bin155205 -> 155205 bytes
-rw-r--r--clientfiles/ppjoy/readme.txt (renamed from facetracknoir/clientfiles/ppjoy/readme.txt)0
-rw-r--r--clientfiles/very-important-source-code/README-CREDIT.txt (renamed from facetracknoir/clientfiles/very-important-source-code/README-CREDIT.txt)0
-rw-r--r--clientfiles/very-important-source-code/ft_tester/Makefile.am (renamed from facetracknoir/clientfiles/very-important-source-code/ft_tester/Makefile.am)0
-rw-r--r--clientfiles/very-important-source-code/ft_tester/Makefile.in (renamed from facetracknoir/clientfiles/very-important-source-code/ft_tester/Makefile.in)0
-rw-r--r--clientfiles/very-important-source-code/ft_tester/fttester.rc.in (renamed from facetracknoir/clientfiles/very-important-source-code/ft_tester/fttester.rc.in)0
-rw-r--r--clientfiles/very-important-source-code/ft_tester/main.cpp (renamed from facetracknoir/clientfiles/very-important-source-code/ft_tester/main.cpp)0
-rw-r--r--clientfiles/very-important-source-code/ft_tester/resource.h (renamed from facetracknoir/clientfiles/very-important-source-code/ft_tester/resource.h)0
-rw-r--r--clientfiles/very-important-source-code/important-stuff/NPClient.h (renamed from facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient.h)0
-rw-r--r--clientfiles/very-important-source-code/important-stuff/NPClient.spec (renamed from facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient.spec)0
-rw-r--r--clientfiles/very-important-source-code/important-stuff/NPClient_dll.h (renamed from facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient_dll.h)0
-rw-r--r--clientfiles/very-important-source-code/important-stuff/NPClient_main.c (renamed from facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient_main.c)0
-rw-r--r--clientfiles/very-important-source-code/important-stuff/game_data.c (renamed from facetracknoir/clientfiles/very-important-source-code/important-stuff/game_data.c)0
-rw-r--r--clientfiles/very-important-source-code/important-stuff/game_data.h (renamed from facetracknoir/clientfiles/very-important-source-code/important-stuff/game_data.h)0
-rw-r--r--clientfiles/very-important-source-code/tester/Makefile.am (renamed from facetracknoir/clientfiles/very-important-source-code/tester/Makefile.am)0
-rw-r--r--clientfiles/very-important-source-code/tester/Makefile.in (renamed from facetracknoir/clientfiles/very-important-source-code/tester/Makefile.in)0
-rw-r--r--clientfiles/very-important-source-code/tester/main.cpp (renamed from facetracknoir/clientfiles/very-important-source-code/tester/main.cpp)0
-rw-r--r--clientfiles/very-important-source-code/tester/npifc.c (renamed from facetracknoir/clientfiles/very-important-source-code/tester/npifc.c)0
-rw-r--r--clientfiles/very-important-source-code/tester/npifc.h (renamed from facetracknoir/clientfiles/very-important-source-code/tester/npifc.h)0
-rw-r--r--clientfiles/very-important-source-code/tester/npview.rc.in (renamed from facetracknoir/clientfiles/very-important-source-code/tester/npview.rc.in)0
-rw-r--r--clientfiles/very-important-source-code/tester/resource.h (renamed from facetracknoir/clientfiles/very-important-source-code/tester/resource.h)0
-rw-r--r--clientfiles/vjoy/VJoy.dll (renamed from facetracknoir/clientfiles/vjoy/VJoy.dll)bin94208 -> 94208 bytes
-rw-r--r--cmake/mingw-w64.cmake8
-rw-r--r--csv/csv.cpp (renamed from ftnoir_csv/csv.cpp)0
-rw-r--r--csv/csv.h (renamed from ftnoir_csv/csv.h)0
-rw-r--r--facetracknoir/curve-config.cpp4
-rw-r--r--facetracknoir/curve-config.h2
-rw-r--r--facetracknoir/facetracknoir.ui1079
-rw-r--r--facetracknoir/ftnoir_curves.ui1069
-rw-r--r--facetracknoir/global-shortcuts.cpp139
-rw-r--r--facetracknoir/images/curves.png (renamed from facetracknoir/uielements/curves.png)bin3457 -> 3457 bytes
-rw-r--r--facetracknoir/images/filter-16.png (renamed from ftnoir_filter_ewma2/images/filter-16.png)bin642 -> 642 bytes
-rw-r--r--facetracknoir/images/no-feed.pngbin0 -> 4471 bytes
-rw-r--r--facetracknoir/images/tools.png (renamed from facetracknoir/uielements/tools.png)bin3053 -> 3053 bytes
-rw-r--r--facetracknoir/keyboard.ui307
-rw-r--r--facetracknoir/main-facetracknoir.qrc9
-rw-r--r--facetracknoir/main.cpp20
-rw-r--r--facetracknoir/main.ui1196
-rw-r--r--facetracknoir/mapping.ui1142
-rw-r--r--facetracknoir/shortcut-dialog.cpp47
-rw-r--r--facetracknoir/shortcut-dialog.hpp21
-rw-r--r--facetracknoir/ui-res.qrc10
-rw-r--r--facetracknoir/ui.cpp (renamed from facetracknoir/facetracknoir.cpp)378
-rw-r--r--facetracknoir/ui.h (renamed from facetracknoir/facetracknoir.h)90
-rw-r--r--facetracknoir/uielements/no-feed.pngbin128664 -> 0 bytes
-rw-r--r--freetrackclient/build-msvc.sh33
-rw-r--r--freetrackclient/freetrackclient.c39
-rw-r--r--freetrackclient/fttypes.h (renamed from ftnoir_protocol_ft/fttypes.h)1
-rw-r--r--ftnoir_filter_accela/accela-filter.qrc5
-rw-r--r--ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui552
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela.cpp84
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela.h60
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp39
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp7
-rw-r--r--ftnoir_filter_accela/images/filter-16-ac.pngbin725 -> 0 bytes
-rw-r--r--ftnoir_filter_ewma2/ewma-filter.qrc5
-rw-r--r--ftnoir_filter_ewma2/images/filter-32.pngbin1904 -> 0 bytes
-rwxr-xr-xftnoir_filter_kalman/ftnoir_filter_kalman.h11
-rw-r--r--ftnoir_filter_kalman/images/filter-16-ac.pngbin725 -> 0 bytes
-rw-r--r--ftnoir_filter_kalman/kalman-filter.qrc5
-rw-r--r--ftnoir_filter_kalman/kalman.cpp35
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg.cpp5
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg.h10
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp4
-rw-r--r--ftnoir_protocol_ft/ftnoir_protocol_ft.cpp80
-rw-r--r--ftnoir_protocol_ft/ftnoir_protocol_ft.h12
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp43
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse.h13
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp4
-rw-r--r--ftnoir_protocol_wine/ftnoir_protocol_wine.cpp2
-rw-r--r--ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx6
-rw-r--r--ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx12
-rw-r--r--ftnoir_tracker_aruco/aruco-trackercontrols.ui9
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp96
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco.h1
-rw-r--r--ftnoir_tracker_freepie-udp/freepie-udp-controls.ui260
-rw-r--r--ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp45
-rw-r--r--ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h11
-rw-r--r--ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp7
-rw-r--r--ftnoir_tracker_hatire/ftnoir_arduino_type.h32
-rw-r--r--ftnoir_tracker_hatire/ftnoir_hat.qrc7
-rw-r--r--ftnoir_tracker_hatire/ftnoir_hatcontrols.ui1243
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp549
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat.h154
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.cpp426
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h114
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp102
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp170
-rw-r--r--ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.h70
-rw-r--r--ftnoir_tracker_hatire/images/hat.icobin0 -> 1150 bytes
-rw-r--r--ftnoir_tracker_hatire/images/hat.pngbin0 -> 249 bytes
-rw-r--r--ftnoir_tracker_hatire/images/hat_logo.pngbin0 -> 15210 bytes
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.cpp5
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp89
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick.h19
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui441
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp11
-rw-r--r--ftnoir_tracker_libevdev/ftnoir_libevdev.ui56
-rw-r--r--ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.cpp109
-rw-r--r--ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.h59
-rw-r--r--ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dialog.cpp35
-rw-r--r--ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dll.cpp7
-rw-r--r--ftnoir_tracker_pt/FTNoIR_PT_Controls.ui629
-rw-r--r--ftnoir_tracker_pt/camera.cpp174
-rw-r--r--ftnoir_tracker_pt/camera.h14
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt.cpp165
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt.h28
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp97
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h9
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h17
-rw-r--r--ftnoir_tracker_pt/point_extractor.cpp25
-rw-r--r--ftnoir_tracker_pt/point_extractor.h11
-rw-r--r--ftnoir_tracker_pt/point_tracker.cpp160
-rw-r--r--ftnoir_tracker_pt/point_tracker.h100
-rw-r--r--ftnoir_tracker_pt/trans_calib.cpp2
-rw-r--r--ftnoir_tracker_rift/ftnoir_tracker_rift.cpp4
-rw-r--r--ftnoir_tracker_udp/ftnoir_tracker_udp.cpp2
-rw-r--r--make-tar.sh3
-rw-r--r--opentrack/ftnoir_keyboardshortcuts.ui210
-rw-r--r--opentrack/global-shortcuts.cpp68
-rw-r--r--opentrack/main-settings.hpp15
-rw-r--r--opentrack/mappings.hpp49
-rw-r--r--opentrack/mingw-version-script.txt (renamed from facetracknoir/mingw-version-script.txt)0
-rw-r--r--opentrack/options.hpp123
-rw-r--r--opentrack/plugin-support.cpp71
-rw-r--r--opentrack/plugin-support.h17
-rw-r--r--opentrack/pose.hpp24
-rw-r--r--opentrack/posix-version-script.txt (renamed from facetracknoir/posix-version-script.txt)0
-rw-r--r--opentrack/quat.hpp66
-rw-r--r--opentrack/shortcuts.cpp117
-rw-r--r--opentrack/shortcuts.h97
-rw-r--r--opentrack/simple-mat.hpp155
-rw-r--r--opentrack/state.hpp23
-rw-r--r--opentrack/timer.hpp11
-rw-r--r--opentrack/tracker.cpp216
-rw-r--r--opentrack/tracker.h41
-rw-r--r--opentrack/work.hpp18
-rw-r--r--pose-widget/glwidget.cpp (renamed from ftnoir_posewidget/glwidget.cpp)42
-rw-r--r--pose-widget/glwidget.h (renamed from ftnoir_posewidget/glwidget.h)4
-rw-r--r--pose-widget/images/side1.png (renamed from ftnoir_posewidget/images/side1.png)bin26449 -> 26449 bytes
-rw-r--r--pose-widget/images/side6.png (renamed from ftnoir_posewidget/images/side6.png)bin26493 -> 26493 bytes
-rw-r--r--pose-widget/posewidget.qrc (renamed from ftnoir_posewidget/posewidget.qrc)0
-rw-r--r--qfunctionconfigurator/functionconfig.cpp10
-rw-r--r--qfunctionconfigurator/qfunctionconfigurator.cpp63
-rw-r--r--qfunctionconfigurator/qfunctionconfigurator.h2
166 files changed, 8526 insertions, 5215 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.gitmodules
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01c5eba5..c7e3cedc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,7 +12,6 @@ if(GIT_FOUND)
git_describe(OPENTRACK__COMMIT --tags --always)
endif()
-#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
SET(CMAKE_SKIP_INSTALL_RPATH FALSE)
@@ -22,10 +21,11 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-find_package(OpenCV REQUIRED)
+find_package(OpenCV)
include_directories(${OpenCV_INCLUDE_DIRS})
-find_package(Qt5 REQUIRED COMPONENTS Core Xml Network Widgets Gui ${maybe-serial-port} QUIET)
+find_package(Qt5 REQUIRED COMPONENTS Core Xml Network Widgets Gui QUIET)
+find_package(Qt5 COMPONENTS SerialPort QUIET)
include_directories(${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})
@@ -35,8 +35,6 @@ if(WIN32) # hack to avoid breakage on buildbot
endif()
set(MY_QT_LIBS ${Qt5Widgets_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Xml_LIBRARIES} ${Qt5Core_LIBRARIES} ${my-qt-deps})
-#include_directories(${CMAKE_SOURCE_DIR})
-
# note, hatire supports both ftnoir and opentrack
# don't remove without being sure as hell -sh 20140922
add_definitions(-DOPENTRACK_API)
@@ -94,7 +92,7 @@ macro(opentrack_library n dir)
target_link_libraries(${n} ${MY_QT_LIBS})
if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE)
SET_TARGET_PROPERTIES(${n} PROPERTIES
- LINK_FLAGS "${foolib_LINK} -Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/${version-script}-version-script.txt"
+ LINK_FLAGS "${foolib_LINK} -Wl,--version-script=\"${CMAKE_SOURCE_DIR}/opentrack/${version-script}-version-script.txt\""
COMPILE_FLAGS "${foolib_COMPILE} -fvisibility=hidden -fvisibility-inlines-hidden"
)
else()
@@ -109,37 +107,36 @@ function(link_with_dinput8 n)
endif()
endfunction()
+# ----
+
# cache variables
# ----
-if(UNIX)
- set(SDK_ENABLE_LIBEVDEV FALSE CACHE BOOL "libevdev virtual joystick protocol support (probably Linux only)")
-endif()
-
IF(WIN32)
SET(SDK_VJOY "" CACHE PATH "VJoy SDK path")
- SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console build")
+ SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console window visible at runtime")
ENDIF()
IF("${CMAKE_SYSTEM}" MATCHES "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")
-SET(SDK_HYDRA_AMD64 FALSE CACHE BOOL "whether target is amd64 (else ia-32)")
-SET(SDK_RIFT "" CACHE PATH "libOVR path")
+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 "" CACHE PATH "libOVR path for Oculus Rift")
-set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Path to Aruco static library")
+set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Aruco paper marker tracker static library path")
if(WIN32)
- set(SDK_SIMCONNECT "" CACHE PATH "Path to SimConnect SDK")
- set(SDK_FSUIPC "" CACHE PATH "Path to FSUIPC")
+ set(SDK_SIMCONNECT "" CACHE PATH "SimConnect SDK path for MS FSX")
+ set(SDK_FSUIPC "" CACHE PATH "FSUIPC for older MS FSX path")
endif()
if(NOT WIN32)
- set(SDK_WINE_PREFIX "" CACHE PATH "Path where Wine is installed")
- set(SDK_WINE_NO_WRAPPER FALSE CACHE BOOL "Don't build wrapper, for instance X-Plane is native Linux app")
+ 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()
# ----
@@ -158,7 +155,7 @@ string(REPLACE "refs/heads/" "" filename-branch_1 "${filename-branch_0}")
string(REPLACE "/" "-" filename-branch "${filename-branch_1}")
set(filename_0 opentrack-${filename-ostype}-${filename-branch}-${filename-date}-${filename-hash})
string(TOLOWER "${filename_0}" filename_1)
-set(filename "${CMAKE_BINARY_DIR}/${filename_1}.tar.xz")
+set(filename "${CMAKE_BINARY_DIR}/${filename_1}.zip")
add_custom_command(OUTPUT ${filename} COMMAND env sh "${CMAKE_SOURCE_DIR}/make-tar.sh" "${CMAKE_INSTALL_PREFIX}" "${filename}")
add_custom_target(tarball DEPENDS ${filename})
@@ -167,7 +164,7 @@ add_custom_target(tarball DEPENDS ${filename})
opentrack_module(opentrack-api opentrack)
opentrack_qt(opentrack-api)
add_library(opentrack-api STATIC ${opentrack-api-all})
-target_link_libraries(opentrack-api ${OpenCV_LIBS} ${MY_QT_LIBS})
+target_link_libraries(opentrack-api ${MY_QT_LIBS})
if(NOT WIN32)
target_link_libraries(opentrack-api dl)
@@ -200,11 +197,11 @@ endif()
opentrack_module(opentrack-compat compat)
opentrack_module(opentrack-xplane-plugin x-plane-plugin)
-opentrack_module(freetrackclient freetrackclient)
+#opentrack_module(freetrackclient freetrackclient)
if(SDK_XPLANE)
# probably librt already included
- add_library(opentrack-xplane-plugin STATIC ${opentrack-xplane-plugin-c})
+ add_library(opentrack-xplane-plugin SHARED ${opentrack-xplane-plugin-c})
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC AND NOT APPLE)
SET_TARGET_PROPERTIES(opentrack-xplane-plugin
PROPERTIES LINK_FLAGS
@@ -228,13 +225,14 @@ if(NOT WIN32 AND NOT APPLE)
target_link_libraries(opentrack-compat rt)
endif()
-opentrack_module(opentrack-csv ftnoir_csv)
+opentrack_module(opentrack-csv csv)
add_library(opentrack-csv STATIC ${opentrack-csv-c})
target_link_libraries(opentrack-csv ${MY_QT_LIBS})
-opentrack_module(opentrack-pose-widget ftnoir_posewidget)
-include_directories(ftnoir_posewidget/)
+opentrack_module(opentrack-pose-widget pose-widget)
+include_directories(pose-widget/) # else Qt moc breaks
opentrack_qt(opentrack-pose-widget)
+
add_library(opentrack-pose-widget STATIC ${opentrack-pose-widget-all})
target_link_libraries(opentrack-pose-widget ${MY_QT_LIBS})
@@ -253,8 +251,6 @@ opentrack_library(opentrack-filter-accela ftnoir_filter_accela)
opentrack_library(opentrack-filter-kalman ftnoir_filter_kalman)
opentrack_library(opentrack-filter-ewma ftnoir_filter_ewma2)
-target_link_libraries(opentrack-filter-kalman ${OpenCV_LIBS})
-
opentrack_library(opentrack-proto-fgfs ftnoir_protocol_fg)
if(SDK_VJOY)
@@ -269,11 +265,9 @@ endif()
if(SDK_ENABLE_LIBEVDEV)
opentrack_library(opentrack-proto-libevdev ftnoir_protocol_libevdev)
- opentrack_library(opentrack-tracker-libevdev ftnoir_tracker_libevdev)
pkg_check_modules(libevdev REQUIRED QUIET libevdev)
include_directories(${libevdev_INCLUDE_DIRS})
target_link_libraries(opentrack-proto-libevdev ${libevdev_LIBRARIES})
- target_link_libraries(opentrack-tracker-libevdev ${libevdev_LIBRARIES})
endif()
if(SDK_FSUIPC)
@@ -293,17 +287,18 @@ if(WIN32)
opentrack_library(opentrack-proto-win32-mouse ftnoir_protocol_mouse)
endif()
-if(WIN32)
- add_library(freetrackclient SHARED ${freetrackclient-c})
- set_target_properties(freetrackclient PROPERTIES PREFIX "")
-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)
+ include_directories(${Qt5SerialPort_INCLUDE_DIRS})
+ target_link_libraries(opentrack-tracker-hatire ${Qt5SerialPort_LIBRARIES})
+endif()
+
if(SDK_WINE_PREFIX)
opentrack_library(opentrack-proto-wine ftnoir_protocol_wine)
target_link_libraries(opentrack-proto-wine opentrack-compat opentrack-csv)
@@ -331,16 +326,19 @@ endif()
opentrack_library(opentrack-tracker-ht ftnoir_tracker_ht)
target_link_libraries(opentrack-tracker-ht opentrack-compat)
-if(SDK_ARUCO_LIBPATH)
- opentrack_library(opentrack-tracker-aruco ftnoir_tracker_aruco)
- target_link_libraries(opentrack-tracker-aruco ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS})
-endif()
-
-opentrack_library(opentrack-tracker-pt ftnoir_tracker_pt)
-target_link_libraries(opentrack-tracker-pt ${OpenCV_LIBS})
opentrack_library(opentrack-tracker-udp ftnoir_tracker_udp)
opentrack_library(opentrack-tracker-freepie-udp ftnoir_tracker_freepie-udp)
+if(OpenCV_FOUND)
+ opentrack_library(opentrack-tracker-pt ftnoir_tracker_pt)
+ target_link_libraries(opentrack-tracker-pt ${OpenCV_LIBS})
+ if(SDK_ARUCO_LIBPATH)
+ opentrack_library(opentrack-tracker-aruco ftnoir_tracker_aruco)
+ target_link_libraries(opentrack-tracker-aruco ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS})
+ endif()
+ target_link_libraries(opentrack-filter-kalman ${OpenCV_LIBS})
+endif()
+
link_with_dinput8(opentrack-tracker-ht)
link_with_dinput8(opentrack-tracker-joystick)
link_with_dinput8(opentrack-tracker-pt)
@@ -467,13 +465,14 @@ endif()
if(WIN32)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/bin/tracker-ht DESTINATION .)
- install(TARGETS freetrackclient RUNTIME DESTINATION . LIBRARY DESTINATION . )
+ #install(TARGETS freetrackclient RUNTIME DESTINATION . LIBRARY DESTINATION . )
endif()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty-notices DESTINATION .)
+install(FILES "${CMAKE_SOURCE_DIR}/bin/freetrackclient.dll" DESTINATION .)
install(FILES "${CMAKE_SOURCE_DIR}/bin/NPClient.dll" "${CMAKE_SOURCE_DIR}/bin/NPClient64.dll" "${CMAKE_SOURCE_DIR}/bin/TrackIR.exe" DESTINATION .)
-install(DIRECTORY "${CMAKE_SOURCE_DIR}/bin/settings" "${CMAKE_SOURCE_DIR}/facetracknoir/clientfiles" DESTINATION .)
+install(DIRECTORY "${CMAKE_SOURCE_DIR}/bin/settings" "${CMAKE_SOURCE_DIR}/clientfiles" DESTINATION .)
if(NOT WIN32 AND SDK_WINE_PREFIX AND NOT SDK_WINE_NO_WRAPPER)
install(FILES "${CMAKE_BINARY_DIR}/opentrack-wrapper-wine.exe.so"
diff --git a/README.md b/README.md
index a362b136..85139930 100644
--- a/README.md
+++ b/README.md
@@ -1,45 +1,55 @@
-=======
-Windows binary builds are available at <https://www.dropbox.com/sh/544fbhsokdpy3n7/AAAKwl6BluqwT9Xn2slyp0dCa>
+opentrack project home at <<http://github.com/opentrack/opentrack>>.
-Source code access available at <http://github.com/opentrack/opentrack/>
+Binary releases at <<https://github.com/opentrack/opentrack/releases>>.
---
+Please first refer to <<https://github.com/opentrack/opentrack/wiki>>
+for new user guide, frequent questions, specific tracker/filter
+documentation.
+
+***
**opentrack** is an application dedicated to tracking user's head
-movements and relaying them to games and flight simulation software.
+movements and relaying the information to games and flight simulation
+software.
Not to be confused with railway planning software <<http://opentrack.ch>>
-See our wiki at <<https://github.com/opentrack/opentrack/wiki>>
+***
# Tracking sources
- PointTracker by Patrick Ruoff, freetrack-like light sources
- Oculus Rift
-- AR marker support via the ArUco library <https://github.com/rmsalinas/aruco>
-- HT tracker <https://github.com/sthalik/headtracker>
+- Paper marker support via the ArUco library <<https://github.com/rmsalinas/aruco>>
+- Human face tracker <<https://github.com/sthalik/headtracker>>
- Razer Hydra
- Relaying via UDP from a different computer
-- Joystick analog axes (Windows only)
+- Relaying UDP via FreePIE-specific Android app
+- Joystick analog axes (Windows, Linux)
+- Windows Phone [tracker](http://www.windowsphone.com/en-us/store/app/opentrack-head-tracking/1c604f32-6d68-40ef-aa44-3163e30f547f) over opentrack UDP protocol
# Output
-- FlightGear Nasal script
-- FSUIPC for Microsoft Flight Simulator (Windows)
- SimConnect for newer Microsoft Flight Simulator (Windows)
-- freetrack emulation (Windows)
-- Relaying udp to another computer
-- Joystick support via freedesktop.org libevdev (Linux)
-- Joystick support via VJoy (Windows)
+- freetrack implementation (Windows)
+- Relaying UDP to another computer
+- Virtual joystick output (Linux, Windows)
- Wine freetrack glue protocol (Linux, OSX)
-- Tablet-like coordinate output (Windows)
+- X-Plane plugin (Linux)
+- Tablet-like mouse output (Windows)
+- FlightGear Nasal script
+- FSUIPC for Microsoft Flight Simulator 2002/2004 (Windows)
+
+***
# Configuration
-**opentrack** offers output shaping, filtering, is buildable on
-MS Windows, MacOSX and GNU/Linux.
+**opentrack** allows for output shaping, filtering, the codebase builds
+on on Microsoft Windows, Apple OSX, and GNU/Linux.
+
+Don't be afraid to submit an issue/feature request if need arises.
-Don't be afraid to submit an issue/feature request if the need arises.
+***
# Credits
@@ -49,13 +59,14 @@ Don't be afraid to submit an issue/feature request if the need arises.
- Ryan Spicer (OSX tester, contributor)
- Patrick Ruoff (PT tracker)
- Ulf Schreiber (PT tracker)
+- Andrzej Czarnowski (quality assurance)
- uglyDwarf (high CON)
- Wim Vriend (historically)
# Licensing information
-The code originally licensed under GPLv3, new code is required to be
-compatible with it unless resides in separate address space.
+The code originally licensed under GPLv3, new code required legally
+compatible unless resides in separate address space.
-It's recommended to submit new code under ISC license, it's a shorter
-boilerplate header than MIT/X11 or new BSD.
+Recommended to submit new code under ISC license, shorter boilerplate
+header than MIT/X11 or new BSD.
diff --git a/bin/freetrackclient.dll b/bin/freetrackclient.dll
new file mode 100755
index 00000000..ad25e145
--- /dev/null
+++ b/bin/freetrackclient.dll
Binary files differ
diff --git a/facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml b/clientfiles/FlightGear/Protocol/headtracker.xml
index 8c14119a..8c14119a 100644
--- a/facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml
+++ b/clientfiles/FlightGear/Protocol/headtracker.xml
diff --git a/facetracknoir/clientfiles/FlightGear/readme.txt b/clientfiles/FlightGear/readme.txt
index 48cee837..48cee837 100644
--- a/facetracknoir/clientfiles/FlightGear/readme.txt
+++ b/clientfiles/FlightGear/readme.txt
diff --git a/facetracknoir/clientfiles/Tir4Fun/npclient.dll b/clientfiles/Tir4Fun/npclient.dll
index e392442e..e392442e 100644
--- a/facetracknoir/clientfiles/Tir4Fun/npclient.dll
+++ b/clientfiles/Tir4Fun/npclient.dll
Binary files differ
diff --git a/facetracknoir/clientfiles/Tir4Fun/readme.txt b/clientfiles/Tir4Fun/readme.txt
index d64af301..d64af301 100644
--- a/facetracknoir/clientfiles/Tir4Fun/readme.txt
+++ b/clientfiles/Tir4Fun/readme.txt
diff --git a/facetracknoir/clientfiles/Tir4Fun/tir4fun.exe b/clientfiles/Tir4Fun/tir4fun.exe
index a51eced0..a51eced0 100644
--- a/facetracknoir/clientfiles/Tir4Fun/tir4fun.exe
+++ b/clientfiles/Tir4Fun/tir4fun.exe
Binary files differ
diff --git a/facetracknoir/clientfiles/aruco/aruco_create_marker.exe b/clientfiles/aruco/aruco_create_marker.exe
index 4400e80e..4400e80e 100644
--- a/facetracknoir/clientfiles/aruco/aruco_create_marker.exe
+++ b/clientfiles/aruco/aruco_create_marker.exe
Binary files differ
diff --git a/facetracknoir/clientfiles/aruco/test3.jpg b/clientfiles/aruco/test3.jpg
index 2ff6dbd0..2ff6dbd0 100644
--- a/facetracknoir/clientfiles/aruco/test3.jpg
+++ b/clientfiles/aruco/test3.jpg
Binary files differ
diff --git a/facetracknoir/clientfiles/cfs3/readme.txt b/clientfiles/cfs3/readme.txt
index e51cebfa..e51cebfa 100644
--- a/facetracknoir/clientfiles/cfs3/readme.txt
+++ b/clientfiles/cfs3/readme.txt
diff --git a/facetracknoir/clientfiles/cfs3/tirviews.dll b/clientfiles/cfs3/tirviews.dll
index a1fb306f..a1fb306f 100644
--- a/facetracknoir/clientfiles/cfs3/tirviews.dll
+++ b/clientfiles/cfs3/tirviews.dll
Binary files differ
diff --git a/facetracknoir/clientfiles/cute-octopus-vector-material_15-1831.jpg b/clientfiles/cute-octopus-vector-material_15-1831.jpg
index c4e5318f..c4e5318f 100644
--- a/facetracknoir/clientfiles/cute-octopus-vector-material_15-1831.jpg
+++ b/clientfiles/cute-octopus-vector-material_15-1831.jpg
Binary files differ
diff --git a/clientfiles/freepie-udp/com.freepie.android.imu.apk b/clientfiles/freepie-udp/com.freepie.android.imu.apk
new file mode 100644
index 00000000..0277b82a
--- /dev/null
+++ b/clientfiles/freepie-udp/com.freepie.android.imu.apk
Binary files differ
diff --git a/facetracknoir/clientfiles/freetracktest/freetracktest.exe b/clientfiles/freetracktest/freetracktest.exe
index 2965a07f..2965a07f 100644
--- a/facetracknoir/clientfiles/freetracktest/freetracktest.exe
+++ b/clientfiles/freetracktest/freetracktest.exe
Binary files differ
diff --git a/facetracknoir/clientfiles/freetracktest/readme.txt b/clientfiles/freetracktest/readme.txt
index ca40906f..ca40906f 100644
--- a/facetracknoir/clientfiles/freetracktest/readme.txt
+++ b/clientfiles/freetracktest/readme.txt
diff --git a/facetracknoir/clientfiles/fs2002 and fs2004/fsuipc.dll b/clientfiles/fs2002 and fs2004/fsuipc.dll
index 264d14c5..264d14c5 100644
--- a/facetracknoir/clientfiles/fs2002 and fs2004/fsuipc.dll
+++ b/clientfiles/fs2002 and fs2004/fsuipc.dll
Binary files differ
diff --git a/facetracknoir/clientfiles/glovepie/facetracknoir2trackir.pie b/clientfiles/glovepie/facetracknoir2trackir.pie
index d0839e5d..d0839e5d 100644
--- a/facetracknoir/clientfiles/glovepie/facetracknoir2trackir.pie
+++ b/clientfiles/glovepie/facetracknoir2trackir.pie
diff --git a/facetracknoir/clientfiles/glovepie/readme.txt b/clientfiles/glovepie/readme.txt
index 3639e26b..3639e26b 100644
--- a/facetracknoir/clientfiles/glovepie/readme.txt
+++ b/clientfiles/glovepie/readme.txt
diff --git a/facetracknoir/clientfiles/make-csv.pl b/clientfiles/make-csv.pl
index ee60364e..ee60364e 100755
--- a/facetracknoir/clientfiles/make-csv.pl
+++ b/clientfiles/make-csv.pl
diff --git a/facetracknoir/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg b/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg
index 052c6899..052c6899 100644
--- a/facetracknoir/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg
+++ b/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg
Binary files differ
diff --git a/facetracknoir/clientfiles/ppjoy/readme.txt b/clientfiles/ppjoy/readme.txt
index 20c52111..20c52111 100644
--- a/facetracknoir/clientfiles/ppjoy/readme.txt
+++ b/clientfiles/ppjoy/readme.txt
diff --git a/facetracknoir/clientfiles/very-important-source-code/README-CREDIT.txt b/clientfiles/very-important-source-code/README-CREDIT.txt
index 82214139..82214139 100644
--- a/facetracknoir/clientfiles/very-important-source-code/README-CREDIT.txt
+++ b/clientfiles/very-important-source-code/README-CREDIT.txt
diff --git a/facetracknoir/clientfiles/very-important-source-code/ft_tester/Makefile.am b/clientfiles/very-important-source-code/ft_tester/Makefile.am
index 02747edb..02747edb 100644
--- a/facetracknoir/clientfiles/very-important-source-code/ft_tester/Makefile.am
+++ b/clientfiles/very-important-source-code/ft_tester/Makefile.am
diff --git a/facetracknoir/clientfiles/very-important-source-code/ft_tester/Makefile.in b/clientfiles/very-important-source-code/ft_tester/Makefile.in
index d1fff34d..d1fff34d 100644
--- a/facetracknoir/clientfiles/very-important-source-code/ft_tester/Makefile.in
+++ b/clientfiles/very-important-source-code/ft_tester/Makefile.in
diff --git a/facetracknoir/clientfiles/very-important-source-code/ft_tester/fttester.rc.in b/clientfiles/very-important-source-code/ft_tester/fttester.rc.in
index 332f3c73..332f3c73 100644
--- a/facetracknoir/clientfiles/very-important-source-code/ft_tester/fttester.rc.in
+++ b/clientfiles/very-important-source-code/ft_tester/fttester.rc.in
diff --git a/facetracknoir/clientfiles/very-important-source-code/ft_tester/main.cpp b/clientfiles/very-important-source-code/ft_tester/main.cpp
index a737f88f..a737f88f 100644
--- a/facetracknoir/clientfiles/very-important-source-code/ft_tester/main.cpp
+++ b/clientfiles/very-important-source-code/ft_tester/main.cpp
diff --git a/facetracknoir/clientfiles/very-important-source-code/ft_tester/resource.h b/clientfiles/very-important-source-code/ft_tester/resource.h
index 8bba17b4..8bba17b4 100644
--- a/facetracknoir/clientfiles/very-important-source-code/ft_tester/resource.h
+++ b/clientfiles/very-important-source-code/ft_tester/resource.h
diff --git a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient.h b/clientfiles/very-important-source-code/important-stuff/NPClient.h
index 770e1c71..770e1c71 100644
--- a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient.h
+++ b/clientfiles/very-important-source-code/important-stuff/NPClient.h
diff --git a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient.spec b/clientfiles/very-important-source-code/important-stuff/NPClient.spec
index 7fe5f1b4..7fe5f1b4 100644
--- a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient.spec
+++ b/clientfiles/very-important-source-code/important-stuff/NPClient.spec
diff --git a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient_dll.h b/clientfiles/very-important-source-code/important-stuff/NPClient_dll.h
index b0bab5db..b0bab5db 100644
--- a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient_dll.h
+++ b/clientfiles/very-important-source-code/important-stuff/NPClient_dll.h
diff --git a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient_main.c b/clientfiles/very-important-source-code/important-stuff/NPClient_main.c
index f892f89e..f892f89e 100644
--- a/facetracknoir/clientfiles/very-important-source-code/important-stuff/NPClient_main.c
+++ b/clientfiles/very-important-source-code/important-stuff/NPClient_main.c
diff --git a/facetracknoir/clientfiles/very-important-source-code/important-stuff/game_data.c b/clientfiles/very-important-source-code/important-stuff/game_data.c
index f80a7d44..f80a7d44 100644
--- a/facetracknoir/clientfiles/very-important-source-code/important-stuff/game_data.c
+++ b/clientfiles/very-important-source-code/important-stuff/game_data.c
diff --git a/facetracknoir/clientfiles/very-important-source-code/important-stuff/game_data.h b/clientfiles/very-important-source-code/important-stuff/game_data.h
index b71f7a15..b71f7a15 100644
--- a/facetracknoir/clientfiles/very-important-source-code/important-stuff/game_data.h
+++ b/clientfiles/very-important-source-code/important-stuff/game_data.h
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/Makefile.am b/clientfiles/very-important-source-code/tester/Makefile.am
index e025209a..e025209a 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/Makefile.am
+++ b/clientfiles/very-important-source-code/tester/Makefile.am
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/Makefile.in b/clientfiles/very-important-source-code/tester/Makefile.in
index cc49d754..cc49d754 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/Makefile.in
+++ b/clientfiles/very-important-source-code/tester/Makefile.in
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/main.cpp b/clientfiles/very-important-source-code/tester/main.cpp
index 95ca0d9b..95ca0d9b 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/main.cpp
+++ b/clientfiles/very-important-source-code/tester/main.cpp
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/npifc.c b/clientfiles/very-important-source-code/tester/npifc.c
index b036464e..b036464e 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/npifc.c
+++ b/clientfiles/very-important-source-code/tester/npifc.c
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/npifc.h b/clientfiles/very-important-source-code/tester/npifc.h
index d580e16d..d580e16d 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/npifc.h
+++ b/clientfiles/very-important-source-code/tester/npifc.h
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/npview.rc.in b/clientfiles/very-important-source-code/tester/npview.rc.in
index 231002f1..231002f1 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/npview.rc.in
+++ b/clientfiles/very-important-source-code/tester/npview.rc.in
diff --git a/facetracknoir/clientfiles/very-important-source-code/tester/resource.h b/clientfiles/very-important-source-code/tester/resource.h
index 328d9cb7..328d9cb7 100644
--- a/facetracknoir/clientfiles/very-important-source-code/tester/resource.h
+++ b/clientfiles/very-important-source-code/tester/resource.h
diff --git a/facetracknoir/clientfiles/vjoy/VJoy.dll b/clientfiles/vjoy/VJoy.dll
index e3446675..e3446675 100644
--- a/facetracknoir/clientfiles/vjoy/VJoy.dll
+++ b/clientfiles/vjoy/VJoy.dll
Binary files differ
diff --git a/cmake/mingw-w64.cmake b/cmake/mingw-w64.cmake
index a60f0008..07268212 100644
--- a/cmake/mingw-w64.cmake
+++ b/cmake/mingw-w64.cmake
@@ -19,10 +19,8 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-set(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math -flto -flto-partition=none -march=i686 -mtune=prescott -mno-sse3 -mno-avx -frename-registers" CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math -flto -fno-use-linker-plugin -march=i686 -mtune=prescott -msse -msse2 -mno-sse3 -mno-avx -frename-registers" CACHE STRING "" FORCE)
+set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-msse -msse2 -mno-sse3 -mno-avx -fno-use-linker-plugin -flto" CACHE STRING "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS_RELEASE ${CMAKE_SHARED_LINKER_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
set(CMAKE_BUILD_TYPE "RELEASE" CACHE STRING "" FORCE)
-
-# these are merely for my own convenience
-set(OpenCV_DIR /home/sthalik/opentrack-win32-sdk/opencv/build)
-set(Qt5_DIR /home/sthalik/opentrack-win32-sdk/qt-install-5.3.1/lib/cmake/Qt5)
diff --git a/ftnoir_csv/csv.cpp b/csv/csv.cpp
index 71db8ecb..71db8ecb 100644
--- a/ftnoir_csv/csv.cpp
+++ b/csv/csv.cpp
diff --git a/ftnoir_csv/csv.h b/csv/csv.h
index e0eac7dd..e0eac7dd 100644
--- a/ftnoir_csv/csv.h
+++ b/csv/csv.h
diff --git a/facetracknoir/curve-config.cpp b/facetracknoir/curve-config.cpp
index f00d3657..ac34e57a 100644
--- a/facetracknoir/curve-config.cpp
+++ b/facetracknoir/curve-config.cpp
@@ -1,4 +1,3 @@
-#include "./facetracknoir.h"
#include "./curve-config.h"
#include "opentrack/main-settings.hpp"
MapWidget::MapWidget(Mappings& m, main_settings& s) :
@@ -77,6 +76,9 @@ MapWidget::MapWidget(Mappings& m, main_settings& s) :
tie_setting(s.a_x.src, ui.src_x);
tie_setting(s.a_y.src, ui.src_y);
tie_setting(s.a_z.src, ui.src_z);
+
+ tie_setting(s.camera_yaw, ui.camera_yaw);
+ tie_setting(s.camera_pitch, ui.camera_pitch);
}
void MapWidget::doOK() {
diff --git a/facetracknoir/curve-config.h b/facetracknoir/curve-config.h
index 2104b7fa..d1ef7ad2 100644
--- a/facetracknoir/curve-config.h
+++ b/facetracknoir/curve-config.h
@@ -1,7 +1,7 @@
#pragma once
#include <QWidget>
#include "opentrack/mappings.hpp"
-#include "ui_ftnoir_curves.h"
+#include "ui_mapping.h"
class MapWidget: public QWidget
{
diff --git a/facetracknoir/facetracknoir.ui b/facetracknoir/facetracknoir.ui
deleted file mode 100644
index 5ccdfb46..00000000
--- a/facetracknoir/facetracknoir.ui
+++ /dev/null
@@ -1,1079 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <author>WVR</author>
- <class>OpentrackUI</class>
- <widget class="QMainWindow" name="OpentrackUI">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>956</width>
- <height>740</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowIcon">
- <iconset resource="main-facetracknoir.qrc">
- <normaloff>:/images/facetracknoir.png</normaloff>:/images/facetracknoir.png</iconset>
- </property>
- <property name="styleSheet">
- <string notr="true">#headpose, #video_frame_label, #controls, #video_frame { border: 0; }
-#video_frame { margin: 0; padding: 0; }
-</string>
- </property>
- <widget class="QWidget" name="centralWidget">
- <layout class="QGridLayout" name="gridLayout_11">
- <item row="0" column="0">
- <widget class="QGroupBox" name="octopus">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Tracking preview</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="GLWidget" name="pose_display" native="true">
- <property name="minimumSize">
- <size>
- <width>90</width>
- <height>120</height>
- </size>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="1" colspan="2">
- <widget class="QGroupBox" name="headpose">
- <property name="title">
- <string/>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>10</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QGroupBox" name="box_raw_headpose">
- <property name="title">
- <string notr="true">Raw pose</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_8">
- <item row="1" column="1">
- <widget class="QLCDNumber" name="lcdNumY">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Outline</enum>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QLCDNumber" name="lcdNumRotX">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Outline</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="lblRotY_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>pitch</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="lblX_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLCDNumber" name="lcdNumZ">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Outline</enum>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLCDNumber" name="lcdNumX">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Outline</enum>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="lblZ_3">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="lblY_3">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QLCDNumber" name="lcdNumRotY">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Outline</enum>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="lblRotX_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>yaw</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QLabel" name="lblRotZ_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>roll</string>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QLCDNumber" name="lcdNumRotZ">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Outline</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="box_mapped_headpose">
- <property name="title">
- <string notr="true">Game data</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_10">
- <item row="0" column="0">
- <widget class="QLabel" name="lblX_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLCDNumber" name="lcdNumOutputPosX">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="smallDecimalPoint">
- <bool>true</bool>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLCDNumber" name="lcdNumOutputPosY">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="smallDecimalPoint">
- <bool>true</bool>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="lblRotY_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="text">
- <string>pitch</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QLCDNumber" name="lcdNumOutputRotY">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="smallDecimalPoint">
- <bool>true</bool>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="lblZ_2">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QLCDNumber" name="lcdNumOutputRotX">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="smallDecimalPoint">
- <bool>true</bool>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="lblY_2">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="lblRotX_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="text">
- <string>yaw</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLCDNumber" name="lcdNumOutputPosZ">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="smallDecimalPoint">
- <bool>true</bool>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QLabel" name="lblRotZ_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="text">
- <string>roll</string>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QLCDNumber" name="lcdNumOutputRotZ">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="smallDecimalPoint">
- <bool>true</bool>
- </property>
- <property name="digitCount">
- <number>4</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="0" colspan="2">
- <widget class="QGroupBox" name="video_feed">
- <property name="title">
- <string>Video preview</string>
- </property>
- <layout class="QFormLayout">
- <property name="horizontalSpacing">
- <number>0</number>
- </property>
- <property name="verticalSpacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item row="0" column="0">
- <widget class="QFrame" name="video_frame">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>640</width>
- <height>480</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>640</width>
- <height>480</height>
- </size>
- </property>
- <widget class="QLabel" name="video_frame_label">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>640</width>
- <height>480</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>640</width>
- <height>480</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>640</width>
- <height>480</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QGroupBox" name="controls">
- <property name="title">
- <string/>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>3</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Connected game</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_9">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="game_name">
- <property name="text">
- <string>Not connected</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupProfile">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Profile</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_7">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="1" column="1">
- <widget class="QPushButton" name="btnSave">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QPushButton" name="btnLoad">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Load</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QComboBox" name="iconcomboProfile">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maxVisibleItems">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QPushButton" name="btnSaveAs">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Save As ...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupTrackerSource">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Tracker</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="0" column="0">
- <widget class="QComboBox" name="iconcomboTrackerSource">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QPushButton" name="btnShowEngineControls">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupFilter">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Filter</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="0" column="0">
- <widget class="QComboBox" name="iconcomboFilter">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QPushButton" name="btnShowFilterControls">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupGameProtocol">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Protocol</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="0" column="1">
- <widget class="QPushButton" name="btnShowServerControls">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QComboBox" name="iconcomboProtocol">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupWindows">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="title">
- <string>Settings</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_6">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="0" column="0">
- <widget class="QPushButton" name="btnEditCurves">
- <property name="text">
- <string>Mapping</string>
- </property>
- <property name="icon">
- <iconset resource="main-facetracknoir.qrc">
- <normaloff>:/uielements/curves.png</normaloff>:/uielements/curves.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>91</width>
- <height>20</height>
- </size>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QPushButton" name="btnShortcuts">
- <property name="text">
- <string>Keys</string>
- </property>
- <property name="icon">
- <iconset resource="main-facetracknoir.qrc">
- <normaloff>:/uielements/tools.png</normaloff>:/uielements/tools.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>98</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupStartStop">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>65536</width>
- <height>65536</height>
- </size>
- </property>
- <property name="title">
- <string notr="true">Controls</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_5">
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>3</number>
- </property>
- <item row="0" column="1">
- <widget class="QPushButton" name="btnStopTracker">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Stop</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QPushButton" name="btnStartTracker">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Start</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- <customwidgets>
- <customwidget>
- <class>GLWidget</class>
- <extends>QWidget</extends>
- <header>glwidget.h</header>
- </customwidget>
- </customwidgets>
- <resources>
- <include location="main-facetracknoir.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/facetracknoir/ftnoir_curves.ui b/facetracknoir/ftnoir_curves.ui
deleted file mode 100644
index 9f422b9b..00000000
--- a/facetracknoir/ftnoir_curves.ui
+++ /dev/null
@@ -1,1069 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>UICCurveConfigurationDialog</class>
- <widget class="QWidget" name="UICCurveConfigurationDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>970</width>
- <height>655</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Mapping properties</string>
- </property>
- <property name="windowIcon">
- <iconset>
- <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">background-color: #ccc;</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="tabPosition">
- <enum>QTabWidget::North</enum>
- </property>
- <property name="currentIndex">
- <number>6</number>
- </property>
- <widget class="QWidget" name="tabWidgetPage1">
- <attribute name="title">
- <string>Yaw</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="rxconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- <widget class="QCheckBox" name="rx_altp">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>260</y>
- <width>166</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Asymmetric mapping below</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="rxconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>300</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>255</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tabWidgetPage2">
- <attribute name="title">
- <string>Pitch</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="ryconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>0</red>
- <green>255</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- <widget class="QCheckBox" name="ry_altp">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>260</y>
- <width>199</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Asymmetric mapping below</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="ryconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>300</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>0</red>
- <green>255</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tabWidgetPage3">
- <attribute name="title">
- <string>Roll</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="rzconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>0</red>
- <green>0</green>
- <blue>255</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- <widget class="QCheckBox" name="rz_altp">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>260</y>
- <width>271</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Asymmetric mapping below</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="rzconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>300</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>0</red>
- <green>0</green>
- <blue>255</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tabWidgetPage4">
- <attribute name="title">
- <string>X</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="txconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>0</green>
- <blue>255</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- <widget class="QCheckBox" name="tx_altp">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>270</y>
- <width>228</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Asymmetric mapping below</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="txconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>300</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>0</green>
- <blue>255</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tabWidgetPage5">
- <attribute name="title">
- <string>Y</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="tyconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>255</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- <widget class="QCheckBox" name="ty_altp">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>270</y>
- <width>229</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Asymmetric mapping below</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="tyconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>300</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>255</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tabWidgetPage6">
- <attribute name="title">
- <string>Z</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="tzconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>0</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- <widget class="QCheckBox" name="tz_altp">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>270</y>
- <width>263</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Asymmetric mapping below</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="tzconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>300</y>
- <width>930</width>
- <height>260</height>
- </rect>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>0</red>
- <green>255</green>
- <blue>255</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
- </color>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tabWidgetPage7">
- <attribute name="title">
- <string>Options</string>
- </attribute>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Center pose</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="1">
- <widget class="QDoubleSpinBox" name="pos_rz">
- <property name="suffix">
- <string> deg.</string>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>-180.000000000000000</double>
- </property>
- <property name="maximum">
- <double>180.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QDoubleSpinBox" name="pos_tz">
- <property name="suffix">
- <string> cm</string>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>-100.000000000000000</double>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <widget class="QDoubleSpinBox" name="pos_tx">
- <property name="suffix">
- <string> cm</string>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>-100.000000000000000</double>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>RY</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QDoubleSpinBox" name="pos_ry">
- <property name="suffix">
- <string> deg.</string>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>-180.000000000000000</double>
- </property>
- <property name="maximum">
- <double>180.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>RZ</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QDoubleSpinBox" name="pos_ty">
- <property name="suffix">
- <string> cm</string>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>-100.000000000000000</double>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>RX</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="pos_rx">
- <property name="suffix">
- <string> deg.</string>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>-180.000000000000000</double>
- </property>
- <property name="maximum">
- <double>180.000000000000000</double>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QGroupBox" name="groupBox_4">
- <property name="maximumSize">
- <size>
- <width>65536</width>
- <height>65536</height>
- </size>
- </property>
- <property name="font">
- <font>
- <kerning>true</kerning>
- </font>
- </property>
- <property name="title">
- <string>Output remap</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,0,0,0,0,0" columnstretch="0,0,0">
- <property name="sizeConstraint">
- <enum>QLayout::SetMinAndMaxSize</enum>
- </property>
- <property name="spacing">
- <number>6</number>
- </property>
- <item row="4" column="0">
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>X</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Yaw</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>Pitch</string>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Y</string>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_12">
- <property name="text">
- <string>Z</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Roll</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QCheckBox" name="invert_yaw">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QCheckBox" name="invert_pitch">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="4" column="2">
- <widget class="QCheckBox" name="invert_x">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QCheckBox" name="invert_roll">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="5" column="2">
- <widget class="QCheckBox" name="invert_y">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="6" column="2">
- <widget class="QCheckBox" name="invert_z">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QComboBox" name="src_yaw">
- <item>
- <property name="text">
- <string>X</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Y</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Z</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Yaw</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Pitch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Roll</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Disabled</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QComboBox" name="src_pitch">
- <item>
- <property name="text">
- <string>X</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Y</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Z</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Yaw</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Pitch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Roll</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Disabled</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QComboBox" name="src_roll">
- <item>
- <property name="text">
- <string>X</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Y</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Z</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Yaw</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Pitch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Roll</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Disabled</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QComboBox" name="src_x">
- <item>
- <property name="text">
- <string>X</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Y</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Z</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Yaw</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Pitch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Roll</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Disabled</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QComboBox" name="src_y">
- <item>
- <property name="text">
- <string>X</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Y</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Z</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Yaw</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Pitch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Roll</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Disabled</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QComboBox" name="src_z">
- <item>
- <property name="text">
- <string>X</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Y</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Z</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Yaw</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Pitch</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Roll</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Disabled</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="label_13">
- <property name="text">
- <string>Source</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="label_14">
- <property name="text">
- <string>Invert</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_15">
- <property name="text">
- <string>Destination</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QGroupBox" name="groupBox_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="title">
- <string>Translation compensation</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <layout class="QFormLayout" name="formLayout_2">
- <item row="0" column="0">
- <widget class="QCheckBox" name="tcomp_enable">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Enable</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="tcomp_rz">
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Disable Z axis compensation</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>QFunctionConfigurator</class>
- <extends>QWidget</extends>
- <header>qfunctionconfigurator.h</header>
- </customwidget>
- </customwidgets>
- <tabstops>
- <tabstop>pos_rx</tabstop>
- <tabstop>pos_ry</tabstop>
- <tabstop>pos_rz</tabstop>
- <tabstop>ry_altp</tabstop>
- <tabstop>rz_altp</tabstop>
- <tabstop>tx_altp</tabstop>
- <tabstop>ty_altp</tabstop>
- <tabstop>tz_altp</tabstop>
- <tabstop>tcomp_enable</tabstop>
- <tabstop>tabWidget</tabstop>
- <tabstop>pos_tx</tabstop>
- <tabstop>buttonBox</tabstop>
- <tabstop>pos_ty</tabstop>
- <tabstop>rx_altp</tabstop>
- <tabstop>pos_tz</tabstop>
- </tabstops>
- <resources/>
- <connections/>
- <slots>
- <slot>startEngineClicked()</slot>
- <slot>stopEngineClicked()</slot>
- <slot>cameraSettingsClicked()</slot>
- </slots>
-</ui>
diff --git a/facetracknoir/global-shortcuts.cpp b/facetracknoir/global-shortcuts.cpp
deleted file mode 100644
index 9b6591a7..00000000
--- a/facetracknoir/global-shortcuts.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-# include <QList>
-# include <QString>
-
-#if defined(_WIN32)
-# ifndef DIRECTINPUT_VERSION
-# define DIRECTINPUT_VERSION 0x800
-# endif
-# include <windows.h>
-# include <dinput.h>
-
-QList<int> global_windows_key_sequences =
- QList<int>()
- << 0
- << DIK_A
- << DIK_B
- << DIK_C
- << DIK_D
- << DIK_E
- << DIK_F
- << DIK_G
- << DIK_H
- << DIK_I
- << DIK_J
- << DIK_K
- << DIK_L
- << DIK_M
- << DIK_N
- << DIK_O
- << DIK_P
- << DIK_Q
- << DIK_R
- << DIK_S
- << DIK_T
- << DIK_U
- << DIK_V
- << DIK_W
- << DIK_X
- << DIK_Y
- << DIK_Z
- << DIK_F1
- << DIK_F2
- << DIK_F3
- << DIK_F4
- << DIK_F5
- << DIK_F6
- << DIK_F7
- << DIK_F8
- << DIK_F9
- << DIK_F10
- << DIK_F11
- << DIK_F12
- << DIK_1
- << DIK_2
- << DIK_3
- << DIK_4
- << DIK_5
- << DIK_6
- << DIK_7
- << DIK_8
- << DIK_9
- << DIK_0
- << DIK_LEFT
- << DIK_RIGHT
- << DIK_UP
- << DIK_DOWN
- << DIK_PGUP
- << DIK_DOWN
- << DIK_HOME
- << DIK_END
- << DIK_BACK
- << DIK_DELETE
- << DIK_RETURN;
-#endif
-
-QList<QString> global_key_sequences =
- QList<QString>()
- << ""
- << "A"
- << "B"
- << "C"
- << "D"
- << "E"
- << "F"
- << "G"
- << "H"
- << "I"
- << "J"
- << "K"
- << "L"
- << "M"
- << "N"
- << "O"
- << "P"
- << "Q"
- << "R"
- << "S"
- << "T"
- << "U"
- << "V"
- << "W"
- << "X"
- << "Y"
- << "Z"
- << "F1"
- << "F2"
- << "F3"
- << "F4"
- << "F5"
- << "F6"
- << "F7"
- << "F8"
- << "F9"
- << "F10"
- << "F11"
- << "F12"
- << "1"
- << "2"
- << "3"
- << "4"
- << "5"
- << "6"
- << "7"
- << "8"
- << "9"
- << "0"
- << "Left"
- << "Right"
- << "Up"
- << "Down"
- << "PgUp"
- << "PgDown"
- << "Home"
- << "End"
- << "Backspace"
- << "Del"
- << "Enter"
-;
-
-
diff --git a/facetracknoir/uielements/curves.png b/facetracknoir/images/curves.png
index 3f953a0a..3f953a0a 100644
--- a/facetracknoir/uielements/curves.png
+++ b/facetracknoir/images/curves.png
Binary files differ
diff --git a/ftnoir_filter_ewma2/images/filter-16.png b/facetracknoir/images/filter-16.png
index ecde6a10..ecde6a10 100644
--- a/ftnoir_filter_ewma2/images/filter-16.png
+++ b/facetracknoir/images/filter-16.png
Binary files differ
diff --git a/facetracknoir/images/no-feed.png b/facetracknoir/images/no-feed.png
new file mode 100644
index 00000000..02aa227a
--- /dev/null
+++ b/facetracknoir/images/no-feed.png
Binary files differ
diff --git a/facetracknoir/uielements/tools.png b/facetracknoir/images/tools.png
index 2da8f9f5..2da8f9f5 100644
--- a/facetracknoir/uielements/tools.png
+++ b/facetracknoir/images/tools.png
Binary files differ
diff --git a/facetracknoir/keyboard.ui b/facetracknoir/keyboard.ui
new file mode 100644
index 00000000..cdfc0657
--- /dev/null
+++ b/facetracknoir/keyboard.ui
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UICKeyboardShortcutDialog</class>
+ <widget class="QWidget" name="UICKeyboardShortcutDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>461</width>
+ <height>181</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Keyboard shortcuts</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="chkToggleShift">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Shift</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QCheckBox" name="chkToggleCtrl">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Ctrl</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="chkZeroShift">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Shift</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="textLabel2_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Zero</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QCheckBox" name="chkZeroAlt">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Alt</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QCheckBox" name="chkZeroCtrl">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Ctrl</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="5">
+ <widget class="QLabel" name="textLabel2_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Keyboard</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QCheckBox" name="chkToggleAlt">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Alt</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QCheckBox" name="chkCenterCtrl">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Ctrl</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="chkCenterShift">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Shift</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="textLabel2_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Center</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <widget class="QComboBox" name="cbxCenterKey">
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select Number</string>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::InsertAlphabetically</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="textLabel2_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Toggle</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <widget class="QComboBox" name="cbxToggleKey">
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select Number</string>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::InsertAlphabetically</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QCheckBox" name="chkCenterAlt">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Alt</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="5">
+ <widget class="QComboBox" name="cbxZeroKey">
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Select Number</string>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::InsertAlphabetically</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="center_at_startup">
+ <property name="text">
+ <string>Center at startup</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="trayp">
+ <property name="text">
+ <string>Minimize to tray</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/facetracknoir/main-facetracknoir.qrc b/facetracknoir/main-facetracknoir.qrc
deleted file mode 100644
index e37c2529..00000000
--- a/facetracknoir/main-facetracknoir.qrc
+++ /dev/null
@@ -1,9 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>uielements/tools.png</file>
- <file>images/settings16.png</file>
- <file>uielements/curves.png</file>
- <file>images/facetracknoir.png</file>
- <file>uielements/no-feed.png</file>
- </qresource>
-</RCC>
diff --git a/facetracknoir/main.cpp b/facetracknoir/main.cpp
index 7fb37864..9c2ced45 100644
--- a/facetracknoir/main.cpp
+++ b/facetracknoir/main.cpp
@@ -1,18 +1,14 @@
-#include "facetracknoir.h"
+#include "ui.h"
#include <QApplication>
#include <QStyleFactory>
#include <QStringList>
#include <memory>
-#ifndef _WIN32
-# include <unistd.h>
-#endif
-
int main(int argc, char** argv)
{
// workaround QTBUG-38598
QCoreApplication::addLibraryPath(".");
-
+
// qt5 designer-made controls look like shit on 'doze -sh 20140921
#ifdef _WIN32
{
@@ -28,18 +24,14 @@ int main(int argc, char** argv)
}
}
#endif
-
+
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
QApplication app(argc, argv);
-
- auto w = std::make_shared<FaceTrackNoIR>();
+
+ auto w = std::make_shared<MainWindow>();
w->show();
app.exec();
-
-#ifndef _WIN32
- _exit(0);
-#endif
-
+
return 0;
}
diff --git a/facetracknoir/main.ui b/facetracknoir/main.ui
new file mode 100644
index 00000000..ecf106be
--- /dev/null
+++ b/facetracknoir/main.ui
@@ -0,0 +1,1196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <author>Lovecraftian Octopus</author>
+ <class>OpentrackUI</class>
+ <widget class="QMainWindow" name="OpentrackUI">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>708</width>
+ <height>504</height>
+ </rect>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="ui-res.qrc">
+ <normaloff>:/images/facetracknoir.png</normaloff>:/images/facetracknoir.png</iconset>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">#video_feed { border: 0; }
+</string>
+ </property>
+ <widget class="QWidget" name="content">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="horizontalSpacing">
+ <number>0</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QFrame" name="video_feed">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>480</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>480</width>
+ <height>360</height>
+ </size>
+ </property>
+ <widget class="QFrame" name="video_frame">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>480</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QLabel" name="video_frame_label">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>480</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>480</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>480</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QFrame" name="top_display">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>12</number>
+ </property>
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>12</number>
+ </property>
+ <property name="rightMargin">
+ <number>8</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <item>
+ <widget class="GLWidget" name="pose_display" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>90</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="box_raw_headpose">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string notr="true">Raw tracker data</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_12">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>3</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QLCDNumber" name="raw_x">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Outline</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="lblRotX_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="lblRotZ_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblZ_4">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="lblRotY_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLCDNumber" name="raw_y">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Outline</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QLCDNumber" name="raw_yaw">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Outline</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QLCDNumber" name="raw_roll">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Outline</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLCDNumber" name="raw_z">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Outline</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="lblX_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLCDNumber" name="raw_pitch">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Outline</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblY_4">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="box_mapped_headpose">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string notr="true">Game data</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_14">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>3</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblY_2">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="lblRotY_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLCDNumber" name="pose_x">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="lblRotX_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="lblRotZ_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblZ_2">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLCDNumber" name="pose_y">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QLCDNumber" name="pose_roll">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QLCDNumber" name="pose_yaw">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLCDNumber" name="pose_z">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="lblx">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLCDNumber" name="pose_pitch">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>true</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QFrame" name="bottom_controls">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>6</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <item row="1" column="1">
+ <widget class="QGroupBox" name="groupStartStop">
+ <property name="title">
+ <string notr="true">Controls</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>12</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>12</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QToolButton" name="btnStopTracker">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QToolButton" name="btnStartTracker">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Start</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QGroupBox" name="groupWindows">
+ <property name="title">
+ <string>Settings</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_6">
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="btnShortcuts">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Keys</string>
+ </property>
+ <property name="icon">
+ <iconset resource="ui-res.qrc">
+ <normaloff>:/images/tools.png</normaloff>:/images/tools.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>80</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QPushButton" name="btnEditCurves">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Mapping</string>
+ </property>
+ <property name="icon">
+ <iconset resource="ui-res.qrc">
+ <normaloff>:/images/curves.png</normaloff>:/images/curves.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>80</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QGroupBox" name="groupFilter">
+ <property name="title">
+ <string>Filter</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="iconcomboFilter"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QToolButton" name="btnShowFilterControls">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="flat" stdset="0">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupTrackerSource">
+ <property name="title">
+ <string>Tracker</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="iconcomboTrackerSource"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QToolButton" name="btnShowEngineControls">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="flat" stdset="0">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QGroupBox" name="groupGameProtocol">
+ <property name="title">
+ <string>Protocol</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QToolButton" name="btnShowServerControls">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="flat" stdset="0">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="iconcomboProtocol"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupProfile">
+ <property name="title">
+ <string>Profile</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_7">
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>2</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="iconcomboProfile">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxVisibleItems">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QToolButton" name="btnLoad">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Load</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QToolButton" name="btnSave">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QToolButton" name="btnSaveAs">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Save...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>GLWidget</class>
+ <extends>QWidget</extends>
+ <header>glwidget.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>btnStartTracker</tabstop>
+ <tabstop>btnStopTracker</tabstop>
+ <tabstop>iconcomboTrackerSource</tabstop>
+ <tabstop>btnShowEngineControls</tabstop>
+ <tabstop>iconcomboProtocol</tabstop>
+ <tabstop>btnShowServerControls</tabstop>
+ <tabstop>iconcomboFilter</tabstop>
+ <tabstop>btnShowFilterControls</tabstop>
+ <tabstop>iconcomboProfile</tabstop>
+ <tabstop>btnLoad</tabstop>
+ <tabstop>btnSave</tabstop>
+ <tabstop>btnSaveAs</tabstop>
+ <tabstop>btnEditCurves</tabstop>
+ <tabstop>btnShortcuts</tabstop>
+ </tabstops>
+ <resources>
+ <include location="ui-res.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/facetracknoir/mapping.ui b/facetracknoir/mapping.ui
new file mode 100644
index 00000000..47e91daf
--- /dev/null
+++ b/facetracknoir/mapping.ui
@@ -0,0 +1,1142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UICCurveConfigurationDialog</class>
+ <widget class="QWidget" name="UICCurveConfigurationDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>970</width>
+ <height>664</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>970</width>
+ <height>664</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>970</width>
+ <height>664</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Mapping properties</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-color: #ccc;</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="tabPosition">
+ <enum>QTabWidget::North</enum>
+ </property>
+ <property name="currentIndex">
+ <number>6</number>
+ </property>
+ <widget class="QWidget" name="tabWidgetPage1">
+ <attribute name="title">
+ <string>Yaw</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QFunctionConfigurator" name="rxconfig" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="rx_altp">
+ <property name="text">
+ <string>Asymmetric mapping below</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFunctionConfigurator" name="rxconfig_alt" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage2">
+ <attribute name="title">
+ <string>Pitch</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QFunctionConfigurator" name="ryconfig" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="ry_altp">
+ <property name="text">
+ <string>Asymmetric mapping below</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFunctionConfigurator" name="ryconfig_alt" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage3">
+ <attribute name="title">
+ <string>Roll</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QFunctionConfigurator" name="rzconfig" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="rz_altp">
+ <property name="text">
+ <string>Asymmetric mapping below</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFunctionConfigurator" name="rzconfig_alt" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage4">
+ <attribute name="title">
+ <string>X</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QFunctionConfigurator" name="txconfig" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="tx_altp">
+ <property name="text">
+ <string>Asymmetric mapping below</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFunctionConfigurator" name="txconfig_alt" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage5">
+ <attribute name="title">
+ <string>Y</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QFunctionConfigurator" name="tyconfig" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="ty_altp">
+ <property name="text">
+ <string>Asymmetric mapping below</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFunctionConfigurator" name="tyconfig_alt" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage6">
+ <attribute name="title">
+ <string>Z</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QFunctionConfigurator" name="tzconfig" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="tz_altp">
+ <property name="text">
+ <string>Asymmetric mapping below</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFunctionConfigurator" name="tzconfig_alt" native="true">
+ <property name="colorBezier" stdset="0">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="colorBackground" stdset="0">
+ <color>
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabWidgetPage7">
+ <attribute name="title">
+ <string>Options</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Center pose</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1">
+ <widget class="QDoubleSpinBox" name="pos_rz">
+ <property name="suffix">
+ <string> deg.</string>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QDoubleSpinBox" name="pos_tz">
+ <property name="suffix">
+ <string> cm</string>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-100.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>100.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QDoubleSpinBox" name="pos_tx">
+ <property name="suffix">
+ <string> cm</string>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-100.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>100.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>RY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="pos_ry">
+ <property name="suffix">
+ <string> deg.</string>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>RZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QDoubleSpinBox" name="pos_ty">
+ <property name="suffix">
+ <string> cm</string>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-100.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>100.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>RX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QDoubleSpinBox" name="pos_rx">
+ <property name="suffix">
+ <string> deg.</string>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <kerning>true</kerning>
+ </font>
+ </property>
+ <property name="title">
+ <string>Output remap</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0" columnstretch="0">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinAndMaxSize</enum>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_20">
+ <property name="text">
+ <string>Assign input axis to output axis.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignVCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QFrame" name="frame_2">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="7" column="2">
+ <widget class="QCheckBox" name="invert_y">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>X</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>Invert</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="src_x">
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QComboBox" name="src_y">
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="src_yaw">
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QCheckBox" name="invert_roll">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="text">
+ <string>Destination</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QCheckBox" name="invert_pitch">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QCheckBox" name="invert_x">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_13">
+ <property name="text">
+ <string>Source</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="src_pitch">
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QCheckBox" name="invert_yaw">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="src_roll">
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QComboBox" name="src_z">
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="8" column="2">
+ <widget class="QCheckBox" name="invert_z">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ <zorder>label_15</zorder>
+ <zorder>label_13</zorder>
+ <zorder>label_14</zorder>
+ <zorder>src_yaw</zorder>
+ <zorder>invert_yaw</zorder>
+ <zorder>label_7</zorder>
+ <zorder>src_pitch</zorder>
+ <zorder>label_8</zorder>
+ <zorder>invert_pitch</zorder>
+ <zorder>label_9</zorder>
+ <zorder>src_roll</zorder>
+ <zorder>invert_roll</zorder>
+ <zorder>label_10</zorder>
+ <zorder>src_x</zorder>
+ <zorder>invert_x</zorder>
+ <zorder>label_11</zorder>
+ <zorder>src_y</zorder>
+ <zorder>invert_y</zorder>
+ <zorder>label_12</zorder>
+ <zorder>src_z</zorder>
+ <zorder>invert_z</zorder>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="title">
+ <string>Translation compensation</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="tcomp_enable">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Enable</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="tcomp_rz">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Disable Z axis compensation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>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.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignVCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Camera offset</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="3" column="0">
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_18">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="camera_yaw">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>-90</number>
+ </property>
+ <property name="maximum">
+ <number>90</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_19">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="camera_pitch">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>-90</number>
+ </property>
+ <property name="maximum">
+ <number>90</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_17">
+ <property name="text">
+ <string>Specify an angle for off-center camera as a basis for which direction is which, avoiding axis interconnect.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignVCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QFunctionConfigurator</class>
+ <extends>QWidget</extends>
+ <header>qfunctionconfigurator.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>pos_rx</tabstop>
+ <tabstop>pos_ry</tabstop>
+ <tabstop>pos_rz</tabstop>
+ <tabstop>ry_altp</tabstop>
+ <tabstop>rz_altp</tabstop>
+ <tabstop>tx_altp</tabstop>
+ <tabstop>ty_altp</tabstop>
+ <tabstop>tz_altp</tabstop>
+ <tabstop>tcomp_enable</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>pos_tx</tabstop>
+ <tabstop>buttonBox</tabstop>
+ <tabstop>pos_ty</tabstop>
+ <tabstop>rx_altp</tabstop>
+ <tabstop>pos_tz</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/facetracknoir/shortcut-dialog.cpp b/facetracknoir/shortcut-dialog.cpp
new file mode 100644
index 00000000..c157078e
--- /dev/null
+++ b/facetracknoir/shortcut-dialog.cpp
@@ -0,0 +1,47 @@
+#include "shortcut-dialog.hpp"
+
+KeyboardShortcutDialog::KeyboardShortcutDialog()
+{
+ ui.setupUi( this );
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ for ( int i = 0; i < global_key_sequences.size(); i++) {
+ ui.cbxCenterKey->addItem(global_key_sequences.at(i));
+ ui.cbxToggleKey->addItem(global_key_sequences.at(i));
+ ui.cbxZeroKey->addItem(global_key_sequences.at(i));
+ }
+
+ tie_setting(s.center.key_index, ui.cbxCenterKey);
+ tie_setting(s.center.alt, ui.chkCenterAlt);
+ tie_setting(s.center.shift, ui.chkCenterShift);
+ tie_setting(s.center.ctrl, ui.chkCenterCtrl);
+
+ tie_setting(s.toggle.key_index, ui.cbxToggleKey);
+ tie_setting(s.toggle.alt, ui.chkToggleAlt);
+ tie_setting(s.toggle.shift, ui.chkToggleShift);
+ tie_setting(s.toggle.ctrl, ui.chkToggleCtrl);
+
+ tie_setting(s.zero.key_index, ui.cbxZeroKey);
+ tie_setting(s.zero.alt, ui.chkZeroAlt);
+ tie_setting(s.zero.shift, ui.chkZeroShift);
+ tie_setting(s.zero.ctrl, ui.chkZeroCtrl);
+
+ tie_setting(s.s_main.tray_enabled, ui.trayp);
+
+ tie_setting(s.s_main.center_at_startup, ui.center_at_startup);
+}
+
+void KeyboardShortcutDialog::doOK() {
+ s.b->save();
+ s.s_main.b->save();
+ this->close();
+ emit reload();
+}
+
+void KeyboardShortcutDialog::doCancel() {
+ s.b->reload();
+ s.s_main.b->reload();
+ close();
+}
diff --git a/facetracknoir/shortcut-dialog.hpp b/facetracknoir/shortcut-dialog.hpp
new file mode 100644
index 00000000..2a364822
--- /dev/null
+++ b/facetracknoir/shortcut-dialog.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <QObject>
+#include <QWidget>
+#include "ui_keyboard.h"
+#include "opentrack/shortcuts.h"
+
+class KeyboardShortcutDialog: public QWidget
+{
+ Q_OBJECT
+signals:
+ void reload();
+public:
+ KeyboardShortcutDialog();
+private:
+ Ui::UICKeyboardShortcutDialog ui;
+ Shortcuts::settings s;
+private slots:
+ void doOK();
+ void doCancel();
+};
diff --git a/facetracknoir/ui-res.qrc b/facetracknoir/ui-res.qrc
new file mode 100644
index 00000000..030a6153
--- /dev/null
+++ b/facetracknoir/ui-res.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/tools.png</file>
+ <file>images/settings16.png</file>
+ <file>images/curves.png</file>
+ <file>images/facetracknoir.png</file>
+ <file>images/no-feed.png</file>
+ <file>images/filter-16.png</file>
+ </qresource>
+</RCC>
diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/ui.cpp
index 638bd543..54e4646e 100644
--- a/facetracknoir/facetracknoir.cpp
+++ b/facetracknoir/ui.cpp
@@ -1,42 +1,49 @@
-/********************************************************************************
-* 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) 2011 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage *
-* *
-* This program is free software; you can redistribute it and/or modify it *
-* under the terms of the GNU General Public License as published by the *
-* Free Software Foundation; either version 3 of the License, or (at your *
-* option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, but *
-* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
-* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
-* more details. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
+/*******************************************************************************
+* 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) 2011 Wim Vriend (Developing)
+* Ron Hendriks (Researching and Testing)
+*
+* Homepage
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 3 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
-#include "facetracknoir.h"
+#include "ui.h"
#include "opentrack/tracker.h"
+#include "opentrack/options.hpp"
#include <QFileDialog>
-FaceTrackNoIR::FaceTrackNoIR() :
+#ifndef _WIN32
+# include <unistd.h>
+#else
+# include <windows.h>
+#endif
+
+MainWindow::MainWindow() :
pose_update_timer(this),
kbd_quit(QKeySequence("Ctrl+Q"), this),
- no_feed_pixmap(":/uielements/no-feed.png")
+ no_feed_pixmap(":/images/no-feed.png")
{
ui.setupUi(this);
-
+
setFixedSize(size());
+
updateButtonState(false, false);
ui.video_frame_label->setPixmap(no_feed_pixmap);
- QDir::setCurrent(QCoreApplication::applicationDirPath());
-
+
connect(ui.btnLoad, SIGNAL(clicked()), this, SLOT(open()));
connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save()));
connect(ui.btnSaveAs, SIGNAL(clicked()), this, SLOT(saveAs()));
@@ -47,18 +54,17 @@ FaceTrackNoIR::FaceTrackNoIR() :
connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showProtocolSettings()));
connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterSettings()));
- modules.filters().push_back(std::make_shared<dylib>("", dylib::Filter));
- ui.iconcomboFilter->addItem(QIcon(), "");
-
+ modules.filters().push_front(std::make_shared<dylib>("", 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);
-
+
fill_profile_combobox();
tie_setting(s.tracker_dll, ui.iconcomboTrackerSource);
@@ -68,40 +74,50 @@ FaceTrackNoIR::FaceTrackNoIR() :
connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker()));
connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker()));
connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int)));
-
+
connect(&pose_update_timer, SIGNAL(timeout()), this, SLOT(showHeadPose()));
connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit()));
kbd_quit.setEnabled(true);
+
+ ensure_tray();
}
-FaceTrackNoIR::~FaceTrackNoIR()
+MainWindow::~MainWindow()
{
+ if (tray)
+ tray->hide();
stopTracker();
save();
+ _exit(0);
}
-void FaceTrackNoIR::open() {
- QFileDialog dialog(this);
- dialog.setFileMode(QFileDialog::ExistingFile);
-
- QString fileName = dialog.getOpenFileName(
- this,
- tr("Open the settings file"),
- QCoreApplication::applicationDirPath() + "/settings/",
- tr("Settings file (*.ini);;All Files (*)"),
- NULL);
+void MainWindow::set_working_directory()
+{
+ QDir::setCurrent(QCoreApplication::applicationDirPath());
+}
+void MainWindow::open() {
+ QFileDialog dialog(this);
+ dialog.setFileMode(QFileDialog::ExistingFile);
+ QString dir_path = QFileInfo(group::ini_pathname()).absolutePath();
+ QString fileName = dialog.getOpenFileName(
+ this,
+ tr("Open the settings file"),
+ dir_path,
+ tr("Settings file (*.ini);;All Files (*)"));
+ set_working_directory();
+
if (! fileName.isEmpty() ) {
{
- QSettings settings("opentrack");
- settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath());
+ QSettings settings(group::org);
+ settings.setValue(group::filename_key, remove_app_path(fileName));
}
fill_profile_combobox();
load_settings();
}
}
-void FaceTrackNoIR::save_mappings() {
+void MainWindow::save_mappings() {
pose.save_mappings();
}
@@ -109,13 +125,13 @@ void FaceTrackNoIR::save_mappings() {
# include <unistd.h>
#endif
-void FaceTrackNoIR::save() {
- b->save();
+void MainWindow::save() {
+ s.b->save();
save_mappings();
+ mem<QSettings> settings = group::ini_file();
+ settings->sync();
#if defined(__unix) || defined(__linux)
- QSettings settings("opentrack");
- const QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
QByteArray bytes = QFile::encodeName(currentFile);
const char* filename_as_asciiz = bytes.constData();
@@ -126,51 +142,43 @@ void FaceTrackNoIR::save() {
#endif
}
-void FaceTrackNoIR::saveAs()
+void MainWindow::saveAs()
{
- QSettings settings("opentrack");
- QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
-
+ QString oldFile = group::ini_pathname();
QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"),
oldFile,
tr("Settings file (*.ini);;All Files (*)"));
- if (!fileName.isEmpty()) {
-
- QFileInfo newFileInfo ( fileName );
- if ((newFileInfo.exists()) && (oldFile != fileName)) {
- QFile newFileFile ( fileName );
- newFileFile.remove();
- }
-
- QFileInfo oldFileInfo ( oldFile );
- if (oldFileInfo.exists()) {
- QFile oldFileFile ( oldFile );
- oldFileFile.copy( fileName );
- }
-
- settings.setValue ("SettingsFile", fileName);
- save();
+ set_working_directory();
+
+ if (fileName.isEmpty())
+ return;
+
+ (void) QFile::remove(fileName);
+
+ {
+ (void) QFile::copy(oldFile, fileName);
+ QSettings settings(group::org);
+ settings.setValue (group::filename_key, remove_app_path(fileName));
}
-
+
+ save();
fill_profile_combobox();
}
-void FaceTrackNoIR::load_mappings() {
+void MainWindow::load_mappings() {
pose.load_mappings();
}
-void FaceTrackNoIR::load_settings() {
- b->reload();
+void MainWindow::load_settings() {
+ s.b->reload();
load_mappings();
}
extern "C" volatile const char* opentrack_version;
-void FaceTrackNoIR::fill_profile_combobox()
+void MainWindow::fill_profile_combobox()
{
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath()
- + "/settings/default.ini" ).toString();
+ QString currentFile = group::ini_pathname();
qDebug() << "Config file now" << currentFile;
QFileInfo pathInfo ( currentFile );
setWindowTitle(QString( const_cast<const char*>(opentrack_version) + QStringLiteral(" :: ")) + pathInfo.fileName());
@@ -182,7 +190,7 @@ void FaceTrackNoIR::fill_profile_combobox()
ui.iconcomboProfile->setCurrentText(pathInfo.fileName());
}
-void FaceTrackNoIR::updateButtonState(bool running, bool inertialp)
+void MainWindow::updateButtonState(bool running, bool inertialp)
{
bool not_running = !running;
ui.iconcomboProfile->setEnabled ( not_running );
@@ -191,28 +199,29 @@ void FaceTrackNoIR::updateButtonState(bool running, bool inertialp)
ui.iconcomboProtocol->setEnabled ( not_running );
ui.iconcomboFilter->setEnabled ( not_running );
ui.iconcomboTrackerSource->setEnabled(not_running);
- ui.btnStartTracker->setEnabled(not_running);
- ui.btnStopTracker->setEnabled(running);
ui.video_frame_label->setVisible(not_running || inertialp);
+ ui.btnSaveAs->setEnabled(not_running);
+ ui.btnLoad->setEnabled(not_running);
}
-void FaceTrackNoIR::bindKeyboardShortcuts()
+void MainWindow::bindKeyboardShortcuts()
{
if (work)
work->reload_shortcuts();
+ ensure_tray();
}
-void FaceTrackNoIR::startTracker( ) {
- b->save();
+void MainWindow::startTracker( ) {
+ s.b->save();
load_settings();
bindKeyboardShortcuts();
-
+
// tracker dtor needs run first
work = nullptr;
-
+
libs = SelectedLibraries(ui.video_frame, current_tracker(), current_protocol(), current_filter());
work = std::make_shared<Work>(s, pose, libs, this, winId());
-
+
{
double p[6] = {0,0,0, 0,0,0};
display_pose(p, p);
@@ -226,8 +235,16 @@ void FaceTrackNoIR::startTracker( ) {
QMessageBox::NoButton);
return;
}
-
- ui.video_frame->show();
+
+ 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
@@ -236,33 +253,33 @@ void FaceTrackNoIR::startTracker( ) {
updateButtonState(true, is_inertial);
}
-void FaceTrackNoIR::stopTracker( ) {
- ui.game_name->setText("Not connected");
+void MainWindow::stopTracker( ) {
+ //ui.game_name->setText("Not connected");
pose_update_timer.stop();
ui.pose_display->rotateBy(0, 0, 0);
-
+
if (pTrackerDialog)
{
pTrackerDialog->unregister_tracker();
pTrackerDialog = nullptr;
}
-
+
if (pProtocolDialog)
{
pProtocolDialog->unregister_protocol();
pProtocolDialog = nullptr;
}
-
+
if (pFilterDialog)
{
pFilterDialog->unregister_filter();
pFilterDialog = nullptr;
}
-
+
work = nullptr;
libs = SelectedLibraries();
-
+
{
double p[6] = {0,0,0, 0,0,0};
display_pose(p, p);
@@ -270,37 +287,37 @@ void FaceTrackNoIR::stopTracker( ) {
updateButtonState(false, false);
}
-void FaceTrackNoIR::display_pose(const double *mapped, const double *raw)
+void MainWindow::display_pose(const double *mapped, const double *raw)
{
- ui.pose_display->rotateBy(mapped[Yaw], mapped[Roll], mapped[Pitch]);
+ ui.pose_display->rotateBy(mapped[Yaw], mapped[Pitch], mapped[Roll]);
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.lcdNumX->display(raw_[TX]);
- ui.lcdNumY->display(raw_[TY]);
- ui.lcdNumZ->display(raw_[TZ]);
- ui.lcdNumRotX->display(raw_[Yaw]);
- ui.lcdNumRotY->display(raw_[Pitch]);
- ui.lcdNumRotZ->display(raw_[Roll]);
-
- ui.lcdNumOutputPosX->display(mapped_[TX]);
- ui.lcdNumOutputPosY->display(mapped_[TY]);
- ui.lcdNumOutputPosZ->display(mapped_[TZ]);
- ui.lcdNumOutputRotX->display(mapped_[Yaw]);
- ui.lcdNumOutputRotY->display(mapped_[Pitch]);
- ui.lcdNumOutputRotZ->display(mapped_[Roll]);
+ 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]);
}
-void FaceTrackNoIR::showHeadPose()
+void MainWindow::showHeadPose()
{
double mapped[6], raw[6];
@@ -308,96 +325,163 @@ void FaceTrackNoIR::showHeadPose()
display_pose(mapped, raw);
+#if 0
if (libs.pProtocol)
{
const QString name = libs.pProtocol->game_name();
ui.game_name->setText(name);
}
+#endif
}
template<typename t>
-ptr<t> mk_dialog(ptr<dylib> lib)
-{
- if (lib)
+mem<t> mk_dialog(mem<dylib> lib)
+{
+ if (lib && lib->Dialog)
{
- auto dialog = ptr<t>(reinterpret_cast<t*>(lib->Dialog()));
+ auto dialog = mem<t>(reinterpret_cast<t*>(lib->Dialog()));
dialog->setWindowFlags(Qt::Dialog);
dialog->setFixedSize(dialog->size());
return dialog;
}
-
+
return nullptr;
}
-void FaceTrackNoIR::showTrackerSettings()
+void MainWindow::showTrackerSettings()
{
- int idx = ui.iconcomboTrackerSource->currentIndex();
- auto dialog = mk_dialog<ITrackerDialog>(modules.trackers().value(idx, nullptr));
-
+ auto dialog = mk_dialog<ITrackerDialog>(current_tracker());
+
if (dialog) {
pTrackerDialog = dialog;
- dialog->register_tracker(libs.pTracker.get());
+ if (libs.pTracker != nullptr)
+ dialog->register_tracker(libs.pTracker.get());
dialog->show();
}
}
-void FaceTrackNoIR::showProtocolSettings() {
- int idx = ui.iconcomboProtocol->currentIndex();
- auto dialog = mk_dialog<IProtocolDialog>(modules.protocols().value(idx, nullptr));
-
+void MainWindow::showProtocolSettings() {
+ auto dialog = mk_dialog<IProtocolDialog>(current_protocol());
+
if (dialog) {
pProtocolDialog = dialog;
+ if (libs.pProtocol != nullptr)
+ dialog->register_protocol(libs.pProtocol.get());
dialog->show();
}
}
-void FaceTrackNoIR::showFilterSettings() {
- int idx = ui.iconcomboFilter->currentIndex();
- auto dialog = mk_dialog<IFilterDialog>(modules.filters().value(idx, nullptr));
-
- if (dialog) {
+void MainWindow::showFilterSettings() {
+ auto dialog = mk_dialog<IFilterDialog>(current_filter());
+
+ if (dialog)
+ {
pFilterDialog = dialog;
- dialog->register_filter(libs.pFilter.get());
+ if (libs.pFilter != nullptr)
+ dialog->register_filter(libs.pFilter.get());
dialog->show();
}
}
-void FaceTrackNoIR::showKeyboardShortcuts() {
+void MainWindow::showKeyboardShortcuts() {
shortcuts_widget = std::make_shared<KeyboardShortcutDialog>();
shortcuts_widget->setWindowFlags(Qt::Dialog);
connect(shortcuts_widget.get(), SIGNAL(reload()), this, SLOT(bindKeyboardShortcuts()));
shortcuts_widget->show();
}
-void FaceTrackNoIR::showCurveConfiguration() {
+void MainWindow::showCurveConfiguration() {
mapping_widget = std::make_shared<MapWidget>(pose, s);
mapping_widget->setWindowFlags(Qt::Dialog);
mapping_widget->show();
}
-void FaceTrackNoIR::exit() {
+void MainWindow::exit() {
QCoreApplication::exit(0);
}
-void FaceTrackNoIR::profileSelected(int index)
+QString MainWindow::remove_app_path(const QString full_path)
{
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- QFileInfo pathInfo ( currentFile );
- settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + ui.iconcomboProfile->itemText(index));
+ QFileInfo path_info(full_path);
+ QString path = path_info.absolutePath();
+
+ QFileInfo app_path(QCoreApplication::applicationDirPath());
+ QString app_prefix(app_path.absoluteFilePath());
+
+ if (path == app_prefix)
+ {
+ path = ".";
+ }
+ else if (path.startsWith(app_prefix + "/"))
+ {
+ path = "./" + path.mid(app_prefix.size() + 1);
+ }
+
+ return path + "/" + path_info.fileName();
+}
+
+void MainWindow::profileSelected(int index)
+{
+ if (index == -1)
+ return;
+
+ {
+ QSettings settings(group::org);
+ settings.setValue (group::filename_key, remove_app_path(QFileInfo(group::ini_pathname()).absolutePath() + "/" +
+ ui.iconcomboProfile->itemText(index)));
+ }
load_settings();
}
-void FaceTrackNoIR::shortcutRecentered()
+void MainWindow::shortcutRecentered()
{
qDebug() << "Center";
if (work)
work->tracker->center();
}
-void FaceTrackNoIR::shortcutToggled()
+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<QSystemTrayIcon>(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);
+}
diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/ui.h
index e3a438e4..cc7af1bf 100644
--- a/facetracknoir/facetracknoir.h
+++ b/facetracknoir/ui.h
@@ -1,25 +1,25 @@
-/********************************************************************************
-* 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 *
-* *
-* This program is free software; you can redistribute it and/or modify it *
-* under the terms of the GNU General Public License as published by the *
-* Free Software Foundation; either version 3 of the License, or (at your *
-* option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, but *
-* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
-* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
-* more details. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
+/*******************************************************************************
+* MainWindow 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
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 3 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
@@ -36,13 +36,15 @@
#include <QPixmap>
#include <QLabel>
#include <QTimer>
+#include <QSystemTrayIcon>
+
#if !defined(_WIN32)
-# include "qxt-mini/QxtGlobalShortcut"
+# include "qxt-mini/QxtGlobalShortcut"
#else
-# include <windows.h>
+# include <windows.h>
#endif
-#include "ui_facetracknoir.h"
+#include "ui_main.h"
#include "opentrack/options.hpp"
#include "opentrack/main-settings.hpp"
@@ -52,46 +54,52 @@
#include "opentrack/work.hpp"
#include "opentrack/state.hpp"
#include "curve-config.h"
+#include "shortcut-dialog.hpp"
using namespace options;
-class FaceTrackNoIR : public QMainWindow, private State
+class MainWindow : public QMainWindow, private State
{
Q_OBJECT
-
+
Ui::OpentrackUI ui;
-
+ mem<QSystemTrayIcon> tray;
QTimer pose_update_timer;
- ptr<KeyboardShortcutDialog> shortcuts_widget;
- ptr<MapWidget> mapping_widget;
+ mem<KeyboardShortcutDialog> shortcuts_widget;
+ mem<MapWidget> mapping_widget;
QShortcut kbd_quit;
QPixmap no_feed_pixmap;
- ptr<IFilterDialog> pFilterDialog;
- ptr<IProtocolDialog> pProtocolDialog;
- ptr<ITrackerDialog> pTrackerDialog;
-
- ptr<dylib> current_tracker()
+ mem<IFilterDialog> pFilterDialog;
+ mem<IProtocolDialog> pProtocolDialog;
+ mem<ITrackerDialog> pTrackerDialog;
+
+ mem<dylib> current_tracker()
{
return modules.trackers().value(ui.iconcomboTrackerSource->currentIndex(), nullptr);
}
- ptr<dylib> current_protocol()
+ mem<dylib> current_protocol()
{
return modules.protocols().value(ui.iconcomboProtocol->currentIndex(), nullptr);
}
- ptr<dylib> current_filter()
+ mem<dylib> current_filter()
{
return modules.filters().value(ui.iconcomboFilter->currentIndex(), nullptr);
}
+ void changeEvent(QEvent* e) override;
+
void createIconGroupBox();
void load_settings();
void updateButtonState(bool running, bool inertialp);
void fill_profile_combobox();
void display_pose(const double* mapped, const double* raw);
-
+ void ensure_tray();
+ void set_working_directory();
+ QString remove_app_path(const QString full_path);
public slots:
void shortcutRecentered();
void shortcutToggled();
+ void shortcutZeroed();
void bindKeyboardShortcuts();
private slots:
void open();
@@ -109,9 +117,11 @@ private slots:
void startTracker();
void stopTracker();
+
+ void restore_from_tray(QSystemTrayIcon::ActivationReason);
public:
- FaceTrackNoIR();
- ~FaceTrackNoIR();
+ MainWindow();
+ ~MainWindow();
void save_mappings();
void load_mappings();
};
diff --git a/facetracknoir/uielements/no-feed.png b/facetracknoir/uielements/no-feed.png
deleted file mode 100644
index 6494e9c6..00000000
--- a/facetracknoir/uielements/no-feed.png
+++ /dev/null
Binary files differ
diff --git a/freetrackclient/build-msvc.sh b/freetrackclient/build-msvc.sh
deleted file mode 100644
index 4fd303a0..00000000
--- a/freetrackclient/build-msvc.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-export PATH="/bin:/usr/bin:$PATH"
-
-case "$(uname -s 2>/dev/null)" in
-*CYG*|*MING*|'') wrap= ;;
-*) wrap=wine ;;
-esac
-
-c_src=".\\freetrackclient.c"
-c_bin="..\\facetracknoir\\clientfiles\\freetrackclient.dll"
-opt_link="-nologo -LTCG -SAFESEH:NO -OPT:REF,ICF"
-opt_cl="
--nologo -arch:SSE2 -fp:fast -EHc -EH- -GL -GR- -GS- -Gw -LD -MT -O1
--Ob2 -Og -Oi -Ot -Oy -QIfist -volatile:iso -Ze -Fe\"${c_bin}\"
-"
-
-MSVC="VS140COMNTOOLS"
-
-test -z "$MSVC" && {
- echo "uh-oh, no MSVC" >&2
- exit 1
-}
-
-sep="\&"
-
-cd "$(dirname "$0")"
-
-$wrap cmd.exe /C $(echo "
- del /F /Q $c_bin $sep
- call %${MSVC}%/vsvars32.bat 2>nul >nul $sep
- cl $opt_cl $c_src -link $opt_link
- " | tr '\n' ' ')
diff --git a/freetrackclient/freetrackclient.c b/freetrackclient/freetrackclient.c
index 4bc39d67..8e6c2b7f 100644
--- a/freetrackclient/freetrackclient.c
+++ b/freetrackclient/freetrackclient.c
@@ -27,13 +27,12 @@
#define NP_AXIS_MAX 16383
-#include <stdbool.h>
#include <string.h>
#include <windows.h>
-#include "../ftnoir_protocol_ft/fttypes.h"
+#include "fttypes.h"
-#define FT_EXPORT(t) __declspec(dllexport) t __stdcall
+#define FT_EXPORT(t) t __stdcall
#if 0
# include <stdio.h>
@@ -49,10 +48,10 @@ static HANDLE ipc_mutex = 0;
static const char* dllVersion = "1.0.0.0";
static const char* dllProvider = "FreeTrack";
-static bool impl_create_mapping(void)
+static BOOL impl_create_mapping(void)
{
if (ipc_heap != NULL)
- return true;
+ return TRUE;
hFTMemMap = CreateFileMappingA(INVALID_HANDLE_VALUE,
NULL,
@@ -62,29 +61,26 @@ static bool impl_create_mapping(void)
(LPCSTR) FREETRACK_HEAP);
if (hFTMemMap == NULL)
- return (ipc_heap = NULL), false;
+ return (ipc_heap = NULL), FALSE;
ipc_heap = (FTHeap*) MapViewOfFile(hFTMemMap, FILE_MAP_WRITE, 0, 0, sizeof(FTHeap));
- ipc_mutex = CreateMutexA(NULL, false, FREETRACK_MUTEX);
+ ipc_mutex = CreateMutexA(NULL, FALSE, FREETRACK_MUTEX);
- return true;
+ return TRUE;
}
-#pragma comment (linker, "/export:FTGetData")
-FT_EXPORT(bool) FTGetData(FTData* data)
+FT_EXPORT(BOOL) FTGetData(FTData* data)
{
- if (impl_create_mapping() == false)
- return false;
+ if (impl_create_mapping() == FALSE)
+ return FALSE;
if (ipc_mutex && WaitForSingleObject(ipc_mutex, 16) == WAIT_OBJECT_0) {
- if (ipc_heap) {
- if (ipc_heap->data.DataID > (1 << 29))
- ipc_heap->data.DataID = 0;
- data->DataID = ipc_heap->data.DataID;
- }
+ memcpy(data, &ipc_heap->data, sizeof(FTData));
+ if (ipc_heap->data.DataID > (1 << 29))
+ ipc_heap->data.DataID = 0;
ReleaseMutex(ipc_mutex);
}
- return true;
+ return TRUE;
}
/*
@@ -92,23 +88,24 @@ FT_EXPORT(bool) FTGetData(FTData* data)
// The Delphi-code from the FreeTrack repo suggest a char * as argument, so it cost me an afternoon to figure it out (and keep ArmA2 from crashing).
// Thanks guys!
*/
-#pragma comment (linker, "/export:FTReportName")
FT_EXPORT(void) FTReportName( int name )
{
dbg_report("FTReportName request (ID = %d).\n", name);
}
-#pragma comment (linker, "/export:FTGetDllVersion")
FT_EXPORT(const char*) FTGetDllVersion(void)
{
dbg_report("FTGetDllVersion request.\n");
return dllVersion;
}
-#pragma comment (linker, "/export:FTProvider")
FT_EXPORT(const char*) FTProvider(void)
{
dbg_report("FTProvider request.\n");
return dllProvider;
}
+#pragma comment (linker, "/export:FTReportName=_FTReportName@4")
+#pragma comment (linker, "/export:FTGetDllVersion=_FTGetDllVersion@0")
+#pragma comment (linker, "/export:FTProvider=_FTProvider@0")
+#pragma comment (linker, "/export:FTGetData=_FTGetData@4")
diff --git a/ftnoir_protocol_ft/fttypes.h b/freetrackclient/fttypes.h
index f41350c8..ad974110 100644
--- a/ftnoir_protocol_ft/fttypes.h
+++ b/freetrackclient/fttypes.h
@@ -23,6 +23,7 @@
# include <inttypes.h>
#else
typedef unsigned __int32 uint32_t;
+typedef __int32 int32_t;
#endif
#define FREETRACK_HEAP "FT_SharedMem"
diff --git a/ftnoir_filter_accela/accela-filter.qrc b/ftnoir_filter_accela/accela-filter.qrc
deleted file mode 100644
index 9a7d75fa..00000000
--- a/ftnoir_filter_accela/accela-filter.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>images/filter-16-ac.png</file>
- </qresource>
-</RCC>
diff --git a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui
index c544263d..6895cb8d 100644
--- a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui
+++ b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui
@@ -9,279 +9,155 @@
<rect>
<x>0</x>
<y>0</y>
- <width>261</width>
- <height>330</height>
+ <width>501</width>
+ <height>302</height>
</rect>
</property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>6667</width>
- <height>6666</height>
- </size>
- </property>
<property name="windowTitle">
<string>Accela filter settings</string>
</property>
<property name="windowIcon">
- <iconset resource="../ftnoir_filter_ewma2/ewma-filter.qrc">
+ <iconset resource="../facetracknoir/ui-res.qrc">
<normaloff>:/images/filter-16.png</normaloff>:/images/filter-16.png</iconset>
</property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
<layout class="QGridLayout" name="gridLayout">
- <property name="bottomMargin">
- <number>5</number>
- </property>
- <property name="horizontalSpacing">
- <number>7</number>
- </property>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Translation</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="rotation_alpha">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="correctionMode">
- <enum>QAbstractSpinBox::CorrectToPreviousValue</enum>
- </property>
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>0.100000000000000</double>
- </property>
- <property name="maximum">
- <double>65535.000000000000000</double>
- </property>
- <property name="value">
- <double>1.000000000000000</double>
- </property>
- </widget>
- </item>
<item row="0" column="0">
- <widget class="QLabel" name="label_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Rotation</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>Exponent</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_12">
- <property name="text">
- <string>Order #3</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QDoubleSpinBox" name="translation_alpha">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>0.100000000000000</double>
- </property>
- <property name="maximum">
- <double>65535.000000000000000</double>
- </property>
- <property name="value">
- <double>1.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Order #2</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QDoubleSpinBox" name="rot_deadzone">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>0.000000000000000</double>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.050000000000000</double>
- </property>
- <property name="value">
- <double>0.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="lblSensYaw_6">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>25</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>150</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#0;
-background:none;</string>
- </property>
- <property name="text">
- <string>Rotation deadband</string>
- </property>
- </widget>
- </item>
- <item row="8" column="0" colspan="2">
- <widget class="QLabel" name="label_9">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="font">
- <font>
- <pointsize>7</pointsize>
- </font>
- </property>
+ <widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
- <property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;Accela by &lt;a href=&quot;https://github.com/sthalik&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;Stanisław Halik&lt;/span&gt;&lt;/a&gt;&lt;br/&gt;Help from &lt;a href=&quot;https://github.com/dbaarda&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;Donovan Baarda&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;2012-2013&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- <property name="scaledContents">
- <bool>false</bool>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <property name="indent">
- <number>0</number>
- </property>
- <property name="openExternalLinks">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="7" column="1">
- <widget class="QDoubleSpinBox" name="expt">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>0.050000000000000</double>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.050000000000000</double>
- </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="3" column="3">
+ <widget class="QSlider" name="translation_slider">
+ <property name="maximum">
+ <number>99</number>
+ </property>
+ <property name="pageStep">
+ <number>5</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QSlider" name="rotation_slider">
+ <property name="maximum">
+ <number>99</number>
+ </property>
+ <property name="pageStep">
+ <number>5</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Translation sensitivity</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblSensYaw_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">color:#0;
+background:none;</string>
+ </property>
+ <property name="text">
+ <string>Rotation sensitivity</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="ewma_label">
+ <property name="minimumSize">
+ <size>
+ <width>32</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0 ms</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="rot_gain">
+ <property name="text">
+ <string>0°</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Smoothing</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="trans_gain">
+ <property name="text">
+ <string>0mm</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QSlider" name="ewma_slider">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>25</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>25</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="9" column="0" colspan="2">
+ <item row="3" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
@@ -294,111 +170,77 @@ background:none;</string>
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QDoubleSpinBox" name="order_3rd">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="correctionMode">
- <enum>QAbstractSpinBox::CorrectToPreviousValue</enum>
- </property>
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>0.100000000000000</double>
- </property>
- <property name="maximum">
- <double>65535.000000000000000</double>
- </property>
- <property name="value">
- <double>1.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QDoubleSpinBox" name="order_2nd">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="correctionMode">
- <enum>QAbstractSpinBox::CorrectToPreviousValue</enum>
- </property>
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>0.100000000000000</double>
- </property>
- <property name="maximum">
- <double>65535.000000000000000</double>
- </property>
- <property name="value">
- <double>1.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Translation deadband</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QDoubleSpinBox" name="trans_deadzone">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="decimals">
- <number>3</number>
- </property>
- <property name="minimum">
- <double>0.000000000000000</double>
- </property>
- <property name="maximum">
- <double>100.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.050000000000000</double>
- </property>
- <property name="value">
- <double>0.000000000000000</double>
- </property>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>GroupBox</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>7</pointsize>
+ </font>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Accela by &lt;/span&gt;&lt;a href=&quot;https://github.com/sthalik&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0057ae;&quot;&gt;Stanisław Halik&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;Thanks to &lt;/span&gt;&lt;a href=&quot;https://github.com/dbaarda&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0057ae;&quot;&gt;Donovan Baarda&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;2012-2015&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="indent">
+ <number>0</number>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Visit &lt;a href=&quot;https://github.com/opentrack/opentrack/wiki/Accela-in-opentrack-2.3&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;our wiki&lt;/span&gt;&lt;/a&gt; for description of the settings.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
- <tabstop>rotation_alpha</tabstop>
- <tabstop>translation_alpha</tabstop>
- <tabstop>order_2nd</tabstop>
- <tabstop>order_3rd</tabstop>
- <tabstop>rot_deadzone</tabstop>
- <tabstop>trans_deadzone</tabstop>
- <tabstop>expt</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
- <include location="../ftnoir_filter_ewma2/ewma-filter.qrc"/>
+ <include location="../facetracknoir/ui-res.qrc"/>
</resources>
<connections/>
<slots>
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.cpp b/ftnoir_filter_accela/ftnoir_filter_accela.cpp
index 37bd8891..dc754b69 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela.cpp
+++ b/ftnoir_filter_accela/ftnoir_filter_accela.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013 Stanislaw Halik
+/* 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
@@ -16,52 +16,66 @@ FTNoIR_Filter::FTNoIR_Filter() : first_run(true)
{
}
-static inline double parabola(const double a, const double x, const double dz, const double expt)
+double FTNoIR_Filter::f(double vec, double thres)
{
- const double sign = x > 0 ? 1 : -1;
- const double a1 = 1./a;
- return a1 * pow(std::max<double>(fabs(x) - dz, 0), expt) * sign;
+ if (vec > thres*high_thres_c)
+ return (vec - thres*high_thres_c) * high_thres_out + thres*high_thres_c;
+ if (vec > thres)
+ return (vec - thres) * low_thres_mult + thres;
+ return pow(vec, 2.0) / thres;
}
-void FTNoIR_Filter::filter(const double* target_camera_position,
- double *new_camera_position)
+void FTNoIR_Filter::filter(const double* input, double *output)
{
- if (first_run)
- {
+ if (first_run)
+ {
for (int i = 0; i < 6; i++)
{
- new_camera_position[i] = target_camera_position[i];
- for (int j = 0; j < 3; j++)
- last_output[j][i] = target_camera_position[i];
+ output[i] = input[i];
+ last_output[i] = input[i];
+ smoothed_input[i] = input[i];
}
-
first_run = false;
- return;
- }
+ t.start();
+ return;
+ }
+
+ const double rot_t = 7. * (1+s.rot_threshold) / 100.;
+ const double trans_t = 5. * (1+s.trans_threshold) / 100.;
+
+ const double dt = t.elapsed() * 1e-9;
+ t.start();
- for (int i=0;i<6;i++)
- {
- const double vec = target_camera_position[i] - last_output[0][i];
- const double vec2 = target_camera_position[i] - last_output[1][i];
- const double vec3 = target_camera_position[i] - last_output[2][i];
- const int sign = vec < 0 ? -1 : 1;
- const double a = i >= 3 ? s.rotation_alpha : s.translation_alpha;
- const double a2 = a * s.second_order_alpha;
- const double a3 = a * s.third_order_alpha;
- const double deadzone = i >= 3 ? s.rot_deadzone : s.trans_deadzone;
- const double velocity =
- parabola(a, vec, deadzone, s.expt) +
- parabola(a2, vec2, deadzone, s.expt) +
- parabola(a3, vec3, deadzone, s.expt);
- const double result = last_output[0][i] + velocity;
- const bool done = sign > 0 ? result >= target_camera_position[i] : result <= target_camera_position[i];
- last_output[2][i] = last_output[1][i];
- last_output[1][i] = last_output[0][i];
- last_output[0][i] = new_camera_position[i] = done ? target_camera_position[i] : result;
- }
+ const double RC = 2 * s.ewma / 1000.; // seconds
+ const double alpha = dt/(dt+RC);
+
+ for (int i = 0; i < 6; i++)
+ {
+ 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 vec_ = fabs(vec);
+ const double t = i >= 3 ? rot_t : trans_t;
+ const double val = f(vec_, t);
+ const double result = last_output[i] + (vec < 0 ? -1 : 1) * dt * val;
+ const bool negp = vec < 0.;
+ const bool done = negp
+ ? result <= in
+ : result >= in;
+ const double ret = done ? in : result;
+
+ last_output[i] = output[i] = ret;
+ }
}
extern "C" OPENTRACK_EXPORT IFilter* GetConstructor()
{
return new FTNoIR_Filter;
}
+
+extern "C" OPENTRACK_EXPORT Metadata* GetMetadata()
+{
+ return new FTNoIR_FilterDll;
+}
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.h b/ftnoir_filter_accela/ftnoir_filter_accela.h
index b5d0995c..98e5cf1f 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela.h
+++ b/ftnoir_filter_accela/ftnoir_filter_accela.h
@@ -1,53 +1,42 @@
#pragma once
#include "ui_ftnoir_accela_filtercontrols.h"
#include "opentrack/plugin-api.hpp"
+#include <atomic>
#include <QMutex>
-
-#define ACCELA_SMOOTHING_ROTATION 60.0
-#define ACCELA_SMOOTHING_TRANSLATION 40.0
-#define ACCELA_SECOND_ORDER_ALPHA 100.0
-#define ACCELA_THIRD_ORDER_ALPHA 180.0
+#include <QTimer>
#include "opentrack/options.hpp"
using namespace options;
+#include "opentrack/timer.hpp"
struct settings {
pbundle b;
- value<double> rotation_alpha,
- translation_alpha,
- second_order_alpha,
- third_order_alpha,
- rot_deadzone,
- trans_deadzone,
- expt;
+ value<int> rot_threshold, trans_threshold, ewma;
settings() :
b(bundle("Accela")),
- rotation_alpha(b, "rotation-alpha", ACCELA_SMOOTHING_ROTATION),
- translation_alpha(b, "translation-alpha", ACCELA_SMOOTHING_TRANSLATION),
- second_order_alpha(b, "second-order-alpha", ACCELA_SECOND_ORDER_ALPHA),
- third_order_alpha(b, "third-order-alpha", ACCELA_THIRD_ORDER_ALPHA),
- rot_deadzone(b, "rotation-deadband", 0),
- trans_deadzone(b, "translation-deadband", 0),
- expt(b, "exponent", 2)
+ rot_threshold(b, "rotation-threshold", 30),
+ trans_threshold(b, "translation-threshold", 50),
+ ewma(b, "ewma", 2)
{}
};
class FTNoIR_Filter : public IFilter
{
public:
- FTNoIR_Filter();
- void filter(const double* target_camera_position, double *new_camera_position);
- void reset() {
- first_run = true;
- }
- void receiveSettings() {
- s.b->reload();
- }
-
+ FTNoIR_Filter();
+ void filter(const double* input, double *output);
private:
settings s;
- bool first_run;
- double last_output[3][6];
+ bool first_run;
+ double last_output[6];
+ double smoothed_input[6];
+ Timer t;
+ static double f(double vec, double thres);
+
+ static constexpr double high_thres_c = 4;
+ static constexpr double high_thres_out = 500;
+
+ static constexpr double low_thres_mult = 100;
};
class FilterControls: public IFilterDialog
@@ -60,17 +49,20 @@ public:
private:
Ui::AccelaUICFilterControls ui;
void discard();
- void save();
+ void save();
FTNoIR_Filter* accela_filter;
settings s;
private slots:
- void doOK();
- void doCancel();
+ void doOK();
+ void doCancel();
+ void update_ewma_display(int value);
+ void update_rot_display(int value);
+ void update_trans_display(int value);
};
class FTNoIR_FilterDll : public Metadata
{
public:
QString name() { return QString("Accela"); }
- QIcon icon() { return QIcon(":/images/filter-16.png"); }
+ 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
index 3a4aaf05..00dc73bf 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp
+++ b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp
@@ -11,29 +11,29 @@ FilterControls::FilterControls() :
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)));
- tie_setting(s.rotation_alpha, ui.rotation_alpha);
- tie_setting(s.translation_alpha, ui.translation_alpha);
- tie_setting(s.second_order_alpha, ui.order_2nd);
- tie_setting(s.third_order_alpha, ui.order_3rd);
- tie_setting(s.rot_deadzone, ui.rot_deadzone);
- tie_setting(s.trans_deadzone, ui.trans_deadzone);
- tie_setting(s.expt, ui.expt);
+ tie_setting(s.rot_threshold, ui.rotation_slider);
+ tie_setting(s.trans_threshold, ui.translation_slider);
+ tie_setting(s.ewma, ui.ewma_slider);
}
void FilterControls::register_filter(IFilter* filter)
{
- accela_filter = (FTNoIR_Filter*) filter;
+ accela_filter = static_cast<FTNoIR_Filter*>(filter);
}
void FilterControls::unregister_filter()
{
- accela_filter = NULL;
+ accela_filter = nullptr;
}
void FilterControls::doOK() {
- save();
- this->close();
+ save();
+ this->close();
}
void FilterControls::doCancel() {
@@ -48,8 +48,21 @@ void FilterControls::discard()
void FilterControls::save() {
s.b->save();
- if (accela_filter)
- accela_filter->receiveSettings();
+}
+
+void FilterControls::update_rot_display(int value)
+{
+ ui.rot_gain->setText(QString::number((value + 1) * 7 / 100.) + "°");
+}
+
+void FilterControls::update_trans_display(int value)
+{
+ ui.trans_gain->setText(QString::number((value + 1) * 5 / 100.) + "mm");
+}
+
+void FilterControls::update_ewma_display(int value)
+{
+ ui.ewma_label->setText(QString::number(value * 2) + "ms");
}
extern "C" OPENTRACK_EXPORT IFilterDialog* GetDialog()
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp
deleted file mode 100644
index ff29227e..00000000
--- a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "ftnoir_filter_accela.h"
-#include "opentrack/plugin-api.hpp"
-
-extern "C" OPENTRACK_EXPORT Metadata* GetMetadata()
-{
- return new FTNoIR_FilterDll;
-}
diff --git a/ftnoir_filter_accela/images/filter-16-ac.png b/ftnoir_filter_accela/images/filter-16-ac.png
deleted file mode 100644
index d263db2d..00000000
--- a/ftnoir_filter_accela/images/filter-16-ac.png
+++ /dev/null
Binary files differ
diff --git a/ftnoir_filter_ewma2/ewma-filter.qrc b/ftnoir_filter_ewma2/ewma-filter.qrc
deleted file mode 100644
index e64ec35a..00000000
--- a/ftnoir_filter_ewma2/ewma-filter.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>images/filter-16.png</file>
- </qresource>
-</RCC>
diff --git a/ftnoir_filter_ewma2/images/filter-32.png b/ftnoir_filter_ewma2/images/filter-32.png
deleted file mode 100644
index 12b02caf..00000000
--- a/ftnoir_filter_ewma2/images/filter-32.png
+++ /dev/null
Binary files differ
diff --git a/ftnoir_filter_kalman/ftnoir_filter_kalman.h b/ftnoir_filter_kalman/ftnoir_filter_kalman.h
index c2947516..f6224530 100755
--- a/ftnoir_filter_kalman/ftnoir_filter_kalman.h
+++ b/ftnoir_filter_kalman/ftnoir_filter_kalman.h
@@ -24,12 +24,13 @@ class OPENTRACK_EXPORT FTNoIR_Filter : public IFilter
public:
FTNoIR_Filter();
void reset();
- void filter(const double *target_camera_position,
- double *new_camera_position);
- double accel_variance;
- double noise_variance;
+ void filter(const double *input, double *output);
+ // Set accel_stddev assuming moving 0.0->100.0 in dt=0.2 is 3 stddevs: (100.0*4/dt^2)/3.
+ const double accel_stddev = (100.0*4/(0.2*0.2))/3.0;
+ // TODO(abo): make noise_stddev a UI setting 0.0->10.0 with 0.1 resolution.
+ const double noise_stddev = 1.0;
cv::KalmanFilter kalman;
- double prev_position[6];
+ double last_input[6];
QElapsedTimer timer;
};
diff --git a/ftnoir_filter_kalman/images/filter-16-ac.png b/ftnoir_filter_kalman/images/filter-16-ac.png
deleted file mode 100644
index d263db2d..00000000
--- a/ftnoir_filter_kalman/images/filter-16-ac.png
+++ /dev/null
Binary files differ
diff --git a/ftnoir_filter_kalman/kalman-filter.qrc b/ftnoir_filter_kalman/kalman-filter.qrc
deleted file mode 100644
index 9a7d75fa..00000000
--- a/ftnoir_filter_kalman/kalman-filter.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>images/filter-16-ac.png</file>
- </qresource>
-</RCC>
diff --git a/ftnoir_filter_kalman/kalman.cpp b/ftnoir_filter_kalman/kalman.cpp
index ab352faa..c5a600af 100644
--- a/ftnoir_filter_kalman/kalman.cpp
+++ b/ftnoir_filter_kalman/kalman.cpp
@@ -16,10 +16,6 @@ FTNoIR_Filter::FTNoIR_Filter() {
// the following was written by Donovan Baarda <abo@minkirri.apana.org.au>
// https://sourceforge.net/p/facetracknoir/discussion/1150909/thread/418615e1/?limit=25#af75/084b
void FTNoIR_Filter::reset() {
- // Set accel_variance for moving 0.0->1.0 in dt=0.1.
- accel_variance = 400.0f;
- // TODO(abo): make noise_variance a UI setting 0.0->1.0.
- noise_variance = 0.1;
// Setup kalman with state (x) is the 6 tracker outputs then
// their 6 corresponding velocities, and the measurement (z) is
// the 6 tracker outputs.
@@ -42,6 +38,7 @@ void FTNoIR_Filter::reset() {
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.
@@ -59,16 +56,16 @@ void FTNoIR_Filter::reset() {
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);
+ 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++) {
- prev_position[i] = 0;
+ last_input[i] = 0;
}
timer.invalidate();
}
-void FTNoIR_Filter::filter(const double* target_camera_position,
- double *new_camera_position)
+void FTNoIR_Filter::filter(const double* input, double *output)
{
// Start the timer if it's not running.
if (!timer.isValid())
@@ -77,11 +74,11 @@ void FTNoIR_Filter::filter(const double* target_camera_position,
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_target = false;
- for (int i = 0; i < 6 && !new_target; i++)
- new_target = (prev_position[i] != target_camera_position[i]);
-
+ 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.
@@ -93,20 +90,20 @@ void FTNoIR_Filter::filter(const double* target_camera_position,
kalman.processNoiseCov.at<double>(i+6,i) = b;
}
// Get the updated predicted position.
- cv::Mat output = kalman.predict();
+ cv::Mat next_output = kalman.predict();
// If we have new tracker input, get the corrected position.
- if (new_target) {
+ if (new_input) {
cv::Mat measurement(6, 1, CV_64F);
for (int i = 0; i < 6; i++) {
- measurement.at<double>(i) = target_camera_position[i];
- // Save prev_position for detecting new tracker input.
- prev_position[i] = target_camera_position[i];
+ measurement.at<double>(i) = input[i];
+ // Save last_input for detecting new tracker input.
+ last_input[i] = input[i];
}
- output = kalman.correct(measurement);
+ next_output = kalman.correct(measurement);
}
- // Set new_camera_position to the output.
+ // Set output to the next_output.
for (int i = 0; i < 6; i++) {
- new_camera_position[i] = output.at<double>(i);
+ output[i] = next_output.at<double>(i);
}
}
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp
index b3243f62..85dd4684 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp
@@ -30,11 +30,6 @@
// For Todd and Arda Kutlu
-void FTNoIR_Protocol::reloadSettings()
-{
- s.b->reload();
-}
-
void FTNoIR_Protocol::pose(const double* headpose) {
FlightData.x = headpose[TX] * 1e-2;
FlightData.y = headpose[TY] * 1e-2;
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.h b/ftnoir_protocol_fg/ftnoir_protocol_fg.h
index d35b9fbd..36768fd5 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg.h
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.h
@@ -57,7 +57,6 @@ public:
QString game_name() {
return "FlightGear";
}
- void reloadSettings();
private:
settings s;
TFlightGearData FlightData;
@@ -70,15 +69,10 @@ class FGControls: public IProtocolDialog
Q_OBJECT
public:
FGControls();
- void register_protocol(IProtocol *protocol) {
- theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
- }
- void unregister_protocol() {
- theProtocol = NULL; // Reset the pointer
- }
+ void register_protocol(IProtocol *) {}
+ void unregister_protocol() {}
private:
Ui::UICFGControls ui;
- FTNoIR_Protocol *theProtocol;
settings s;
private slots:
void doOK();
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp
index 041e9961..d15c9466 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp
@@ -37,7 +37,7 @@
//
// Constructor for server-settings-dialog
//
-FGControls::FGControls() : theProtocol(nullptr)
+FGControls::FGControls()
{
ui.setupUi( this );
@@ -54,8 +54,6 @@ FGControls::FGControls() : theProtocol(nullptr)
void FGControls::doOK() {
s.b->save();
this->close();
- if (theProtocol)
- theProtocol->reloadSettings();
}
void FGControls::doCancel() {
diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp
index c0a186ff..312cf127 100644
--- a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp
+++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp
@@ -1,35 +1,35 @@
-/********************************************************************************
-* 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) 2013 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage *
-* *
-* This program is free software; you can redistribute it and/or modify it *
-* under the terms of the GNU General Public License as published by the *
-* Free Software Foundation; either version 3 of the License, or (at your *
-* option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, but *
-* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
-* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
-* more details. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
-* *
-* FTServer FTServer is the Class, that communicates headpose-data *
-* to games, using the FreeTrackClient.dll. *
+/*******************************************************************************
+* 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) 2013 Wim Vriend (Developing)
+* Ron Hendriks (Researching and Testing)
+*
+* Homepage
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 3 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, see <http://www.gnu.org/licenses/>.
+*
+* FTServer FTServer is the Class, that communicates headpose-data
+* to games, using the FreeTrackClient.dll.
********************************************************************************/
#include "ftnoir_protocol_ft.h"
-#include "ftnoir_csv/csv.h"
+#include "csv/csv.h"
FTNoIR_Protocol::FTNoIR_Protocol() :
- pMemData((FTHeap*) shm.ptr()),
shm(FREETRACK_HEAP, FREETRACK_MUTEX, sizeof(FTHeap)),
+ pMemData((FTHeap*) shm.ptr()),
viewsStart(nullptr),
viewsStop(nullptr),
intGameID(0)
@@ -48,15 +48,15 @@ FTNoIR_Protocol::~FTNoIR_Protocol()
}
void FTNoIR_Protocol::pose(const double* headpose) {
- float yaw = getRadsFromDegrees(headpose[Yaw]);
- float pitch = getRadsFromDegrees(headpose[Pitch]);
+ 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;
shm.lock();
-
+
pMemData->data.RawX = 0;
pMemData->data.RawY = 0;
pMemData->data.RawZ = 0;
@@ -71,7 +71,7 @@ void FTNoIR_Protocol::pose(const double* headpose) {
pMemData->data.Pitch = pitch;
pMemData->data.Roll = roll;
- pMemData->data.X1 = ++pMemData->data.DataID;
+ pMemData->data.X1 = pMemData->data.DataID;
pMemData->data.X2 = 0;
pMemData->data.X3 = 0;
pMemData->data.X4 = 0;
@@ -90,7 +90,7 @@ void FTNoIR_Protocol::pose(const double* headpose) {
connected_game = gamename;
}
- pMemData->data.DataID += 1;
+ pMemData->data.DataID += 1;
shm.unlock();
}
@@ -128,9 +128,9 @@ void FTNoIR_Protocol::start_dummy() {
}
bool FTNoIR_Protocol::correct()
-{
- QSettings settings("Freetrack", "FreetrackClient"); // Registry settings (in HK_USER)
- QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER)
+{
+ QSettings settings("Freetrack", "FreetrackClient"); // Registry settings (in HK_USER)
+ QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER)
if (!shm.success())
return false;
@@ -138,15 +138,15 @@ bool FTNoIR_Protocol::correct()
QString aLocation = QCoreApplication::applicationDirPath() + "/";
switch (s.intUsedInterface) {
- case 0: // Use both interfaces
+ case 0: // Use both interfaces
settings.setValue( "Path" , aLocation );
settingsTIR.setValue( "Path" , aLocation );
break;
- case 1: // Use FreeTrack, disable TrackIR
+ case 1: // Use FreeTrack, disable TrackIR
settings.setValue( "Path" , aLocation );
settingsTIR.setValue( "Path" , "" );
break;
- case 2: // Use TrackIR, disable FreeTrack
+ case 2: // Use TrackIR, disable FreeTrack
settings.setValue( "Path" , "" );
settingsTIR.setValue( "Path" , aLocation );
break;
@@ -166,8 +166,8 @@ bool FTNoIR_Protocol::correct()
pMemData->data.CamHeight = 250;
pMemData->GameID2 = 0;
memset(pMemData->table, 0, 8);
-
- return true;
+
+ return true;
}
extern "C" OPENTRACK_EXPORT IProtocol* GetConstructor()
diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.h b/ftnoir_protocol_ft/ftnoir_protocol_ft.h
index 06992de5..6bbf1bd3 100644
--- a/ftnoir_protocol_ft/ftnoir_protocol_ft.h
+++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.h
@@ -38,7 +38,7 @@
#include <QMutexLocker>
#include "compat/compat.h"
#include "opentrack/options.hpp"
-#include "fttypes.h"
+#include "../freetrackclient/fttypes.h"
using namespace options;
struct settings {
@@ -60,7 +60,7 @@ class FTNoIR_Protocol : public IProtocol
public:
FTNoIR_Protocol();
~FTNoIR_Protocol() override;
- bool correct( );
+ bool correct();
void pose( const double *headpose );
QString game_name() override {
QMutexLocker foo(&game_name_mutex);
@@ -68,18 +68,18 @@ public:
}
private:
settings s;
- FTHeap *pMemData;
PortableLockedShm shm;
+ FTHeap *pMemData;
QLibrary FTIRViewsLib;
QProcess dummyTrackIR;
importTIRViewsStart viewsStart;
- importTIRViewsStop viewsStop;
-
+ 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();
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp
index ac543812..e26f6cbf 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp
@@ -30,34 +30,33 @@
#include "opentrack/plugin-api.hpp"
void FTNoIR_Protocol::pose(const double *headpose ) {
- double fMouse_X = 0;
- double fMouse_Y = 0;
-
- // XXX TODO remove axis selector, use mapping window's
- // axis selection. Mention in UI axis used. -sh 20140920
- int Mouse_X = s.Mouse_X;
- int Mouse_Y = s.Mouse_Y;
-
- if (Mouse_X > 0 && Mouse_X <= 6)
- fMouse_X = headpose[Mouse_X-1] / (Mouse_X < 3 ? 100 : 180);
-
- if (Mouse_Y > 0 && Mouse_Y <= 6)
- fMouse_Y = headpose[Mouse_Y-1] / (Mouse_Y < 3 ? 100 : 180);
-
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
if (hDesktop != NULL && GetWindowRect(hDesktop, &desktop)) {
- fMouse_X *= desktop.right;
- fMouse_Y *= desktop.bottom;
- SetCursorPos(fMouse_X + desktop.right/2, fMouse_Y + desktop.bottom/2);
+ // 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, mouse_y;
+
+ 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;
+
+ POINT pt;
+
+ if (GetCursorPos(&pt))
+ {
+ SetCursorPos(pt.x + mouse_x - last_x, pt.y + mouse_y - last_y);
+ last_x = mouse_x;
+ last_y = mouse_y;
+ }
}
}
-void FTNoIR_Protocol::reload()
-{
- s.b->reload();
-}
-
bool FTNoIR_Protocol::correct()
{
return true;
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h
index 3d04fa15..9f76571b 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h
@@ -59,13 +59,13 @@ struct settings {
class FTNoIR_Protocol : public IProtocol
{
public:
- FTNoIR_Protocol() {}
+ FTNoIR_Protocol() : last_x(0), last_y(0) {}
bool correct();
void pose( const double *headpose);
QString game_name() {
return "Mouse tracker";
}
- void reload();
+ int last_x, last_y;
private:
struct settings s;
};
@@ -75,16 +75,11 @@ class MOUSEControls: public IProtocolDialog
Q_OBJECT
public:
MOUSEControls();
- void register_protocol(IProtocol *protocol) {
- _proto = (FTNoIR_Protocol *) protocol;
- }
- void unregister_protocol() {
- _proto = NULL;
- }
+ void register_protocol(IProtocol *) {}
+ void unregister_protocol() {}
private:
Ui::UICMOUSEControls ui;
settings s;
- FTNoIR_Protocol* _proto;
private slots:
void doOK();
void doCancel();
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp
index 3303e54c..f4ecaa48 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp
@@ -25,7 +25,7 @@
#include "ftnoir_protocol_mouse.h"
#include "opentrack/plugin-api.hpp"
-MOUSEControls::MOUSEControls() : _proto(nullptr)
+MOUSEControls::MOUSEControls()
{
ui.setupUi( this );
ui.cbxSelectMouse_X->addItem("None");
@@ -53,8 +53,6 @@ MOUSEControls::MOUSEControls() : _proto(nullptr)
void MOUSEControls::doOK() {
s.b->save();
- if (_proto)
- _proto->reload();
this->close();
}
diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp b/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp
index db030554..5f80944a 100644
--- a/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp
+++ b/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp
@@ -3,7 +3,7 @@
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
-#include "ftnoir_csv/csv.h"
+#include "csv/csv.h"
FTNoIR_Protocol::FTNoIR_Protocol() : lck_shm(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)), shm(NULL), gameid(0)
{
diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx
index 9a07681c..d5d03011 100644
--- a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx
+++ b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx
@@ -1,6 +1,6 @@
#include <cerrno>
#include <cstdio>
-#include "ftnoir_protocol_ft/fttypes.h"
+#include "freetrackclient/fttypes.h"
#include "ftnoir_protocol_wine/wine-shm.h"
#define OPENTRACK_CROSS_ONLY
@@ -61,8 +61,8 @@ int main(void)
break;
}
lck_wine.lock();
- data->Yaw = shm_posix->data[Yaw];
- data->Pitch = shm_posix->data[Pitch];
+ 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];
diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx
index b7dc531c..5d19608a 100644
--- a/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx
+++ b/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx
@@ -8,14 +8,15 @@
#include "compat/compat.cpp"
#include "wine-shm.h"
-void create_registry_key(void) {
+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,
- "Software\\NaturalPoint\\NATURALPOINT\\NPClient Location",
+ key,
0,
NULL,
0,
@@ -28,8 +29,13 @@ void create_registry_key(void) {
if (dir[i] == '\\')
dir[i] = '/';
strcat(dir, "/");
- (void) RegSetValueExA(hkpath, "Path", 0, REG_SZ, (BYTE*) dir, strlen(dir) + 1);
+ (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_tracker_aruco/aruco-trackercontrols.ui b/ftnoir_tracker_aruco/aruco-trackercontrols.ui
index 099dec02..15184c41 100644
--- a/ftnoir_tracker_aruco/aruco-trackercontrols.ui
+++ b/ftnoir_tracker_aruco/aruco-trackercontrols.ui
@@ -101,12 +101,12 @@
</item>
<item>
<property name="text">
- <string>120</string>
+ <string>125</string>
</property>
</item>
<item>
<property name="text">
- <string>180</string>
+ <string>200</string>
</property>
</item>
</widget>
@@ -236,7 +236,10 @@
<item row="4" column="1">
<widget class="QPushButton" name="btn_calibrate">
<property name="text">
- <string>Calibrate</string>
+ <string>Toggle calibration</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
</property>
</widget>
</item>
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
index bd7e3ff4..27d835f0 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
@@ -112,9 +112,7 @@ Tracker::~Tracker()
delete videoWidget;
if(layout)
delete layout;
- qDebug() << "releasing camera, brace for impact";
camera.release();
- qDebug() << "all done!";
}
void Tracker::start_tracker(QFrame* videoframe)
@@ -164,10 +162,10 @@ void Tracker::run()
fps = 60;
break;
case 3:
- fps = 120;
+ fps = 125;
break;
case 4:
- fps = 180;
+ fps = 200;
break;
}
camera = cv::VideoCapture(s.camera_index);
@@ -201,16 +199,12 @@ void Tracker::run()
if (!camera.read(color))
continue;
auto tm = cv::getTickCount();
-
+
cv::Mat grayscale;
- {
- std::vector<cv::Mat> tmp;
- cv::split(color, tmp);
- // red only, best on CCD, also artifacts on blue ps3eye
- grayscale = tmp[2];
- }
- const int scale = frame.cols > 480 ? 2 : 1;
- detector.setThresholdParams(scale > 1 ? 11 : 7, 4);
+ cv::cvtColor(color, grayscale, cv::COLOR_RGB2GRAY);
+
+ const int scale = grayscale.cols > 480 ? 2 : 1;
+ detector.setThresholdParams(scale > 1 ? 13 : 7, 5);
const float focal_length_w = 0.5 * grayscale.cols / tan(0.5 * s.fov * HT_PI / 180);
const float focal_length_h = 0.5 * grayscale.rows / tan(0.5 * s.fov * grayscale.rows / grayscale.cols * HT_PI / 180.0);
@@ -224,16 +218,16 @@ void Tracker::run()
std::vector< aruco::Marker > markers;
- const double size_min = 0.04;
- const double size_max = 0.28;
-
+ const double size_min = 0.02;
+ const double size_max = 0.4;
+
bool roi_valid = false;
-
+
if (last_roi.width > 0 && last_roi.height)
{
detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width),
std::min(1.0, size_max * grayscale.cols / last_roi.width));
-
+
if (detector.detect(grayscale(last_roi), markers, cv::Mat(), cv::Mat(), -1, false),
markers.size() == 1 && markers[0].size() == 4)
{
@@ -247,13 +241,13 @@ void Tracker::run()
roi_valid = true;
}
}
-
+
if (!roi_valid)
{
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++)
@@ -276,9 +270,9 @@ void Tracker::run()
frame = color.clone();
::sprintf(buf, "Hz: %d", last_fps);
- cv::putText(frame, buf, cv::Point(10, 32), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(0, 255, 0), 1);
+ cv::putText(frame, buf, cv::Point(10, 32), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(0, 255, 0), scale*2);
::sprintf(buf, "Jiffies: %ld", (long) (10000 * (time - tm) / freq));
- cv::putText(frame, buf, cv::Point(10, 54), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(80, 255, 0), 1);
+ cv::putText(frame, buf, cv::Point(10, 54), cv::FONT_HERSHEY_PLAIN, scale, cv::Scalar(80, 255, 0), scale*2);
if (markers.size() == 1 && markers[0].size() == 4) {
const auto& m = markers.at(0);
@@ -289,85 +283,85 @@ void Tracker::run()
obj_points.at<float>(x1,0)=-size + s.headpos_x;
obj_points.at<float>(x1,1)=-size + s.headpos_y;
obj_points.at<float>(x1,2)= 0 + s.headpos_z;
-
+
obj_points.at<float>(x2,0)=size + s.headpos_x;
obj_points.at<float>(x2,1)=-size + s.headpos_y;
obj_points.at<float>(x2,2)= 0 + s.headpos_z;
-
+
obj_points.at<float>(x3,0)=size + s.headpos_x;
obj_points.at<float>(x3,1)=size + s.headpos_y;
obj_points.at<float>(x3,2)= 0 + s.headpos_z;
-
+
obj_points.at<float>(x4,0)= -size + s.headpos_x;
obj_points.at<float>(x4,1)= size + s.headpos_y;
obj_points.at<float>(x4,2)= 0 + s.headpos_z;
-
+
cv::Vec3d rvec, tvec;
-
+
cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec, tvec, false, cv::ITERATIVE);
-
+
std::vector<cv::Point2f> roi_projection(4);
-
+
{
std::vector<cv::Point2f> repr2;
std::vector<cv::Point3f> 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<float>(i, 0) -= s.headpos_x;
obj_points.at<float>(i, 1) -= s.headpos_y;
obj_points.at<float>(i, 2) -= s.headpos_z;
}
-
+
{
cv::Mat rvec_, tvec_;
cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec_, tvec_, false, cv::ITERATIVE);
tvec = tvec_;
}
-
+
cv::Mat roi_points = obj_points * c_search_window;
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<int>(proj.x, last_roi.x),
min_y = std::min<int>(proj.y, last_roi.y);
-
+
int max_x = std::max<int>(proj.x, last_roi.width),
max_y = std::max<int>(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+1 > color.cols)
last_roi.width = color.cols-1;
-
+
if (last_roi.height+1 > color.rows)
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);
@@ -377,6 +371,8 @@ void Tracker::run()
QMutexLocker lck(&mtx);
+ tvec[1] *= -1;
+
for (int i = 0; i < 3; i++)
pose[i] = tvec(i);
pose[Yaw] = euler[1];
@@ -386,7 +382,7 @@ void Tracker::run()
r = rmat;
t = tvec;
}
-
+
if (roi_valid)
cv::rectangle(frame, last_roi, cv::Scalar(255, 0, 255), 1);
}
@@ -461,10 +457,18 @@ 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);
}
}
@@ -482,18 +486,12 @@ void TrackerControls::update_tracker_calibration()
cv::Vec3d t;
tracker->getRT(r, t);
calibrator.update(r, t);
- auto pos = calibrator.get_estimate() * .1;
- s.headpos_x = pos(0);
- s.headpos_y = pos(1);
- s.headpos_z = pos(2);
}
}
void TrackerControls::doOK()
{
s.b->save();
- if (tracker)
- tracker->reload();
this->close();
}
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
index ad139145..ad10f04a 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
@@ -50,7 +50,6 @@ public:
void start_tracker(QFrame* frame);
void data(double *data);
void run();
- void reload() { s.b->reload(); }
void getRT(cv::Matx33d &r, cv::Vec3d &t);
private:
QMutex mtx;
diff --git a/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui b/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui
index 48290bf2..74e5a6f1 100644
--- a/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui
+++ b/ftnoir_tracker_freepie-udp/freepie-udp-controls.ui
@@ -9,48 +9,264 @@
<rect>
<x>0</x>
<y>0</y>
- <width>198</width>
- <height>71</height>
+ <width>227</width>
+ <height>372</height>
</rect>
</property>
<property name="windowTitle">
- <string>UDP tracker settings</string>
+ <string>Tracker settings</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../facetracknoir/images/facetracknoir.png</normaloff>../facetracknoir/images/facetracknoir.png</iconset>
</property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label_5">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QFrame" name="frame">
<property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>UDP port</string>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
</property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>UDP port</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="port">
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="port">
- <property name="minimum">
- <number>0</number>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Axis order</string>
</property>
- <property name="maximum">
- <number>65535</number>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" rowspan="2">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>output yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="input_x">
+ <item>
+ <property name="text">
+ <string>input yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>input pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>input roll</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="1" rowspan="2">
+ <widget class="QComboBox" name="input_y">
+ <item>
+ <property name="text">
+ <string>input yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>input pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>input roll</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0" rowspan="2">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>output pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" rowspan="2">
+ <widget class="QComboBox" name="input_z">
+ <item>
+ <property name="text">
+ <string>input yaw</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>input pitch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>input roll</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>output roll</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Add to axis</string>
</property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="add_yaw">
+ <item>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>+90</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>-90</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>+180</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>-180</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="add_pitch">
+ <item>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>+90</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>-90</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>+180</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>-180</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="add_roll">
+ <item>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>+90</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>-90</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>+180</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>-180</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="1" column="0" colspan="2">
+ <item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
diff --git a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp
index eff1103b..540ef616 100644
--- a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp
+++ b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.cpp
@@ -14,12 +14,21 @@ TrackerImpl::~TrackerImpl()
wait();
}
+template<typename t>
+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;
- uint8_t pad2;
float fl[12];
} data;
#pragma pack(pop)
@@ -28,24 +37,29 @@ void TrackerImpl::run() {
flag_Orient = 1 << 1,
Mask = flag_Raw | flag_Orient
};
+
+ (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
- while (1) {
- if (should_quit)
- break;
-
+ while (!should_quit) {
+ int order[] = {
+ bound<int>(s.idx_x, 0, 2),
+ bound<int>(s.idx_y, 0, 2),
+ bound<int>(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}};
+ t tmp {0,0, {0,0,0, 0,0,0, 0,0,0, 0,0,0}};
(void) sock.readDatagram(reinterpret_cast<char*>(&tmp), sizeof(data));
int flags = tmp.flags & F::Mask;
switch (flags)
{
+ //default:
case flag_Raw:
continue;
case flag_Raw | flag_Orient:
@@ -64,10 +78,24 @@ void TrackerImpl::run() {
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 d2r = 57.295781;
+ static constexpr double r2d = 57.295781;
for (int i = 0; i < 3; i++)
- pose[Yaw + i] = d2r * orient[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);
}
@@ -75,7 +103,6 @@ void TrackerImpl::run() {
void TrackerImpl::start_tracker(QFrame*)
{
- (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
start();
}
diff --git a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h
index 0cec952f..0567beae 100644
--- a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h
+++ b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp.h
@@ -15,10 +15,17 @@ using namespace options;
struct settings {
pbundle b;
- value<int> port;
+ value<int> port, idx_x, idx_y, idx_z;
+ value<int> add_yaw, add_pitch, add_roll;
settings() :
b(bundle("freepie-udp-tracker")),
- port(b, "port", 4237)
+ 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)
{}
};
diff --git a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp
index ec95da90..1f17355f 100644
--- a/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp
+++ b/ftnoir_tracker_freepie-udp/ftnoir_tracker_freepie-udp_dialog.cpp
@@ -9,6 +9,13 @@ TrackerDialog::TrackerDialog()
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() {
diff --git a/ftnoir_tracker_hatire/ftnoir_arduino_type.h b/ftnoir_tracker_hatire/ftnoir_arduino_type.h
new file mode 100644
index 00000000..efcee05c
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_arduino_type.h
@@ -0,0 +1,32 @@
+#ifndef FTNOIR_TARDUINO_TYPE_H
+#define FTNOIR_TARDUINO_TYPE_H
+
+#include <QDataStream>
+
+// 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
new file mode 100644
index 00000000..41d43617
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_hat.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/hat_logo.png</file>
+ <file>images/hat.ico</file>
+ <file>images/hat.png</file>
+ </qresource>
+</RCC>
diff --git a/ftnoir_tracker_hatire/ftnoir_hatcontrols.ui b/ftnoir_tracker_hatire/ftnoir_hatcontrols.ui
new file mode 100644
index 00000000..1611489b
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_hatcontrols.ui
@@ -0,0 +1,1243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UIHATControls</class>
+ <widget class="QWidget" name="UIHATControls">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>370</width>
+ <height>740</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="windowTitle">
+ <string>Head Arduino Tracker settings FaceTrackNoIR</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="ftnoir_hat.qrc">
+ <normaloff>:/images/hat.png</normaloff>:/images/hat.png</iconset>
+ </property>
+ <property name="windowOpacity">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_7">
+ <item row="1" column="2">
+ <widget class="QPushButton" name="btnCancel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="btnOK">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65535</width>
+ <height>65535</height>
+ </size>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab_config">
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string/>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Serial port</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="cbSerialPort">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65535</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLength</enum>
+ </property>
+ <property name="modelColumn">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnZero">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Zero</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCenter">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Center</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnReset">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>Axis Configuration</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_6">
+ <item row="2" column="2">
+ <widget class="QComboBox" name="cb_pitch">
+ <property name="toolTip">
+ <string>Associate Axis</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>RotX</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RotY</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RotZ</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="chkEnableYaw">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QCheckBox" name="chkEnableX">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_pitch">
+ <property name="text">
+ <string>Pitch:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Enable</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="chkEnablePitch">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_yaw">
+ <property name="text">
+ <string>Yaw:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Invert</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_y">
+ <property name="text">
+ <string>Y:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <widget class="QCheckBox" name="chkInvertRoll">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Invert Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_x">
+ <property name="text">
+ <string>X:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="3">
+ <widget class="QCheckBox" name="chkInvertY">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Invert Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="3">
+ <widget class="QCheckBox" name="chkInvertZ">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Invert Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QComboBox" name="cb_z">
+ <property name="toolTip">
+ <string>Associate Axis</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QCheckBox" name="chkEnableZ">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QComboBox" name="cb_y">
+ <property name="toolTip">
+ <string>Associate Axis</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_roll">
+ <property name="text">
+ <string>Roll:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3">
+ <widget class="QCheckBox" name="chkInvertX">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Invert Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QComboBox" name="cb_x">
+ <property name="toolTip">
+ <string>Associate Axis</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QCheckBox" name="chkInvertPitch">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Invert Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_z">
+ <property name="text">
+ <string>Z:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QComboBox" name="cb_roll">
+ <property name="toolTip">
+ <string>Associate Axis</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>RotX</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RotY</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RotZ</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="chkEnableRoll">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QCheckBox" name="chkEnableY">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Enable Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QCheckBox" name="chkInvertYaw">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Invert Axis</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QComboBox" name="cb_yaw">
+ <property name="toolTip">
+ <string>Associate Axis</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>RotX</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RotY</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>RotZ</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Axis</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_status">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Status</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="lab_tps">
+ <property name="minimumSize">
+ <size>
+ <width>31</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Trame per seconde</string>
+ </property>
+ <property name="text">
+ <string>tps :</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="lab_vtps">
+ <property name="minimumSize">
+ <size>
+ <width>31</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true">0</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lab_status">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Info :</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="lab_vstatus">
+ <property name="minimumSize">
+ <size>
+ <width>170</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>HAT STOPPED</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_cmds">
+ <attribute name="title">
+ <string>Command</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="parametersBox">
+ <property name="title">
+ <string>Serial Parameters</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_8">
+ <item row="0" column="1">
+ <widget class="QComboBox" name="QCB_Serial_baudRate"/>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="QCB_Serial_stopBits"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="flowControlLabel">
+ <property name="text">
+ <string>Flow control:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="QCB_Serial_parity"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="QCB_Serial_flowControl"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="stopBitsLabel">
+ <property name="text">
+ <string>Stop bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="parityLabel">
+ <property name="text">
+ <string>Parity:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="baudRateLabel">
+ <property name="text">
+ <string>BaudRate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="QCB_Serial_dataBits"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="dataBitsLabel">
+ <property name="text">
+ <string>Data bits:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Arduino Commands</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QLabel" name="lab_cmd_init_2">
+ <property name="text">
+ <string>Delay Init</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lab_cmd_init">
+ <property name="text">
+ <string>Init</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="le_cmd_init">
+ <property name="toolTip">
+ <string>Command for Initialising Arduino</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="lab_cmd_init_3">
+ <property name="text">
+ <string>Delay Start</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="lab_cmd_start">
+ <property name="text">
+ <string>Start:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="le_cmd_start">
+ <property name="toolTip">
+ <string>Command for Start send sequence</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="lab_cmd_init_4">
+ <property name="text">
+ <string>Delay Sequence</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QSpinBox" name="spb_AfterStart">
+ <property name="toolTip">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Delay after Start Command in ms&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="singleStep">
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="lab_cmd_stop">
+ <property name="text">
+ <string>Stop:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLineEdit" name="le_cmd_stop">
+ <property name="toolTip">
+ <string>Command for Stop send sequence</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="lab_cmd_center">
+ <property name="text">
+ <string>Center:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QLineEdit" name="le_cmd_center">
+ <property name="toolTip">
+ <string>Command for read Center Gyro arduino</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="lab_cmd_zero">
+ <property name="text">
+ <string>Zero:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLineEdit" name="le_cmd_zero">
+ <property name="toolTip">
+ <string>Command for reset Center Gyro arduino</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="lab_cmd_reset">
+ <property name="text">
+ <string>Reset:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QLineEdit" name="le_cmd_reset">
+ <property name="toolTip">
+ <string>Command for Reset Arduino</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="2">
+ <widget class="QCheckBox" name="cb_Endian">
+ <property name="toolTip">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Little or Big Endian for &lt;span style=&quot; font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;&quot;&gt;the serialization of byte order&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;&quot;&gt;Arduino is LittleEndian ( unchecked)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Endian</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QSpinBox" name="spb_BeforeInit">
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Delay before Init command in ms&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="singleStep">
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QSpinBox" name="spb_BeforeStart">
+ <property name="toolTip">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Delay after Init command in ms&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ <property name="singleStep">
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="2">
+ <widget class="QSpinBox" name="spb_Fps">
+ <property name="maximumSize">
+ <size>
+ <width>51</width>
+ <height>19</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Indicate at OpenTrack speed sketch FPS to adjust CPU &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="minimum">
+ <number>10</number>
+ </property>
+ <property name="maximum">
+ <number>200</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_about">
+ <attribute name="title">
+ <string>About</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_info_2">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt; font-weight:600;&quot;&gt;FTNoIR HAT Plugin&lt;br /&gt;by FuraX49&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://hatire.sourceforge.net/&quot;&gt;&lt;span style=&quot; font-size:8pt; font-weight:600; text-decoration: underline; color:#0000ff;&quot;&gt;Manual (external)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="2" colspan="2">
+ <widget class="QPushButton" name="btn_icone">
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normalon>:/images/hat_logo.png</normalon>
+ </iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>128</width>
+ <height>128</height>
+ </size>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_version">
+ <property name="font">
+ <font>
+ <family>Arial Black</family>
+ <pointsize>10</pointsize>
+ <weight>75</weight>
+ <italic>true</italic>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Version 1.0.0</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLineEdit" name="lineSend">
+ <property name="inputMask">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="btnSend">
+ <property name="text">
+ <string>Send</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3">
+ <widget class="QPlainTextEdit" name="pteINFO">
+ <property name="contextMenuPolicy">
+ <enum>Qt::ActionsContextMenu</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="plainText">
+ <string notr="true"/>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ <property name="maximumBlockCount">
+ <number>800</number>
+ </property>
+ <property name="backgroundVisible">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="btnSave">
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>80</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>btnOK</tabstop>
+ <tabstop>btnSave</tabstop>
+ <tabstop>btnCancel</tabstop>
+ <tabstop>cbSerialPort</tabstop>
+ <tabstop>btnZero</tabstop>
+ <tabstop>btnCenter</tabstop>
+ <tabstop>btnReset</tabstop>
+ <tabstop>chkEnableYaw</tabstop>
+ <tabstop>cb_yaw</tabstop>
+ <tabstop>chkInvertYaw</tabstop>
+ <tabstop>chkEnablePitch</tabstop>
+ <tabstop>cb_pitch</tabstop>
+ <tabstop>chkInvertPitch</tabstop>
+ <tabstop>chkEnableRoll</tabstop>
+ <tabstop>cb_roll</tabstop>
+ <tabstop>chkInvertRoll</tabstop>
+ <tabstop>chkEnableX</tabstop>
+ <tabstop>cb_x</tabstop>
+ <tabstop>chkInvertX</tabstop>
+ <tabstop>chkEnableY</tabstop>
+ <tabstop>cb_y</tabstop>
+ <tabstop>chkInvertY</tabstop>
+ <tabstop>chkEnableZ</tabstop>
+ <tabstop>cb_z</tabstop>
+ <tabstop>chkInvertZ</tabstop>
+ <tabstop>spb_BeforeInit</tabstop>
+ <tabstop>le_cmd_init</tabstop>
+ <tabstop>spb_BeforeStart</tabstop>
+ <tabstop>le_cmd_start</tabstop>
+ <tabstop>spb_AfterStart</tabstop>
+ <tabstop>le_cmd_stop</tabstop>
+ <tabstop>le_cmd_center</tabstop>
+ <tabstop>le_cmd_zero</tabstop>
+ <tabstop>le_cmd_reset</tabstop>
+ <tabstop>spb_Fps</tabstop>
+ <tabstop>cb_Endian</tabstop>
+ <tabstop>QCB_Serial_baudRate</tabstop>
+ <tabstop>QCB_Serial_dataBits</tabstop>
+ <tabstop>QCB_Serial_parity</tabstop>
+ <tabstop>QCB_Serial_stopBits</tabstop>
+ <tabstop>QCB_Serial_flowControl</tabstop>
+ <tabstop>lineSend</tabstop>
+ <tabstop>btnSend</tabstop>
+ <tabstop>pteINFO</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>btn_icone</tabstop>
+ </tabstops>
+ <resources>
+ <include location="ftnoir_hat.qrc"/>
+ </resources>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp
new file mode 100644
index 00000000..6bacd5f9
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat.cpp
@@ -0,0 +1,549 @@
+/********************************************************************************
+* FaceTrackNoIR This program is a private project of some enthusiastic *
+* gamers from Holland, who don't like to pay much for *
+* head-tracking. *
+* *
+* Copyright (C) 2012 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* Homepage: http://facetracknoir.sourceforge.net/home/default.htm *
+* *
+* Copyright (C) 2012 FuraX49 (HAT Tracker plugins) *
+* Homepage: http://hatire.sourceforge.net *
+* *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU General Public License as published by the *
+* Free Software Foundation; either version 3 of the License, or (at your *
+* option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but *
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
+* more details. *
+* *
+* You should have received a copy of the GNU General Public License along *
+* with this program; if not, see <http://www.gnu.org/licenses/>. *
+* *
+********************************************************************************/
+
+#include <QDebug>
+#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);
+
+ settings.load_ini();
+}
+
+FTNoIR_Tracker::~FTNoIR_Tracker()
+{
+ qDebug()<<"Tracker::~HAT";
+ if (ComPort!=NULL) {
+ if (ComPort->isOpen() ) {
+
+#ifdef OPENTRACK_API
+ QByteArray Msg;
+ 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() )
+ {
+ 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 ( !ComPort->waitForReadyRead(1000)) {
+ emit sendMsgInfo("TimeOut in response to CMD") ;
+ } else {
+ emit sendMsgInfo(Msg);
+ }
+ } 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;
+
+ 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,"FaceTrackNoIR Error", ComPort->errorString(),QMessageBox::Ok,QMessageBox::NoButton);
+ }
+ }
+ else {
+ QMessageBox::warning(0,"FaceTrackNoIR 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);
+ // 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;
+ 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);
+ 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)
+ ) {
+ qDebug() << QTime::currentTime() << " HAT OPEN on " << ComPort->portName() << ComPort->baudRate() << ComPort->dataBits() << ComPort->parity() << ComPort->stopBits() << ComPort->flowControl();
+
+ // Wait init arduino sequence
+ for (int i = 1; i <=iDelayInit; i+=50) {
+ if (ComPort->waitForReadyRead(50)) break;
+ }
+ 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;
+ }
+ qDebug() << QTime::currentTime() << " HAT wait MPU ";
+ } else {
+ QMessageBox::warning(0,"FaceTrackNoIR Error", ComPort->errorString(),QMessageBox::Ok,QMessageBox::NoButton);
+ }
+ }
+ else {
+ QMessageBox::warning(0,"FaceTrackNoIR 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 ";
+ 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) {
+ 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++;
+ }
+ }
+
+ if (CptError>50) {
+ emit sendMsgInfo("Can't find HAT frame") ;
+ CptError=0;
+#ifndef OPENTRACK_API
+ return false;
+#endif
+ }
+ if (new_frame) {
+#ifdef OPENTRACK_API
+
+ static constexpr double pi = 3.14159265359;
+ static constexpr double d2r = pi / 180.;
+
+ if (bEnableYaw) {
+ if (bInvertYaw ) data[Yaw] = HAT.Rot[iYawAxe] * -1.0f * d2r;
+ else data[Yaw] = HAT.Rot[iYawAxe];
+ } else data[Yaw] =0;
+
+ if (bEnablePitch) {
+ if (bInvertPitch) data[Pitch] = HAT.Rot[iPitchAxe] * -1.0f * d2r;
+ else data[Pitch] = HAT.Rot[iPitchAxe];
+ } else data[Pitch] = 0;
+
+ if (bEnableRoll) {
+ if (bInvertRoll) data[Roll] = HAT.Rot[iRollAxe] * -1.0f * d2r;
+ 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 (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;
+
+ 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
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// 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
+extern "C" OPENTRACK_EXPORT ITracker* GetConstructor()
+#else
+#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
+FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker()
+#endif
+{
+ return new FTNoIR_Tracker;
+}
diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat.h b/ftnoir_tracker_hatire/ftnoir_tracker_hat.h
new file mode 100644
index 00000000..2abeb77d
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat.h
@@ -0,0 +1,154 @@
+#ifndef FTNOIR_TRACKER_HAT_H
+#define FTNOIR_TRACKER_HAT_H
+
+#ifdef OPENTRACK_API
+# include "opentrack/plugin-support.h"
+#else
+# include "..\ftnoir_tracker_base\ftnoir_tracker_base.h"
+#endif
+#include "ftnoir_tracker_hat_settings.h"
+#include "ftnoir_arduino_type.h"
+#include <QObject>
+#include <QPalette>
+#include <QtGui>
+#include <QByteArray>
+#include <QMessageBox>
+#include <QtSerialPort/QSerialPort>
+#include <QtSerialPort/QSerialPortInfo>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QSettings>
+
+#define VER_FILEVERSION_STR "Version 2.1.0\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();
+
+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;
+
+ 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;
+#ifdef OPENTRACK_API
+ int iFpsArduino;
+#endif
+ int CptError;
+
+
+};
+
+
+//*******************************************************************************************************
+// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker
+//*******************************************************************************************************
+class TrackerDll :
+#if defined(OPENTRACK_API)
+ public Metadata
+#else
+ public ITrackerDll
+#endif
+{
+public:
+ TrackerDll();
+ ~TrackerDll();
+
+#ifndef OPENTRACK_API
+ void Initialize();
+#endif
+
+#ifdef OPENTRACK_API
+ QString name();
+ QIcon icon();
+#else
+ void getFullName(QString *strToBeFilled);
+ void getShortName(QString *strToBeFilled);
+ void getDescription(QString *strToBeFilled);
+ void getIcon(QIcon *icon);
+#endif
+
+private:
+ QString trackerFullName; // Trackers' name and description
+ QString trackerShortName;
+ QString trackerDescription;
+};
+
+
+#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
new file mode 100644
index 00000000..51d5918e
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.cpp
@@ -0,0 +1,426 @@
+/********************************************************************************
+* FaceTrackNoIR This program is a private project of some enthusiastic *
+* gamers from Holland, who don't like to pay much for *
+* head-tracking. *
+* *
+* Copyright (C) 2012 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* Homepage: http://facetracknoir.sourceforge.net/home/default.htm *
+* *
+* Copyright (C) 2012 FuraX49 (HAT Tracker plugins) *
+* Homepage: http://hatire.sourceforge.net *
+* *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU General Public License as published by the *
+* Free Software Foundation; either version 3 of the License, or (at your *
+* option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but *
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
+* more details. *
+* *
+* You should have received a copy of the GNU General Public License along *
+* with this program; if not, see <http://www.gnu.org/licenses/>. *
+* *
+********************************************************************************/
+#include "ftnoir_tracker_hat.h"
+#include "ftnoir_tracker_hat_dialog.h"
+
+#include <QScrollBar>
+
+//*******************************************************************************************************
+// 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,"FaceTrackNoIR 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,"FaceTrackNoIR 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.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.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<FTNoIR_Tracker*>(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
+extern "C" OPENTRACK_EXPORT ITrackerDialog* GetDialog( )
+#else
+#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
+FTNOIR_TRACKER_BASE_EXPORT ITrackerDialogPtr __stdcall GetTrackerDialog( )
+#endif
+{
+ return new TrackerControls;
+}
+
diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h
new file mode 100644
index 00000000..cb5e84b5
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dialog.h
@@ -0,0 +1,114 @@
+#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 <QObject>
+#include <QWidget>
+#include <QTime>
+#include <QTimer>
+#include <QMessageBox>
+#include <QMetaType>
+
+// 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();
+ virtual ~TrackerControls();
+#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_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<QSerialPort::BaudRate>(ui.QCB_Serial_baudRate->itemData(val).toInt()) ; settings_changed(); }
+ void set_mod_dataBits(int val) { settings.pDataBits = static_cast<QSerialPort::DataBits>(ui.QCB_Serial_dataBits->itemData(val).toInt()) ; settings_changed(); }
+ void set_mod_parity(int val) { settings.pParity = static_cast<QSerialPort::Parity>(ui.QCB_Serial_parity->itemData(val).toInt()) ; settings_changed(); }
+ void set_mod_stopBits(int val) { settings.pStopBits = static_cast<QSerialPort::StopBits>(ui.QCB_Serial_stopBits->itemData(val).toInt()); settings_changed(); }
+ void set_mod_flowControl(int val) { settings.pFlowControl = static_cast<QSerialPort::FlowControl>(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_dll.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp
new file mode 100644
index 00000000..5f64fe4b
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp
@@ -0,0 +1,102 @@
+/********************************************************************************
+* FaceTrackNoIR This program is a private project of some enthusiastic *
+* gamers from Holland, who don't like to pay much for *
+* head-tracking. *
+* *
+* Copyright (C) 2012 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* Homepage: http://facetracknoir.sourceforge.net/home/default.htm *
+* *
+* Copyright (C) 2012 FuraX49 (HAT Tracker plugins) *
+* Homepage: http://hatire.sourceforge.net *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU General Public License as published by the *
+* Free Software Foundation; either version 3 of the License, or (at your *
+* option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but *
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
+* more details. *
+* *
+* You should have received a copy of the GNU General Public License along *
+* with this program; if not, see <http://www.gnu.org/licenses/>. *
+* *
+********************************************************************************/
+
+#include "ftnoir_tracker_hat.h"
+#include <QIcon>
+#include <QDebug>
+
+TrackerDll::TrackerDll() {
+ //populate the description strings
+ trackerFullName = "Hatire Arduino";
+ trackerShortName = "HAT";
+ trackerDescription = "FaceTrackNoIR HAT";
+}
+
+TrackerDll::~TrackerDll()
+{
+
+}
+
+#ifndef OPENTRACK_API
+void TrackerDll::Initialize()
+{
+ return;
+}
+#endif
+
+#ifndef OPENTRACK_API
+void TrackerDll::getFullName(QString *strToBeFilled)
+{
+ *strToBeFilled = trackerFullName;
+}
+
+void TrackerDll::getShortName(QString *strToBeFilled)
+{
+ *strToBeFilled = trackerShortName;
+}
+
+void TrackerDll::getDescription(QString *strToBeFilled)
+{
+ *strToBeFilled = trackerDescription;
+}
+
+void TrackerDll::getIcon(QIcon *icon)
+{
+ *icon = QIcon(":/images/hat.png");
+}
+#else
+
+QString TrackerDll::name()
+{
+ return trackerFullName;
+}
+
+QIcon TrackerDll::icon()
+{
+ return QIcon(":/images/hat.png");
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Factory function that creates instances if the Tracker object.
+
+// Export both decorated and undecorated names.
+// GetTrackerDll - Undecorated name, which can be easily used with GetProcAddress
+// Win32 API function.
+// _GetTrackerDll@0 - Common name decoration for __stdcall functions in C language.
+
+#ifdef OPENTRACK_API
+# include "opentrack/plugin-support.h"
+extern "C" OPENTRACK_EXPORT Metadata* GetMetadata()
+#else
+# pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
+FTNOIR_TRACKER_BASE_EXPORT ITrackerDllPtr __stdcall GetTrackerDll()
+#endif
+{
+ return new TrackerDll;
+}
diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp
new file mode 100644
index 00000000..a327c0c1
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.cpp
@@ -0,0 +1,170 @@
+/********************************************************************************
+* FaceTrackNoIR This program is a private project of some enthusiastic *
+* gamers from Holland, who don't like to pay much for *
+* head-tracking. *
+* *
+* Copyright (C) 2012 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* Homepage: http://facetracknoir.sourceforge.net/home/default.htm *
+* *
+* Copyright (C) 2012 FuraX49 (HAT Tracker plugins) *
+* Homepage: http://hatire.sourceforge.net *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU General Public License as published by the *
+* Free Software Foundation; either version 3 of the License, or (at your *
+* option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but *
+* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
+* more details. *
+* *
+* You should have received a copy of the GNU General Public License along *
+* with this program; if not, see <http://www.gnu.org/licenses/>. *
+* *
+********************************************************************************/
+#include <QCoreApplication>
+#include <QSettings>
+#include <QVariant>
+
+#include "ftnoir_tracker_hat_settings.h"
+#ifdef OPENTRACK_API
+#include "opentrack/options.hpp"
+#endif
+
+void TrackerSettings::load_ini()
+{
+#ifdef OPENTRACK_API
+ QSettings settings(options::group::org); // Registry settings (in HK_USER)
+#else
+ QSettings settings("opentrack"); // Registry settings (in HK_USER)
+#endif
+#ifdef OPENTRACK_API
+ QString currentFile = settings.value( options::group::filename_key, QCoreApplication::applicationDirPath() + options::group::default_path ).toString();
+#else
+ QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
+#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();
+
+
+ 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<QSerialPort::BaudRate>(iniFile.value("BaudRate",QSerialPort::Baud115200).toInt());
+ pDataBits=static_cast<QSerialPort::DataBits>(iniFile.value("DataBits",QSerialPort::Data8).toInt());
+ pParity=static_cast<QSerialPort::Parity>(iniFile.value("Parity",QSerialPort::NoParity).toInt());
+ pStopBits=static_cast<QSerialPort::StopBits>(iniFile.value("StopBits",QSerialPort::OneStop).toInt());
+ pFlowControl=static_cast<QSerialPort::FlowControl>(iniFile.value("FlowControl",QSerialPort::HardwareControl).toInt());
+
+ iniFile.endGroup();
+}
+
+
+void TrackerSettings::save_ini() const
+{
+
+#ifdef OPENTRACK_API
+ QSettings settings(options::group::org); // Registry settings (in HK_USER)
+#else
+ QSettings settings("opentrack"); // Registry settings (in HK_USER)
+#endif
+#ifdef OPENTRACK_API
+ QString currentFile = settings.value( options::group::filename_key, QCoreApplication::applicationDirPath() + options::group::default_path ).toString();
+#else
+ QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
+#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( "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
new file mode 100644
index 00000000..5200e63f
--- /dev/null
+++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat_settings.h
@@ -0,0 +1,70 @@
+/* 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 <QtSerialPort/QSerialPort>
+
+//-----------------------------------------------------------------------------
+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;
+
+ 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
new file mode 100644
index 00000000..d8f5aac4
--- /dev/null
+++ b/ftnoir_tracker_hatire/images/hat.ico
Binary files differ
diff --git a/ftnoir_tracker_hatire/images/hat.png b/ftnoir_tracker_hatire/images/hat.png
new file mode 100644
index 00000000..a5f7852f
--- /dev/null
+++ b/ftnoir_tracker_hatire/images/hat.png
Binary files differ
diff --git a/ftnoir_tracker_hatire/images/hat_logo.png b/ftnoir_tracker_hatire/images/hat_logo.png
new file mode 100644
index 00000000..c3a92b1b
--- /dev/null
+++ b/ftnoir_tracker_hatire/images/hat_logo.png
Binary files differ
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
index 537d3cf6..53a05ce7 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
@@ -115,7 +115,7 @@ void Tracker::load_settings(ht_config_t* config)
config->pyrlk_pyramids = 0;
config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
config->max_keypoints = 150;
- config->keypoint_distance = 6;
+ config->keypoint_distance = 5;
config->force_fps = nframes;
config->camera_index = s.camera_idx - 1;
config->ransac_num_iters = 100;
@@ -124,7 +124,7 @@ void Tracker::load_settings(ht_config_t* config)
config->ransac_abs_max_mean_error = 14;
config->ransac_max_mean_error = 8;
config->debug = 0;
- config->ransac_min_features = 0.86;
+ config->ransac_min_features = 0.8;
int res = s.resolution;
if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
res = 0;
@@ -177,6 +177,7 @@ void Tracker::start_tracker(QFrame* videoframe)
shm->frame.channels = shm->frame.width = shm->frame.height = 0;
shm->pause = shm->terminate = shm->running = false;
shm->timer = 0;
+ shm->result.filled = false;
subprocess.setWorkingDirectory(QCoreApplication::applicationDirPath() + "/tracker-ht");
#if defined(_WIN32)
subprocess.start("\"" + QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir" + "\"");
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp
index 352448a3..2dc0ad6b 100644
--- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp
@@ -36,9 +36,9 @@ FTNoIR_Tracker::~FTNoIR_Tracker()
g_pJoystick->Release();
}
if (g_pDI)
- {
+ {
g_pDI->Release();
- }
+ }
}
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
@@ -47,7 +47,7 @@ static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
VOID* pContext )
{
auto self = (FTNoIR_Tracker*) pContext;
-
+
if( pdidoi->dwType & DIDFT_AXIS )
{
DIPROPRANGE diprg = {0};
@@ -55,8 +55,8 @@ static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
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;
+ 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;
@@ -69,14 +69,14 @@ static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext )
{
- auto self = reinterpret_cast<FTNoIR_Tracker*>(pContext);
- bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid;
+ auto self = reinterpret_cast<FTNoIR_Tracker*>(pContext);
+ bool stop = QString(pdidInstance->tszInstanceName) == self->s.joyid;
- if (stop)
- {
- (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL);
- qDebug() << "device" << static_cast<QString>(self->s.joyid);
- }
+ if (stop)
+ {
+ (void) self->g_pDI->CreateDevice( pdidInstance->guidInstance, &self->g_pJoystick, NULL);
+ qDebug() << "device" << static_cast<QString>(self->s.joyid);
+ }
return stop ? DIENUM_STOP : DIENUM_CONTINUE;
}
@@ -94,8 +94,8 @@ void FTNoIR_Tracker::start_tracker(QFrame* frame)
qDebug() << "create";
goto fail;
}
-
- if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
+
+ if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
EnumJoysticksCallback,
this,
DIEDFL_ATTACHEDONLY)))
@@ -152,52 +152,67 @@ void FTNoIR_Tracker::data(double *data)
if( !g_pDI || !g_pJoystick)
return;
- bool ok = false;
+ 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;
- }
+ 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;
+ if (!ok)
+ return;
- HRESULT hr = 0;
+ HRESULT hr = 0;
if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof( js ), &js ) ) )
return;
const LONG values[] = {
- js.lRx,
- js.lRy,
- js.lRz,
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,
- 90,
+ 180,
180
};
-
+
for (int i = 0; i < 6; i++)
- data[i] = values[i] * limits[i] / AXIS_MAX;
+ {
+ int k = map[i] - 1;
+ if (k < 0 || k >= 8)
+ data[i] = 0;
+ else
+ data[i] = values[k] * limits[i] / AXIS_MAX;
+ }
}
extern "C" OPENTRACK_EXPORT ITracker* GetConstructor()
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h
index d1ae427b..7fb26dfd 100644
--- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h
@@ -32,17 +32,24 @@ using namespace options;
struct settings {
pbundle b;
value<QString> joyid;
+ value<int> joy_1, joy_2, joy_3, joy_4, joy_5, joy_6;
settings() :
b(bundle("tracker-joystick")),
- joyid(b, "joy-id", "")
+ joyid(b, "joy-id", ""),
+ 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)
{}
};
class FTNoIR_Tracker : public ITracker
{
public:
- FTNoIR_Tracker();
- ~FTNoIR_Tracker();
+ FTNoIR_Tracker();
+ ~FTNoIR_Tracker();
void start_tracker(QFrame *frame);
void data(double *data);
void reload();
@@ -53,7 +60,7 @@ public:
DIDEVICEINSTANCE def;
int iter; // XXX bad style
settings s;
- static constexpr int AXIS_MAX = 65535;
+ static constexpr int AXIS_MAX = 65535;
};
class TrackerControls: public ITrackerDialog
@@ -68,8 +75,8 @@ public:
FTNoIR_Tracker* tracker;
settings s;
private slots:
- void doOK();
- void doCancel();
+ void doOK();
+ void doCancel();
};
class FTNoIR_TrackerDll : public Metadata
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui
index 424d1c44..3533f93d 100644
--- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui
@@ -9,36 +9,18 @@
<rect>
<x>0</x>
<y>0</y>
- <width>458</width>
- <height>134</height>
+ <width>251</width>
+ <height>303</height>
</rect>
</property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
<property name="windowTitle">
- <string>Joystick protocol settings</string>
+ <string>Tracker settings</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../facetracknoir/images/facetracknoir.png</normaloff>../facetracknoir/images/facetracknoir.png</iconset>
</property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <property name="horizontalSpacing">
- <number>6</number>
- </property>
- <property name="verticalSpacing">
- <number>6</number>
- </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>12</number>
</property>
@@ -51,42 +33,417 @@
<property name="bottomMargin">
<number>6</number>
</property>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Joystick</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="joylist">
+ <item>
+ <widget class="QFrame" name="frame">
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Device</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="joylist">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="2" column="0" colspan="2">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Mapping</string>
</property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QComboBox" name="joy_1">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="joy_2">
+ <property name="currentIndex">
+ <number>2</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="joy_3">
+ <property name="currentIndex">
+ <number>3</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="joy_4">
+ <property name="currentIndex">
+ <number>4</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="joy_5">
+ <property name="currentIndex">
+ <number>5</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="joy_6">
+ <property name="currentIndex">
+ <number>6</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disabled</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Joystick axis #8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>X</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="1" column="0" colspan="2">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Only first 6 axes available.
-Adjust order in mapping window &quot;output remap&quot; option.</string>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
- <tabstop>joylist</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp
index bb95dd92..b201f3f8 100644
--- a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp
@@ -37,8 +37,15 @@ fin:
if (g_pDI)
g_pDI->Release();
}
-
- tie_setting(s.joyid, ui.joylist);
+
+ tie_setting(s.joyid, ui.joylist);
+
+ 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() {
diff --git a/ftnoir_tracker_libevdev/ftnoir_libevdev.ui b/ftnoir_tracker_libevdev/ftnoir_libevdev.ui
deleted file mode 100644
index 6c1ebcae..00000000
--- a/ftnoir_tracker_libevdev/ftnoir_libevdev.ui
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ui_libevdev_tracker_dialog</class>
- <widget class="QWidget" name="ui_libevdev_tracker_dialog">
- <property name="windowModality">
- <enum>Qt::NonModal</enum>
- </property>
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>677</width>
- <height>90</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>libevdev tracker settings</string>
- </property>
- <property name="windowIcon">
- <iconset>
- <normaloff>../facetracknoir/images/facetracknoir.png</normaloff>../facetracknoir/images/facetracknoir.png</iconset>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="1">
- <widget class="QComboBox" name="comboBox"/>
- </item>
- <item row="1" column="1">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Device</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
- <slots>
- <slot>startEngineClicked()</slot>
- <slot>stopEngineClicked()</slot>
- <slot>cameraSettingsClicked()</slot>
- </slots>
-</ui>
diff --git a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.cpp b/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.cpp
deleted file mode 100644
index 6557eada..00000000
--- a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "ftnoir_tracker_libevdev.h"
-#include "opentrack/plugin-api.hpp"
-
-#include <algorithm>
-
-#include <QDir>
-#include <QDebug>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <unistd.h>
-#include <string>
-
-static const int ot_libevdev_joystick_axes[6] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-
-FTNoIR_Tracker::FTNoIR_Tracker() : node(nullptr), success(false), should_quit(false)
-{
-}
-
-FTNoIR_Tracker::~FTNoIR_Tracker()
-{
- if (success)
- {
- should_quit = true;
- wait();
- }
- if (node)
- libevdev_free(node);
- if (fd != -1)
- close(fd);
-}
-
-void FTNoIR_Tracker::start_tracker(QFrame*)
-{
- QString node_name = s.device_name;
- std::string str = (QString("/dev/input/by-id/") + node_name).toStdString();
- const char* filename = str.c_str();
-
- fd = open(filename, 0, O_RDWR);
- if (fd == -1)
- {
- qDebug() << "error opening" << filename;
- return;
- }
-
- int ret = libevdev_new_from_fd(fd, &node);
- if (ret)
- {
- qDebug() << "libevdev open error" << ret;
- return;
- }
-
- for (int i = 0; i < 6; i++)
- {
- // no error checking here, errors result in SIGFPE
- a_min[i] = libevdev_get_abs_minimum(node, ot_libevdev_joystick_axes[i]);
- a_max[i] = libevdev_get_abs_maximum(node, ot_libevdev_joystick_axes[i]);
- qDebug() << "axis limits" << i << a_min[i] << "->" << a_max[i];
- }
-
- success = true;
-
- QThread::start();
-}
-
-void FTNoIR_Tracker::run()
-{
- while (!should_quit)
- {
- struct input_event ev;
- int status = libevdev_next_event(node, LIBEVDEV_READ_FLAG_NORMAL, &ev);
- if (status != LIBEVDEV_READ_STATUS_SUCCESS)
- continue;
- if (ev.type == EV_ABS || ev.type == EV_MSC)
- {
- const int code = ev.code;
- for (int i = 0; i < 6; i++)
- {
- if (ot_libevdev_joystick_axes[i] == code)
- {
- QMutexLocker l(&mtx);
- values[i] = ev.value;
- break;
- }
- }
- }
- }
-}
-
-void FTNoIR_Tracker::data(double *data)
-{
- if (node)
- {
- QMutexLocker l(&mtx);
- for (int i = 0; i < 6; i++)
- {
- int val = values[i];
- double v = (val - a_min[i])*(i >= Yaw ? 180. : 100.) / a_max[i] - a_min[i];
- data[i] = v;
- }
- }
-}
-
-extern "C" OPENTRACK_EXPORT ITracker* GetConstructor()
-{
- return new FTNoIR_Tracker;
-}
diff --git a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.h b/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.h
deleted file mode 100644
index 0ae1c8b3..00000000
--- a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma once
-#include <cmath>
-#include "libevdev/libevdev.h"
-#include "opentrack/plugin-api.hpp"
-#include "opentrack/options.hpp"
-#include "./ui_ftnoir_libevdev.h"
-#include <QThread>
-#include <QMutex>
-#include <QMutexLocker>
-using namespace options;
-
-struct settings {
- pbundle b;
- value<QString> device_name;
- settings() :
- b(bundle("libevdev-tracker")),
- device_name(b, "device-name", "")
- {}
-};
-
-class FTNoIR_Tracker : public ITracker, private QThread
-{
-public:
- FTNoIR_Tracker();
- ~FTNoIR_Tracker() override;
- void start_tracker(QFrame *);
- void data(double *data);
-private:
- void run() override;
- struct libevdev* node;
- int fd;
- settings s;
- bool success;
- int a_min[6], a_max[6], values[6];
- QMutex mtx;
- volatile bool should_quit;
-};
-
-class TrackerControls: public ITrackerDialog
-{
- Q_OBJECT
-public:
- TrackerControls();
- void register_tracker(ITracker *) {}
- void unregister_tracker() {}
-private:
- Ui::ui_libevdev_tracker_dialog ui;
- settings s;
-private slots:
- void doOK();
- void doCancel();
-};
-
-class FTNoIR_TrackerDll : public Metadata
-{
-public:
- QString name() { return QString("libevdev joystick input"); }
- QIcon icon() { return QIcon(":/images/facetracknoir.png"); }
-};
diff --git a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dialog.cpp b/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dialog.cpp
deleted file mode 100644
index 02f48639..00000000
--- a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dialog.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "ftnoir_tracker_libevdev.h"
-#include "opentrack/plugin-api.hpp"
-
-#include <QDir>
-
-TrackerControls::TrackerControls()
-{
- ui.setupUi(this);
-
- connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
- connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
-
- ui.comboBox->clear();
-
- QDir dir("/dev/input/by-id");
- auto devices = dir.entryList(QStringList { "usb-?*-event-?*"});
- for (QString dev : devices)
- ui.comboBox->addItem(dev);
- tie_setting(s.device_name, ui.comboBox);
-}
-
-void TrackerControls::doOK() {
- s.b->save();
- this->close();
-}
-
-void TrackerControls::doCancel() {
- s.b->reload();
- this->close();
-}
-
-extern "C" OPENTRACK_EXPORT ITrackerDialog* GetDialog()
-{
- return new TrackerControls;
-}
diff --git a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dll.cpp b/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dll.cpp
deleted file mode 100644
index 26c858b9..00000000
--- a/ftnoir_tracker_libevdev/ftnoir_tracker_libevdev_dll.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "ftnoir_tracker_libevdev.h"
-#include "opentrack/plugin-api.hpp"
-
-extern "C" OPENTRACK_EXPORT Metadata* GetMetadata()
-{
- return new FTNoIR_TrackerDll;
-}
diff --git a/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui b/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui
index 73b1f767..0e6048c3 100644
--- a/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui
+++ b/ftnoir_tracker_pt/FTNoIR_PT_Controls.ui
@@ -9,12 +9,12 @@
<rect>
<x>0</x>
<y>0</y>
- <width>453</width>
- <height>621</height>
+ <width>397</width>
+ <height>588</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -36,82 +36,10 @@
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
- <item row="1" column="0">
- <widget class="QGroupBox" name="groupBox_5">
- <property name="title">
- <string>Status</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_10">
- <item row="2" column="2">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Extracted Points:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_38">
- <property name="text">
- <string>Camera Info:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QDialogButtonBox" name="buttonBox_2">
- <property name="standardButtons">
- <set>QDialogButtonBox::Apply</set>
- </property>
- <property name="centerButtons">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="caminfo_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>120</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="pointinfo_label">
- <property name="minimumSize">
- <size>
- <width>50</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -155,21 +83,30 @@
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QComboBox" name="camdevice_combo">
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="res_x_spin">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="minimumContentsLength">
+ <property name="toolTip">
+ <string>Desired capture width</string>
+ </property>
+ <property name="suffix">
+ <string> px</string>
+ </property>
+ <property name="maximum">
+ <number>2000</number>
+ </property>
+ <property name="singleStep">
<number>10</number>
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_36">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_41">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -177,34 +114,38 @@
</sizepolicy>
</property>
<property name="text">
- <string>Width</string>
+ <string>Height</string>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="res_x_spin">
+ <item row="0" column="1">
+ <widget class="QComboBox" name="camdevice_combo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="toolTip">
- <string>Desired capture width</string>
- </property>
- <property name="suffix">
- <string> px</string>
+ <property name="minimumContentsLength">
+ <number>10</number>
</property>
- <property name="maximum">
- <number>2000</number>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_36">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- <property name="singleStep">
- <number>10</number>
+ <property name="text">
+ <string>Width</string>
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_41">
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -212,7 +153,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Height</string>
+ <string>Field of view</string>
</property>
</widget>
</item>
@@ -273,116 +214,39 @@
</property>
</widget>
</item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_4">
- <property name="title">
- <string>Camera orientation</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="label_18">
- <property name="text">
- <string>Roll</string>
- </property>
- <property name="buddy">
- <cstring>camroll_combo</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="camroll_combo">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Rotation of the camera image</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Pitch</string>
- </property>
- <property name="buddy">
- <cstring>campitch_spin</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="campitch_spin">
- <property name="contextMenuPolicy">
- <enum>Qt::DefaultContextMenu</enum>
- </property>
- <property name="toolTip">
- <string>The angle the camera is facing upwards</string>
- </property>
+ <item row="4" column="1">
+ <widget class="QSpinBox" name="fov">
<property name="suffix">
- <string> deg</string>
+ <string>°</string>
+ </property>
+ <property name="prefix">
+ <string/>
</property>
<property name="minimum">
- <number>-180</number>
+ <number>10</number>
</property>
<property name="maximum">
- <number>180</number>
+ <number>90</number>
</property>
</widget>
</item>
- <item row="1" column="2">
+ <item row="5" column="0">
<widget class="QLabel" name="label_5">
- <property name="text">
- <string>positive = upwards</string>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_20">
<property name="text">
- <string>Yaw</string>
- </property>
- <property name="buddy">
- <cstring>camyaw_spin</cstring>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QSpinBox" name="camyaw_spin">
- <property name="contextMenuPolicy">
- <enum>Qt::DefaultContextMenu</enum>
- </property>
- <property name="toolTip">
- <string>The angle the camera is facing leftwards</string>
- </property>
- <property name="suffix">
- <string> deg</string>
- </property>
- <property name="prefix">
- <string/>
- </property>
- <property name="minimum">
- <number>-180</number>
- </property>
- <property name="maximum">
- <number>180</number>
+ <string>Dynamic pose resolution</string>
</property>
</widget>
</item>
- <item row="2" column="2">
- <widget class="QLabel" name="label_21">
+ <item row="5" column="1">
+ <widget class="QCheckBox" name="dynamic_pose">
<property name="text">
- <string>positve = left</string>
+ <string/>
</property>
</widget>
</item>
@@ -520,14 +384,20 @@
<attribute name="title">
<string>Model</string>
</attribute>
- <layout class="QVBoxLayout" name="verticalLayout_16">
- <item>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
<widget class="QTabWidget" name="model_tabs">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<property name="usesScrollButtons">
<bool>false</bool>
@@ -545,6 +415,18 @@
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>331</width>
+ <height>208</height>
+ </size>
+ </property>
<property name="title">
<string>Model Dimensions</string>
</property>
@@ -558,7 +440,7 @@
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -570,14 +452,14 @@
<widget class="QSpinBox" name="clip_bheight_spin">
<property name="geometry">
<rect>
- <x>110</x>
- <y>115</y>
+ <x>150</x>
+ <y>130</y>
<width>100</width>
<height>22</height>
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -589,7 +471,7 @@
<widget class="QLabel" name="label_44">
<property name="geometry">
<rect>
- <x>40</x>
+ <x>65</x>
<y>55</y>
<width>71</width>
<height>111</height>
@@ -605,8 +487,8 @@
<widget class="QLabel" name="label_50">
<property name="geometry">
<rect>
- <x>10</x>
- <y>35</y>
+ <x>20</x>
+ <y>40</y>
<width>46</width>
<height>13</height>
</rect>
@@ -619,13 +501,13 @@
<property name="geometry">
<rect>
<x>50</x>
- <y>165</y>
+ <y>160</y>
<width>100</width>
<height>22</height>
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -637,14 +519,14 @@
<widget class="QSpinBox" name="clip_theight_spin">
<property name="geometry">
<rect>
- <x>110</x>
- <y>75</y>
+ <x>150</x>
+ <y>70</y>
<width>100</width>
<height>22</height>
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -656,7 +538,7 @@
<widget class="QLabel" name="label_51">
<property name="geometry">
<rect>
- <x>255</x>
+ <x>290</x>
<y>40</y>
<width>46</width>
<height>13</height>
@@ -669,8 +551,8 @@
<widget class="QLabel" name="label_45">
<property name="geometry">
<rect>
- <x>265</x>
- <y>60</y>
+ <x>300</x>
+ <y>70</y>
<width>21</width>
<height>111</height>
</rect>
@@ -693,14 +575,20 @@
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QGroupBox" name="groupBox_9">
+ <property name="minimumSize">
+ <size>
+ <width>331</width>
+ <height>208</height>
+ </size>
+ </property>
<property name="title">
<string>Model Dimensions</string>
</property>
<widget class="QLabel" name="label_46">
<property name="geometry">
<rect>
- <x>30</x>
- <y>90</y>
+ <x>100</x>
+ <y>60</y>
<width>111</width>
<height>81</height>
</rect>
@@ -716,7 +604,7 @@
<property name="geometry">
<rect>
<x>20</x>
- <y>35</y>
+ <y>40</y>
<width>46</width>
<height>13</height>
</rect>
@@ -728,14 +616,14 @@
<widget class="QSpinBox" name="cap_length_spin">
<property name="geometry">
<rect>
- <x>20</x>
- <y>70</y>
+ <x>90</x>
+ <y>40</y>
<width>101</width>
<height>22</height>
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -744,37 +632,11 @@
<number>65535</number>
</property>
</widget>
- <widget class="QLabel" name="label_54">
- <property name="geometry">
- <rect>
- <x>140</x>
- <y>90</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>R</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_55">
- <property name="geometry">
- <rect>
- <x>290</x>
- <y>85</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>R</string>
- </property>
- </widget>
<widget class="QLabel" name="label_47">
<property name="geometry">
<rect>
- <x>270</x>
- <y>85</y>
+ <x>220</x>
+ <y>100</y>
<width>81</width>
<height>81</height>
</rect>
@@ -789,14 +651,14 @@
<widget class="QSpinBox" name="cap_width_spin">
<property name="geometry">
<rect>
- <x>255</x>
- <y>55</y>
- <width>100</width>
+ <x>240</x>
+ <y>70</y>
+ <width>81</width>
<height>22</height>
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -808,8 +670,8 @@
<widget class="QLabel" name="label_49">
<property name="geometry">
<rect>
- <x>290</x>
- <y>35</y>
+ <x>240</x>
+ <y>40</y>
<width>46</width>
<height>13</height>
</rect>
@@ -821,14 +683,14 @@
<widget class="QSpinBox" name="cap_height_spin">
<property name="geometry">
<rect>
- <x>60</x>
- <y>120</y>
- <width>116</width>
+ <x>20</x>
+ <y>90</y>
+ <width>81</width>
<height>22</height>
</rect>
</property>
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -868,7 +730,7 @@
<item row="2" column="5">
<widget class="QSpinBox" name="m2y_spin">
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -894,7 +756,7 @@
<item row="1" column="2">
<widget class="QSpinBox" name="m1x_spin">
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -907,7 +769,7 @@
<item row="2" column="2">
<widget class="QSpinBox" name="m1y_spin">
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -920,7 +782,7 @@
<item row="3" column="5">
<widget class="QSpinBox" name="m2z_spin">
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -933,7 +795,7 @@
<item row="1" column="5">
<widget class="QSpinBox" name="m2x_spin">
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -945,15 +807,21 @@
</item>
<item row="0" column="0" colspan="6">
<widget class="QLabel" name="label_56">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Location of the two remaining model points&lt;br/&gt;with respect to the reference point in default pose&lt;/p&gt;&lt;p&gt;Use any units you want, e.g. millimeters, inches, parsecs...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Location of the two remaining model points&lt;br/&gt;with respect to the reference point in default pose&lt;/p&gt;&lt;p&gt;Use any units you want, not necessarily centimeters.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="m1z_spin">
<property name="suffix">
- <string> units</string>
+ <string> mm</string>
</property>
<property name="minimum">
<number>-65535</number>
@@ -1011,7 +879,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:16pt;&quot;&gt;P&lt;/span&gt;&lt;span style=&quot; font-size:16pt; vertical-align:sub;&quot;&gt;3&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:16pt;&quot;&gt;P&lt;/span&gt;&lt;span style=&quot; font-size:16pt; vertical-align:sub;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -1048,86 +916,122 @@
</widget>
</widget>
</item>
- <item>
+ <item row="1" column="0">
<widget class="QGroupBox" name="groupBox_10">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="title">
<string>Model position</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
- <item row="1" column="1">
- <widget class="QSpinBox" name="tx_spin">
- <property name="suffix">
- <string> units</string>
- </property>
- <property name="minimum">
- <number>-65535</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
+ <item row="0" column="0">
+ <widget class="QFrame" name="frame_2">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_11">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_61">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>x:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="tx_spin">
+ <property name="suffix">
+ <string> mm</string>
+ </property>
+ <property name="minimum">
+ <number>-65535</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_62">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>y:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="ty_spin">
+ <property name="suffix">
+ <string> mm</string>
+ </property>
+ <property name="minimum">
+ <number>-65535</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_66">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>z:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="tz_spin">
+ <property name="suffix">
+ <string> mm</string>
+ </property>
+ <property name="minimum">
+ <number>-65535</number>
+ </property>
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="0" column="0" colspan="3">
+ <item row="0" column="1">
<widget class="QLabel" name="label_59">
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Translation from head center to model reference point&lt;br/&gt; in default pose&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Only pitch and yaw during calibration.&lt;/p&gt;&lt;p&gt;Don't roll and don't translate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="2" column="1">
- <widget class="QSpinBox" name="ty_spin">
- <property name="suffix">
- <string> units</string>
- </property>
- <property name="minimum">
- <number>-65535</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_62">
- <property name="text">
- <string>y:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_66">
- <property name="text">
- <string>z:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_61">
- <property name="text">
- <string>x:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QSpinBox" name="tz_spin">
- <property name="suffix">
- <string> units</string>
- </property>
- <property name="minimum">
- <number>-65535</number>
- </property>
- <property name="maximum">
- <number>65536</number>
- </property>
- </widget>
- </item>
- <item row="4" column="2">
<widget class="QPushButton" name="tcalib_button">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
- <string>Calibrate</string>
+ <string>Toggle calibration</string>
</property>
<property name="checkable">
<bool>true</bool>
@@ -1174,17 +1078,89 @@
</widget>
</widget>
</item>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox_5">
+ <property name="title">
+ <string>Status</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_10">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Extracted Points:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_38">
+ <property name="text">
+ <string>Camera Info:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="pointinfo_label">
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="caminfo_label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>120</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>camdevice_combo</tabstop>
<tabstop>res_x_spin</tabstop>
- <tabstop>camroll_combo</tabstop>
- <tabstop>campitch_spin</tabstop>
- <tabstop>camyaw_spin</tabstop>
+ <tabstop>res_y_spin</tabstop>
+ <tabstop>fps_spin</tabstop>
+ <tabstop>fov</tabstop>
<tabstop>threshold_slider</tabstop>
+ <tabstop>mindiam_spin</tabstop>
+ <tabstop>threshold_secondary_slider</tabstop>
+ <tabstop>maxdiam_spin</tabstop>
<tabstop>model_tabs</tabstop>
+ <tabstop>clip_tlength_spin</tabstop>
+ <tabstop>clip_theight_spin</tabstop>
+ <tabstop>clip_bheight_spin</tabstop>
+ <tabstop>clip_blength_spin</tabstop>
+ <tabstop>cap_length_spin</tabstop>
+ <tabstop>cap_width_spin</tabstop>
+ <tabstop>cap_height_spin</tabstop>
<tabstop>m1x_spin</tabstop>
<tabstop>m1y_spin</tabstop>
<tabstop>m1z_spin</tabstop>
@@ -1194,6 +1170,7 @@
<tabstop>tx_spin</tabstop>
<tabstop>ty_spin</tabstop>
<tabstop>tz_spin</tabstop>
+ <tabstop>tcalib_button</tabstop>
</tabstops>
<resources>
<include location="ftnoir_tracker_pt.qrc"/>
diff --git a/ftnoir_tracker_pt/camera.cpp b/ftnoir_tracker_pt/camera.cpp
index fec503e1..432e0158 100644
--- a/ftnoir_tracker_pt/camera.cpp
+++ b/ftnoir_tracker_pt/camera.cpp
@@ -119,13 +119,12 @@ void Camera::set_fps(int 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();
- _set_fps();
- }
+ 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_frame(float dt, cv::Mat* frame)
@@ -143,20 +142,20 @@ bool Camera::get_frame(float dt, cv::Mat* frame)
return new_frame;
}
-// ----------------------------------------------------------------------------
-#ifdef OPENTRACK_API
void CVCamera::start()
{
+ if (cap)
+ delete cap;
cap = new VideoCapture(desired_index);
- // extract camera info
+ _set_res();
+ _set_fps();
+ // extract camera info
if (cap->isOpened())
- {
- _set_fps();
- _set_res();
- active = true;
- active_index = desired_index;
- cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH);
- cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT);
+ {
+ active = true;
+ active_index = desired_index;
+ cam_info.res_x = 0;
+ cam_info.res_y = 0;
} else {
delete cap;
cap = nullptr;
@@ -169,25 +168,28 @@ void CVCamera::stop()
{
cap->release();
delete cap;
+ cap = nullptr;
}
- active = false;
+ active = false;
}
bool CVCamera::_get_frame(Mat* frame)
{
if (cap && cap->isOpened())
- {
+ {
Mat img;
for (int i = 0; i < 100 && !cap->read(img); i++)
;;
- if (img.empty())
- return false;
+ if (img.empty())
+ return false;
- *frame = img;
- return true;
- }
- return false;
+ *frame = img;
+ cam_info.res_x = img.cols;
+ cam_info.res_y = img.rows;
+ return true;
+ }
+ return false;
}
void CVCamera::_set_fps()
@@ -197,13 +199,11 @@ void CVCamera::_set_fps()
void CVCamera::_set_res()
{
- if (cap)
- {
+ if (cap)
+ {
cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x);
cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y);
- cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH);
- cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT);
- }
+ }
}
void CVCamera::_set_device_index()
{
@@ -214,117 +214,3 @@ void CVCamera::_set_device_index()
}
cap = new VideoCapture(desired_index);
}
-
-#else
-// ----------------------------------------------------------------------------
-VICamera::VICamera() : frame_buffer(NULL)
-{
- VI.listDevices();
-}
-
-void VICamera::start()
-{
- if (desired_index >= 0)
- {
- if (cam_desired.res_x == 0 || cam_desired.res_y == 0)
- VI.setupDevice(desired_index);
- else
- VI.setupDevice(desired_index, cam_desired.res_x, cam_desired.res_y);
-
- active = true;
- active_index = desired_index;
-
- cam_info.res_x = VI.getWidth(active_index);
- cam_info.res_y = VI.getHeight(active_index);
- new_frame = cv::Mat(cam_info.res_y, cam_info.res_x, CV_8UC3);
- // If matrix is not continuous we have to copy manually via frame_buffer
- if (!new_frame.isContinuous()) {
- unsigned int size = VI.getSize(active_index);
- frame_buffer = new unsigned char[size];
- }
- }
-}
-
-void VICamera::stop()
-{
- if (active)
- {
- VI.stopDevice(active_index);
- }
- if (frame_buffer)
- {
- delete[] frame_buffer;
- frame_buffer = NULL;
- }
- active = false;
-}
-
-bool VICamera::_get_frame(Mat* frame)
-{
- if (active && VI.isFrameNew(active_index))
- {
- if (new_frame.isContinuous())
- {
- VI.getPixels(active_index, new_frame.data, false, true);
- }
- else
- {
- // If matrix is not continuous we have to copy manually via frame_buffer
- VI.getPixels(active_index, frame_buffer, false, true);
- new_frame = cv::Mat(cam_info.res_y, cam_info.res_x, CV_8UC3, frame_buffer).clone();
- }
- *frame = new_frame;
- return true;
- }
- return false;
-}
-
-void VICamera::_set_device_index()
-{
- if (active) restart();
-}
-
-void VICamera::_set_f()
-{
- cam_info.f = cam_desired.f;
-}
-
-void VICamera::_set_fps()
-{
- bool was_active = active;
- if (active) stop();
- VI.setIdealFramerate(desired_index, cam_desired.fps);
- if (was_active) start();
-}
-
-void VICamera::_set_res()
-{
- if (active) restart();
-}
-#endif
-
-// ----------------------------------------------------------------------------
-Mat FrameRotation::rotate_frame(Mat frame)
-{
- switch (rotation)
- {
- case CLOCKWISE:
- {
- Mat dst;
- transpose(frame, dst);
- flip(dst, dst, 1);
- return dst;
- }
-
- case COUNTER_CLOCKWISE:
- {
- Mat dst;
- transpose(frame, dst);
- flip(dst, dst, 0);
- return dst;
- }
-
- default:
- return frame;
- }
-}
diff --git a/ftnoir_tracker_pt/camera.h b/ftnoir_tracker_pt/camera.h
index 889bf2d3..2bce6f35 100644
--- a/ftnoir_tracker_pt/camera.h
+++ b/ftnoir_tracker_pt/camera.h
@@ -5,8 +5,7 @@
* copyright notice and this permission notice appear in all copies.
*/
-#ifndef CAMERA_H
-#define CAMERA_H
+#pragma once
#include <opencv2/core/core.hpp>
#ifndef OPENTRACK_API
@@ -128,14 +127,3 @@ enum RotationType
ZERO = 1,
COUNTER_CLOCKWISE = 2
};
-
-// ----------------------------------------------------------------------------
-class FrameRotation
-{
-public:
- RotationType rotation;
-
- cv::Mat rotate_frame(cv::Mat frame);
-};
-
-#endif //CAMERA_H
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp
index 9b3795b9..acf4daa0 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp
+++ b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp
@@ -21,10 +21,11 @@ using namespace cv;
Tracker::Tracker()
: mutex(QMutex::Recursive),
commands(0),
- video_widget(NULL),
+ video_widget(NULL),
video_frame(NULL),
- new_settings(nullptr)
+ ever_success(false)
{
+ connect(s.b.get(), SIGNAL(saving()), this, SLOT(apply_settings()));
}
Tracker::~Tracker()
@@ -48,6 +49,13 @@ void Tracker::reset_command(Command command)
commands &= ~command;
}
+float Tracker::get_focal_length()
+{
+ static constexpr float pi = 3.1415926f;
+ const float fov = static_cast<int>(s.fov) * pi / 180.f;
+ return 0.5f / tan(0.5f * fov);
+}
+
void Tracker::run()
{
#ifdef PT_PERF_LOG
@@ -57,21 +65,43 @@ void Tracker::run()
#endif
while((commands & ABORT) == 0)
- {
- apply_inner();
- const double dt = time.start() * 1e-9;
+ {
+ const double dt = time.elapsed() * 1e-9;
+ time.start();
+ cv::Mat frame;
const bool new_frame = camera.get_frame(dt, &frame);
if (new_frame && !frame.empty())
{
QMutexLocker lock(&mutex);
- frame = frame_rotation.rotate_frame(frame);
- const std::vector<cv::Vec2f>& points = point_extractor.extract_points(frame);
- for (auto p : points)
+ std::vector<cv::Vec2f> points = point_extractor.extract_points(frame);
+
+ bool success = points.size() == PointModel::N_POINTS;
+
+ ever_success |= success;
+
+ if (success)
+ point_tracker.track(points, PointModel(s), get_focal_length(), s.dynamic_pose);
+
{
+ Affine X_CM = pose();
+ Affine X_MH(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
+ float fx = get_focal_length();
+ cv::Vec2f p_(p[0] / p[2] * fx, p[1] / p[2] * fx); // projected to screen
+
+ points.push_back(p_);
+ }
+
+ for (int 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),
@@ -83,8 +113,7 @@ void Tracker::run()
color,
4);
}
- if (points.size() == PointModel::N_POINTS)
- point_tracker.track(points, model);
+
video_widget->update_image(frame);
}
#ifdef PT_PERF_LOG
@@ -92,64 +121,18 @@ void Tracker::run()
if (!frame.empty()) log_stream<<" fps: "<<camera.get_info().fps;
log_stream<<"\n";
#endif
- }
-
- qDebug()<<"Tracker:: Thread stopping";
-}
-void Tracker::apply(settings& s)
-{
- // caller guarantees object lifetime
- new_settings = &s;
+ }
+ qDebug()<<"Tracker:: Thread stopping";
}
-void Tracker::apply_inner()
+void Tracker::apply_settings()
{
- settings* tmp = new_settings.exchange(nullptr);
- if (tmp == nullptr)
- return;
- reset();
- auto& s = *tmp;
qDebug()<<"Tracker:: Applying settings";
-
- {
- cv::Vec3f M01(s.m01_x, s.m01_y, s.m01_z);
- cv::Vec3f M02(s.m02_x, s.m02_y, s.m02_z);
- model = PointModel(M01, M02);
- }
+ QMutexLocker lock(&mutex);
camera.set_device_index(s.cam_index);
camera.set_res(s.cam_res_x, s.cam_res_y);
camera.set_fps(s.cam_fps);
- frame_rotation.rotation = static_cast<RotationType>(static_cast<int>(s.cam_roll));
- point_extractor.threshold_val = s.threshold;
- point_extractor.threshold_secondary_val = s.threshold_secondary;
- point_extractor.min_size = s.min_point_size;
- point_extractor.max_size = s.max_point_size;
- t_MH = cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z);
- R_GC = Matx33f( cos(deg2rad*s.cam_yaw), 0, sin(deg2rad*s.cam_yaw),
- 0, 1, 0,
- -sin(deg2rad*s.cam_yaw), 0, cos(deg2rad*s.cam_yaw));
- R_GC = R_GC * Matx33f( 1, 0, 0,
- 0, cos(deg2rad*s.cam_pitch), sin(deg2rad*s.cam_pitch),
- 0, -sin(deg2rad*s.cam_pitch), cos(deg2rad*s.cam_pitch));
-
- FrameTrafo X_MH(Matx33f::eye(), t_MH);
- X_GH_0 = R_GC * X_MH;
- qDebug()<<"Tracker::apply ends";
-}
-
-void Tracker::reset()
-{
- QMutexLocker lock(&mutex);
- point_tracker.reset();
-}
-
-void Tracker::center()
-{
- point_tracker.reset(); // we also do a reset here since there is no reset shortkey yet
- QMutexLocker lock(&mutex);
- FrameTrafo X_CM_0 = point_tracker.pose();
- FrameTrafo X_MH(Matx33f::eye(), t_MH);
- X_GH_0 = R_GC * X_CM_0 * X_MH;
+ qDebug()<<"Tracker::apply ends";
}
void Tracker::start_tracker(QFrame *parent_window)
@@ -163,8 +146,7 @@ void Tracker::start_tracker(QFrame *parent_window)
video_layout->addWidget(video_widget);
video_frame->setLayout(video_layout);
video_widget->resize(video_frame->width(), video_frame->height());
- apply(s);
- apply_inner();
+ apply_settings();
camera.start();
start();
}
@@ -172,7 +154,7 @@ void Tracker::start_tracker(QFrame *parent_window)
#ifndef OPENTRACK_API
void Tracker::StopTracker(bool exit)
{
- set_command(PAUSE);
+ set_command(PAUSE);
}
#endif
@@ -182,37 +164,38 @@ void Tracker::StopTracker(bool exit)
void Tracker::data(THeadPoseData *data)
{
- {
- QMutexLocker lock(&mutex);
-
- FrameTrafo X_CM = point_tracker.pose();
- FrameTrafo X_MH(Matx33f::eye(), t_MH);
- FrameTrafo X_GH = R_GC * X_CM * X_MH;
- Matx33f R = X_GH.R * X_GH_0.R.t();
- Vec3f t = X_GH.t - X_GH_0.t;
-
+ if (ever_success)
+ {
+ Affine X_CM = pose();
+
+ Affine X_MH(Matx33f::eye(), cv::Vec3f(s.t_MH_x, s.t_MH_y, s.t_MH_z));
+ Affine X_GH = X_CM * X_MH;
+
+ Matx33f R = X_GH.R;
+ Vec3f t = X_GH.t;
+
+ // translate rotation matrix from opengl (G) to roll-pitch-yaw (E) frame
+ // -z -> x, y -> z, x -> -y
+ 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;
-
- // translate rotation matrix from opengl (G) to roll-pitch-yaw (E) frame
- // -z -> x, y -> z, x -> -y
- 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));
-
- data[Yaw] = rad2deg * alpha;
- data[Pitch] = - rad2deg * beta; // FTNoIR expects a minus here
- data[Roll] = rad2deg * gamma;
- }
+ }
}
//-----------------------------------------------------------------------------
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.h b/ftnoir_tracker_pt/ftnoir_tracker_pt.h
index 921d61cf..349cf2c8 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt.h
+++ b/ftnoir_tracker_pt/ftnoir_tracker_pt.h
@@ -33,22 +33,20 @@
//-----------------------------------------------------------------------------
// Constantly processes the tracking chain in a separate thread
-class Tracker : public ITracker, protected QThread
+class Tracker : public QThread, public ITracker
{
+ Q_OBJECT
public:
Tracker();
~Tracker() override;
void start_tracker(QFrame* parent_window) override;
void data(double* data) override;
- void apply(settings& s);
- void apply_inner();
- void center();
- void reset(); // reset the trackers internal state variables
-
- void pose(FrameTrafo* X_CM) { QMutexLocker lock(&mutex); *X_CM = point_tracker.pose(); }
+ Affine pose() { QMutexLocker lock(&mutex); return point_tracker.pose(); }
int get_n_points() { QMutexLocker lock(&mutex); return point_extractor.get_points().size(); }
void get_cam_info(CamInfo* info) { QMutexLocker lock(&mutex); *info = camera.get_info(); }
+public slots:
+ void apply_settings();
protected:
void run() override;
private:
@@ -59,31 +57,25 @@ private:
};
void set_command(Command command);
void reset_command(Command command);
+
+ float get_focal_length();
+
volatile int commands;
CVCamera camera;
- FrameRotation frame_rotation;
PointExtractor point_extractor;
PointTracker point_tracker;
- FrameTrafo X_GH_0; // for centering
- cv::Vec3f t_MH; // translation from model frame to head frame
- cv::Matx33f R_GC; // rotation from opengl reference frame to camera frame
-
- // --- ui ---
- cv::Mat frame; // the output frame for display
-
PTVideoWidget* video_widget;
QFrame* video_frame;
settings s;
- std::atomic<settings*> new_settings;
Timer time;
+
+ volatile bool ever_success;
static constexpr double rad2deg = 180.0/3.14159265;
static constexpr double deg2rad = 3.14159265/180.0;
-
- PointModel model;
};
#undef VideoWidget
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp
index a15e97b9..7be05bb7 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp
+++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp
@@ -34,17 +34,10 @@ TrackerDialog::TrackerDialog()
ui.camdevice_combo->addItem(iter->c_str());
}
- ui.camroll_combo->addItem("-90");
- ui.camroll_combo->addItem("0");
- ui.camroll_combo->addItem("90");
-
tie_setting(s.cam_index, 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.cam_roll, ui.camroll_combo);
- tie_setting(s.cam_pitch, ui.campitch_spin);
- tie_setting(s.cam_yaw, ui.camyaw_spin);
tie_setting(s.threshold_secondary, ui.threshold_secondary_slider);
tie_setting(s.threshold, ui.threshold_slider);
@@ -72,53 +65,20 @@ TrackerDialog::TrackerDialog()
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);
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(accepted()), this, SLOT(doOK()));
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
- ui.model_tabs->setCurrentIndex(s.active_model_panel);
-
- connect(ui.model_tabs, SIGNAL(currentChanged(int)), this, SLOT(set_model(int)));
connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info()));
timer.start(100);
-
- connect(ui.buttonBox_2, SIGNAL(clicked(QAbstractButton*)), this, SLOT(do_apply_without_saving(QAbstractButton*)));
-}
-
-void TrackerDialog::set_model_clip()
-{
- s.m01_x = 0;
- s.m01_y = static_cast<double>(s.clip_ty);
- s.m01_z = -static_cast<double>(s.clip_tz);
- s.m02_x = 0;
- s.m02_y = -static_cast<double>(s.clip_by);
- s.m02_z = -static_cast<double>(s.clip_bz);
-
- settings_changed();
-}
-
-void TrackerDialog::set_model_cap()
-{
- s.m01_x = -static_cast<double>(s.cap_x);
- s.m01_y = -static_cast<double>(s.cap_y);
- s.m01_z = -static_cast<double>(s.cap_z);
- s.m02_x = static_cast<double>(s.cap_x);
- s.m02_y = -static_cast<double>(s.cap_y);
- s.m02_z = -static_cast<double>(s.cap_z);
-
- settings_changed();
-}
-
-void TrackerDialog::set_model_custom()
-{
- settings_changed();
-}
-
-void TrackerDialog::set_model(int val)
-{
- s.active_model_panel = val;
}
void TrackerDialog::startstop_trans_calib(bool start)
@@ -128,10 +88,13 @@ void TrackerDialog::startstop_trans_calib(bool 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:: Stoppping translation calibration";
+ qDebug()<<"TrackerDialog:: Stopping translation calibration";
trans_calib_running = false;
{
auto tmp = trans_calib.get_estimate();
@@ -139,7 +102,6 @@ void TrackerDialog::startstop_trans_calib(bool start)
s.t_MH_y = tmp[1];
s.t_MH_z = tmp[2];
}
- settings_changed();
}
}
@@ -179,24 +141,13 @@ void TrackerDialog::trans_calib_step()
{
if (tracker)
{
- FrameTrafo X_CM;
- tracker->pose(&X_CM);
+ Affine X_CM = tracker->pose();
trans_calib.update(X_CM.R, X_CM.t);
- cv::Vec3f t_MH = trans_calib.get_estimate();
- s.t_MH_x = t_MH[0];
- s.t_MH_y = t_MH[1];
- s.t_MH_z = t_MH[2];
}
}
-void TrackerDialog::settings_changed()
-{
- if (tracker) tracker->apply(s);
-}
-
void TrackerDialog::save()
{
- do_apply_without_saving(nullptr);
s.b->save();
}
@@ -206,28 +157,6 @@ void TrackerDialog::doOK()
close();
}
-void TrackerDialog::do_apply_without_saving(QAbstractButton*)
-{
- switch (s.active_model_panel) {
- default:
- case 0:
- set_model_clip();
- break;
- case 1:
- set_model_cap();
- break;
- case 2:
- set_model_custom();
- break;
- }
- if (tracker) tracker->apply(s);
-}
-
-void TrackerDialog::doApply()
-{
- save();
-}
-
void TrackerDialog::doCancel()
{
s.b->reload();
@@ -238,8 +167,6 @@ void TrackerDialog::register_tracker(ITracker *t)
{
qDebug()<<"TrackerDialog:: Tracker registered";
tracker = static_cast<Tracker*>(t);
- if (isVisible() & s.b->modifiedp())
- tracker->apply(s);
ui.tcalib_button->setEnabled(true);
//ui.center_button->setEnabled(true);
}
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h
index 7f634c04..c6f7f8e1 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h
+++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h
@@ -36,19 +36,10 @@ public:
public slots:
void doOK();
void doCancel();
- void doApply();
- void do_apply_without_saving(QAbstractButton *);
void startstop_trans_calib(bool start);
void poll_tracker_info();
- void set_model(int idx);
private:
- void set_model_clip();
- void set_model_cap();
- void set_model_custom();
-
- void settings_changed();
-
settings s;
Tracker* tracker;
QTimer timer;
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h
index 9365eb9a..57752ed6 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h
+++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h
@@ -9,7 +9,6 @@
#define FTNOIR_TRACKER_PT_SETTINGS_H
#include <opencv2/core/core.hpp>
-#include "point_tracker.h"
#include "opentrack/options.hpp"
using namespace options;
@@ -21,9 +20,6 @@ struct settings
cam_res_x,
cam_res_y,
cam_fps,
- cam_roll,
- cam_pitch,
- cam_yaw,
threshold,
threshold_secondary,
min_point_size,
@@ -36,8 +32,10 @@ struct settings
value<int> clip_ty, clip_tz, clip_by, clip_bz;
value<int> active_model_panel, cap_x, cap_y, cap_z;
-
- // XXX todo red channel only, good for crapola CCD sensors -sh 20140922
+
+ value<int> fov;
+
+ value<bool> dynamic_pose;
settings() :
b(bundle("tracker-pt")),
@@ -45,9 +43,6 @@ struct settings
cam_res_x(b, "camera-res-width", 640),
cam_res_y(b, "camera-res-height", 480),
cam_fps(b, "camera-fps", 30),
- cam_roll(b, "camera-roll", 1),
- cam_pitch(b, "camera-pitch", 0),
- cam_yaw(b, "camera-yaw", 0),
threshold(b, "threshold-primary", 128),
threshold_secondary(b, "threshold-secondary", 128),
min_point_size(b, "min-point-size", 10),
@@ -68,7 +63,9 @@ struct settings
active_model_panel(b, "active-model-panel", 0),
cap_x(b, "cap-x", 0),
cap_y(b, "cap-y", 0),
- cap_z(b, "cap-z", 0)
+ cap_z(b, "cap-z", 0),
+ fov(b, "camera-fov", 56),
+ dynamic_pose(b, "dynamic-pose-resolution", false)
{}
};
diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp
index 819bf5e8..94096f9d 100644
--- a/ftnoir_tracker_pt/point_extractor.cpp
+++ b/ftnoir_tracker_pt/point_extractor.cpp
@@ -20,7 +20,7 @@ PointExtractor::PointExtractor(){
//freopen("CON", "w", stderr);
}
// ----------------------------------------------------------------------------
-const vector<Vec2f>& PointExtractor::extract_points(Mat& frame)
+std::vector<Vec2f> PointExtractor::extract_points(Mat& frame)
{
const int W = frame.cols;
const int H = frame.rows;
@@ -37,7 +37,8 @@ const vector<Vec2f>& PointExtractor::extract_points(Mat& frame)
Mat frame_gray;
cvtColor(frame, frame_gray, CV_RGB2GRAY);
- int secondary = threshold_secondary_val;
+ int secondary = s.threshold_secondary;
+ int primary = s.threshold;
// mask for everything that passes the threshold (or: the upper threshold of the hysteresis)
Mat frame_bin;
@@ -49,15 +50,15 @@ const vector<Vec2f>& PointExtractor::extract_points(Mat& frame)
Mat frame_last_and_low;
if(secondary==0){
- threshold(frame_gray, frame_bin, threshold_val, 255, THRESH_BINARY);
+ threshold(frame_gray, frame_bin, primary, 255, THRESH_BINARY);
}else{
// we recombine a number of buffers, this might be slower than a single loop of per-pixel logic
// but it might as well be faster if openCV makes good use of SIMD
- float t = threshold_val;
+ float t = primary;
//float hyst = float(threshold_secondary_val)/512.;
//threshold(frame_gray, frame_bin, (t + ((255.-t)*hyst)), 255, THRESH_BINARY);
- float hyst = float(threshold_secondary_val)/256.;
- threshold(frame_gray, frame_bin, t, 255, THRESH_BINARY);
+ float hyst = float(primary)/(256.*8.);
+ threshold(frame_gray, frame_bin, t, 255, THRESH_BINARY);
threshold(frame_gray, frame_bin_low,std::max(float(1), t - (t*hyst)), 255, THRESH_BINARY);
frame_bin.copyTo(frame_bin_copy);
@@ -71,6 +72,10 @@ const vector<Vec2f>& PointExtractor::extract_points(Mat& frame)
frame_last.copyTo(frame_bin);
}
}
+
+ int min_size = s.min_point_size;
+ int max_size = s.max_point_size;
+
unsigned int region_size_min = 3.14*min_size*min_size/4.0;
unsigned int region_size_max = 3.14*max_size*max_size/4.0;
@@ -118,7 +123,7 @@ const vector<Vec2f>& PointExtractor::extract_points(Mat& frame)
if(secondary==0){
val = frame_gray.at<unsigned char>(i,j);
- val = float(val - threshold_val)/(256 - threshold_val);
+ val = float(val - primary)/(256 - primary);
val = val*val; // makes it more stable (less emphasis on low values, more on the peak)
}else{
//hysteresis point detection gets stability from ignoring pixel noise so we decidedly leave the actual pixel values out of the picture
@@ -149,10 +154,10 @@ const vector<Vec2f>& PointExtractor::extract_points(Mat& frame)
channels.push_back(frame_gray - frame_bin);
}else{
frame_bin_copy.setTo(120, frame_bin_copy);
- frame_bin_low.setTo(90, frame_bin_low);
+ //frame_bin_low.setTo(90, frame_bin_low);
channels.push_back(frame_gray + frame_bin_copy);
- channels.push_back(frame_gray + frame_last_and_low);
- channels.push_back(frame_gray + frame_bin_low);
+ channels.push_back(frame_gray - frame_bin_copy);
+ channels.push_back(frame_gray - frame_bin_copy);
//channels.push_back(frame_gray + frame_bin);
}
merge(channels, frame);
diff --git a/ftnoir_tracker_pt/point_extractor.h b/ftnoir_tracker_pt/point_extractor.h
index 5252b68d..06d148d6 100644
--- a/ftnoir_tracker_pt/point_extractor.h
+++ b/ftnoir_tracker_pt/point_extractor.h
@@ -11,6 +11,8 @@
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
+#include "ftnoir_tracker_pt_settings.h"
+
// ----------------------------------------------------------------------------
// Extracts points from an opencv image
class PointExtractor
@@ -19,14 +21,11 @@ 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
- const std::vector<cv::Vec2f>& extract_points(cv::Mat &frame);
+ std::vector<cv::Vec2f> extract_points(cv::Mat &frame);
const std::vector<cv::Vec2f>& get_points() { return points; }
PointExtractor();
-
- int threshold_val;
- int threshold_secondary_val;
- int min_size, max_size;
-
+
+ settings s;
private:
std::vector<cv::Vec2f> points;
cv::Mat frame_last;
diff --git a/ftnoir_tracker_pt/point_tracker.cpp b/ftnoir_tracker_pt/point_tracker.cpp
index 8a633c5d..e4c999ad 100644
--- a/ftnoir_tracker_pt/point_tracker.cpp
+++ b/ftnoir_tracker_pt/point_tracker.cpp
@@ -33,44 +33,6 @@ static void set_row(Matx33f& m, int i, const Vec3f& v)
m(i,2) = v[2];
}
-PointModel::PointModel() :
- M01 { 0, 0, 0 },
- M02 { 0, 0, 0 }
-{
-}
-
-PointModel::PointModel(Vec3f M01, Vec3f M02)
- : M01(M01), M02(M02)
-{
- // 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) * Matx22f(s22, -s12,
- -s12, s11);
- // calculate d and d_order for simple freetrack-like point correspondence
- vector<Vec2f> points;
- points.push_back(Vec2f(0,0));
- points.push_back(Vec2f(M01[0], M01[1]));
- points.push_back(Vec2f(M02[0], M02[1]));
- // fit line to orthographically projected points
- // ERROR: yields wrong results with colinear points?!
- /*
- Vec4f line;
- fitLine(points, line, CV_DIST_L2, 0, 0.01, 0.01);
- d[0] = line[0]; d[1] = line[1];
- */
- // TODO: fix this
- d = Vec2f(M01[0]-M02[0], M01[1]-M02[1]);
-
- // sort model points
- get_d_order(points, d_order);
-}
-
#ifdef OPENTRACK_API
static bool d_vals_sort(const pair<float,int> a, const pair<float,int> b)
{
@@ -78,10 +40,11 @@ static bool d_vals_sort(const pair<float,int> a, const pair<float,int> b)
}
#endif
-void PointModel::get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const
+void PointModel::get_d_order(const std::vector<cv::Vec2f>& points, int d_order[], cv::Vec2f d) const
{
- // get sort indices with respect to d scalar product
+ // fit line to orthographically projected points
vector< pair<float,int> > d_vals;
+ // get sort indices with respect to d scalar product
for (unsigned i = 0; i<points.size(); ++i)
d_vals.push_back(pair<float, int>(d.dot(points[i]), i));
@@ -99,69 +62,85 @@ void PointModel::get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]
}
-// ----------------------------------------------------------------------------
PointTracker::PointTracker()
{
- X_CM.t[2] = 1000; // default position: 1 m away from cam;
}
-void PointTracker::reset()
+PointTracker::PointOrder PointTracker::find_correspondences_previous(const vector<Vec2f>& points, const PointModel& model, float f)
{
- // enter init phase
- X_CM = FrameTrafo();
-}
+ PointTracker::PointOrder p;
+ p.points[0] = project(Vec3f(0,0,0), f);
+ p.points[1] = project(model.M01, f);
+ p.points[2] = project(model.M02, f);
-void PointTracker::track(const vector<Vec2f>& projected_points, const PointModel& model)
-{
- const PointOrder& order = find_correspondences(projected_points, model);
- int iters = POSIT(model, order);
- qDebug()<<"POSIT iterations:"<<iters;
-}
-
-PointTracker::PointOrder PointTracker::find_correspondences(const std::vector<cv::Vec2f>& projected_points, const PointModel& model)
-{
- // ... otherwise we look at the distance to the projection of the expected model points
- // project model points under current pose
- Vec2f p_exp[3];
- p_exp[0] = project(Vec3f(0,0,0));
- p_exp[1] = project(model.get_M01());
- p_exp[2] = project(model.get_M02());
-
// set correspondences by minimum distance to projected model point
bool point_taken[PointModel::N_POINTS];
for (int i=0; i<PointModel::N_POINTS; ++i)
- point_taken[i] = false;
-
- PointOrder p;
- for (int i=0; i<PointModel::N_POINTS; ++i)
- p.points[i] = Vec2f(0, 0);
-
+ point_taken[i] = false;
+
for (int i=0; i<PointModel::N_POINTS; ++i)
{
- float min_sdist = 1e4;
- int min_idx = 0;
- // find closest point to projected model point i
- for (int j=0; j<PointModel::N_POINTS; ++j)
- {
- Vec2f d = p_exp[i]-projected_points[j];
- float sdist = d.dot(d);
- if (sdist < min_sdist)
+ float min_sdist = 0;
+ int min_idx = 0;
+ // find closest point to projected model point i
+ for (int j=0; j<PointModel::N_POINTS; ++j)
{
- min_idx = j;
- min_sdist = sdist;
+ Vec2f d = p.points[i]-points[j];
+ float sdist = d.dot(d);
+ if (sdist < min_sdist || j==0)
+ {
+ min_idx = j;
+ min_sdist = sdist;
+ }
}
- }
- // if one point is closest to more than one model point, abort
- if (point_taken[min_idx]) return p;
- point_taken[min_idx] = true;
- p.points[i] = projected_points[min_idx];
+ // if one point is closest to more than one model point, fallback
+ if (point_taken[min_idx])
+ {
+ return find_correspondences(points, model);
+ }
+ point_taken[min_idx] = true;
+ p.points[i] = points[min_idx];
}
return p;
}
+void PointTracker::track(const vector<Vec2f>& points, const PointModel& model, float f, bool dynamic_pose)
+{
+ PointOrder order;
+
+ if (!dynamic_pose)
+ order = find_correspondences(points, model);
+ else
+ order = find_correspondences_previous(points, model, f);
+
+ POSIT(model, order, f);
+}
+PointTracker::PointOrder PointTracker::find_correspondences(const std::vector<cv::Vec2f>& 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> {
+ Vec2f{0,0},
+ Vec2f(model.M01[0], model.M01[1]),
+ Vec2f(model.M02[0], model.M02[1])
+ },
+ model_d_order,
+ d);
+ // set correspondences
+ PointOrder p;
+ for (int i=0; i<PointModel::N_POINTS; ++i)
+ p.points[model_d_order[i]] = points[point_d_order[i]];
+
+ return p;
+}
-int PointTracker::POSIT(const PointModel& model, const PointOrder& order_)
+int PointTracker::POSIT(const PointModel& model, const PointOrder& order_, float focal_length)
{
// POSIT algorithm for coplanar points as presented in
// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
@@ -169,13 +148,12 @@ int PointTracker::POSIT(const PointModel& model, const PointOrder& order_)
// The expected rotation used for resolving the ambiguity in POSIT:
// In every iteration step the rotation closer to R_expected is taken
- Matx33f R_expected;
- R_expected = X_CM.R; // later we want to be close to the last (predicted) rotation
+ Matx33f R_expected = Matx33f::eye();
// initial pose = last (predicted) pose
Vec3f k;
- get_row(R_expected, 2, k);
- float Z0 = std::abs(X_CM.t[2]) < 1e-3 ? 1e3 : X_CM.t[2];
+ get_row(R_expected, 2, k);
+ float Z0 = 1000.f;
float old_epsilon_1 = 0;
float old_epsilon_2 = 0;
@@ -287,3 +265,9 @@ int PointTracker::POSIT(const PointModel& model, const PointOrder& order_)
//
//qDebug()<<"r: "<<r[0]<<' '<<r[1]<<' '<<r[2]<<'\n';
}
+
+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
index dac99b87..10bd2cef 100644
--- a/ftnoir_tracker_pt/point_tracker.h
+++ b/ftnoir_tracker_pt/point_tracker.h
@@ -16,34 +16,38 @@
#endif
#include <vector>
+#include "ftnoir_tracker_pt_settings.h"
+
+#include <QObject>
+
// ----------------------------------------------------------------------------
// Affine frame trafo
-class FrameTrafo
+class Affine
{
public:
- FrameTrafo() : R(cv::Matx33f::eye()), t(0,0,0) {}
- FrameTrafo(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {}
+ 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 FrameTrafo operator*(const FrameTrafo& X, const FrameTrafo& Y)
+inline Affine operator*(const Affine& X, const Affine& Y)
{
- return FrameTrafo(X.R*Y.R, X.R*Y.t + X.t);
+ return Affine(X.R*Y.R, X.R*Y.t + X.t);
}
-inline FrameTrafo operator*(const cv::Matx33f& X, const FrameTrafo& Y)
+inline Affine operator*(const cv::Matx33f& X, const Affine& Y)
{
- return FrameTrafo(X*Y.R, X*Y.t);
+ return Affine(X*Y.R, X*Y.t);
}
-inline FrameTrafo operator*(const FrameTrafo& X, const cv::Matx33f& Y)
+inline Affine operator*(const Affine& X, const cv::Matx33f& Y)
{
- return FrameTrafo(X.R*Y, X.t);
+ return Affine(X.R*Y, X.t);
}
-inline cv::Vec3f operator*(const FrameTrafo& X, const cv::Vec3f& v)
+inline cv::Vec3f operator*(const Affine& X, const cv::Vec3f& v)
{
return X.R*v + X.t;
}
@@ -59,24 +63,49 @@ class PointModel
public:
static constexpr int N_POINTS = 3;
- PointModel(cv::Vec3f M01, cv::Vec3f M02);
- PointModel();
-
- inline const cv::Vec3f& get_M01() const { return M01; }
- inline const cv::Vec3f& get_M02() const { return M02; }
-
-private:
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;
-
- cv::Vec2f d; // determinant vector for point correspondence
- int d_order[3]; // sorting of projected model points with respect to d scalar product
-
- void get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const;
+
+ enum Model { Clip = 0, Cap = 1, Custom = 2 };
+
+ PointModel(settings& 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& s)
+ {
+ switch (s.active_model_panel)
+ {
+ case Clip:
+ M01 = cv::Vec3f(0, static_cast<double>(s.clip_ty), -static_cast<double>(s.clip_tz));
+ M02 = cv::Vec3f(0, -static_cast<double>(s.clip_by), -static_cast<double>(s.clip_bz));
+ break;
+ case Cap:
+ M01 = cv::Vec3f(-static_cast<double>(s.cap_x), -static_cast<double>(s.cap_y), -static_cast<double>(s.cap_z));
+ M02 = cv::Vec3f(static_cast<double>(s.cap_x), -static_cast<double>(s.cap_y), -static_cast<double>(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<cv::Vec2f>& points, int* d_order, cv::Vec2f d) const;
};
// ----------------------------------------------------------------------------
@@ -90,25 +119,26 @@ public:
// 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<cv::Vec2f>& projected_points, const PointModel& model);
- FrameTrafo pose() const { return X_CM; }
- void reset();
-
+ void track(const std::vector<cv::Vec2f>& projected_points, const PointModel& model, float f, bool dynamic_pose);
+ Affine pose() const { return X_CM; }
+ cv::Vec2f project(const cv::Vec3f& v_M, float f);
private:
// the points in model order
- typedef struct { cv::Vec2f points[PointModel::N_POINTS]; } PointOrder;
- static constexpr float focal_length = 1.0f;
-
- inline cv::Vec2f project(const cv::Vec3f& v_M)
+ struct PointOrder
{
- cv::Vec3f v_C = X_CM * v_M;
- return cv::Vec2f(focal_length*v_C[0]/v_C[2], focal_length*v_C[1]/v_C[2]);
- }
+ 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<cv::Vec2f>& projected_points, const PointModel &model);
- int POSIT(const PointModel& point_model, const PointOrder& order); // The POSIT algorithm, returns the number of iterations
+ PointOrder find_correspondences_previous(const std::vector<cv::Vec2f>& 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
- FrameTrafo X_CM; // trafo from model to camera
+ Affine X_CM; // trafo from model to camera
};
#endif //POINTTRACKER_H
diff --git a/ftnoir_tracker_pt/trans_calib.cpp b/ftnoir_tracker_pt/trans_calib.cpp
index 729a0b7f..2994eb48 100644
--- a/ftnoir_tracker_pt/trans_calib.cpp
+++ b/ftnoir_tracker_pt/trans_calib.cpp
@@ -41,4 +41,4 @@ Vec3f TranslationCalibrator::get_estimate()
{
Vec6f x = P.inv() * y;
return Vec3f(-x[0], -x[1], -x[2]);
-} \ No newline at end of file
+}
diff --git a/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp b/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp
index 724c7d3d..0328428f 100644
--- a/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp
+++ b/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp
@@ -58,8 +58,8 @@ void Rift_Tracker::data(double *data)
old_yaw=yaw;
}
constexpr double d2r = 57.295781;
- data[Yaw] = yaw * d2r;
- data[Pitch] = pitch * -d2r;
+ data[Yaw] = yaw * -d2r;
+ data[Pitch] = pitch * d2r;
data[Roll] = roll * d2r;
data[TX] = pose.Position.x * -1e2;
data[TY] = pose.Position.y * 1e2;
diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp
index 507543be..c900fb67 100644
--- a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp
+++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp
@@ -12,6 +12,7 @@ FTNoIR_Tracker::~FTNoIR_Tracker()
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;
@@ -25,7 +26,6 @@ void FTNoIR_Tracker::run() {
void FTNoIR_Tracker::start_tracker(QFrame*)
{
- (void) sock.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
start();
}
diff --git a/make-tar.sh b/make-tar.sh
index 26b65dcb..d3670984 100644
--- a/make-tar.sh
+++ b/make-tar.sh
@@ -4,9 +4,8 @@ prefix="$1"
filename="$2"
if : &&
- make install &&
cd $(dirname -- "${prefix}") &&
- tar Jcf "${filename}" $(basename "${prefix}")
+ zip -9r "${filename}" $(basename "${prefix}")
then
ls -lh -- "${filename}"
else
diff --git a/opentrack/ftnoir_keyboardshortcuts.ui b/opentrack/ftnoir_keyboardshortcuts.ui
deleted file mode 100644
index f576d8fb..00000000
--- a/opentrack/ftnoir_keyboardshortcuts.ui
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>UICKeyboardShortcutDialog</class>
- <widget class="QWidget" name="UICKeyboardShortcutDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>415</width>
- <height>143</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Keyboard shortcuts</string>
- </property>
- <property name="windowIcon">
- <iconset>
- <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="0">
- <widget class="QLabel" name="textLabel2_5">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Toggle</string>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="textLabel2_3">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Center</string>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="chkToggleShift">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Shift</string>
- </property>
- </widget>
- </item>
- <item row="2" column="4">
- <widget class="QComboBox" name="cbxToggleKey">
- <property name="minimumSize">
- <size>
- <width>90</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Select Number</string>
- </property>
- <property name="insertPolicy">
- <enum>QComboBox::InsertAlphabetically</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QCheckBox" name="chkCenterAlt">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Alt</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QCheckBox" name="chkToggleCtrl">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Ctrl</string>
- </property>
- </widget>
- </item>
- <item row="0" column="4">
- <widget class="QLabel" name="textLabel2_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Keyboard</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QCheckBox" name="chkToggleAlt">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Alt</string>
- </property>
- </widget>
- </item>
- <item row="3" column="3" colspan="2">
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QCheckBox" name="chkCenterCtrl">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Ctrl</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="chkCenterShift">
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Shift</string>
- </property>
- </widget>
- </item>
- <item row="1" column="4">
- <widget class="QComboBox" name="cbxCenterKey">
- <property name="minimumSize">
- <size>
- <width>90</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Select Number</string>
- </property>
- <property name="insertPolicy">
- <enum>QComboBox::InsertAlphabetically</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
- <slots>
- <slot>startEngineClicked()</slot>
- <slot>stopEngineClicked()</slot>
- <slot>cameraSettingsClicked()</slot>
- </slots>
-</ui>
diff --git a/opentrack/global-shortcuts.cpp b/opentrack/global-shortcuts.cpp
new file mode 100644
index 00000000..7569fd9a
--- /dev/null
+++ b/opentrack/global-shortcuts.cpp
@@ -0,0 +1,68 @@
+#include <QList>
+#include <QString>
+
+extern QList<QString> global_key_sequences;
+extern QList<int> global_windows_key_sequences;
+
+#if defined(_WIN32)
+# ifndef DIRECTINPUT_VERSION
+# define DIRECTINPUT_VERSION 0x800
+# endif
+# include <windows.h>
+# include <dinput.h>
+
+QList<int> global_windows_key_sequences =
+ QList<int>()
+ << 0
+ << DIK_F1
+ << DIK_F2
+ << DIK_F3
+ << DIK_F4
+ << DIK_F5
+ << DIK_F6
+ << DIK_F7
+ << DIK_F8
+ << DIK_F9
+ << DIK_F10
+ << DIK_F11
+ << DIK_F12
+ << DIK_LEFT
+ << DIK_RIGHT
+ << DIK_UP
+ << DIK_DOWN
+ << DIK_PGUP
+ << DIK_PGDN
+ << DIK_HOME
+ << DIK_END
+ << DIK_BACK
+ << DIK_DELETE
+ << DIK_RETURN;
+#endif
+
+QList<QString> global_key_sequences =
+ QList<QString>()
+ << ""
+ << "F1"
+ << "F2"
+ << "F3"
+ << "F4"
+ << "F5"
+ << "F6"
+ << "F7"
+ << "F8"
+ << "F9"
+ << "F10"
+ << "F11"
+ << "F12"
+ << "Left"
+ << "Right"
+ << "Up"
+ << "Down"
+ << "PgUp"
+ << "PgDown"
+ << "Home"
+ << "End"
+ << "Del"
+;
+
+
diff --git a/opentrack/main-settings.hpp b/opentrack/main-settings.hpp
index e41a23c9..0468aeb1 100644
--- a/opentrack/main-settings.hpp
+++ b/opentrack/main-settings.hpp
@@ -12,7 +12,7 @@ struct axis_opts {
value<int> src;
axis_opts(pbundle b, QString pfx, int idx) :
zero(b, n(pfx, "zero-pos"), 0),
- invert(b, n(pfx, "invert-axis"), false),
+ invert(b, n(pfx, "invert-sign"), false),
altp(b, n(pfx, "alt-axis-sign"), false),
src(b, n(pfx, "source-index"), idx)
{}
@@ -27,8 +27,11 @@ struct main_settings {
value<QString> tracker_dll, tracker2_dll, filter_dll, protocol_dll;
axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll;
value<bool> tcomp_p, tcomp_tz;
- main_settings(pbundle b) :
- b(b),
+ value<bool> tray_enabled;
+ value<int> camera_yaw, camera_pitch;
+ value<bool> center_at_startup;
+ main_settings() :
+ b(bundle("opentrack-ui")),
tracker_dll(b, "tracker-dll", ""),
tracker2_dll(b, "tracker2-dll", ""),
filter_dll(b, "filter-dll", ""),
@@ -40,6 +43,10 @@ struct main_settings {
a_pitch(b, "pitch", Pitch),
a_roll(b, "roll", Roll),
tcomp_p(b, "compensate-translation", true),
- tcomp_tz(b, "compensate-translation-disable-z-axis", false)
+ tcomp_tz(b, "compensate-translation-disable-z-axis", false),
+ tray_enabled(b, "use-system-tray", false),
+ camera_yaw(b, "camera-yaw", 0),
+ camera_pitch(b, "camera-pitch", 0),
+ center_at_startup(b, "center-at-startup", true)
{}
};
diff --git a/opentrack/mappings.hpp b/opentrack/mappings.hpp
index 86126db9..3336dcd8 100644
--- a/opentrack/mappings.hpp
+++ b/opentrack/mappings.hpp
@@ -10,23 +10,18 @@ class Mapping {
public:
Mapping(QString primary,
QString secondary,
- int maxInput1,
- int maxOutput1,
- int maxInput2,
- int maxOutput2,
+ int max_x,
+ int max_y,
axis_opts& opts) :
- curve(maxInput1, maxOutput1),
- curveAlt(maxInput2, maxOutput2),
+ curve(max_x, max_y),
+ curveAlt(max_x, max_y),
opts(opts),
name1(primary),
name2(secondary)
{
- // XXX TODO move all this qsettings boilerplate into a single header -sh 20141004
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- QSettings iniFile(currentFile, QSettings::IniFormat);
- curve.loadSettings(iniFile, primary);
- curveAlt.loadSettings(iniFile, secondary);
+ mem<QSettings> iniFile = group::ini_file();
+ curve.loadSettings(*iniFile, primary);
+ curveAlt.loadSettings(*iniFile, secondary);
}
Map curve;
Map curveAlt;
@@ -40,12 +35,12 @@ private:
public:
Mappings(std::vector<axis_opts*> opts) :
axes {
- Mapping("tx","tx_alt", 100, 100, 100, 100, *opts[TX]),
- Mapping("ty","ty_alt", 100, 100, 100, 100, *opts[TY]),
- Mapping("tz","tz_alt", 100, 100, 100, 100, *opts[TZ]),
- Mapping("rx", "rx_alt", 180, 180, 180, 180, *opts[Yaw]),
- Mapping("ry", "ry_alt", 180, 180, 180, 180, *opts[Pitch]),
- Mapping("rz", "rz_alt", 180, 180, 180, 180, *opts[Roll])
+ Mapping("tx","tx_alt", 100, 100, *opts[TX]),
+ Mapping("ty","ty_alt", 100, 100, *opts[TY]),
+ Mapping("tz","tz_alt", 100, 100, *opts[TZ]),
+ Mapping("rx", "rx_alt", 180, 180, *opts[Yaw]),
+ Mapping("ry", "ry_alt", 180, 180, *opts[Pitch]),
+ Mapping("rz", "rz_alt", 180, 180, *opts[Roll])
}
{}
@@ -54,29 +49,25 @@ public:
void load_mappings()
{
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
+ mem<QSettings> iniFile = group::ini_file();
for (int i = 0; i < 6; i++)
{
- axes[i].curve.loadSettings(iniFile, axes[i].name1);
- axes[i].curveAlt.loadSettings(iniFile, axes[i].name2);
+ axes[i].curve.loadSettings(*iniFile, axes[i].name1);
+ axes[i].curveAlt.loadSettings(*iniFile, axes[i].name2);
}
}
void save_mappings()
{
- QSettings settings("opentrack");
- QString currentFile = settings.value("SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini").toString();
- QSettings iniFile(currentFile, QSettings::IniFormat);
+ mem<QSettings> iniFile = group::ini_file();
for (int i = 0; i < 6; i++)
{
- axes[i].curve.saveSettings(iniFile, axes[i].name1);
- axes[i].curveAlt.saveSettings(iniFile, axes[i].name2);
+ axes[i].curve.saveSettings(*iniFile, axes[i].name1);
+ axes[i].curveAlt.saveSettings(*iniFile, axes[i].name2);
}
}
-
+
void invalidate_unsaved()
{
for (int i = 0; i < 6; i++)
diff --git a/facetracknoir/mingw-version-script.txt b/opentrack/mingw-version-script.txt
index fe20ad37..fe20ad37 100644
--- a/facetracknoir/mingw-version-script.txt
+++ b/opentrack/mingw-version-script.txt
diff --git a/opentrack/options.hpp b/opentrack/options.hpp
index 6c15d729..5eae754f 100644
--- a/opentrack/options.hpp
+++ b/opentrack/options.hpp
@@ -26,17 +26,21 @@
#include <QSlider>
#include <QLineEdit>
#include <QLabel>
+#include <QTabWidget>
#include <QCoreApplication>
#include <cinttypes>
#include <QDebug>
+#include <memory>
+template<typename t> using mem = std::shared_ptr<t>;
+
namespace options {
template<typename k, typename v>
using map = std::map<k, v>;
using std::string;
-
+
template<typename t>
// don't elide usages of the function, qvariant default implicit
// conversion results in nonsensical runtime behavior -sh
@@ -77,12 +81,6 @@ namespace options {
private:
map<string, QVariant> kvs;
string name;
- static const QString ini_pathname()
- {
- QSettings settings(group::org);
- return settings.value("SettingsFile",
- QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- }
public:
group(const string& name) : name(name)
{
@@ -97,8 +95,8 @@ namespace options {
}
conf.endGroup();
}
- static constexpr const char* org = "opentrack";
-
+ static constexpr const char* org = "opentrack-2.3";
+
void save()
{
QSettings s(ini_pathname(), QSettings::IniFormat);
@@ -110,26 +108,41 @@ namespace options {
s.setValue(k, i.second);
}
s.endGroup();
+ s.sync();
}
-
+
template<typename t>
t get(const string& k)
{
return qcruft_to_t<t>(kvs[k]);
}
-
+
void put(const string& s, const QVariant& d)
{
kvs[s] = d;
}
-
+
bool contains(const string& s)
{
return kvs.count(s) != 0;
}
+
+ static constexpr const char* filename_key = "settings-file";
+ static constexpr const char* default_path = "/settings/default.ini";
+
+ static const QString ini_pathname()
+ {
+ QSettings settings(group::org);
+ return settings.value(filename_key, QCoreApplication::applicationDirPath() + default_path).toString();
+ }
+ static const mem<QSettings> ini_file()
+ {
+ return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat);
+ }
};
class impl_bundle : public QObject {
+ Q_OBJECT
protected:
QMutex mtx;
const string group_name;
@@ -138,6 +151,9 @@ namespace options {
bool modified;
impl_bundle(const impl_bundle&) = delete;
impl_bundle& operator=(const impl_bundle&) = delete;
+ signals:
+ void reloading();
+ void saving();
public:
impl_bundle(const string& group_name) :
mtx(QMutex::Recursive),
@@ -147,28 +163,29 @@ namespace options {
modified(false)
{
}
-
+
string name() { return group_name; }
-
+
void reload() {
- QMutexLocker l(&mtx);
- saved = group(group_name);
- transient = saved;
- modified = false;
+ {
+ QMutexLocker l(&mtx);
+ saved = group(group_name);
+ transient = saved;
+ modified = false;
+ }
+ emit reloading();
}
-
- bool store_kv(const string& name, const QVariant& datum)
+
+ void store_kv(const string& name, const QVariant& datum)
{
QMutexLocker l(&mtx);
-
+
auto old = transient.get<QVariant>(name);
if (!transient.contains(name) || datum != old)
{
modified = true;
transient.put(name, datum);
- return true;
}
- return false;
}
bool contains(const string& name)
{
@@ -183,10 +200,13 @@ namespace options {
}
void save()
{
- QMutexLocker l(&mtx);
- modified = false;
- saved = transient;
- transient.save();
+ {
+ QMutexLocker l(&mtx);
+ modified = false;
+ saved = transient;
+ transient.save();
+ }
+ emit saving();
}
bool modifiedp() {
@@ -194,9 +214,9 @@ namespace options {
return modified;
}
};
-
+
class opt_bundle;
-
+
namespace
{
template<typename k, typename v, typename cnt = int>
@@ -210,51 +230,52 @@ namespace options {
map<k, tt> implsgl_data;
public:
opt_singleton() : implsgl_mtx(QMutex::Recursive) {}
-
+
static opt_singleton<k, v>& datum()
{
static auto ret = std::make_shared<opt_singleton<k, v>>();
return *ret;
}
-
+
pbundle bundle(const k& key)
{
QMutexLocker l(&implsgl_mtx);
-
+
if (implsgl_data.count(key) != 0)
return std::get<1>(implsgl_data[key]);
+ qDebug() << "bundle +" << QString::fromStdString(key);
+
auto shr = std::make_shared<v>(key);
implsgl_data[key] = tt(cnt(1), shr);
return shr;
}
-
+
void bundle_decf(const k& key)
{
QMutexLocker l(&implsgl_mtx);
-
+
if (--std::get<0>(implsgl_data[key]) == 0)
implsgl_data.erase(key);
}
-
+
~opt_singleton() { implsgl_data.clear(); }
};
-
+
using pbundle = std::shared_ptr<opt_bundle>;
using t_fact = opt_singleton<string, opt_bundle>;
}
-
+
static inline t_fact::pbundle bundle(const string name) { return t_fact::datum().bundle(name); }
-
+
class opt_bundle : public impl_bundle
{
public:
opt_bundle() : impl_bundle("i-have-no-name") {}
opt_bundle(const string& group_name) : impl_bundle(group_name)
{
- qDebug() << "bundle +" << QString::fromStdString(group_name);
}
-
+
~opt_bundle()
{
qDebug() << "bundle -" << QString::fromStdString(group_name);
@@ -281,16 +302,18 @@ namespace options {
template<typename t>
void store(const t& datum)
{
- if (b->store_kv(self_name, datum))
- emit valueChanged(static_cast<t>(datum));
+ b->store_kv(self_name, datum);
+ emit valueChanged(static_cast<t>(datum));
}
public slots:
DEFINE_SLOT(double)
DEFINE_SLOT(int)
DEFINE_SLOT(QString)
DEFINE_SLOT(bool)
+ public slots:
+ virtual void reload() = 0;
};
-
+
static inline string string_from_qstring(const QString& datum)
{
auto tmp = datum.toUtf8();
@@ -309,6 +332,9 @@ namespace options {
static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection;
value(pbundle b, const string& name, t def) : base_value(b, name)
{
+ QObject::connect(b.get(), SIGNAL(reloading()),
+ this, SLOT(reload()),
+ DIRECT_CONNTYPE);
if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)
*this = def;
}
@@ -319,6 +345,9 @@ namespace options {
{
return b->get<t>(self_name);
}
+ void reload() override {
+ *this = static_cast<t>(*this);
+ }
};
template<typename t, typename q>
@@ -389,4 +418,12 @@ namespace options {
lb->setText(v);
base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE);
}
+
+ template<>
+ inline void tie_setting(value<int>& v, QTabWidget* t)
+ {
+ t->setCurrentIndex(v);
+ base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE);
+ }
}
diff --git a/opentrack/plugin-support.cpp b/opentrack/plugin-support.cpp
index ec56b1e1..2c129906 100644
--- a/opentrack/plugin-support.cpp
+++ b/opentrack/plugin-support.cpp
@@ -5,6 +5,8 @@
#include <QFile>
#include <QDir>
+#include <iostream>
+
#ifndef _WIN32
# include <dlfcn.h>
#endif
@@ -14,16 +16,19 @@ SelectedLibraries::~SelectedLibraries()
}
template<typename t>
-static ptr<t> make_instance(ptr<dylib> lib)
+static mem<t> make_instance(mem<dylib> lib)
{
- ptr<t> ret = nullptr;
- if (lib && lib->Constructor)
- ret = ptr<t>(reinterpret_cast<t*>(reinterpret_cast<CTOR_FUNPTR>(lib->Constructor)()));
- //qDebug() << "lib" << (lib ? lib->filename : "<null>") << "ptr" << (intptr_t)ret.get();
+ mem<t> ret;
+ if (lib != nullptr && lib->Constructor)
+ {
+ qDebug() << "dylib" << (lib ? lib->filename : "<null>") << "ptr" << (intptr_t) lib->Constructor;
+ std::cout.flush();
+ ret = mem<t>(reinterpret_cast<t*>(reinterpret_cast<CTOR_FUNPTR>(lib->Constructor)()));
+ }
return ret;
}
-SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibtr f) :
+SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) :
pTracker(nullptr),
pFilter(nullptr),
pProtocol(nullptr),
@@ -32,20 +37,19 @@ SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibt
pTracker = make_instance<ITracker>(t);
pProtocol = make_instance<IProtocol>(p);
pFilter = make_instance<IFilter>(f);
-
- if (!pTracker|| !pProtocol)
+
+ if (!pTracker || !pProtocol)
{
- qDebug() << "load failure tracker" << (intptr_t)pTracker.get() << "protocol" << (intptr_t)pProtocol.get();
+ qDebug() << "dylib load failure";
+ return;
+ }
+
+ if(!pProtocol->correct())
+ {
+ qDebug() << "protocol load failure";
return;
}
- if (pProtocol)
- if(!pProtocol->correct())
- {
- qDebug() << "protocol load failure";
- return;
- }
-
pTracker->start_tracker(frame);
correct = true;
@@ -67,7 +71,7 @@ SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibt
# define LIB_PREFIX "lib"
#endif
-static bool get_metadata(ptr<dylib> lib, QString& name, QIcon& icon)
+static bool get_metadata(mem<dylib> lib, QString& name, QIcon& icon)
{
Metadata* meta;
if (!lib->Meta || ((meta = lib->Meta()), !meta))
@@ -78,7 +82,7 @@ static bool get_metadata(ptr<dylib> lib, QString& name, QIcon& icon)
return true;
}
-QList<ptr<dylib>> dylib::enum_libraries()
+QList<mem<dylib>> dylib::enum_libraries()
{
#define BASE "opentrack-"
#define SUFF "-*."
@@ -86,11 +90,11 @@ QList<ptr<dylib>> dylib::enum_libraries()
BASE "tracker" SUFF,
BASE "proto" SUFF };
const Type filters_t[] = { Filter, Tracker, Protocol };
-
+
QDir settingsDir( QCoreApplication::applicationDirPath() );
-
- QList<ptr<dylib>> ret;
-
+
+ QList<mem<dylib>> ret;
+
for (int i = 0; i < 3; i++)
{
QString filter = filters_n[i];
@@ -110,7 +114,7 @@ QList<ptr<dylib>> dylib::enum_libraries()
ret.push_back(lib);
}
}
-
+
return ret;
}
@@ -123,12 +127,12 @@ dylib::dylib(const QString& filename, Type t) :
// otherwise dlopen opens the calling executable
if (filename.size() == 0)
return;
-
+
this->filename = filename;
#if defined(_WIN32)
QString fullPath = QCoreApplication::applicationDirPath() + "/" + this->filename;
handle = new QLibrary(fullPath);
-
+
struct _foo {
static bool die(QLibrary*& l, bool failp)
{
@@ -141,18 +145,18 @@ dylib::dylib(const QString& filename, Type t) :
return failp;
}
};
-
+
if (_foo::die(handle, !handle->load()))
return;
-
+
Dialog = (CTOR_FUNPTR) handle->resolve("GetDialog");
if (_foo::die(handle, !Dialog))
return;
-
+
Constructor = (CTOR_FUNPTR) handle->resolve("GetConstructor");
if (_foo::die(handle, !Constructor))
return;
-
+
Meta = (METADATA_FUNPTR) handle->resolve("GetMetadata");
if (_foo::die(handle, !Meta))
return;
@@ -199,9 +203,9 @@ dylib::dylib(const QString& filename, Type t) :
(void) _foo::err(handle);
}
#endif
-
- auto m = ptr<Metadata>(Meta());
-
+
+ auto m = mem<Metadata>(Meta());
+
icon = m->icon();
name = m->name();
}
@@ -209,7 +213,8 @@ dylib::dylib(const QString& filename, Type t) :
dylib::~dylib()
{
#if defined(_WIN32)
- handle->unload();
+ if (handle)
+ delete handle;
#else
if (handle)
(void) dlclose(handle);
diff --git a/opentrack/plugin-support.h b/opentrack/plugin-support.h
index 238aeb53..a2b6d403 100644
--- a/opentrack/plugin-support.h
+++ b/opentrack/plugin-support.h
@@ -1,6 +1,7 @@
#pragma once
#include "plugin-api.hpp"
+#include "options.hpp"
#include <QWidget>
#include <QDebug>
@@ -9,8 +10,6 @@
#include <QFrame>
#include <QList>
-#include <memory>
-template<typename t> using ptr = std::shared_ptr<t>;
extern "C" typedef void* (*CTOR_FUNPTR)(void);
extern "C" typedef Metadata* (*METADATA_FUNPTR)(void);
@@ -20,7 +19,7 @@ struct dylib {
dylib(const QString& filename, Type t);
~dylib();
- static QList<ptr<dylib>> enum_libraries();
+ static QList<mem<dylib>> enum_libraries();
Type type;
QString filename;
@@ -40,12 +39,12 @@ private:
};
struct SelectedLibraries {
- using dylibtr = ptr<dylib>;
- ptr<ITracker> pTracker;
- ptr<IFilter> pFilter;
- ptr<IProtocol> pProtocol;
- SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibtr f);
+ using dylibptr = mem<dylib>;
+ mem<ITracker> pTracker;
+ mem<IFilter> pFilter;
+ mem<IProtocol> pProtocol;
+ SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f);
SelectedLibraries() : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) {}
~SelectedLibraries();
bool correct;
-}; \ No newline at end of file
+};
diff --git a/opentrack/pose.hpp b/opentrack/pose.hpp
index 41e984f5..93d467a9 100644
--- a/opentrack/pose.hpp
+++ b/opentrack/pose.hpp
@@ -2,7 +2,6 @@
#include <utility>
#include <algorithm>
-#include "./quat.hpp"
#include "./plugin-api.hpp"
class Pose {
@@ -13,32 +12,11 @@ private:
double axes[6];
public:
- Pose() : axes {0,0,0, 0,0,0 } {}
+ Pose() : axes {0,0,0, 0,0,0} {}
inline operator double*() { return axes; }
inline operator const double*() const { return axes; }
inline double& operator()(int i) { return axes[i]; }
inline double operator()(int i) const { return axes[i]; }
-
- Quat quat() const
- {
- return Quat(axes[Yaw]*d2r, axes[Pitch]*d2r, axes[Roll]*d2r);
- }
-
- static Pose fromQuat(const Quat& q)
- {
- Pose ret;
- q.to_euler_degrees(ret(Yaw), ret(Pitch), ret(Roll));
- return ret;
- }
-
- Pose operator&(const Pose& B) const
- {
- const Quat q = quat() * B.quat().inv();
- Pose ret = fromQuat(q);
- for (int i = TX; i < TX + 3; i++)
- ret(i) = axes[i] - B.axes[i];
- return ret;
- }
};
diff --git a/facetracknoir/posix-version-script.txt b/opentrack/posix-version-script.txt
index 97edb9aa..97edb9aa 100644
--- a/facetracknoir/posix-version-script.txt
+++ b/opentrack/posix-version-script.txt
diff --git a/opentrack/quat.hpp b/opentrack/quat.hpp
deleted file mode 100644
index 6d777b28..00000000
--- a/opentrack/quat.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#pragma once
-#include <cmath>
-
-class Quat {
-private:
- static constexpr double pi = 3.141592653;
- static constexpr double r2d = 180./pi;
- double a,b,c,d; // quaternion coefficients
-public:
- Quat() : a(1.),b(0.),c(0.),d(0.) {}
- Quat(double yaw, double pitch, double roll) { from_euler_rads(yaw, pitch, roll); }
- Quat(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {}
-
- Quat inv(){
- return Quat(a,-b,-c, -d);
- }
-
- // conversions
- // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
- void from_euler_rads(double yaw, double pitch, double roll)
- {
-
- const double sin_phi = sin(roll/2.);
- const double cos_phi = cos(roll/2.);
- const double sin_the = sin(pitch/2.);
- const double cos_the = cos(pitch/2.);
- const double sin_psi = sin(yaw/2.);
- const double cos_psi = cos(yaw/2.);
-
- a = cos_phi*cos_the*cos_psi + sin_phi*sin_the*sin_psi;
- b = sin_phi*cos_the*cos_psi - cos_phi*sin_the*sin_psi;
- c = cos_phi*sin_the*cos_psi + sin_phi*cos_the*sin_psi;
- d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi;
- }
-
- void to_euler_rads(double& yaw, double& pitch, double& roll) const
- {
- roll = atan2(2.*(a*b + c*d), 1. - 2.*(b*b + c*c));
- pitch = asin(2.*(a*c - b*d));
- yaw = atan2(2.*(a*d + b*c), 1. - 2.*(c*c + d*d));
- }
-
- void to_euler_degrees(double& yaw, double& pitch, double& roll) const
- {
- to_euler_rads(yaw, pitch, roll);
- yaw *= r2d;
- pitch *= r2d;
- roll *= r2d;
- }
-
- const Quat operator*(const Quat& B) const
- {
- const Quat& A = *this;
- return Quat(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication
- A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c,
- A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b,
- A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a);
- }
-};
diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp
index d1cfa503..e81b6bb0 100644
--- a/opentrack/shortcuts.cpp
+++ b/opentrack/shortcuts.cpp
@@ -1,42 +1,19 @@
#include "shortcuts.h"
+#include <QMutexLocker>
-KeyboardShortcutDialog::KeyboardShortcutDialog()
-{
- ui.setupUi( this );
-
- connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
- connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
-
- for ( int i = 0; i < global_key_sequences.size(); i++) {
- ui.cbxCenterKey->addItem(global_key_sequences.at(i));
- ui.cbxToggleKey->addItem(global_key_sequences.at(i));
- }
- tie_setting(s.center.key_index, ui.cbxCenterKey);
- tie_setting(s.center.alt, ui.chkCenterAlt);
- tie_setting(s.center.shift, ui.chkCenterShift);
- tie_setting(s.center.ctrl, ui.chkCenterCtrl);
-
- tie_setting(s.toggle.key_index, ui.cbxToggleKey);
- tie_setting(s.toggle.alt, ui.chkToggleAlt);
- tie_setting(s.toggle.shift, ui.chkToggleShift);
- tie_setting(s.toggle.ctrl, ui.chkToggleCtrl);
-}
+#if defined(_WIN32)
+#include <windows.h>
-void KeyboardShortcutDialog::doOK() {
- s.b->save();
- this->close();
- emit reload();
-}
+void KeybindingWorker::set_keys(Key kCenter_, Key kToggle_, Key kZero_)
+{
+ QMutexLocker l(&mtx);
-void KeyboardShortcutDialog::doCancel() {
- s.b->reload();
- close();
+ kCenter = kCenter_;
+ kToggle = kToggle_;
+ kZero = kZero_;
}
-#if defined(_WIN32)
-#include <windows.h>
-
KeybindingWorker::~KeybindingWorker() {
should_quit = true;
wait();
@@ -48,8 +25,8 @@ KeybindingWorker::~KeybindingWorker() {
din->Release();
}
-KeybindingWorker::KeybindingWorker(Key keyCenter, Key keyToggle, WId handle) :
- din(0), dinkeyboard(0), kCenter(keyCenter), kToggle(keyToggle), should_quit(true)
+KeybindingWorker::KeybindingWorker(Key keyCenter, Key keyToggle, Key keyZero, WId handle, Shortcuts& sc) :
+ sc(sc), din(0), dinkeyboard(0), kCenter(keyCenter), kToggle(keyToggle), kZero(keyZero), should_quit(true)
{
if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) {
qDebug() << "setup DirectInput8 Creation failed!" << GetLastError();
@@ -94,7 +71,8 @@ static bool isKeyPressed( const Key *key, const BYTE *keystate ) {
bool ctrl;
bool alt;
- if (keystate[key->keycode] & 0x80) {
+ if (key->keycode != 0 && keystate[key->keycode] & 0x80)
+ {
shift = ( (keystate[DIK_LSHIFT] & 0x80) || (keystate[DIK_RSHIFT] & 0x80) );
ctrl = ( (keystate[DIK_LCONTROL] & 0x80) || (keystate[DIK_RCONTROL] & 0x80) );
alt = ( (keystate[DIK_LALT] & 0x80) || (keystate[DIK_RALT] & 0x80) );
@@ -108,12 +86,9 @@ static bool isKeyPressed( const Key *key, const BYTE *keystate ) {
return false;
}
-#define PROCESS_KEY(k, s) \
- if (isKeyPressed(&k, keystate) && (!k.ever_pressed ? (k.timer.start(), k.ever_pressed = true) : k.timer.restart() > 100)) \
- emit s;
-
void KeybindingWorker::run() {
BYTE keystate[256];
+
while (!should_quit)
{
if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) {
@@ -122,10 +97,19 @@ void KeybindingWorker::run() {
continue;
}
- PROCESS_KEY(kCenter, center());
- PROCESS_KEY(kToggle, toggle());
+ QMutexLocker l(&mtx);
- Sleep(25);
+ if (isKeyPressed(&kCenter, keystate) && kCenter.should_process())
+ emit sc.center();
+
+ if (isKeyPressed(&kToggle, keystate) && kToggle.should_process())
+ emit sc.toggle();
+
+ if (isKeyPressed(&kZero, keystate) && kZero.should_process())
+ emit sc.zero();
+
+ // keypresses get dropped with high values
+ Sleep(15);
}
}
#endif
@@ -156,16 +140,47 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k)
}
}
#else
+ key = K();
int idx = k.key_index;
- if (idx > 0)
+ key.keycode = 0;
+ key.shift = key.alt = key.ctrl = 0;
+ if (idx > 0 && idx < global_windows_key_sequences.size())
+ key.keycode = global_windows_key_sequences[idx];
+ key.shift = k.shift;
+ key.alt = k.alt;
+ key.ctrl = k.ctrl;
+#endif
+}
+
+void Shortcuts::reload() {
+#ifndef _WIN32
+ if (keyCenter)
{
- key.keycode = 0;
- key.shift = key.alt = key.ctrl = 0;
- if (idx < global_windows_key_sequences.size())
- key.keycode = global_windows_key_sequences[idx];
- key.shift = k.shift;
- key.alt = k.alt;
- key.ctrl = k.ctrl;
+ keyCenter->setShortcut(QKeySequence::UnknownKey);
+ keyCenter->setEnabled(false);
+ }
+ if (keyToggle)
+ {
+ keyToggle->setShortcut(QKeySequence::UnknownKey);
+ keyToggle->setEnabled(false);
+ }
+ if (keyZero)
+ {
+ keyZero->setShortcut(QKeySequence::UnknownKey);
+ keyZero->setEnabled(false);
}
#endif
-} \ No newline at end of file
+ bind_keyboard_shortcut(keyCenter, s.center);
+ bind_keyboard_shortcut(keyToggle, s.toggle);
+ bind_keyboard_shortcut(keyZero, s.zero);
+#ifdef _WIN32
+ bool is_new = keybindingWorker == nullptr;
+ if (is_new)
+ {
+ keybindingWorker = std::make_shared<KeybindingWorker>(keyCenter, keyToggle, keyZero, handle, *this);
+ keybindingWorker->start();
+ }
+ else
+ keybindingWorker->set_keys(keyCenter, keyToggle, keyZero);
+#endif
+}
diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h
index 8fe1a39b..4d4b19d3 100644
--- a/opentrack/shortcuts.h
+++ b/opentrack/shortcuts.h
@@ -1,4 +1,5 @@
#pragma once
+#include <QObject>
#include <QWidget>
#include <QElapsedTimer>
#include <QThread>
@@ -6,11 +7,12 @@
#include <QCheckBox>
#include <QComboBox>
#include <QSettings>
+#include <QMutex>
#include "qxt-mini/QxtGlobalShortcut"
#include "opentrack/plugin-support.h"
#include "opentrack/options.hpp"
-#include "ui_ftnoir_keyboardshortcuts.h"
+#include "opentrack/main-settings.hpp"
using namespace options;
@@ -40,112 +42,89 @@ struct Key {
bool shift;
bool ctrl;
bool alt;
- bool ever_pressed;
QElapsedTimer timer;
public:
- Key() : keycode(0), shift(false), ctrl(false), alt(false), ever_pressed(false)
+ Key() : keycode(0), shift(false), ctrl(false), alt(false)
{
}
+
+ bool should_process()
+ {
+ return !timer.isValid() ? (timer.start(), true) : timer.restart() > 100;
+ }
};
#else
typedef unsigned char BYTE;
struct Key { int foo; };
#endif
+struct Shortcuts;
+
struct KeybindingWorker : public QThread {
- Q_OBJECT
#ifdef _WIN32
private:
+ Shortcuts& sc;
LPDIRECTINPUT8 din;
LPDIRECTINPUTDEVICE8 dinkeyboard;
Key kCenter;
Key kToggle;
+ Key kZero;
+ QMutex mtx;
public:
volatile bool should_quit;
~KeybindingWorker();
- KeybindingWorker(Key keyCenter, Key keyToggle, WId handle);
- void run();
+ KeybindingWorker(Key keyCenter, Key keyToggle, Key keyZero, WId handle, Shortcuts& sc);
+ void run();
+ void set_keys(Key kCenter, Key kToggle, Key kZero);
#else
public:
- KeybindingWorker(Key, Key, WId) {}
- void run() {}
+ KeybindingWorker(Key, Key, Key, WId) {}
+ void run() {}
#endif
-signals:
- void center();
- void toggle();
};
+struct Shortcuts : public QObject {
+ Q_OBJECT
-struct Shortcuts {
+public:
using K =
#ifndef _WIN32
- ptr<QxtGlobalShortcut>
+ mem<QxtGlobalShortcut>
#else
Key
#endif
;
-
+
K keyCenter;
K keyToggle;
+ K keyZero;
WId handle;
#ifdef _WIN32
- ptr<KeybindingWorker> keybindingWorker;
+ mem<KeybindingWorker> keybindingWorker;
#endif
-
+
struct settings {
pbundle b;
- key_opts center, toggle;
+ key_opts center, toggle, zero;
+ main_settings s_main;
settings() :
b(bundle("keyboard-shortcuts")),
center(b, "center"),
- toggle(b, "toggle")
+ toggle(b, "toggle"),
+ zero(b, "zero")
{}
} s;
- Shortcuts(WId handle) : handle(handle)
- {
- reload();
- }
+ Shortcuts(WId handle) : handle(handle) { reload(); }
- void reload()
- {
-#ifndef _WIN32
- if (keyCenter)
- {
- keyCenter->setShortcut(QKeySequence::UnknownKey);
- keyCenter->setEnabled(false);
- }
- if (keyToggle)
- {
- keyToggle->setShortcut(QKeySequence::UnknownKey);
- keyToggle->setEnabled(false);
- }
-#endif
- bind_keyboard_shortcut(keyCenter, s.center);
- bind_keyboard_shortcut(keyToggle, s.toggle);
-#ifdef _WIN32
- keybindingWorker = nullptr;
- keybindingWorker = std::make_shared<KeybindingWorker>(keyCenter, keyToggle, handle);
- keybindingWorker->start();
-#endif
- }
+ void reload();
private:
void bind_keyboard_shortcut(K &key, key_opts& k);
-};
-
-class KeyboardShortcutDialog: public QWidget
-{
- Q_OBJECT
-public:
- KeyboardShortcutDialog();
-private:
- Ui::UICKeyboardShortcutDialog ui;
- Shortcuts::settings s;
- ptr<Shortcuts> sc;
signals:
- void reload();
-private slots:
- void doOK();
- void doCancel();
+ void center();
+ void toggle();
+ void zero();
};
+
+
diff --git a/opentrack/simple-mat.hpp b/opentrack/simple-mat.hpp
new file mode 100644
index 00000000..158cb30d
--- /dev/null
+++ b/opentrack/simple-mat.hpp
@@ -0,0 +1,155 @@
+#pragma once
+#include <initializer_list>
+
+template<typename num, int h, int w>
+struct Mat
+{
+ num data[h][w];
+
+ Mat<num, h, w> operator+(const Mat<num, h, w>& other) const
+ {
+ Mat<num, h, w> ret;
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret(j, i) = this->operator ()(j, i) + other(j, i);
+ return ret;
+ }
+
+ Mat<num, h, w> operator-(const Mat<num, h, w>& other) const
+ {
+ Mat<num, h, w> ret;
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret(j, i) = this->operator ()(j, i) - other(j, i);
+ return ret;
+ }
+
+ template<int p>
+ Mat<num, w, p> operator*(const Mat<num, w, p>& other) const
+ {
+ Mat<num, w, p> ret;
+ for (int j = 0; j < w; j++)
+ for (int i = 0; i < p; i++)
+ {
+ num sum = num(0);
+
+ for (int k = 0; k < h; k++)
+ sum += data[j][k]*other.data[k][i];
+
+ ret.data[j][i] = sum;
+ }
+
+ return ret;
+ }
+
+ num operator()(int j, int i) const { return data[j][i]; }
+ num& operator()(int j, int i) { return data[j][i]; }
+
+ Mat(std::initializer_list<num>&& list)
+ {
+ auto iter = list.begin();
+ for (int i = 0; i < h; i++)
+ for (int j = 0; j < w; j++)
+ data[i][j] = *iter++;
+ }
+
+ Mat()
+ {
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ data[j][i] = 0;
+ }
+
+ Mat(const num* mem)
+ {
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ data[j][i] = mem[i*h+j];
+ }
+
+ // XXX add more operators as needed, third-party dependencies mostly
+ // not needed merely for matrix algebra -sh 20141030
+
+ static Mat<num, h, h> eye()
+ {
+ Mat<num, h, h> ret;
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret.data[j][i] = 0;
+
+ for (int i = 0; i < h; i++)
+ ret.data[i][i] = 1;
+
+ return ret;
+ }
+
+ Mat<num, w, h> t() const
+ {
+ Mat<num, w, h> ret;
+
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ ret.data[i][j] = data[j][i];
+
+ return ret;
+ }
+
+ template<int h_, int w_> using dmat = Mat<double, h_, w_>;
+
+ // http://stackoverflow.com/a/18436193
+ static dmat<3, 1> rmat_to_euler(const dmat<3, 3>& R)
+ {
+ static constexpr double pi = 3.141592653;
+ const double up = 90 * pi / 180.;
+ static constexpr double bound = 1. - 2e-4;
+ if (R(0, 2) > bound)
+ {
+ double roll = atan(R(1, 0) / R(2, 0));
+ return dmat<3, 1>({0., up, roll});
+ }
+ if (R(0, 2) < -bound)
+ {
+ double roll = atan(R(1, 0) / R(2, 0));
+ return dmat<3, 1>({0., -up, roll});
+ }
+ double pitch = asin(-R(0, 2));
+ double roll = atan2(R(1, 2), R(2, 2));
+ double yaw = atan2(R(0, 1), R(0, 0));
+ return dmat<3, 1>({yaw, pitch, roll});
+ }
+
+ // tait-bryan angles, not euler
+ static dmat<3, 3> euler_to_rmat(const double* input)
+ {
+ static constexpr double pi = 3.141592653;
+ auto H = input[0] * pi / 180;
+ auto P = input[1] * pi / 180;
+ auto B = input[2] * pi / 180;
+
+ const auto c1 = cos(H);
+ const auto s1 = sin(H);
+ const auto c2 = cos(P);
+ const auto s2 = sin(P);
+ const auto c3 = cos(B);
+ const auto s3 = sin(B);
+
+ double foo[] = {
+ // z
+ c1 * c2,
+ c1 * s2 * s3 - c3 * s1,
+ s1 * s3 + c1 * c3 * s2,
+ // y
+ c2 * s1,
+ c1 * c3 + s1 * s2 * s3,
+ c3 * s1 * s2 - c1 * s3,
+ // x
+ -s2,
+ c2 * s3,
+ c2 * c3
+ };
+
+ return dmat<3, 3>(foo);
+ }
+};
+
+template<int h, int w> using dmat = Mat<double, h, w>;
diff --git a/opentrack/state.hpp b/opentrack/state.hpp
index 7fde64dc..2c37e5eb 100644
--- a/opentrack/state.hpp
+++ b/opentrack/state.hpp
@@ -12,18 +12,18 @@ struct Modules {
tracker_modules(filter(dylib::Tracker)),
protocol_modules(filter(dylib::Protocol))
{}
- QList<ptr<dylib>>& filters() { return filter_modules; }
- QList<ptr<dylib>>& trackers() { return tracker_modules; }
- QList<ptr<dylib>>& protocols() { return protocol_modules; }
+ QList<mem<dylib>>& filters() { return filter_modules; }
+ QList<mem<dylib>>& trackers() { return tracker_modules; }
+ QList<mem<dylib>>& protocols() { return protocol_modules; }
private:
- QList<ptr<dylib>> module_list;
- QList<ptr<dylib>> filter_modules;
- QList<ptr<dylib>> tracker_modules;
- QList<ptr<dylib>> protocol_modules;
+ QList<mem<dylib>> module_list;
+ QList<mem<dylib>> filter_modules;
+ QList<mem<dylib>> tracker_modules;
+ QList<mem<dylib>> protocol_modules;
- QList<ptr<dylib>> filter(dylib::Type t)
+ QList<mem<dylib>> filter(dylib::Type t)
{
- QList<ptr<dylib>> ret;
+ QList<mem<dylib>> ret;
for (auto x : module_list)
if (x->type == t)
ret.push_back(x);
@@ -35,14 +35,11 @@ struct Work;
struct State {
State() :
- b(bundle("opentrack-ui")),
- s(b),
pose(std::vector<axis_opts*>{&s.a_x, &s.a_y, &s.a_z, &s.a_yaw, &s.a_pitch, &s.a_roll})
{}
Modules modules;
SelectedLibraries libs;
- pbundle b;
main_settings s;
Mappings pose;
- ptr<Work> work;
+ mem<Work> work;
};
diff --git a/opentrack/timer.hpp b/opentrack/timer.hpp
index 628365c9..eb956213 100644
--- a/opentrack/timer.hpp
+++ b/opentrack/timer.hpp
@@ -2,6 +2,9 @@
#include <ctime>
#if defined (_WIN32)
# include <windows.h>
+# ifndef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC -1
+# endif
static inline void opentrack_clock_gettime(int, struct timespec* ts)
{
static LARGE_INTEGER freq;
@@ -50,12 +53,8 @@ public:
Timer() {
start();
}
- long start() {
- struct timespec cur;
- (void) clock_gettime(CLOCK_MONOTONIC, &cur);
- long ret = conv(cur);
- state = cur;
- return ret;
+ void start() {
+ (void) clock_gettime(CLOCK_MONOTONIC, &state);
}
long elapsed() {
struct timespec cur;
diff --git a/opentrack/tracker.cpp b/opentrack/tracker.cpp
index 8f1854e9..f70dd819 100644
--- a/opentrack/tracker.cpp
+++ b/opentrack/tracker.cpp
@@ -12,9 +12,8 @@
* originally written by Wim Vriend.
*/
-#include <opencv2/core/core.hpp>
-#include "./tracker.h"
+#include "tracker.h"
#include <cmath>
#include <algorithm>
@@ -25,10 +24,13 @@
Tracker::Tracker(main_settings& s, Mappings &m, SelectedLibraries &libs) :
s(s),
m(m),
- centerp(false),
+ centerp(s.center_at_startup),
enabledp(true),
+ zero_(false),
should_quit(false),
- libs(libs)
+ libs(libs),
+ r_b(dmat<3,3>::eye()),
+ t_b {0,0,0}
{
}
@@ -38,112 +40,145 @@ Tracker::~Tracker()
wait();
}
-double Tracker::map(double pos, Mapping& axis) {
+double Tracker::map(double pos, Mapping& axis)
+{
bool altp = (pos < 0) && axis.opts.altp;
axis.curve.setTrackingActive( !altp );
axis.curveAlt.setTrackingActive( altp );
auto& fc = altp ? axis.curveAlt : axis.curve;
- double invert = axis.opts.invert ? -1 : 1;
- return invert * (fc.getValue(pos) + axis.opts.zero);
-}
-
-static cv::Matx33d euler_to_rmat(const double* input)
-{
- static constexpr double pi = 3.141592653;
- const auto H = input[0] * pi / -180;
- const auto P = input[1] * pi / -180;
- const auto B = input[2] * pi / 180;
-
- const auto cosH = cos(H);
- const auto sinH = sin(H);
- const auto cosP = cos(P);
- const auto sinP = sin(P);
- const auto cosB = cos(B);
- const auto sinB = sin(B);
-
- double foo[] = {
- cosH * cosB - sinH * sinP * sinB,
- - sinB * cosP,
- sinH * cosB + cosH * sinP * sinB,
- cosH * sinB + sinH * sinP * cosB,
- cosB * cosP,
- sinB * sinH - cosH * sinP * cosB,
- - sinH * cosP,
- - sinP,
- cosH * cosP,
- };
-
- return cv::Matx33d(foo);
+ return fc.getValue(pos) + axis.opts.zero;
}
-void Tracker::t_compensate(const double* input, double* output, bool rz)
+void Tracker::t_compensate(const rmat& rmat, const double* xyz, double* output, bool rz)
{
- const cv::Matx33d rmat = euler_to_rmat(&input[Yaw]);
- const cv::Vec3d tvec(input);
- const cv::Vec3d ret = rmat * tvec;
-
- const int max = !rz ? 3 : 2;
-
- for (int i = 0; i < max; i++)
- output[i] = ret(i);
+ // TY is really yaw axis. need swapping accordingly.
+ dmat<3, 1> tvec({ xyz[2], -xyz[0], -xyz[1] });
+ const dmat<3, 1> ret = rmat * tvec;
+ if (!rz)
+ output[2] = ret(0, 0);
+ else
+ output[2] = xyz[2];
+ output[1] = -ret(2, 0);
+ output[0] = -ret(1, 0);
}
void Tracker::logic()
{
- libs.pTracker->data(newpose);
+ bool inverts[6] = {
+ m(0).opts.invert,
+ m(1).opts.invert,
+ m(2).opts.invert,
+ m(3).opts.invert,
+ m(4).opts.invert,
+ m(5).opts.invert,
+ };
- Pose final_raw_;
-
- if (enabledp)
- {
+ static constexpr double pi = 3.141592653;
+ static constexpr double r2d = 180. / pi;
+
+ Pose value, raw;
+
+ if (!zero_)
for (int i = 0; i < 6; i++)
{
- auto& axis = m(i);
- int k = axis.opts.src;
- if (k < 0 || k >= 6)
- {
- final_raw_(i) = 0;
- continue;
- }
- // not really raw, after axis remap -sh
- final_raw_(i) = newpose[k];
+ value(i) = newpose[i];
+ raw(i) = newpose[i];
+ }
+ else
+ {
+ auto mat = rmat::rmat_to_euler(r_b);
+
+ for (int i = 0; i < 3; i++)
+ {
+ raw(i+3) = value(i+3) = mat(i, 0) * r2d;
+ raw(i) = value(i) = t_b[i];
}
- final_raw = final_raw_;
}
+
+ const double off[] = {
+ s.camera_yaw,
+ s.camera_pitch,
+ 0.
+ };
+ const rmat cam = rmat::euler_to_rmat(off);
+ rmat r = rmat::euler_to_rmat(&value[Yaw]);
+ dmat<3, 1> t { value(0), value(1), value(2) };
- Pose filtered_pose;
+ r = cam * r;
+ t = cam * t;
- if (libs.pFilter)
- libs.pFilter->filter(final_raw, filtered_pose);
- else
- filtered_pose = final_raw;
+ bool can_center = false;
if (centerp)
{
+ for (int i = 0; i < 6; i++)
+ if (fabs(newpose[i]) != 0)
+ {
+ can_center = true;
+ break;
+ }
+ }
+
+ if (can_center)
+ {
centerp = false;
- raw_center = final_raw;
+ for (int i = 0; i < 3; i++)
+ t_b[i] = t(i, 0);
+ r_b = r;
}
- Pose raw_centered = filtered_pose & raw_center;
+ {
+ double tmp[3] = { t(0, 0) - t_b[0], t(1, 0) - t_b[1], t(2, 0) - t_b[2] };
+ t_compensate(cam, tmp, tmp, false);
+ const rmat m_ = r * r_b.t();
+ const dmat<3, 1> euler = rmat::rmat_to_euler(m_);
+ for (int i = 0; i < 3; i++)
+ {
+ value(i) = tmp[i];
+ value(i+3) = euler(i, 0) * r2d;
+ }
+ }
- Pose mapped_pose_precomp;
+ for (int i = 3; i < 6; i++)
+ value(i) = map(value(i), m(i));
- for (int i = 0; i < 6; i++)
- mapped_pose_precomp(i) = map(raw_centered(i), m(i));
+ {
+ Pose tmp = value;
+
+ if (libs.pFilter)
+ libs.pFilter->filter(tmp, value);
+ }
+
+ if (s.tcomp_p)
+ t_compensate(rmat::euler_to_rmat(&value[Yaw]),
+ value,
+ value,
+ s.tcomp_tz);
- Pose mapped_pose;
+ for (int i = 0; i < 3; i++)
+ value(i) = map(value(i), m(i));
- mapped_pose = mapped_pose_precomp;
- if (s.tcomp_p)
- t_compensate(mapped_pose_precomp, mapped_pose, s.tcomp_tz);
+ for (int i = 0; i < 6; i++)
+ value[i] *= inverts[i] ? -1. : 1.;
- libs.pProtocol->pose(mapped_pose);
+ Pose output_pose_;
+ for (int i = 0; i < 6; i++)
{
- QMutexLocker foo(&mtx);
- output_pose = mapped_pose;
- raw_6dof = final_raw;
+ auto& axis = m(i);
+ int k = axis.opts.src;
+ if (k < 0 || k >= 6)
+ output_pose_(i) = 0;
+ else
+ output_pose_(i) = value(k);
}
+
+
+ libs.pProtocol->pose(output_pose_);
+
+ QMutexLocker foo(&mtx);
+ output_pose = output_pose_;
+ raw_6dof = raw;
}
void Tracker::run() {
@@ -156,13 +191,28 @@ void Tracker::run() {
while (!should_quit)
{
t.start();
-
+
+ double tmp[6] {0,0,0, 0,0,0};
+ libs.pTracker->data(tmp);
+
+ if (enabledp)
+ for (int i = 0; i < 6; i++)
+ newpose[i] = tmp[i];
+
logic();
- double q = sleep_ms * 1000L;
- q -= t.elapsed();
- q = std::max(0., q);
- usleep((long)q);
+ long q = sleep_ms * 1000L - t.elapsed()/1000L;
+ usleep(std::max(1L, q));
+ }
+
+ {
+ // do one last pass with origin pose
+ for (int i = 0; i < 6; i++)
+ newpose[i] = 0;
+ logic();
+ // filter may inhibit exact origin
+ Pose p;
+ libs.pProtocol->pose(p);
}
#if defined(_WIN32)
diff --git a/opentrack/tracker.h b/opentrack/tracker.h
index 462f4e50..ace9fa3c 100644
--- a/opentrack/tracker.h
+++ b/opentrack/tracker.h
@@ -1,16 +1,16 @@
#pragma once
-#include <atomic>
#include <vector>
-#include "./timer.hpp"
-#include "./plugin-support.h"
-#include "./mappings.hpp"
-#include "./pose.hpp"
+#include "timer.hpp"
+#include "plugin-support.h"
+#include "mappings.hpp"
+#include "pose.hpp"
+#include "simple-mat.hpp"
#include "../qfunctionconfigurator/functionconfig.h"
-#include "./main-settings.hpp"
-#include "./options.hpp"
+#include "main-settings.hpp"
+#include "options.hpp"
#include <QMutex>
#include <QThread>
@@ -21,26 +21,35 @@ private:
QMutex mtx;
main_settings& s;
Mappings& m;
-
+
Timer t;
- Pose output_pose, raw_6dof, raw_center, final_raw;
+ Pose output_pose, raw_6dof;
+
double newpose[6];
- std::atomic<bool> centerp;
- std::atomic<bool> enabledp;
- std::atomic<bool> should_quit;
+ volatile bool centerp;
+ volatile bool enabledp;
+ volatile bool zero_;
+ volatile bool should_quit;
SelectedLibraries const& libs;
+
+ using rmat = dmat<3, 3>;
+ dmat<3, 3> r_b;
+ double t_b[3];
+
double map(double pos, Mapping& axis);
void logic();
-
- static void t_compensate(const double* input, double* output, bool rz);
+
+ void t_compensate(const dmat<3, 3>& rmat, const double* ypr, double* output, bool rz);
void run() override;
+
public:
Tracker(main_settings& s, Mappings& m, SelectedLibraries& libs);
~Tracker();
void get_raw_and_mapped_poses(double* mapped, double* raw) const;
void start() { QThread::start(); }
- void toggle_enabled() { enabledp.store(!enabledp.load()); }
- void center() { centerp.store(!centerp.load()); }
+ void toggle_enabled() { enabledp = !enabledp; }
+ void center() { centerp = !centerp; }
+ void zero() { zero_ = !zero_; }
};
diff --git a/opentrack/work.hpp b/opentrack/work.hpp
index d0130018..b93c71b6 100644
--- a/opentrack/work.hpp
+++ b/opentrack/work.hpp
@@ -13,10 +13,10 @@ struct Work
{
main_settings& s;
SelectedLibraries libs;
- ptr<Tracker> tracker;
- ptr<Shortcuts> sc;
+ mem<Tracker> tracker;
+ mem<Shortcuts> sc;
WId handle;
-
+
Work(main_settings& s, Mappings& m, SelectedLibraries& libs, QObject* recv, WId handle) :
s(s), libs(libs),
tracker(std::make_shared<Tracker>(s, m, libs)),
@@ -26,22 +26,24 @@ struct Work
#ifndef _WIN32
QObject::connect(sc->keyCenter.get(), SIGNAL(activated()), recv, SLOT(shortcutRecentered()));
QObject::connect(sc->keyToggle.get(), SIGNAL(activated()), recv, SLOT(shortcutToggled()));
+ QObject::connect(sc->keyZero.get(), SIGNAL(activated()), recv, SLOT(shortcutZeroed()));
#else
- QObject::connect(sc->keybindingWorker.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered()));
- QObject::connect(sc->keybindingWorker.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled()));
+ QObject::connect(sc.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered()));
+ QObject::connect(sc.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled()));
+ QObject::connect(sc.get(), SIGNAL(zero()), recv, SLOT(shortcutZeroed()));
#endif
tracker->start();
}
-
+
void reload_shortcuts()
{
sc->reload();
}
-
+
~Work()
{
// order matters, otherwise use-after-free -sh
tracker = nullptr;
libs = SelectedLibraries();
- }
+ }
};
diff --git a/ftnoir_posewidget/glwidget.cpp b/pose-widget/glwidget.cpp
index 26803385..07445c8a 100644
--- a/ftnoir_posewidget/glwidget.cpp
+++ b/pose-widget/glwidget.cpp
@@ -5,14 +5,17 @@
* copyright notice and this permission notice appear in all copies.
*/
-#include <QtGui>
#include "glwidget.h"
-#include <QWidget>
#include <cmath>
#include <algorithm>
+#include <QPainter>
+#include <QPaintEvent>
+
GLWidget::GLWidget(QWidget *parent) : QWidget(parent)
{
+ Q_INIT_RESOURCE(posewidget);
+
front = QImage(QString(":/images/side1.png"));
back = QImage(QString(":/images/side6.png"));
rotateBy(0, 0, 0);
@@ -23,7 +26,6 @@ GLWidget::~GLWidget()
}
void GLWidget::paintEvent ( QPaintEvent * event ) {
- QWidget::paintEvent(event);
QPainter p(this);
project_quad_texture();
p.drawImage(event->rect(), texture);
@@ -31,23 +33,23 @@ void GLWidget::paintEvent ( QPaintEvent * event ) {
void GLWidget::rotateBy(double xAngle, double yAngle, double zAngle)
{
-
- double ch = cos(xAngle / 57.295781);
- double sh = sin(xAngle / 57.295781);
- double ca = cos(yAngle / 57.295781);
- double sa = sin(yAngle / 57.295781);
- double cb = cos(zAngle / 57.295781);
- double sb = sin(zAngle / 57.295781);
-
- matrix[0 * 3 + 0] = ch * ca;
- matrix[0 * 3 + 1]= sh*sb - ch*sa*cb;
- matrix[0 * 3 + 2]= ch*sa*sb + sh*cb;
- matrix[1 * 3 + 0]= sa;
- matrix[1 * 3 + 1]= ca*cb;
- matrix[1 * 3 + 2]= -ca*sb;
- matrix[2 * 3 + 0]= -sh*ca;
- matrix[2 * 3 + 1]= sh*sa*cb + ch*sb;
- matrix[2 * 3 + 2]= -sh*sa*sb + ch*cb;
+
+ double c1 = cos(yAngle / 57.295781);
+ double s1 = sin(yAngle / 57.295781);
+ double c2 = cos(xAngle / 57.295781);
+ double s2 = sin(xAngle / 57.295781);
+ double c3 = cos(zAngle / 57.295781);
+ double s3 = sin(zAngle / 57.295781);
+
+ double foo[] = {
+ c2*c3, -c2*s3, s2,
+ c1*s3+c3*s1*s2, c1*c3-s1*s2*s3, -c2*s1,
+ s1*s3-c1*c3*s2, c3*s1+c1*s2*s3, c1*c2,
+ };
+
+ for (int i = 0; i < 9; i++)
+ matrix[i] = foo[i];
+
update();
}
diff --git a/ftnoir_posewidget/glwidget.h b/pose-widget/glwidget.h
index 6ac12fbf..43a0f853 100644
--- a/ftnoir_posewidget/glwidget.h
+++ b/pose-widget/glwidget.h
@@ -7,7 +7,7 @@
#pragma once
-#include <QtGui>
+#include <QWidget>
#include <QPixmap>
#include "opentrack/plugin-api.hpp"
@@ -47,7 +47,7 @@ struct Vec2f {
}
};
-class OPENTRACK_EXPORT GLWidget : public QWidget
+class GLWidget : public QWidget
{
public:
GLWidget(QWidget *parent);
diff --git a/ftnoir_posewidget/images/side1.png b/pose-widget/images/side1.png
index d7467943..d7467943 100644
--- a/ftnoir_posewidget/images/side1.png
+++ b/pose-widget/images/side1.png
Binary files differ
diff --git a/ftnoir_posewidget/images/side6.png b/pose-widget/images/side6.png
index eaa80d7e..eaa80d7e 100644
--- a/ftnoir_posewidget/images/side6.png
+++ b/pose-widget/images/side6.png
Binary files differ
diff --git a/ftnoir_posewidget/posewidget.qrc b/pose-widget/posewidget.qrc
index e799432f..e799432f 100644
--- a/ftnoir_posewidget/posewidget.qrc
+++ b/pose-widget/posewidget.qrc
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index a0715754..70393246 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -24,8 +24,12 @@ Map::Map() :
float Map::getValue(float x) {
QMutexLocker foo(&_mutex);
- int x2 = x * (double) MEMOIZE_PRECISION;
- float ret = getValueInternal(x2);
+ float q = x * MEMOIZE_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(x);
last_input_value.setY(ret);
return ret;
@@ -45,7 +49,7 @@ float Map::getValueInternal(int x) {
if (sz == 0)
ret = 0;
else
- ret = cur.data[std::max(std::min(x, sz-1), 0)];
+ ret = cur.data[std::min<unsigned>(x, sz-1)];
return ret * sign;
}
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index 94a31be5..c1f11ffa 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -1,9 +1,10 @@
+#include "../opentrack/options.hpp"
+using namespace options;
#include "qfunctionconfigurator/qfunctionconfigurator.h"
#include <QPainter>
#include <QPaintEvent>
#include <QPen>
#include <QPixmap>
-#include <QTimer>
#include <cmath>
#include <algorithm>
@@ -20,11 +21,8 @@ QFunctionConfigurator::QFunctionConfigurator(QWidget *parent) :
}
void QFunctionConfigurator::setConfig(Map* config, const QString& name) {
- QSettings settings("opentrack");
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
-
- config->loadSettings(iniFile, name);
+ mem<QSettings> iniFile = group::ini_file();
+ config->loadSettings(*iniFile, name);
_config = config;
_draw_function = true;
update_range();
@@ -36,7 +34,7 @@ void QFunctionConfigurator::drawBackground()
if (!_config)
return;
_background = QPixmap(width(), height());
-
+
QPainter painter(&_background);
painter.fillRect(rect(), QColor::fromRgb(204, 204, 204));
@@ -135,7 +133,7 @@ void QFunctionConfigurator::drawFunction()
static constexpr double step = 1.02;
const double max = _config->maxInput();
-
+
QPointF prev = point_to_pixel(QPointF(0, 0));
for (double i = 0; i < max; i += step) {
double val = _config->getValue(i);
@@ -156,25 +154,19 @@ void QFunctionConfigurator::paintEvent(QPaintEvent *e)
_draw_function = false;
drawFunction();
}
-
+
p.drawPixmap(e->rect(), _function);
if (_config) {
QPen pen(Qt::white, 1, Qt::SolidLine);
QList<QPointF> points = _config->getPoints();
if (points.size() && moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {
- QPointF prev = points[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;
}
- pen.setWidth(1);
- pen.setColor( Qt::white );
- pen.setStyle( Qt::DashLine );
- QPointF pixel_pos = point_to_pixel(points[moving_control_point_idx]);
- drawLine(&p, QPoint(pixel_bounds.left(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_pos.y()), pen);
- drawLine(&p, QPoint(pixel_pos.x(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_bounds.height() + pixel_bounds.top()), pen);
}
// If the Tracker is active, the 'Last Point' it requested is recorded.
@@ -184,12 +176,6 @@ void QFunctionConfigurator::paintEvent(QPaintEvent *e)
if (_config->getLastPoint(last)) {
QPointF pixel_pos = point_to_pixel( QPointF(fabs(last.x()), fabs(last.y())) );
drawPoint(&p, pixel_pos, QColor(255, 0, 0, 120));
-
- pen.setWidth(1);
- pen.setColor( Qt::black );
- pen.setStyle( Qt::SolidLine );
- drawLine(&p, QPoint(pixel_bounds.left(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_pos.y()), pen);
- drawLine(&p, QPoint(pixel_pos.x(), pixel_pos.y()), QPoint(pixel_pos.x(), pixel_bounds.width()), pen);
}
}
}
@@ -260,32 +246,25 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)
{
if (!_config)
return;
-
- static constexpr int min_refresh_delay = 12;
-
- if (timer.isValid() && timer.elapsed() < min_refresh_delay)
- return;
-
- static constexpr int refresh_delay = 17;
+
QList<QPointF> points = _config->getPoints();
if (moving_control_point_idx != -1 && moving_control_point_idx < points.size()) {
setCursor(Qt::ClosedHandCursor);
-
+
bool overlap = false;
-
+
QPointF new_pt = pixel_coord_to_point(e->pos());
-
+
if (moving_control_point_idx + 1 < points.size())
overlap |= new_pt.x() > points[moving_control_point_idx+1].x();
if (moving_control_point_idx != 0)
overlap |= new_pt.x() < points[moving_control_point_idx-1].x();
-
+
if (overlap)
moving_control_point_idx = -1;
- else if (timer.isValid() && timer.elapsed() > refresh_delay)
+ else
{
- timer.restart();
points[moving_control_point_idx] = new_pt;
_config->movePoint(moving_control_point_idx, new_pt);
_draw_function = true;
@@ -323,7 +302,7 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
}
setCursor(Qt::ArrowCursor);
moving_control_point_idx = -1;
-
+
_draw_function = true;
update();
}
@@ -333,23 +312,24 @@ 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(pixel_bounds.x() + pt.x() * c.x(),
- (pixel_bounds.y() + pixel_bounds.height() - pt.y() * c.y()));
+ 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;
}
@@ -384,5 +364,4 @@ QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point)
void QFunctionConfigurator::resizeEvent(QResizeEvent *)
{
update_range();
- update();
}
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index 52ea40b4..ac9b52e2 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -12,7 +12,6 @@
#include <QWidget>
#include <QtGui>
#include <QPointF>
-#include <QElapsedTimer>
#include "qfunctionconfigurator/functionconfig.h"
#include "opentrack/plugin-api.hpp"
@@ -60,7 +59,6 @@ private:
QRectF pixel_bounds;
int moving_control_point_idx;
- QElapsedTimer timer;
QPointF c;
QColor spline_color;