diff options
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" @@ -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 Binary files differnew file mode 100755 index 00000000..ad25e145 --- /dev/null +++ b/bin/freetrackclient.dll 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 Binary files differindex e392442e..e392442e 100644 --- a/facetracknoir/clientfiles/Tir4Fun/npclient.dll +++ b/clientfiles/Tir4Fun/npclient.dll 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 Binary files differindex a51eced0..a51eced0 100644 --- a/facetracknoir/clientfiles/Tir4Fun/tir4fun.exe +++ b/clientfiles/Tir4Fun/tir4fun.exe diff --git a/facetracknoir/clientfiles/aruco/aruco_create_marker.exe b/clientfiles/aruco/aruco_create_marker.exe Binary files differindex 4400e80e..4400e80e 100644 --- a/facetracknoir/clientfiles/aruco/aruco_create_marker.exe +++ b/clientfiles/aruco/aruco_create_marker.exe diff --git a/facetracknoir/clientfiles/aruco/test3.jpg b/clientfiles/aruco/test3.jpg Binary files differindex 2ff6dbd0..2ff6dbd0 100644 --- a/facetracknoir/clientfiles/aruco/test3.jpg +++ b/clientfiles/aruco/test3.jpg 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 Binary files differindex a1fb306f..a1fb306f 100644 --- a/facetracknoir/clientfiles/cfs3/tirviews.dll +++ b/clientfiles/cfs3/tirviews.dll diff --git a/facetracknoir/clientfiles/cute-octopus-vector-material_15-1831.jpg b/clientfiles/cute-octopus-vector-material_15-1831.jpg Binary files differindex c4e5318f..c4e5318f 100644 --- a/facetracknoir/clientfiles/cute-octopus-vector-material_15-1831.jpg +++ b/clientfiles/cute-octopus-vector-material_15-1831.jpg diff --git a/clientfiles/freepie-udp/com.freepie.android.imu.apk b/clientfiles/freepie-udp/com.freepie.android.imu.apk Binary files differnew file mode 100644 index 00000000..0277b82a --- /dev/null +++ b/clientfiles/freepie-udp/com.freepie.android.imu.apk diff --git a/facetracknoir/clientfiles/freetracktest/freetracktest.exe b/clientfiles/freetracktest/freetracktest.exe Binary files differindex 2965a07f..2965a07f 100644 --- a/facetracknoir/clientfiles/freetracktest/freetracktest.exe +++ b/clientfiles/freetracktest/freetracktest.exe 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 Binary files differindex 264d14c5..264d14c5 100644 --- a/facetracknoir/clientfiles/fs2002 and fs2004/fsuipc.dll +++ b/clientfiles/fs2002 and fs2004/fsuipc.dll 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 Binary files differindex 052c6899..052c6899 100644 --- a/facetracknoir/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg +++ b/clientfiles/ppjoy/ppjoy mapping for facetracknoir.jpg 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 Binary files differindex e3446675..e3446675 100644 --- a/facetracknoir/clientfiles/vjoy/VJoy.dll +++ b/clientfiles/vjoy/VJoy.dll 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 Binary files differindex 3f953a0a..3f953a0a 100644 --- a/facetracknoir/uielements/curves.png +++ b/facetracknoir/images/curves.png diff --git a/ftnoir_filter_ewma2/images/filter-16.png b/facetracknoir/images/filter-16.png Binary files differindex ecde6a10..ecde6a10 100644 --- a/ftnoir_filter_ewma2/images/filter-16.png +++ b/facetracknoir/images/filter-16.png diff --git a/facetracknoir/images/no-feed.png b/facetracknoir/images/no-feed.png Binary files differnew file mode 100644 index 00000000..02aa227a --- /dev/null +++ b/facetracknoir/images/no-feed.png diff --git a/facetracknoir/uielements/tools.png b/facetracknoir/images/tools.png Binary files differindex 2da8f9f5..2da8f9f5 100644 --- a/facetracknoir/uielements/tools.png +++ b/facetracknoir/images/tools.png 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 Binary files differdeleted file mode 100644 index 6494e9c6..00000000 --- a/facetracknoir/uielements/no-feed.png +++ /dev/null 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><html><head/><body><p align="justify">Accela by <a href="https://github.com/sthalik"><span style=" text-decoration: underline; color:#0057ae;">Stanisław Halik</span></a><br/>Help from <a href="https://github.com/dbaarda"><span style=" text-decoration: underline; color:#0057ae;">Donovan Baarda</span></a></p><p align="justify">2012-2013</p></body></html></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><html><head/><body><p align="justify"><br/><span style=" font-size:10pt;">Accela by </span><a href="https://github.com/sthalik"><span style=" font-size:10pt; text-decoration: underline; color:#0057ae;">Stanisław Halik</span></a><span style=" font-size:10pt;"><br/>Thanks to </span><a href="https://github.com/dbaarda"><span style=" font-size:10pt; text-decoration: underline; color:#0057ae;">Donovan Baarda</span></a></p><p align="right"><span style=" font-size:10pt;">2012-2015</span></p><p align="right"><br/></p></body></html></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><html><head/><body><p>Visit <a href="https://github.com/opentrack/opentrack/wiki/Accela-in-opentrack-2.3"><span style=" text-decoration: underline; color:#0000ff;">our wiki</span></a> for description of the settings.</p></body></html></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 Binary files differdeleted file mode 100644 index d263db2d..00000000 --- a/ftnoir_filter_accela/images/filter-16-ac.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 12b02caf..00000000 --- a/ftnoir_filter_ewma2/images/filter-32.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index d263db2d..00000000 --- a/ftnoir_filter_kalman/images/filter-16-ac.png +++ /dev/null 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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay after Start Command in ms</span></p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Little or Big Endian for <span style=" font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;">the serialization of byte order</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial,Geneva,Helvetica,sans-serif'; font-size:medium; color:#000000;">Arduino is LittleEndian ( unchecked)</span></p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay before Init command in ms</span></p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Delay after Init command in ms</span></p></body></html></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><html><head/><body><p>Indicate at OpenTrack speed sketch FPS to adjust CPU </p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">FTNoIR HAT Plugin<br />by FuraX49</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://hatire.sourceforge.net/"><span style=" font-size:8pt; font-weight:600; text-decoration: underline; color:#0000ff;">Manual (external)</span></a></p></body></html></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 Binary files differnew file mode 100644 index 00000000..d8f5aac4 --- /dev/null +++ b/ftnoir_tracker_hatire/images/hat.ico diff --git a/ftnoir_tracker_hatire/images/hat.png b/ftnoir_tracker_hatire/images/hat.png Binary files differnew file mode 100644 index 00000000..a5f7852f --- /dev/null +++ b/ftnoir_tracker_hatire/images/hat.png diff --git a/ftnoir_tracker_hatire/images/hat_logo.png b/ftnoir_tracker_hatire/images/hat_logo.png Binary files differnew file mode 100644 index 00000000..c3a92b1b --- /dev/null +++ b/ftnoir_tracker_hatire/images/hat_logo.png 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 "output remap" 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><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, e.g. millimeters, inches, parsecs...</p></body></html></string> + <string><html><head/><body><p>Location of the two remaining model points<br/>with respect to the reference point in default pose</p><p>Use any units you want, not necessarily centimeters.</p></body></html></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><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">3</span></p></body></html></string> + <string><html><head/><body><p><span style=" font-size:16pt;">P</span><span style=" font-size:16pt; vertical-align:sub;">2</span></p></body></html></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><html><head/><body><p>Translation from head center to model reference point<br/> in default pose</p></body></html></string> + <string><html><head/><body><p>Only pitch and yaw during calibration.</p><p>Don't roll and don't translate.</p></body></html></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 Binary files differindex d7467943..d7467943 100644 --- a/ftnoir_posewidget/images/side1.png +++ b/pose-widget/images/side1.png diff --git a/ftnoir_posewidget/images/side6.png b/pose-widget/images/side6.png Binary files differindex eaa80d7e..eaa80d7e 100644 --- a/ftnoir_posewidget/images/side6.png +++ b/pose-widget/images/side6.png 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; |