summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDonovan Baarda <abo@minkirri.apana.org.au>2014-06-12 14:53:43 +1000
committerDonovan Baarda <abo@minkirri.apana.org.au>2014-06-12 14:53:43 +1000
commit0669a40347ffa233bc6042b0f65d244509a61394 (patch)
tree36a4577bdaa1ed28ca1ad222a54777012dd2dda8
parent72540e0a96a3120a5d02271e714aba29e136ab78 (diff)
parent7454496476ba17ea622781d280606161581c9544 (diff)
Merge branch 'master' of https://github.com/opentrack/opentrack into dev/ewma2
Resolved conflicts manually in files: ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp ftnoir_filter_ewma2/ftnoir_filter_ewma2.h
-rw-r--r--.gitignore2
-rw-r--r--3rdparty-notices/ARUCO-COPYING.txt35
-rw-r--r--3rdparty-notices/FACETRACKNOIR-COPYING.txt23
-rw-r--r--3rdparty-notices/GOOGLE-BREAKPAD-COPYING.txt29
-rw-r--r--3rdparty-notices/LIBOVR-COPYING.txt5
-rw-r--r--3rdparty-notices/LIBQXT-COPYING.txt40
-rw-r--r--3rdparty-notices/NFAILCLIENT-CREDIT.txt4
-rw-r--r--3rdparty-notices/OPENCV-COPYING.txt37
-rw-r--r--3rdparty-notices/QT5-COPYING.txt514
-rw-r--r--CMakeLists.txt1052
-rw-r--r--FTNoIR_Tracker_PT/FTNoIR_PT_Controls.ui (renamed from ftnoir_tracker_pt/ftnoir_pt_controls.ui)873
-rw-r--r--FTNoIR_Tracker_PT/Resources/Logo_IR.png (renamed from ftnoir_tracker_pt/resources/logo_ir.png)bin10386 -> 10386 bytes
-rw-r--r--FTNoIR_Tracker_PT/Resources/cap_front.png (renamed from ftnoir_tracker_pt/resources/cap_front.png)bin1164 -> 1164 bytes
-rw-r--r--FTNoIR_Tracker_PT/Resources/cap_side.png (renamed from ftnoir_tracker_pt/resources/cap_side.png)bin1733 -> 1733 bytes
-rw-r--r--FTNoIR_Tracker_PT/Resources/clip_front.png (renamed from ftnoir_tracker_pt/resources/clip_front.png)bin571 -> 571 bytes
-rw-r--r--FTNoIR_Tracker_PT/Resources/clip_side.png (renamed from ftnoir_tracker_pt/resources/clip_side.png)bin2677 -> 2677 bytes
-rw-r--r--FTNoIR_Tracker_PT/boost-compat.h5
-rw-r--r--FTNoIR_Tracker_PT/camera.cpp351
-rw-r--r--FTNoIR_Tracker_PT/camera.h145
-rw-r--r--FTNoIR_Tracker_PT/doc/index.htm262
-rw-r--r--FTNoIR_Tracker_PT/doc/logo.pngbin0 -> 10386 bytes
-rw-r--r--FTNoIR_Tracker_PT/doc/ptrack.icobin0 -> 4286 bytes
-rw-r--r--FTNoIR_Tracker_PT/doc/settings1.pngbin0 -> 25013 bytes
-rw-r--r--FTNoIR_Tracker_PT/doc/settings2.pngbin0 -> 26841 bytes
-rw-r--r--FTNoIR_Tracker_PT/doc/settings3.pngbin0 -> 29547 bytes
-rw-r--r--FTNoIR_Tracker_PT/doc/style.css131
-rw-r--r--FTNoIR_Tracker_PT/frame_observer.cpp18
-rw-r--r--FTNoIR_Tracker_PT/frame_observer.h76
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp268
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt.h94
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc9
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp321
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.h70
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.cpp (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp)14
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.h (renamed from ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h)15
-rw-r--r--FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h90
-rw-r--r--FTNoIR_Tracker_PT/point_extractor.cpp163
-rw-r--r--FTNoIR_Tracker_PT/point_extractor.h (renamed from ftnoir_tracker_pt/point_extractor.h)4
-rw-r--r--FTNoIR_Tracker_PT/point_tracker.cpp (renamed from ftnoir_tracker_pt/point_tracker.cpp)48
-rw-r--r--FTNoIR_Tracker_PT/point_tracker.h (renamed from ftnoir_tracker_pt/point_tracker.h)23
-rw-r--r--FTNoIR_Tracker_PT/pt_video_widget.cpp64
-rw-r--r--FTNoIR_Tracker_PT/pt_video_widget.h71
-rw-r--r--FTNoIR_Tracker_PT/trans_calib.cpp (renamed from ftnoir_tracker_pt/trans_calib.cpp)0
-rw-r--r--FTNoIR_Tracker_PT/trans_calib.h (renamed from ftnoir_tracker_pt/trans_calib.h)2
-rw-r--r--README.md64
-rw-r--r--TODO.txt29
-rwxr-xr-x[-rw-r--r--]bin/NPClient.dllbin39417 -> 15872 bytes
-rwxr-xr-x[-rw-r--r--]bin/NPClient64.dllbin42054 -> 19968 bytes
-rw-r--r--bin/licence.rtf361
-rw-r--r--bin/settings/default.ini130
-rw-r--r--bin/settings/facetracknoir supported games.csv23
-rw-r--r--cmake/FindQxt.cmake155
-rw-r--r--cmake/GetGitRevisionDescription.cmake123
-rw-r--r--cmake/GetGitRevisionDescription.cmake.in38
-rw-r--r--compat/compat.cpp33
-rw-r--r--compat/compat.h17
-rw-r--r--compat/qt-bug-appeasement.cpp1
-rw-r--r--faceapi/build_options.h8
-rw-r--r--faceapi/ftnoir-faceapi-wrapper.exe.manifest15
-rw-r--r--faceapi/ftnoir-faceapi-wrapper.rc2
-rw-r--r--faceapi/lock.h35
-rw-r--r--faceapi/lockfree.h65
-rw-r--r--faceapi/main.cpp538
-rw-r--r--faceapi/mutex.h46
-rw-r--r--faceapi/stdafx.cpp8
-rw-r--r--faceapi/stdafx.h36
-rw-r--r--faceapi/utils.h349
-rw-r--r--facetracknoir/clientfiles/FlightGear/Nasal/headtracker.xml83
-rw-r--r--facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml27
-rw-r--r--facetracknoir/clientfiles/FlightGear/readme.txt27
-rw-r--r--facetracknoir/clientfiles/FlightGear/win32/start_fg.bat1
-rw-r--r--facetracknoir/clientfiles/aruco/test3.jpgbin0 -> 2145 bytes
-rw-r--r--facetracknoir/clientfiles/vjoy/VJoy.dllbin0 -> 94208 bytes
-rw-r--r--facetracknoir/curve-config.cpp117
-rw-r--r--facetracknoir/curve-config.h22
-rw-r--r--facetracknoir/facetracknoir.cpp2299
-rw-r--r--facetracknoir/facetracknoir.h462
-rw-r--r--facetracknoir/facetracknoir.icobin23558 -> 67134 bytes
-rw-r--r--facetracknoir/facetracknoir.ui3436
-rw-r--r--facetracknoir/ftnoir_curves.ui1818
-rw-r--r--facetracknoir/ftnoir_keyboardshortcuts.ui372
-rw-r--r--facetracknoir/global-settings.cpp15
-rw-r--r--facetracknoir/global-settings.h14
-rw-r--r--facetracknoir/global-shortcuts.cpp11
-rw-r--r--facetracknoir/images/facetracknoir.pngbin691 -> 26466 bytes
-rw-r--r--facetracknoir/images/settingsopen16.pngbin686 -> 0 bytes
-rw-r--r--facetracknoir/main-facetracknoir.qrc1
-rw-r--r--facetracknoir/main-settings.hpp56
-rw-r--r--facetracknoir/main.cpp134
-rw-r--r--facetracknoir/mingw-version-script.txt8
-rw-r--r--facetracknoir/options.h319
-rw-r--r--facetracknoir/qt-moc.h10
-rw-r--r--facetracknoir/rotation.h128
-rw-r--r--facetracknoir/shortcuts.cpp150
-rw-r--r--facetracknoir/shortcuts.h85
-rw-r--r--facetracknoir/timer.hpp66
-rw-r--r--facetracknoir/tracker.cpp324
-rw-r--r--facetracknoir/tracker.h252
-rw-r--r--facetracknoir/tracker_types.cpp88
-rw-r--r--facetracknoir/tracker_types.h65
-rw-r--r--facetracknoir/uielements/logo_facetracknoir_32px.jpgbin1082 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logo_facetracknoir_32px.pngbin2822 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logo_noir.pngbin26173 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logo_noir_small.pngbin6384 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logo_noir_small_target.pngbin5971 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logo_noir_small_target90px.pngbin5582 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logofacetracknoir.pngbin5437 -> 0 bytes
-rw-r--r--facetracknoir/uielements/logofacetracknoir60px.pngbin3369 -> 0 bytes
-rw-r--r--freetrackclient/freetrackclient.cpp89
-rw-r--r--freetrackclient/freetrackclient.def6
-rw-r--r--freetrackclient/ftclient.h30
-rw-r--r--ftnoir_csv/csv.cpp10
-rw-r--r--ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui849
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela.cpp174
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela.h138
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp308
-rw-r--r--ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp64
-rw-r--r--ftnoir_filter_base/ftnoir_filter_base.h45
-rw-r--r--ftnoir_filter_base/ftnoir_filter_base_global.h28
-rw-r--r--ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui16
-rw-r--r--ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp47
-rw-r--r--ftnoir_filter_ewma2/ftnoir_filter_ewma2.h60
-rw-r--r--ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp264
-rw-r--r--ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp88
-rw-r--r--ftnoir_filter_kalman/ftnoir_filter_kalman.h69
-rw-r--r--ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui91
-rw-r--r--ftnoir_filter_kalman/images/filter-16-ac.pngbin0 -> 725 bytes
-rw-r--r--ftnoir_filter_kalman/kalman-filter.qrc (renamed from ftnoir_protocol_ftn/ftn-protocol.qrc)2
-rw-r--r--ftnoir_filter_kalman/kalman.cpp136
-rw-r--r--ftnoir_posewidget/glwidget.cpp427
-rw-r--r--ftnoir_posewidget/glwidget.h213
-rw-r--r--ftnoir_posewidget/images/side1.pngbin9018 -> 26449 bytes
-rw-r--r--ftnoir_posewidget/images/side6.pngbin4768 -> 26493 bytes
-rw-r--r--ftnoir_protocol_base/ftnoir_protocol_base.h148
-rw-r--r--ftnoir_protocol_base/ftnoir_protocol_base_global.h28
-rw-r--r--ftnoir_protocol_fg/fgtypes.h54
-rw-r--r--ftnoir_protocol_fg/ftnoir_fgcontrols.ui334
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg.cpp292
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg.h217
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp290
-rw-r--r--ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp89
-rw-r--r--ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui280
-rw-r--r--ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp379
-rw-r--r--ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h241
-rw-r--r--ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp255
-rw-r--r--ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp88
-rw-r--r--ftnoir_protocol_ft/ftnoir_ftcontrols.ui494
-rw-r--r--ftnoir_protocol_ft/ftnoir_protocol_ft.cpp508
-rw-r--r--ftnoir_protocol_ft/ftnoir_protocol_ft.h261
-rw-r--r--ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp329
-rw-r--r--ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp84
-rw-r--r--ftnoir_protocol_ft/fttypes.h55
-rw-r--r--ftnoir_protocol_ftn/ftnoir_ftncontrols.ui15
-rw-r--r--ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp179
-rw-r--r--ftnoir_protocol_ftn/ftnoir_protocol_ftn.h196
-rw-r--r--ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp250
-rw-r--r--ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp88
-rw-r--r--ftnoir_protocol_ftn/images/facetracknoir.pngbin634 -> 0 bytes
-rw-r--r--ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui111
-rw-r--r--ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp101
-rw-r--r--ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h69
-rw-r--r--ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp26
-rw-r--r--ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dll.cpp16
-rw-r--r--ftnoir_protocol_libevdev/images/linux.pngbin0 -> 668 bytes
-rw-r--r--ftnoir_protocol_libevdev/libevdev-protocol.qrc (renamed from ftnoir_tracker_sm/sm-tracker.qrc)2
-rw-r--r--ftnoir_protocol_mouse/ftnoir_mousecontrols.ui17
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp174
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse.h237
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp258
-rw-r--r--ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp88
-rw-r--r--ftnoir_protocol_sc/ftnoir-protocol-sc.rc4
-rw-r--r--ftnoir_protocol_sc/ftnoir_protocol_sc.cpp614
-rw-r--r--ftnoir_protocol_sc/ftnoir_protocol_sc.h333
-rw-r--r--ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp207
-rw-r--r--ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp89
-rw-r--r--ftnoir_protocol_sc/ftnoir_sccontrols.ui150
-rw-r--r--ftnoir_protocol_sc/scserver-acceleration.manifest13
-rw-r--r--ftnoir_protocol_sc/scserver-sp2.manifest13
-rw-r--r--ftnoir_protocol_sc/scserver.manifest7
-rw-r--r--ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp4
-rw-r--r--ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h49
-rw-r--r--ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp15
-rw-r--r--ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui5
-rw-r--r--ftnoir_protocol_vjoy/vjoy.def5
-rw-r--r--ftnoir_protocol_wine/ftnoir_protocol_wine.cpp53
-rw-r--r--ftnoir_protocol_wine/ftnoir_protocol_wine.h19
-rw-r--r--ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp32
-rw-r--r--ftnoir_protocol_wine/ftnoir_protocol_wine_dll.cpp32
-rw-r--r--ftnoir_protocol_wine/ftnoir_winecontrols.ui7
-rw-r--r--ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx6
-rw-r--r--ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx7
-rw-r--r--ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx4
-rw-r--r--ftnoir_tracker_aruco/ar_video_widget.cpp42
-rw-r--r--ftnoir_tracker_aruco/ar_video_widget.h (renamed from ftnoir_tracker_pt/video_widget.h)89
-rw-r--r--ftnoir_tracker_aruco/aruco-trackercontrols.ui782
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp530
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco.h90
-rw-r--r--ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h3
-rw-r--r--ftnoir_tracker_aruco/include/boarddetector.h2
-rw-r--r--ftnoir_tracker_aruco/include/cvdrawingutils.h2
-rw-r--r--ftnoir_tracker_aruco/include/markerdetector.h11
-rw-r--r--ftnoir_tracker_aruco/video_widget.cpp30
-rw-r--r--ftnoir_tracker_aruco/video_widget.h39
-rw-r--r--ftnoir_tracker_base/ftnoir_tracker_base.h166
-rw-r--r--ftnoir_tracker_base/ftnoir_tracker_base_global.h30
-rw-r--r--ftnoir_tracker_base/ftnoir_tracker_ma_types.h33
-rw-r--r--ftnoir_tracker_base/ftnoir_tracker_sm_types.h36
-rw-r--r--ftnoir_tracker_base/ftnoir_tracker_types.h41
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.cpp316
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht.h64
-rw-r--r--ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h3
-rw-r--r--ftnoir_tracker_ht/ht-api.h68
-rw-r--r--ftnoir_tracker_ht/ht-trackercontrols.ui596
-rw-r--r--ftnoir_tracker_ht/ht_video_widget.cpp44
-rw-r--r--ftnoir_tracker_ht/ht_video_widget.h (renamed from ftnoir_tracker_ht/video_widget.h)20
-rw-r--r--ftnoir_tracker_ht/stdafx.h1
-rw-r--r--ftnoir_tracker_ht/video_widget.cpp30
-rw-r--r--ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui479
-rw-r--r--ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp111
-rw-r--r--ftnoir_tracker_hydra/ftnoir_tracker_hydra.h74
-rw-r--r--ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp168
-rw-r--r--ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp31
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp230
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick.h104
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui439
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp66
-rw-r--r--ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp28
-rw-r--r--ftnoir_tracker_pt/camera.cpp213
-rw-r--r--ftnoir_tracker_pt/camera.h119
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt.cpp261
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt.h96
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt.qrc10
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt.rc61
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp337
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h102
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp150
-rw-r--r--ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h84
-rw-r--r--ftnoir_tracker_pt/point_extractor.cpp96
-rw-r--r--ftnoir_tracker_pt/resource.h14
-rw-r--r--ftnoir_tracker_pt/resources/icon.pngbin1701 -> 0 bytes
-rw-r--r--ftnoir_tracker_pt/timer.cpp65
-rw-r--r--ftnoir_tracker_pt/timer.h44
-rw-r--r--ftnoir_tracker_pt/video_widget.cpp52
-rw-r--r--ftnoir_tracker_pt/videoinput/videoinput.h385
-rw-r--r--ftnoir_tracker_pt/videoinput/videoinput_vc8.libbin2145206 -> 0 bytes
-rw-r--r--ftnoir_tracker_pt/videoinput/videoinput_vc9.libbin2119546 -> 0 bytes
-rw-r--r--ftnoir_tracker_rift/ftnoir_rift.qrc7
-rw-r--r--ftnoir_tracker_rift/ftnoir_rift_clientcontrols.ui473
-rw-r--r--ftnoir_tracker_rift/ftnoir_tracker_rift.cpp181
-rw-r--r--ftnoir_tracker_rift/ftnoir_tracker_rift.h76
-rw-r--r--ftnoir_tracker_rift/ftnoir_tracker_rift_dialog.cpp171
-rw-r--r--ftnoir_tracker_rift/ftnoir_tracker_rift_dll.cpp19
-rw-r--r--ftnoir_tracker_rift/images/medium.pngbin0 -> 5764 bytes
-rw-r--r--ftnoir_tracker_rift/images/rift_medium.pngbin0 -> 5764 bytes
-rw-r--r--ftnoir_tracker_rift/images/rift_small.pngbin0 -> 1212 bytes
-rw-r--r--ftnoir_tracker_rift/images/rift_tiny.pngbin0 -> 624 bytes
-rw-r--r--ftnoir_tracker_rift/images/small.pngbin0 -> 1212 bytes
-rw-r--r--ftnoir_tracker_rift/images/tiny.pngbin0 -> 624 bytes
-rw-r--r--ftnoir_tracker_sm/ftnoir_sm_controls.ui405
-rw-r--r--ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp173
-rw-r--r--ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp282
-rw-r--r--ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp80
-rw-r--r--ftnoir_tracker_sm/ftnoir_tracker_sm.h156
-rw-r--r--ftnoir_tracker_sm/images/sm.pngbin1263 -> 0 bytes
-rw-r--r--ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui13
-rw-r--r--ftnoir_tracker_udp/ftnoir_tracker_udp.cpp256
-rw-r--r--ftnoir_tracker_udp/ftnoir_tracker_udp.h174
-rw-r--r--ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp240
-rw-r--r--ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp133
-rwxr-xr-xinstall-fail-tool19
-rw-r--r--installer/opentrack-installer.iss52
-rw-r--r--opentrack-api/context.cpp112
-rw-r--r--opentrack-api/gnuc-version-script.txt12
-rw-r--r--opentrack-api/opentrack-guts.h57
-rw-r--r--opentrack-api/opentrack.h58
-rw-r--r--opentrack-api/trackers.cpp38
-rw-r--r--opentrack-version.h7
-rw-r--r--qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp (renamed from qfunctionconfigurator/qfunctionconfiguratorplugin.cpp)47
-rw-r--r--qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h (renamed from qfunctionconfigurator/qfunctionconfiguratorplugin.h)9
-rw-r--r--qfunctionconfigurator/functionconfig.cpp563
-rw-r--r--qfunctionconfigurator/functionconfig.h153
-rw-r--r--qfunctionconfigurator/qfunctionconfigurator.cpp853
-rw-r--r--qfunctionconfigurator/qfunctionconfigurator.h171
-rw-r--r--qxt-mini/QxtGlobalShortcut2
-rw-r--r--qxt-mini/plat/qxtglobalshortcut_mac.cpp265
-rw-r--r--qxt-mini/plat/qxtglobalshortcut_x11.cpp235
-rw-r--r--qxt-mini/qplatformnativeinterface.h99
-rw-r--r--qxt-mini/qxtglobal.h233
-rw-r--r--qxt-mini/qxtglobalshortcut.cpp224
-rw-r--r--qxt-mini/qxtglobalshortcut.h64
-rw-r--r--qxt-mini/qxtglobalshortcut_p.h81
-rw-r--r--readme.txt1
-rw-r--r--x-plane-plugin/plugin.c122
293 files changed, 18565 insertions, 23037 deletions
diff --git a/.gitignore b/.gitignore
index 7a420ac8..9c4f50ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@
/bin/tracker-ht/bounding-box.raw
/bin/tracker-ht/flandmark_model.dat
/bin/tracker-ht/head.raw
+/installer/Output
+/nbproject/
diff --git a/3rdparty-notices/ARUCO-COPYING.txt b/3rdparty-notices/ARUCO-COPYING.txt
new file mode 100644
index 00000000..24e57080
--- /dev/null
+++ b/3rdparty-notices/ARUCO-COPYING.txt
@@ -0,0 +1,35 @@
+The ARUCO Library has been developed by the Ava group of the Univeristy of Cordoba(Spain)
+Contact to Rafael Muñoz Salinas <rmsalinas@uco.es>
+
+-----------------------------------------------------------------------
+
+Copyright 2011 Rafael Muñoz Salinas. All rights reserved.
+
+
+Redistribution and use in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer.
+
+
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ of conditions and the following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+
+THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+The views and conclusions contained in the software and documentation are those of the
+authors and should not be interpreted as representing official policies, either expressed
+or implied, of Rafael Muñoz Salinas.
diff --git a/3rdparty-notices/FACETRACKNOIR-COPYING.txt b/3rdparty-notices/FACETRACKNOIR-COPYING.txt
new file mode 100644
index 00000000..befeafb5
--- /dev/null
+++ b/3rdparty-notices/FACETRACKNOIR-COPYING.txt
@@ -0,0 +1,23 @@
+********************************************************************************
+* 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/>. *
+*********************************************************************************
diff --git a/3rdparty-notices/GOOGLE-BREAKPAD-COPYING.txt b/3rdparty-notices/GOOGLE-BREAKPAD-COPYING.txt
new file mode 100644
index 00000000..80f54ae2
--- /dev/null
+++ b/3rdparty-notices/GOOGLE-BREAKPAD-COPYING.txt
@@ -0,0 +1,29 @@
+Copyright (c) 2006, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/3rdparty-notices/LIBOVR-COPYING.txt b/3rdparty-notices/LIBOVR-COPYING.txt
new file mode 100644
index 00000000..e23c0490
--- /dev/null
+++ b/3rdparty-notices/LIBOVR-COPYING.txt
@@ -0,0 +1,5 @@
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form. \ No newline at end of file
diff --git a/3rdparty-notices/LIBQXT-COPYING.txt b/3rdparty-notices/LIBQXT-COPYING.txt
new file mode 100644
index 00000000..252b76ba
--- /dev/null
+++ b/3rdparty-notices/LIBQXT-COPYING.txt
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
diff --git a/3rdparty-notices/NFAILCLIENT-CREDIT.txt b/3rdparty-notices/NFAILCLIENT-CREDIT.txt
new file mode 100644
index 00000000..7a69b0ae
--- /dev/null
+++ b/3rdparty-notices/NFAILCLIENT-CREDIT.txt
@@ -0,0 +1,4 @@
+NFailClient is a clean-room implementation of NFail LLC NFailClient.
+
+Completed as an operation spanning the whole Europe, NFailClient was
+written by gnomes, halflings and rakshasa. \ No newline at end of file
diff --git a/3rdparty-notices/OPENCV-COPYING.txt b/3rdparty-notices/OPENCV-COPYING.txt
new file mode 100644
index 00000000..8824228d
--- /dev/null
+++ b/3rdparty-notices/OPENCV-COPYING.txt
@@ -0,0 +1,37 @@
+IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+
+ By downloading, copying, installing or using the software you agree to this license.
+ If you do not agree to this license, do not download, install,
+ copy or use the software.
+
+
+ License Agreement
+ For Open Source Computer Vision Library
+
+Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
+Third party copyrights are property of their respective owners.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * The name of the copyright holders may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as is" and
+any express or implied warranties, including, but not limited to, the implied
+warranties of merchantability and fitness for a particular purpose are disclaimed.
+In no event shall the Intel Corporation or contributors be liable for any direct,
+indirect, incidental, special, exemplary, or consequential damages
+(including, but not limited to, procurement of substitute goods or services;
+loss of use, data, or profits; or business interruption) however caused
+and on any theory of liability, whether in contract, strict liability,
+or tort (including negligence or otherwise) arising in any way out of
+the use of this software, even if advised of the possibility of such damage.
diff --git a/3rdparty-notices/QT5-COPYING.txt b/3rdparty-notices/QT5-COPYING.txt
new file mode 100644
index 00000000..b2e7909d
--- /dev/null
+++ b/3rdparty-notices/QT5-COPYING.txt
@@ -0,0 +1,514 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+
+ The Qt Toolkit is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ Contact: http://www.qt-project.org/legal
+
+ You may use, distribute and copy the Qt GUI Toolkit under the terms of
+ GNU Lesser General Public License version 2.1, which is displayed below.
+
+-------------------------------------------------------------------------
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3731d7ec..7e101bad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,686 +1,596 @@
project(opentrack)
cmake_minimum_required(VERSION 2.8)
+
+include(CMakeParseArguments)
+
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake/")
+include(GetGitRevisionDescription)
+find_package(Git QUIET)
+if(GIT_FOUND)
+ git_describe(OPENTRACK__COMMIT --tags --always)
+endif()
+
+include_directories(${CMAKE_SOURCE_DIR})
+
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set(CMAKE_COMPILER_IS_GNUCC TRUE)
+ set(CMAKE_COMPILER_IS_GNUCXX TRUE)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE)
+ if(MINGW)
+ set(version-script mingw)
+ else()
+ set(version-script posix)
+ endif()
+endif()
+
+if(APPLE)
+ set(apple-frameworks "-stdlib=libc++ -framework Cocoa -framework CoreFoundation -lobjc -lz -framework Carbon")
+ set(CMAKE_SHARED_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_SHARED_LINKER_FLAGS}")
+ set(CMAKE_STATIC_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_STATIC_LINKER_FLAGS}")
+ set(CMAKE_EXE_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_EXE_LINKER_FLAGS}")
+ set(CMAKE_MODULE_LINKER_FLAGS " ${apple-frameworks} ${CMAKE_MODULE_LINKER_FLAGS}")
+ set(CMAKE_CXX_FLAGS " -stdlib=libc++ -std=c++11 ${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+endif()
+
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
-SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
SET(CMAKE_SKIP_INSTALL_RPATH FALSE)
SET(CMAKE_SKIP_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}")
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-if(WIN32)
- SET(SDK_FACEAPI_ONLY FALSE CACHE BOOL "FaceAPI only (MSVC 2005)")
+add_definitions(-DOPENTRACK_API -DIN_OPENTRACK)
+
+if(MSVC)
+ add_definitions(-DNOMINMAX)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE)
+ add_definitions(-std=c++11)
+endif()
+
+if(WIN32 AND MSVC)
+ set(SDK_GOOGLE_BREAKPAD "" CACHE PATH "google-breakpad for crash reporting")
+endif()
+
+if(MINGW)
+ set(SDK_MINGW_PREFIX "" CACHE PATH "mingw prefix")
+endif()
+
+if(SDK_GOOGLE_BREAKPAD AND WIN32)
+ add_definitions(-DOPENTRACK_BREAKPAD)
+ include_directories("${SDK_GOOGLE_BREAKPAD}/src/client/windows/handler")
+ include_directories("${SDK_GOOGLE_BREAKPAD}/src/")
+endif()
+
+if(WIN32 AND DEFINED MSVC_VERSION AND NOT ${MSVC_VERSION} LESS 1700)
+ find_path (WIN8_SDK_ROOT_DIR
+ Include/um/windows.h
+ PATHS
+ "$ENV{ProgramFiles}/Windows Kits/8.0"
+ "$ENV{ProgramFiles(x86)}/Windows Kits/8.0"
+ DOC "Windows 8 SDK root directory"
+ )
+
+ if(WIN8_SDK_ROOT_DIR)
+ SET(CMAKE_LIBRARY_PATH "${WIN8_SDK_ROOT_DIR}/Lib/win8/um/x86")
+ endif()
+endif()
+
+if(WIN32 AND DEFINED MSVC_VERSION AND NOT ${MSVC_VERSION} LESS 1700)
+ SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
+ SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
+ SET (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
+endif()
+
+if(UNIX)
+ set(SDK_ENABLE_LIBEVDEV FALSE CACHE BOOL "libevdev virtual joystick protocol support (probably Linux only)")
endif()
if(WIN32)
SET(SDK_CONSOLE_DEBUG FALSE CACHE BOOL "Console build")
endif()
IF(WIN32)
- SET(SDK_SM_FACEAPI_PATH "" CACHE PATH "SeeingMachines FaceAPI SDK path")
- SET(SDK_RIFT "" CACHE PATH "libOVR path")
- SET(SDK_HYDRA "" CACHE PATH "libSixense path")
SET(SDK_VJOY "" CACHE PATH "VJoy SDK path")
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")
-file(GLOB opentrack-faceapi-wrapper-c "faceapi/*.cpp")
include_directories(${CMAKE_SOURCE_DIR})
-if(NOT SDK_FACEAPI_ONLY)
- find_package(OpenCV)
- find_package(Qt4 COMPONENTS QtCore QtGui QtDesigner QtXml QtNetwork REQUIRED)
+if(MINGW)
+ # qt scripts are broken
+ set(Qt5Gui_user32_LIBRARY ${SDK_MINGW_PREFIX}/mingw/lib/libuser32.a)
+ set(Qt5Gui_opengl32_LIBRARY ${SDK_MINGW_PREFIX}/mingw/lib/libopengl32.a)
+ set(Qt5Gui_glu32_LIBRARY ${SDK_MINGW_PREFIX}/mingw/lib/libglu32.a)
+ set(Qt5Gui_gdi32_LIBRARY ${SDK_MINGW_PREFIX}/mingw/lib/libgdi32.a)
+endif()
- if(WIN32 AND NOT CMAKE_COMPILER_IS_GNUCC)
- add_definitions(-DFTNOIR_FILTER_BASE_LIB -DFTNOIR_TRACKER_BASE_LIB -DFTNOIR_PROTOCOL_BASE_LIB)
- endif(WIN32 AND NOT CMAKE_COMPILER_IS_GNUCC)
+find_package(OpenCV REQUIRED)
- if(NOT WIN32)
- if(NOT QXT_QXTGUI_LIB_RELEASE)
- find_package(Qxt COMPONENTS QxtGui REQUIRED)
- endif()
+find_package(Qt5 REQUIRED COMPONENTS Core Xml Network Widgets Gui ${maybe-serial-port} QUIET)
+cmake_policy(SET CMP0020 NEW)
+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})
- if(NOT QXT_QXTGUI_INCLUDE_DIR OR QXT_QXTGUI_INCLUDE_DIR STREQUAL "QXT_QXTGUI_INCLUDE_DIR-NOTFOUND")
- message(FATAL_ERROR "Qxt not found, required for keybindings, get from http://libqxt.org")
- endif()
- include_directories(${QXT_QXTGUI_INCLUDE_DIR})
- include_directories(${QXT_QXTCORE_INCLUDE_DIR})
- if(EXISTS "${QXT_QXTCORE_INCLUDE_DIR}/QxtCore/")
- include_directories(${QXT_QXTCORE_INCLUDE_DIR}/QxtCore)
- endif()
- if(EXISTS "${QXT_QXTGUI_INCLUDE_DIR}/QxtGui/")
- include_directories(${QXT_QXTGUI_INCLUDE_DIR}/QxtGui)
- endif()
- endif()
- INCLUDE_DIRECTORIES(${QT_QTDESIGNER_INCLUDE_DIR})
-
- INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/qfunctionconfigurator)
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ftnoir_posewidget)
-
- set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Path to Aruco static library")
-
- SET(SDK_OPENCV_STATIC FALSE CACHE BOOL "Whether OpenCV is statically linked")
- if (WIN32)
- SET(SDK_SM_FACEAPI_PATH "" CACHE PATH "SeeingMachines FaceAPI SDK path")
- set(SDK_SIMCONNECT "" CACHE PATH "Path to SimConnect SDK")
- set(SDK_DIRECTX "" CACHE PATH "Path to DirectX SDK")
- set(SDK_FSUIPC "" CACHE PATH "Path to FSUIPC")
- if(SDK_DIRECTX)
- include_directories("${SDK_DIRECTX}/Include")
- link_directories("${SDK_DIRECTX}/Lib")
- endif()
- endif()
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/qfunctionconfigurator)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ftnoir_posewidget)
- 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")
- endif()
- IF("${CMAKE_SYSTEM}" MATCHES "Linux")
- set(SDK_XPLANE "" CACHE PATH "Path to X-Plane SDK")
- endif()
+set(SDK_ARUCO_LIBPATH "" CACHE FILEPATH "Path to Aruco static library")
- if(SDK_XPLANE)
- INCLUDE_DIRECTORIES("${SDK_XPLANE}/CHeaders" "${SDK_XPLANE}/CHeaders/XPLM")
+SET(SDK_OPENCV_STATIC FALSE CACHE BOOL "Whether OpenCV is statically linked")
+if(WIN32)
+ set(SDK_SIMCONNECT "" CACHE PATH "Path to SimConnect SDK")
+ set(SDK_DIRECTX "" CACHE PATH "Path to DirectX SDK")
+ set(SDK_FSUIPC "" CACHE PATH "Path to FSUIPC")
+ if(SDK_DIRECTX)
+ include_directories("${SDK_DIRECTX}/Include")
+ link_directories("${SDK_DIRECTX}/Lib")
endif()
+endif()
- if(WIN32)
- ENABLE_LANGUAGE(RC)
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- set(CMAKE_RC_COMPILER_INIT windres)
- SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
- else()
- set(CMAKE_RC_COMPILER_INIT rc)
- endif()
- endif(WIN32)
+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")
+endif()
+IF("${CMAKE_SYSTEM}" MATCHES "Linux" OR APPLE)
+ set(SDK_XPLANE "" CACHE PATH "Path to X-Plane SDK")
+endif()
+
+if(SDK_XPLANE)
+ INCLUDE_DIRECTORIES("${SDK_XPLANE}/CHeaders" "${SDK_XPLANE}/CHeaders/XPLM")
+endif()
+
+if(WIN32)
+ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
+ set(CMAKE_RC_COMPILER_INIT i686-w64-mingw32-windres)
+ SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
+ endif()
+ ENABLE_LANGUAGE(RC)
+endif(WIN32)
if(SDK_FSUIPC AND WIN32)
include_directories("${SDK_FSUIPC}")
link_directories("${SDK_FSUIPC}")
endif()
-if(NOT SDK_FACEAPI_ONLY)
-# main app
+# Qxt bundled :: sorry for this, but gentoo ebuild is broken
+if(APPLE)
+ set(qxt-mini-c qxt-mini/plat/qxtglobalshortcut_mac.cpp qxt-mini/qxtglobalshortcut.cpp)
+ include_directories("qxt-mini/")
+else()
+ if(UNIX)
+ set(qxt-mini-c qxt-mini/plat/qxtglobalshortcut_x11.cpp qxt-mini/qxtglobalshortcut.cpp)
+ include_directories("qxt-mini/")
+ endif()
+endif()
- file(GLOB opentrack-bin-c "facetracknoir/*.cpp" "facetracknoir/*.rc")
- file(GLOB opentrack-bin-h "facetracknoir/*.h")
- QT4_WRAP_CPP(opentrack-bin-moc ${opentrack-bin-h})
- file(GLOB opentrack-bin-ui "facetracknoir/*.ui")
- file(GLOB opentrack-bin-rc "facetracknoir/*.qrc")
- QT4_WRAP_UI(opentrack-bin-uih ${opentrack-bin-ui})
- QT4_ADD_RESOURCES(opentrack-bin-rcc ${opentrack-bin-rc})
+# qt being broken as usual
+set(EXTRA-MOCS "${CMAKE_SOURCE_DIR}/facetracknoir/options.h")
+
+function(link_with_dinput8 n)
+ if(WIN32)
+ if(MSVC)
+ target_link_libraries(${n}
+ "${CMAKE_SOURCE_DIR}/dinput/dinput8.lib"
+ "${CMAKE_SOURCE_DIR}/dinput/dxguid.lib"
+ "${CMAKE_SOURCE_DIR}/dinput/strmiids.lib"
+ uuid)
+ else()
+ target_link_libraries(${n} dinput8 dxguid strmiids)
+ endif()
+ endif()
+endfunction()
+
+macro(opentrack_module n dir)
+ file(GLOB ${n}-c "${dir}/*.cpp" "${dir}/*.h" "${dir}/*.rc" "${dir}/*.hpp" ${EXTRA-MOCS})
+ file(GLOB ${n}-ui "${dir}/*.ui")
+ file(GLOB ${n}-rc "${dir}/*.qrc")
+ QT5_WRAP_UI(${n}-uih ${${n}-ui})
+ QT5_ADD_RESOURCES(${n}-rcc ${${n}-rc})
+endmacro()
+
+macro(opentrack_library n)
+ cmake_parse_arguments(foolib "" "LINK;COMPILE" "" ${ARGN})
+ if(NOT " ${foolib_UNPARSED_ARGUMENTS}" STREQUAL " ")
+ message(FATAL_ERROR "opentrack_library bad formals")
+ endif()
+ add_library(${n} SHARED ${${n}-c} ${${n}-uih} ${${n}-rcc})
+ 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"
+ COMPILE_FLAGS "${foolib_COMPILE}"
+ )
+ else()
+ set_target_properties(${n} PROPERTIES LINK_FLAGS "${foolib_LINK}" COMPILE_FLAGS "${foolib_COMPILE}")
+ endif()
+ install(TARGETS ${n} RUNTIME DESTINATION . LIBRARY DESTINATION .)
+endmacro()
- file(GLOB opentrack-pose-widget-c "ftnoir_posewidget/*.cpp")
- file(GLOB opentrack-pose-widget-h "ftnoir_posewidget/*.h")
- QT4_WRAP_CPP(opentrack-pose-widget-moc ${opentrack-pose-widget-h})
- file(GLOB opentrack-pose-widget-rc "ftnoir_posewidget/*.qrc")
- QT4_ADD_RESOURCES(opentrack-pose-widget-rcc ${opentrack-pose-widget-rc})
+file(GLOB opentrack-lib-c "opentrack-api/*.cpp" "facetracknoir/global-settings.cpp" "opentrack-api/*.h" "facetracknoir/global-settings.h")
- file(GLOB opentrack-spline-widget-c "qfunctionconfigurator/*.cpp")
- file(GLOB opentrack-spline-widget-h "qfunctionconfigurator/*.h")
- QT4_WRAP_CPP(opentrack-spline-widget-moc ${opentrack-spline-widget-h})
+opentrack_module(opentrack-bin facetracknoir)
+opentrack_module(opentrack-pose-widget ftnoir_posewidget)
+opentrack_module(opentrack-spline-widget qfunctionconfigurator)
# filters
- file(GLOB opentrack-filter-accela-c "ftnoir_filter_accela/*.cpp")
- file(GLOB opentrack-filter-accela-h "ftnoir_filter_accela/*.h")
- QT4_WRAP_CPP(opentrack-filter-accela-moc ${opentrack-filter-accela-h})
- file(GLOB opentrack-filter-accela-ui "ftnoir_filter_accela/*.ui")
- file(GLOB opentrack-filter-accela-rc "ftnoir_filter_accela/*.qrc")
- QT4_WRAP_UI(opentrack-filter-accela-uih ${opentrack-filter-accela-ui})
- QT4_ADD_RESOURCES(opentrack-filter-accela-rcc ${opentrack-filter-accela-rc})
-
- file(GLOB opentrack-filter-ewma-c "ftnoir_filter_ewma2/*.cpp")
- file(GLOB opentrack-filter-ewma-h "ftnoir_filter_ewma2/*.h")
- QT4_WRAP_CPP(opentrack-filter-ewma-moc ${opentrack-filter-ewma-h})
- file(GLOB opentrack-filter-ewma-ui "ftnoir_filter_ewma2/*.ui")
- file(GLOB opentrack-filter-ewma-rc "ftnoir_filter_ewma2/*.qrc")
- QT4_WRAP_UI(opentrack-filter-ewma-uih ${opentrack-filter-ewma-ui})
- QT4_ADD_RESOURCES(opentrack-filter-ewma-rcc ${opentrack-filter-ewma-rc})
+opentrack_module(opentrack-filter-accela ftnoir_filter_accela)
+opentrack_module(opentrack-filter-kalman ftnoir_filter_kalman)
+opentrack_module(opentrack-filter-ewma ftnoir_filter_ewma2)
# protocols
- file(GLOB opentrack-proto-fgfs-c "ftnoir_protocol_fg/*.cpp")
- file(GLOB opentrack-proto-fgfs-h "ftnoir_protocol_fg/*.h")
- QT4_WRAP_CPP(opentrack-proto-fgfs-moc ${opentrack-proto-fgfs-h})
- file(GLOB opentrack-proto-fgfs-ui "ftnoir_protocol_fg/*.ui")
- file(GLOB opentrack-proto-fgfs-rc "ftnoir_protocol_fg/*.qrc")
- QT4_WRAP_UI(opentrack-proto-fgfs-uih ${opentrack-proto-fgfs-ui})
- QT4_ADD_RESOURCES(opentrack-proto-fgfs-rcc ${opentrack-proto-fgfs-rc})
-
- file(GLOB opentrack-proto-fsuipc-c "ftnoir_protocol_fsuipc/*.cpp")
- file(GLOB opentrack-proto-fsuipc-h "ftnoir_protocol_fsuipc/*.h")
- QT4_WRAP_CPP(opentrack-proto-fsuipc-moc ${opentrack-proto-fsuipc-h})
- file(GLOB opentrack-proto-fsuipc-ui "ftnoir_protocol_fsuipc/*.ui")
- file(GLOB opentrack-proto-fsuipc-rc "ftnoir_protocol_fsuipc/*.qrc")
- QT4_WRAP_UI(opentrack-proto-fsuipc-uih ${opentrack-proto-fsuipc-ui})
- QT4_ADD_RESOURCES(opentrack-proto-fsuipc-rcc ${opentrack-proto-fsuipc-rc})
-
- file(GLOB opentrack-proto-freetrack-c "ftnoir_protocol_ft/*.cpp")
- file(GLOB opentrack-proto-freetrack-h "ftnoir_protocol_ft/*.h")
- QT4_WRAP_CPP(opentrack-proto-freetrack-moc ${opentrack-proto-freetrack-h})
- file(GLOB opentrack-proto-freetrack-ui "ftnoir_protocol_ft/*.ui")
- file(GLOB opentrack-proto-freetrack-rc "ftnoir_protocol_ft/*.qrc")
- QT4_WRAP_UI(opentrack-proto-freetrack-uih ${opentrack-proto-freetrack-ui})
- QT4_ADD_RESOURCES(opentrack-proto-freetrack-rcc ${opentrack-proto-freetrack-rc})
-
- file(GLOB opentrack-proto-udp-c "ftnoir_protocol_ftn/*.cpp")
- file(GLOB opentrack-proto-udp-h "ftnoir_protocol_ftn/*.h")
- QT4_WRAP_CPP(opentrack-proto-udp-moc ${opentrack-proto-udp-h})
- file(GLOB opentrack-proto-udp-ui "ftnoir_protocol_ftn/*.ui")
- file(GLOB opentrack-proto-udp-rc "ftnoir_protocol_ftn/*.qrc")
- QT4_WRAP_UI(opentrack-proto-udp-uih ${opentrack-proto-udp-ui})
- QT4_ADD_RESOURCES(opentrack-proto-udp-rcc ${opentrack-proto-udp-rc})
-
- file(GLOB opentrack-proto-wine-c "ftnoir_protocol_wine/*.cpp")
- file(GLOB opentrack-proto-wine-h "ftnoir_protocol_wine/*.h")
- QT4_WRAP_CPP(opentrack-proto-wine-moc ${opentrack-proto-wine-h})
- file(GLOB opentrack-proto-wine-ui "ftnoir_protocol_wine/*.ui")
- file(GLOB opentrack-proto-wine-rc "ftnoir_protocol_wine/*.qrc")
- QT4_WRAP_UI(opentrack-proto-wine-uih ${opentrack-proto-wine-ui})
- QT4_ADD_RESOURCES(opentrack-proto-wine-rcc ${opentrack-proto-wine-rc})
-
- file(GLOB opentrack-proto-win32-mouse-c "ftnoir_protocol_mouse/*.cpp")
- file(GLOB opentrack-proto-win32-mouse-h "ftnoir_protocol_mouse/*.h")
- QT4_WRAP_CPP(opentrack-proto-win32-mouse-moc ${opentrack-proto-win32-mouse-h})
- file(GLOB opentrack-proto-win32-mouse-ui "ftnoir_protocol_mouse/*.ui")
- file(GLOB opentrack-proto-win32-mouse-rc "ftnoir_protocol_mouse/*.qrc")
- QT4_WRAP_UI(opentrack-proto-win32-mouse-uih ${opentrack-proto-win32-mouse-ui})
- QT4_ADD_RESOURCES(opentrack-proto-win32-mouse-rcc ${opentrack-proto-win32-mouse-rc})
-
- file(GLOB opentrack-proto-simconnect-c "ftnoir_protocol_sc/*.cpp" "ftnoir_protocol_sc/ftnoir-protocol-sc.rc")
- file(GLOB opentrack-proto-simconnect-h "ftnoir_protocol_sc/*.h")
- QT4_WRAP_CPP(opentrack-proto-simconnect-moc ${opentrack-proto-simconnect-h})
- file(GLOB opentrack-proto-simconnect-ui "ftnoir_protocol_sc/*.ui")
- file(GLOB opentrack-proto-simconnect-rc "ftnoir_protocol_sc/*.qrc")
- QT4_WRAP_UI(opentrack-proto-simconnect-uih ${opentrack-proto-simconnect-ui})
- QT4_ADD_RESOURCES(opentrack-proto-simconnect-rcc ${opentrack-proto-simconnect-rc})
-
- file(GLOB opentrack-proto-vjoy-c "ftnoir_protocol_vjoy/*.cpp")
- file(GLOB opentrack-proto-vjoy-h "ftnoir_protocol_vjoy/*.h")
- QT4_WRAP_CPP(opentrack-proto-vjoy-moc ${opentrack-proto-vjoy-h})
- file(GLOB opentrack-proto-vjoy-ui "ftnoir_protocol_vjoy/*.ui")
- file(GLOB opentrack-proto-vjoy-rc "ftnoir_protocol_vjoy/*.qrc")
- QT4_WRAP_UI(opentrack-proto-vjoy-uih ${opentrack-proto-vjoy-ui})
- QT4_ADD_RESOURCES(opentrack-proto-vjoy-rcc ${opentrack-proto-vjoy-rc})
+opentrack_module(opentrack-proto-fgfs ftnoir_protocol_fg)
+opentrack_module(opentrack-proto-fsuipc ftnoir_protocol_fsuipc)
+opentrack_module(opentrack-proto-freetrack ftnoir_protocol_ft)
+opentrack_module(opentrack-proto-udp ftnoir_protocol_ftn)
+opentrack_module(opentrack-proto-wine ftnoir_protocol_wine)
+opentrack_module(opentrack-proto-win32-mouse ftnoir_protocol_mouse)
+opentrack_module(opentrack-proto-simconnect ftnoir_protocol_sc)
+opentrack_module(opentrack-proto-vjoy ftnoir_protocol_vjoy)
+opentrack_module(opentrack-proto-libevdev ftnoir_protocol_libevdev)
# trackers
- file(GLOB opentrack-tracker-ht-c "ftnoir_tracker_ht/*.cpp")
- file(GLOB opentrack-tracker-ht-h "ftnoir_tracker_ht/*.h")
- QT4_WRAP_CPP(opentrack-tracker-ht-moc ${opentrack-tracker-ht-h})
- file(GLOB opentrack-tracker-ht-ui "ftnoir_tracker_ht/*.ui")
- file(GLOB opentrack-tracker-ht-rc "ftnoir_tracker_ht/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-ht-uih ${opentrack-tracker-ht-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-ht-rcc ${opentrack-tracker-ht-rc})
-
- file(GLOB opentrack-tracker-aruco-c "ftnoir_tracker_aruco/*.cpp")
- file(GLOB opentrack-tracker-aruco-h "ftnoir_tracker_aruco/*.h")
- QT4_WRAP_CPP(opentrack-tracker-aruco-moc ${opentrack-tracker-aruco-h})
- file(GLOB opentrack-tracker-aruco-ui "ftnoir_tracker_aruco/*.ui")
- file(GLOB opentrack-tracker-aruco-rc "ftnoir_tracker_aruco/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-aruco-uih ${opentrack-tracker-aruco-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-aruco-rcc ${opentrack-tracker-aruco-rc})
-
- file(GLOB opentrack-tracker-pt-c "ftnoir_tracker_pt/*.cpp")
- file(GLOB opentrack-tracker-pt-h "ftnoir_tracker_pt/*.h")
- QT4_WRAP_CPP(opentrack-tracker-pt-moc ${opentrack-tracker-pt-h})
- file(GLOB opentrack-tracker-pt-ui "ftnoir_tracker_pt/*.ui")
- file(GLOB opentrack-tracker-pt-rc "ftnoir_tracker_pt/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-pt-uih ${opentrack-tracker-pt-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-pt-rcc ${opentrack-tracker-pt-rc})
-
- file(GLOB opentrack-tracker-udp-c "ftnoir_tracker_udp/*.cpp")
- file(GLOB opentrack-tracker-udp-h "ftnoir_tracker_udp/*.h")
- QT4_WRAP_CPP(opentrack-tracker-udp-moc ${opentrack-tracker-udp-h})
- file(GLOB opentrack-tracker-udp-ui "ftnoir_tracker_udp/*.ui")
- file(GLOB opentrack-tracker-udp-rc "ftnoir_tracker_udp/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-udp-uih ${opentrack-tracker-udp-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-udp-rcc ${opentrack-tracker-udp-rc})
-
- file(GLOB opentrack-tracker-rift-c "ftnoir_tracker_rift/*.cpp")
- file(GLOB opentrack-tracker-rift-h "ftnoir_tracker_rift/*.h")
- QT4_WRAP_CPP(opentrack-tracker-rift-moc ${opentrack-tracker-rift-h})
- file(GLOB opentrack-tracker-rift-ui "ftnoir_tracker_rift/*.ui")
- file(GLOB opentrack-tracker-rift-rc "ftnoir_tracker_rift/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-rift-uih ${opentrack-tracker-rift-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-rift-rcc ${opentrack-tracker-rift-rc})
-
- file(GLOB opentrack-tracker-hydra-c "ftnoir_tracker_hydra/*.cpp")
- file(GLOB opentrack-tracker-hydra-h "ftnoir_tracker_hydra/*.h")
- QT4_WRAP_CPP(opentrack-tracker-hydra-moc ${opentrack-tracker-hydra-h})
- file(GLOB opentrack-tracker-hydra-ui "ftnoir_tracker_hydra/*.ui")
- file(GLOB opentrack-tracker-hydra-rc "ftnoir_tracker_hydra/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-hydra-uih ${opentrack-tracker-hydra-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-hydra-rcc ${opentrack-tracker-hydra-rc})
-
- file(GLOB opentrack-tracker-faceapi-c "ftnoir_tracker_sm/*.cpp")
- file(GLOB opentrack-tracker-faceapi-h "ftnoir_tracker_sm/*.h")
- QT4_WRAP_CPP(opentrack-tracker-faceapi-moc ${opentrack-tracker-faceapi-h})
- file(GLOB opentrack-tracker-faceapi-ui "ftnoir_tracker_sm/*.ui")
- file(GLOB opentrack-tracker-faceapi-rc "ftnoir_tracker_sm/*.qrc")
- QT4_WRAP_UI(opentrack-tracker-faceapi-uih ${opentrack-tracker-faceapi-ui})
- QT4_ADD_RESOURCES(opentrack-tracker-faceapi-rcc ${opentrack-tracker-faceapi-rc})
-
- file(GLOB opentrack-csv-c "ftnoir_csv/*.cpp")
+opentrack_module(opentrack-tracker-ht ftnoir_tracker_ht)
+opentrack_module(opentrack-tracker-aruco ftnoir_tracker_aruco)
+opentrack_module(opentrack-tracker-pt FTNoIR_Tracker_PT)
+opentrack_module(opentrack-tracker-udp ftnoir_tracker_udp)
+opentrack_module(opentrack-tracker-joystick ftnoir_tracker_joystick)
+opentrack_module(opentrack-tracker-rift ftnoir_tracker_rift)
+opentrack_module(opentrack-tracker-hydra ftnoir_tracker_hydra)
+
+file(GLOB opentrack-csv-c "ftnoir_csv/*.cpp" "ftnoir_csv/*.h")
# compat lib for POSIX/win32
- file(GLOB opentrack-compat-c "compat/*.cpp")
+file(GLOB opentrack-compat-c "compat/*.cpp" "compat/*.h")
# x-plane plugin
- file(GLOB opentrack-xplane-plugin-c "x-plane-plugin/*.c")
-
+file(GLOB opentrack-xplane-plugin-c "x-plane-plugin/*.c")
+
# freetrack
- file(GLOB opentrack-freetrack-c "freetrackclient/*.cpp")
-
- if(SDK_XPLANE)
- # probably librt already included
- add_library(opentrack-xplane-plugin SHARED ${opentrack-xplane-plugin-c})
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-xplane-plugin
- PROPERTIES LINK_FLAGS
- "-Wl,--version-script=${CMAKE_SOURCE_DIR}/x-plane-plugin/version-script.txt -shared -rdynamic -nodefaultlibs -undefined_warning -fPIC"
- COMPILE_FLAGS "-Wall -O2 -pipe -fPIC -DLIN -DXPLM210"
- LIBRARY_OUTPUT_NAME "facetracknoir.xpl"
- PREFIX "" SUFFIX "")
- endif()
+file(GLOB opentrack-freetrack-c "freetrackclient/*.cpp")
+
+if(SDK_XPLANE)
+ # probably librt already included
+ 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
+ "-Wl,--version-script=${CMAKE_SOURCE_DIR}/x-plane-plugin/version-script.txt -shared -rdynamic -nodefaultlibs -undefined_warning -fPIC"
+ COMPILE_FLAGS "-Wall -O2 -pipe -fPIC -DLIN -DXPLM210"
+ LIBRARY_OUTPUT_NAME "opentrack.xpl"
+ PREFIX "" SUFFIX "")
+ endif()
+ if(APPLE)
+ SET_TARGET_PROPERTIES(opentrack-xplane-plugin PROPERTIES
+ COMPILE_FLAGS "-iframework ${SDK_XPLANE}/Libraries/Mac/ -DAPL -DXPLM210 -framework XPLM -framework XPWidgets"
+ LINK_FLAGS "-F${SDK_XPLANE}/Libraries/Mac/ -framework XPLM -framework XPWidgets")
+ endif()
+ if(UNIX AND NOT APPLE)
+ target_link_libraries(opentrack-xplane-plugin rt)
endif()
endif()
# some boilerplate
- if(QT_USE_FILE)
- INCLUDE(${QT_USE_FILE})
- endif()
+if(QT_USE_FILE)
+ INCLUDE(${QT_USE_FILE})
+endif()
- if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
- SET (CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS_INIT} -rdynamic CACHE STRING "Flags used by the linker during the creation of dll's.")
- SET (CMAKE_MODULE_LINKER_FLAGS ${CMAKE_MODULE_LINKER_FLAGS_INIT} -rdynamic CACHE STRING "Flags used by the linker during the creation of modules.")
- SET (CMAKE_MODULE_LINKER_FLAGS ${CMAKE_MODULE_LINKER_FLAGS_INIT} -rdynamic CACHE STRING "Flags used by the linker during the creation of modules.")
- endif()
+add_library(opentrack-compat SHARED ${opentrack-compat-c})
+if(NOT WIN32 AND NOT APPLE)
+ target_link_libraries(opentrack-compat rt)
+endif()
+
+# hack to avoid breakage on buildbot
+set(my-qt-deps)
+if(WIN32)
+ set(my-qt-deps ws2_32)
+endif()
+set(MY_QT_LIBS ${Qt5Widgets_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Xml_LIBRARIES} ${Qt5Core_LIBRARIES} ${my-qt-deps})
- add_library(opentrack-compat SHARED ${opentrack-compat-c})
- if(NOT WIN32)
- target_link_libraries(opentrack-compat rt)
- endif()
+add_library(opentrack-csv SHARED ${opentrack-csv-c})
+target_link_libraries(opentrack-csv ${MY_QT_LIBS})
- IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
- SET(MY_QT_LIBS ${QT_QTCORE_LIBRARY_DEBUG} ${QT_QTGUI_LIBRARY_DEBUG} ${QT_QTNETWORK_LIBRARY_DEBUG} ${QT_QTXML_LIBRARY_DEBUG})
- ELSE()
- SET(MY_QT_LIBS ${QT_QTCORE_LIBRARY_RELEASE} ${QT_QTGUI_LIBRARY_RELEASE} ${QT_QTNETWORK_LIBRARY_RELEASE} ${QT_QTXML_LIBRARY_RELEASE})
- ENDIF()
+add_library(opentrack-pose-widget SHARED ${opentrack-pose-widget-c} ${opentrack-pose-widget-rcc})
+target_link_libraries(opentrack-pose-widget ${MY_QT_LIBS})
+add_library(opentrack-spline-widget SHARED ${opentrack-spline-widget-c})
+target_link_libraries(opentrack-spline-widget ${MY_QT_LIBS})
- add_library(opentrack-csv SHARED ${opentrack-csv-c})
- target_link_libraries(opentrack-csv ${MY_QT_LIBS})
+opentrack_library(opentrack-filter-accela)
+opentrack_library(opentrack-filter-kalman)
+opentrack_library(opentrack-filter-ewma)
- add_library(opentrack-pose-widget SHARED ${opentrack-pose-widget-c} ${opentrack-pose-widget-moc} ${opentrack-pose-widget-rcc})
- target_link_libraries(opentrack-pose-widget ${MY_QT_LIBS})
- add_library(opentrack-spline-widget SHARED ${opentrack-spline-widget-c} ${opentrack-spline-widget-moc} ${MY_QT_LIBS} ${QT_QTDESIGNER_LIBRARY_RELEASE})
- target_link_libraries(opentrack-spline-widget ${MY_QT_LIBS})
+target_link_libraries(opentrack-filter-kalman ${OpenCV_LIBS})
- add_library(opentrack-filter-accela SHARED ${opentrack-filter-accela-c} ${opentrack-filter-accela-moc} ${opentrack-filter-accela-uih} ${opentrack-filter-accela-rcc})
- target_link_libraries(opentrack-filter-accela ${MY_QT_LIBS} opentrack-spline-widget)
+opentrack_library(opentrack-proto-fgfs)
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-filter-accela
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
+if(SDK_VJOY)
+ include_directories(${SDK_VJOY})
+ opentrack_library(opentrack-proto-vjoy)
+ if(MSVC)
+ target_link_libraries(opentrack-proto-vjoy ${MY_QT_LIBS} "${SDK_VJOY}/VJoy.lib")
+ else()
+ target_link_libraries(opentrack-proto-vjoy ${MY_QT_LIBS} "${SDK_VJOY}/VJoy.dll")
endif()
+endif()
- add_library(opentrack-filter-ewma SHARED ${opentrack-filter-ewma-uih} ${opentrack-filter-ewma-c} ${opentrack-filter-ewma-moc} ${opentrack-filter-ewma-rcc})
- target_link_libraries(opentrack-filter-ewma ${MY_QT_LIBS})
+if(SDK_ENABLE_LIBEVDEV)
+ opentrack_library(opentrack-proto-libevdev)
+ target_link_libraries(opentrack-proto-libevdev evdev)
+endif()
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-filter-ewma
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
+if(SDK_FSUIPC)
+ if(MSVC)
+ set(link-flags "/NODEFAULTLIB:libc")
endif()
+ opentrack_library(opentrack-proto-fsuipc LINK "${link-flags}")
+ target_link_libraries(opentrack-proto-fsuipc "${SDK_FSUIPC}/FSUIPC_User.lib")
+endif()
- add_library(opentrack-proto-fgfs SHARED ${opentrack-proto-fgfs-c} ${opentrack-proto-fgfs-moc} ${opentrack-proto-fgfs-uih} ${opentrack-proto-fgfs-rcc})
- target_link_libraries(opentrack-proto-fgfs ${MY_QT_LIBS})
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-proto-fgfs
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
+if(SDK_SIMCONNECT)
+ opentrack_library(opentrack-proto-simconnect)
+ include_directories("${SDK_SIMCONNECT}/inc")
+ target_link_libraries(opentrack-proto-simconnect "${SDK_SIMCONNECT}/lib/SimConnect.lib")
+endif()
- if(WIN32 AND SDK_VJOY)
- include_directories(${SDK_VJOY})
- add_library(opentrack-proto-vjoy SHARED ${opentrack-proto-vjoy-c} ${opentrack-proto-vjoy-moc} ${opentrack-proto-vjoy-uih} ${opentrack-proto-vjoy-rcc})
- target_link_libraries(opentrack-proto-vjoy ${MY_QT_LIBS} "${SDK_VJOY}/vjoy.lib")
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-proto-vjoy
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
- endif()
+if(WIN32)
+ opentrack_library(opentrack-proto-freetrack)
+ target_link_libraries(opentrack-proto-freetrack opentrack-csv opentrack-compat)
+ opentrack_library(opentrack-proto-win32-mouse)
+endif()
- if(WIN32)
- if(SDK_FSUIPC)
- add_library(opentrack-proto-fsuipc SHARED ${opentrack-proto-fsuipc-c} ${opentrack-proto-fsuipc-moc} ${opentrack-proto-fsuipc-uih} ${opentrack-proto-fsuipc-rcc})
- target_link_libraries(opentrack-proto-fsuipc ${MY_QT_LIBS} "${SDK_FSUIPC}/FSUIPC_User.lib")
- if(MSVC)
- set_target_properties(opentrack-proto-fsuipc PROPERTIES LINK_FLAGS "/NODEFAULTLIB:libc")
- endif()
- endif()
+if(WIN32)
+ add_library(freetrackclient SHARED ${opentrack-freetrack-c})
+ if(CMAKE_COMPILER_IS_GNUCC)
+ set_target_properties(freetrackclient PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup -fno-lto -Wl,-kill-at" PREFIX "" COMPILE_FLAGS "-fno-lto")
+ endif()
+endif()
- if(SDK_SIMCONNECT)
- add_library(opentrack-proto-simconnect SHARED ${opentrack-proto-simconnect-c} ${opentrack-proto-simconnect-moc} ${opentrack-proto-simconnect-uih} ${opentrack-proto-simconnect-rcc})
- target_link_libraries(opentrack-proto-simconnect ${MY_QT_LIBS})
- include_directories("${SDK_SIMCONNECT}/inc")
- target_link_libraries(opentrack-proto-simconnect "${SDK_SIMCONNECT}/lib/simconnect.lib")
- endif()
+opentrack_library(opentrack-proto-udp)
- add_library(opentrack-proto-freetrack SHARED ${opentrack-proto-freetrack-c} ${opentrack-proto-freetrack-moc} ${opentrack-proto-freetrack-uih} ${opentrack-proto-freetrack-rcc})
- target_link_libraries(opentrack-proto-freetrack opentrack-csv ${MY_QT_LIBS} opentrack-compat)
+if(WIN32)
+ opentrack_library(opentrack-tracker-joystick)
+endif()
- add_library(opentrack-proto-win32-mouse SHARED ${opentrack-proto-win32-mouse-c} ${opentrack-proto-win32-mouse-moc} ${opentrack-proto-win32-mouse-uih} ${opentrack-proto-win32-mouse-rcc})
- target_link_libraries(opentrack-proto-win32-mouse ${MY_QT_LIBS})
- add_library(freetrackclient SHARED ${opentrack-freetrack-c})
+if(SDK_WINE_PREFIX)
+ opentrack_library(opentrack-proto-wine)
+ target_link_libraries(opentrack-proto-wine opentrack-compat opentrack-csv)
+ if(NOT SDK_WINE_NO_WRAPPER)
+ set(my-rt -lrt)
+ if(APPLE)
+ set(my-rt)
+ endif()
+ add_custom_command(
+ OUTPUT opentrack-wrapper-wine.exe.so
+ DEPENDS "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx"
+ "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx"
+ "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx"
+ COMMAND "${SDK_WINE_PREFIX}/bin/wineg++" -g -O2 -m32 -o
+ opentrack-wrapper-wine.exe -I "${CMAKE_SOURCE_DIR}"
+ "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx"
+ "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx"
+ "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx"
+ ${my-rt})
+ add_custom_target(wine-wrapper ALL DEPENDS opentrack-wrapper-wine.exe.so)
+ add_dependencies(wine-wrapper opentrack-compat opentrack-proto-wine)
endif()
+endif()
- add_library(opentrack-proto-udp SHARED ${opentrack-proto-udp-c} ${opentrack-proto-udp-moc} ${opentrack-proto-udp-uih} ${opentrack-proto-udp-rcc})
- target_link_libraries(opentrack-proto-udp ${MY_QT_LIBS})
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-proto-udp
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
+opentrack_library(opentrack-tracker-ht)
+target_link_libraries(opentrack-tracker-ht opentrack-compat)
- if(NOT WIN32 AND SDK_WINE_PREFIX)
- add_library(opentrack-proto-wine SHARED ${opentrack-proto-wine-c} ${opentrack-proto-wine-moc} ${opentrack-proto-wine-uih} ${opentrack-proto-wine-rcc})
- target_link_libraries(opentrack-proto-wine ${MY_QT_LIBS} opentrack-compat opentrack-csv)
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-proto-wine
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
- if(NOT SDK_WINE_NO_WRAPPER)
- add_custom_command(
- OUTPUT opentrack-wrapper-wine.exe.so
- COMMAND "${SDK_WINE_PREFIX}/bin/wineg++" -g -O2 -m32 -o
- opentrack-wrapper-wine.exe -I "${CMAKE_SOURCE_DIR}"
- "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx"
- "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx"
- "${CMAKE_SOURCE_DIR}/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx"
- -lrt)
- add_custom_target(wine-wrapper ALL DEPENDS opentrack-wrapper-wine.exe.so)
- endif()
+if(SDK_ARUCO_LIBPATH)
+ include_directories(${CMAKE_SOURCE_DIR}/ftnoir_tracker_aruco/include)
+ opentrack_library(opentrack-tracker-aruco)
+ target_link_libraries(opentrack-tracker-aruco ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS})
+ if(WIN32 AND MSVC)
+ target_link_libraries(opentrack-tracker-aruco
+ "${CMAKE_SOURCE_DIR}/dinput/dxguid.lib"
+ "${CMAKE_SOURCE_DIR}/dinput/strmiids.lib"
+ uuid)
endif()
+endif()
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-proto-fgfs
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
+link_with_dinput8(opentrack-tracker-ht)
+link_with_dinput8(opentrack-tracker-joystick)
- add_library(opentrack-tracker-ht SHARED ${opentrack-tracker-ht-c} ${opentrack-tracker-ht-moc} ${opentrack-tracker-ht-uih} ${opentrack-tracker-ht-rcc})
- target_link_libraries(opentrack-tracker-ht ${MY_QT_LIBS} opentrack-compat)
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-tracker-ht
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
+opentrack_library(opentrack-tracker-pt)
+target_link_libraries(opentrack-tracker-pt ${OpenCV_LIBS})
- if(SDK_ARUCO_LIBPATH)
- include_directories(${CMAKE_SOURCE_DIR}/ftnoir_tracker_aruco/include)
- add_library(opentrack-tracker-aruco SHARED ${opentrack-tracker-aruco-c} ${opentrack-tracker-aruco-moc} ${opentrack-tracker-aruco-uih} ${opentrack-tracker-aruco-rcc})
- target_link_libraries(opentrack-tracker-aruco ${MY_QT_LIBS} ${SDK_ARUCO_LIBPATH} ${OpenCV_LIBS})
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-tracker-aruco
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
- endif()
+link_with_dinput8(opentrack-tracker-pt)
- if(WIN32 AND NOT CMAKE_COMPILER_IS_GNUCC)
- target_link_libraries(opentrack-tracker-ht
- "${CMAKE_SOURCE_DIR}/dinput/dinput8.lib"
- "${CMAKE_SOURCE_DIR}/dinput/dxguid.lib"
- "${CMAKE_SOURCE_DIR}/dinput/strmiids.lib")
- endif()
-
- if(OpenCV_FOUND)
- include_directories(${OpenCV_INCLUDE_DIRS})
- include_directories(${OpenCV_DIR}/include)
- include_directories(${OpenCV_CONFIG_PATH}/include)
- endif()
+opentrack_library(opentrack-tracker-udp)
- if(OpenCV_FOUND)
- add_library(opentrack-tracker-pt SHARED ${opentrack-tracker-pt-c} ${opentrack-tracker-pt-moc} ${opentrack-tracker-pt-uih} ${opentrack-tracker-pt-rcc})
- target_link_libraries(opentrack-tracker-pt ${MY_QT_LIBS} ${OpenCV_LIBS})
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-tracker-pt
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
+if(SDK_RIFT)
+ include_directories("${SDK_RIFT}/Include")
+ include_directories("${SDK_RIFT}/Src")
+ set(link-flags)
+ set(c-flags)
+ if(APPLE)
+ set(link-flags "-framework CoreFoundation -framework CoreGraphics -framework IOKit -framework Quartz")
+ set(c-flags "-fno-strict-aliasing")
+ else()
+ if(MSVC)
+ set(link-flags "/NODEFAULTLIB:LIBCMT")
+ else()
+ set(c-flags "-fno-strict-aliasing")
endif()
endif()
-
- add_library(opentrack-tracker-udp SHARED ${opentrack-tracker-udp-c} ${opentrack-tracker-udp-moc} ${opentrack-tracker-udp-uih} ${opentrack-tracker-udp-rcc})
- target_link_libraries(opentrack-tracker-udp ${MY_QT_LIBS})
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-tracker-udp
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
-
- if(SDK_RIFT)
- include_directories("${SDK_RIFT}/include")
- include_directories("${SDK_RIFT}/Src")
- add_library(opentrack-tracker-rift SHARED ${opentrack-tracker-rift-c} ${opentrack-tracker-rift-moc} ${opentrack-tracker-rift-uih} ${opentrack-tracker-rift-rcc})
- target_link_libraries(opentrack-tracker-rift ${MY_QT_LIBS})
- if(WIN32)
- target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/lib/win32/libovr.lib" winmm.lib)
- endif()
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-tracker-rift
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
- endif()
- endif()
-
- if(SDK_HYDRA)
- include_directories("${SDK_HYDRA}/include")
- include_directories("${SDK_HYDRA}/include/sixense_utils")
- add_library(opentrack-tracker-hydra SHARED ${opentrack-tracker-hydra-c} ${opentrack-tracker-hydra-moc} ${opentrack-tracker-hydra-uih} ${opentrack-tracker-hydra-rcc})
- target_link_libraries(opentrack-tracker-hydra ${MY_QT_LIBS})
+ opentrack_library(opentrack-tracker-rift LINK "${link-flags}" COMPILE "${c-flags}")
+ if(MSVC)
+ target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/Lib/Win32/libovr.lib" winmm.lib setupapi.lib)
+ else()
if(WIN32)
- target_link_libraries(opentrack-tracker-hydra "${SDK_HYDRA}/lib/win32/release_static/sixense_s.lib" "${SDK_HYDRA}/lib/win32/release_static/sixense_utils_s.lib")
- endif()
- if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC)
- SET_TARGET_PROPERTIES(opentrack-tracker-hydra
- PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt")
+ target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a" winmm setupapi)
else()
- if(MSVC)
- SET_TARGET_PROPERTIES(opentrack-tracker-hydra PROPERTIES LINK_FLAGS "/NODEFAULTLIB:libcmt.lib")
+ if(NOT APPLE)
+ target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a" udev Xinerama)
+ else()
+ target_link_libraries(opentrack-tracker-rift "${SDK_RIFT}/libLibOVR.a")
endif()
endif()
endif()
-
- if(WIN32 AND NOT SDK_CONSOLE_DEBUG)
- set(opentrack-win32-executable WIN32)
- else()
- set(opentrack-win32-executable "")
- endif()
- add_executable(opentrack ${opentrack-win32-executable} ${opentrack-bin-c} ${opentrack-bin-moc} ${opentrack-bin-uih} ${opentrack-bin-rcc})
+endif()
+
+if(SDK_HYDRA)
+ include_directories("${SDK_HYDRA}/include")
+ include_directories("${SDK_HYDRA}/include/sixense_utils")
+ opentrack_library(opentrack-tracker-hydra)
if(WIN32)
- target_link_libraries(opentrack "${CMAKE_SOURCE_DIR}/dinput/dinput8.lib" "${CMAKE_SOURCE_DIR}/dinput/dxguid.lib" "${CMAKE_SOURCE_DIR}/dinput/strmiids.lib" winmm)
- endif()
- if(MSVC)
- SET_TARGET_PROPERTIES(opentrack PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
+ target_link_libraries(opentrack-tracker-hydra
+ "${SDK_HYDRA}/lib/win32/release_dll/sixense.lib"
+ "${SDK_HYDRA}/lib/win32/release_dll/sixense_utils.lib")
+ install(FILES "${SDK_HYDRA}/bin/win32/release_dll/sixense.dll" "${SDK_HYDRA}/bin/win32/release_dll/sixense_utils.dll" DESTINATION .)
+ else()
+ if(SDK_HYDRA_AMD64)
+ set(underscore-sixtyfour _x64)
+ else()
+ set(underscore-sixtyfour)
+ endif()
+ if(APPLE)
+ set(underscore-dll _dll)
+ set(soext dylib)
+ set(sixense-plat osx)
+ else()
+ set(underscore-dll)
+ set(soext so)
+ set(sixense-plat linux)
+ endif()
+ install(FILES
+ "${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense${underscore-sixtyfour}.${soext}"
+ "${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense_utils${underscore-sixtyfour}.${soext}"
+ DESTINATION .
+ )
+ target_link_libraries(opentrack-tracker-hydra "${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense${underscore-sixtyfour}.${soext}" "${SDK_HYDRA}/lib/${sixense-plat}${underscore-sixtyfour}/release${underscore-dll}/libsixense_utils${underscore-sixtyfour}.${soext}")
endif()
- target_link_libraries(opentrack opentrack-pose-widget opentrack-spline-widget ${MY_QT_LIBS} ${QXT_QXTCORE_LIB_RELEASE} ${QXT_QXTGUI_LIB_RELEASE})
- if(NOT WIN32)
- target_link_libraries(opentrack dl)
+endif()
+
+if(WIN32 AND NOT SDK_CONSOLE_DEBUG)
+ set(opentrack-win32-executable WIN32)
+else()
+ set(opentrack-win32-executable "")
+endif()
+if(UNIX OR APPLE)
+ add_library(opentrack-qxt-mini SHARED ${qxt-mini-c})
+ SET_TARGET_PROPERTIES(opentrack-qxt-mini PROPERTIES COMPILE_FLAGS "-DBUILD_QXT_CORE=42 -DBUILD_QXT_WIDGETS=42 -DBUILD_QXT_GUI=42")
+ target_link_libraries(opentrack-qxt-mini ${MY_QT_LIBS})
+ if(NOT APPLE)
+ target_link_libraries(opentrack-qxt-mini X11)
endif()
endif()
+add_executable(opentrack ${opentrack-win32-executable} ${opentrack-bin-c} ${opentrack-bin-uih} ${opentrack-bin-rcc})
+set_target_properties(opentrack PROPERTIES COMPILE_DEFINITIONS OPENTRACK_VERSION=\"${OPENTRACK__COMMIT}\")
+set(OPENTRACK_COMMIT_VERSION \"${OPENTRACK__COMMIT}\")
+configure_file("${CMAKE_SOURCE_DIR}/opentrack-version.h" "${CMAKE_BINARY_DIR}/opentrack-version.h" @ONLY NEWLINE_STYLE UNIX)
-# make install
+if(APPLE)
+ SET_TARGET_PROPERTIES(opentrack-qxt-mini PROPERTIES LINK_FLAGS "-framework Carbon -framework CoreFoundation")
+endif()
-if(SDK_SM_FACEAPI_PATH)
- include_directories("${SDK_SM_FACEAPI_PATH}/include")
- if(WIN32 AND NOT SDK_FACEAPI_ONLY)
- add_library(opentrack-tracker-faceapi SHARED ${opentrack-tracker-faceapi-c} ${opentrack-tracker-faceapi-moc} ${opentrack-tracker-faceapi-uih} ${opentrack-tracker-faceapi-rcc})
- target_link_libraries(opentrack-tracker-faceapi ${MY_QT_LIBS} opentrack-compat)
- endif()
- add_executable(opentrack-faceapi-wrapper ${opentrack-faceapi-wrapper-c})
- target_link_libraries(opentrack-faceapi-wrapper "${SDK_SM_FACEAPI_PATH}/bin/smft32.lib")
-endif()
+add_library(opentrack-api SHARED ${opentrack-lib-c})
+target_link_libraries(opentrack-api ${MY_QT_LIBS})
+if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE)
+ SET_TARGET_PROPERTIES(opentrack-api PROPERTIES
+ LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/opentrack-api/gnuc-version-script.txt"
+ COMPILE_FLAGS "-fvisibility=protected -fvisibility-inlines-hidden"
+ COMPILE_DEFINITIONS IN_OPENTRACK_API
+ )
+endif()
-if(NOT SDK_FACEAPI_ONLY)
- if(SDK_XPLANE)
- install(TARGETS opentrack-xplane-plugin LIBRARY DESTINATION . NAMELINK_SKIP)
- endif()
- if(WIN32)
- install(DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tracker-ht" DESTINATION .)
- install(TARGETS freetrackclient RUNTIME DESTINATION .)
- endif()
+set_target_properties(opentrack PROPERTIES COMPILE_DEFINITIONS OPENTRACK_VERSION=\"${OPENTRACK__COMMIT}\")
- 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 .)
+if(UNIX OR APPLE)
+ target_link_libraries(opentrack opentrack-qxt-mini)
+endif()
+target_link_libraries(opentrack ${OpenCV_LIBS})
+include_directories(${OpenCV_INCLUDE_DIRS})
- if(NOT WIN32 AND SDK_WINE_PREFIX)
- install(FILES "${CMAKE_BINARY_DIR}/opentrack-wrapper-wine.exe.so"
- DESTINATION .)
- install(TARGETS opentrack-proto-wine DESTINATION .)
- endif()
+if(UNIX OR APPLE)
+ install(TARGETS opentrack-qxt-mini RUNTIME DESTINATION . LIBRARY DESTINATION . )
+endif()
- if(OpenCV_FOUND)
- install(TARGETS opentrack-tracker-pt RUNTIME DESTINATION . LIBRARY DESTINATION .)
- endif()
+link_with_dinput8(opentrack)
- if(SDK_ARUCO_LIBPATH)
- install(TARGETS opentrack-tracker-aruco RUNTIME DESTINATION . LIBRARY DESTINATION .)
+if(CMAKE_SYSTEM STREQUAL LINUX)
+ link_libraries(rt)
+endif()
+
+if(MSVC)
+ SET_TARGET_PROPERTIES(opentrack PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
+endif()
+target_link_libraries(opentrack opentrack-pose-widget opentrack-spline-widget ${MY_QT_LIBS} ${QXT_QXTCORE_LIB_RELEASE} ${QXT_QXTWIDGETS_LIB_RELEASE})
+if(NOT WIN32)
+ target_link_libraries(opentrack dl)
+ target_link_libraries(opentrack-api dl)
+endif()
+if(SDK_GOOGLE_BREAKPAD)
+ if(MSVC)
+ target_link_libraries(opentrack
+ "${SDK_GOOGLE_BREAKPAD}/src/client/windows/Release/lib/crash_generation_client.lib"
+ "${SDK_GOOGLE_BREAKPAD}/src/client/windows/Release/lib/exception_handler.lib"
+ "${SDK_GOOGLE_BREAKPAD}/src/client/windows/Release/lib/common.lib")
endif()
+endif()
+set_target_properties(opentrack PROPERTIES COMPILE_FLAGS -DOPENTRACK_MAIN)
- install(TARGETS
- opentrack-compat
- opentrack-csv
- opentrack-pose-widget
- opentrack-spline-widget
- opentrack-filter-accela
- opentrack-filter-ewma
- opentrack-proto-fgfs
- opentrack-proto-udp
- opentrack-tracker-ht
- opentrack-tracker-udp
- opentrack
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP
- )
+# make install
- if(SDK_VJOY)
- install(TARGETS opentrack-proto-vjoy
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP)
- install(FILES "${SDK_VJOY}/VJoy.dll" DESTINATION .)
- endif()
+install(FILES "${CMAKE_SOURCE_DIR}/README.md" DESTINATION .)
- if(SDK_RIFT)
- install(
- TARGETS opentrack-tracker-rift
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP
- )
- endif()
+if(SDK_XPLANE)
+ install(TARGETS opentrack-xplane-plugin RUNTIME DESTINATION . LIBRARY DESTINATION . )
+endif()
- if(SDK_HYDRA)
- install(
- TARGETS opentrack-tracker-hydra
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP
- )
- endif()
+if(WIN32)
+ install(DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tracker-ht" DESTINATION .)
+ install(TARGETS freetrackclient RUNTIME DESTINATION . LIBRARY DESTINATION . )
+endif()
- if(WIN32)
- install(FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config" DESTINATION .)
- if(SDK_SIMCONNECT)
- install(TARGETS opentrack-proto-simconnect
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP)
- endif()
- if(OpenCV_FOUND AND NOT SDK_OPENCV_STATIC)
- get_filename_component(opentrack-opencv-dir "${OpenCV_LIB_DIR_OPT}" PATH)
- if(WIN32 AND NOT CMAKE_COMPILER_IS_GNUCC)
- set(LIB-PREFIX "../bin/Release/")
- else()
- set(LIB-PREFIX "lib")
- endif()
- file(GLOB opentrack-opencv-files
- "${opentrack-opencv-dir}/${LIB-PREFIX}opencv_calib3d*.dll"
- "${opentrack-opencv-dir}/${LIB-PREFIX}opencv_core*.dll"
- "${opentrack-opencv-dir}/${LIB-PREFIX}opencv_highgui*.dll"
- "${opentrack-opencv-dir}/${LIB-PREFIX}opencv_imgproc*.dll"
- "${opentrack-opencv-dir}/${LIB-PREFIX}opencv_flann*.dll"
- "${opentrack-opencv-dir}/${LIB-PREFIX}opencv_features2d*.dll"
- )
- install(FILES ${opentrack-opencv-files} DESTINATION .)
- endif()
- get_filename_component(opentrack-qt-bin "${QT_QMAKE_EXECUTABLE}" PATH)
- if(WIN32 AND NOT CMAKE_COMPILER_IS_GNUCC)
- GET_FILENAME_COMPONENT(qt-dirname "${QT_QTCORE_LIBRARY_RELEASE}" PATH)
- SET(qt-dirname "${qt-dirname}/../bin/")
- if(NOT EXISTS "${qt-dirname}/../bin/")
- GET_FILENAME_COMPONENT(qt-dirname "${QT_QTCORE_LIBRARY_RELEASE}" PATH)
- SET(qt-dirname "${qt-dirname}/../bin/")
- endif()
- install(FILES
- "${qt-dirname}/QtCore4.dll"
- "${qt-dirname}/QtGui4.dll"
- "${qt-dirname}/QtNetwork4.dll"
- "${qt-dirname}/QtSvg4.dll"
- "${qt-dirname}/QtXml4.dll"
- DESTINATION .
- )
- endif()
- install(TARGETS
- opentrack-proto-freetrack
- opentrack-proto-win32-mouse
- #opentrack-proto-simconnect
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP
- )
- if(SDK_FSUIPC)
- install(TARGETS opentrack-proto-fsuipc
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP)
- endif()
+install(DIRECTORY "${CMAKE_SOURCE_DIR}/3rdparty-notices" DESTINATION .)
- endif()
+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 .)
+
+if(NOT WIN32 AND SDK_WINE_PREFIX)
+ install(FILES "${CMAKE_BINARY_DIR}/opentrack-wrapper-wine.exe.so"
+ DESTINATION .)
endif()
-if(SDK_SM_FACEAPI_PATH AND NOT SDK_FACEAPI_ONLY)
- install(TARGETS opentrack-tracker-faceapi
- RUNTIME DESTINATION .
- LIBRARY DESTINATION .
- NAMELINK_SKIP
- )
+
+install(TARGETS
+ opentrack-api
+ opentrack-compat
+ opentrack-csv
+ opentrack-pose-widget
+ opentrack-spline-widget
+ RUNTIME DESTINATION . LIBRARY DESTINATION . )
+
+install(TARGETS opentrack DESTINATION .)
+
+if(SDK_VJOY)
+ install(FILES "${SDK_VJOY}/VJoy.dll" DESTINATION .)
endif()
-if(MSVC)
- file(GLOB pdbs "${CMAKE_BINARY_DIR}/*.pdb")
- install(FILES ${pdbs} DESTINATION .)
+if(WIN32)
+ install(FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config" DESTINATION .)
endif()
-if(WIN32 AND SDK_SM_FACEAPI_PATH)
- install(TARGETS opentrack-faceapi-wrapper
- RUNTIME DESTINATION faceapi
- LIBRARY DESTINATION faceapi
- NAMELINK_SKIP
- )
- install(FILES "${CMAKE_SOURCE_DIR}/bin/cleye.config" DESTINATION faceapi)
- install(FILES
- "${SDK_SM_FACEAPI_PATH}/bin/computation6.0.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/foundation6.0.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/image6.0.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/libpng13.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/pgrflycapturegui.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/QtCore0.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/qt-mt334.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/QtXml4.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/smft32.dll"
- "${SDK_SM_FACEAPI_PATH}/bin/zlib1.dll"
- "${SDK_SM_FACEAPI_PATH}/doc/RELEASE NOTES.txt"
- DESTINATION faceapi
- )
- install(DIRECTORY
- "${SDK_SM_FACEAPI_PATH}/bin/cal"
- "${SDK_SM_FACEAPI_PATH}/bin/resources"
- DESTINATION faceapi
- )
+if(MSVC)
+ file(GLOB pdbs1 "${CMAKE_BINARY_DIR}/Release/*.pdb")
+ file(GLOB pdbs2 "${CMAKE_BINARY_DIR}/*.pdb")
+ install(FILES ${pdbs1} ${pdbs2} DESTINATION .)
endif()
diff --git a/ftnoir_tracker_pt/ftnoir_pt_controls.ui b/FTNoIR_Tracker_PT/FTNoIR_PT_Controls.ui
index 0934a4fb..0bbec7e1 100644
--- a/ftnoir_tracker_pt/ftnoir_pt_controls.ui
+++ b/FTNoIR_Tracker_PT/FTNoIR_PT_Controls.ui
@@ -3,14 +3,14 @@
<class>UICPTClientControls</class>
<widget class="QWidget" name="UICPTClientControls">
<property name="windowModality">
- <enum>Qt::ApplicationModal</enum>
+ <enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>451</width>
- <height>489</height>
+ <width>459</width>
+ <height>621</height>
</rect>
</property>
<property name="sizePolicy">
@@ -23,8 +23,8 @@
<string>PointTracker Settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>:/Resources/icon.png</normaloff>:/Resources/icon.png</iconset>
+ <iconset resource="ftnoir_tracker_pt.qrc">
+ <normaloff>:/Resources/Logo_IR.png</normaloff>:/Resources/Logo_IR.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -54,7 +54,7 @@
<locale language="English" country="UnitedStates"/>
</property>
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@@ -66,134 +66,65 @@
<property name="title">
<string>Tracker Thread</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_6">
- <item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0">
- <widget class="QCheckBox" name="dynpose_check">
- <property name="toolTip">
- <string/>
- </property>
- <property name="text">
- <string>Dynamic Pose Resolution</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="label_39">
- <property name="text">
- <string>Sleep time</string>
- </property>
- <property name="buddy">
- <cstring>sleep_spin</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="3">
- <layout class="QHBoxLayout" name="horizontalLayout_11">
- <item>
- <widget class="QSpinBox" name="sleep_spin">
- <property name="toolTip">
- <string>Time the tracker thread sleeps after each processed frame</string>
- </property>
- <property name="suffix">
- <string/>
- </property>
- <property name="maximum">
- <number>9999</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_40">
- <property name="text">
- <string>ms</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="label_43">
- <property name="text">
- <string>Auto-reset time</string>
- </property>
- <property name="buddy">
- <cstring>reset_spin</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <layout class="QHBoxLayout" name="horizontalLayout_12">
- <item>
- <widget class="QSpinBox" name="reset_spin">
- <property name="toolTip">
- <string>Time until automatic reset of tracker's internal state when no valid tracking result is found</string>
- </property>
- <property name="maximum">
- <number>9999</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_42">
- <property name="text">
- <string>ms</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="0" column="0">
- <widget class="QCheckBox" name="videowidget_check">
- <property name="toolTip">
- <string>Whether to update the content of the VideoWidget</string>
- </property>
- <property name="text">
- <string>Show VideoWidget</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <spacer name="horizontalSpacer_7">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="1">
- <spacer name="horizontalSpacer_11">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0">
- <widget class="QPushButton" name="reset_button">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="toolTip">
- <string>Reset the tracker's internal state</string>
- </property>
- <property name="text">
- <string>Reset</string>
- </property>
- </widget>
- </item>
- </layout>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_43">
+ <property name="text">
+ <string>Auto-reset time</string>
+ </property>
+ <property name="buddy">
+ <cstring>reset_spin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="reset_spin">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Time until automatic reset of tracker's internal state when no valid tracking result is found</string>
+ </property>
+ <property name="suffix">
+ <string>ms</string>
+ </property>
+ <property name="maximum">
+ <number>9999</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_17">
+ <property name="text">
+ <string>Dynamic Pose Resolution</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="dynpose_check">
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="reset_button">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Reset the tracker's internal state</string>
+ </property>
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
</item>
</layout>
</widget>
@@ -450,259 +381,304 @@
</property>
</spacer>
</item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Camera</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QGroupBox" name="groupBox_11">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="toolTip">
+ <string>The camera device used as input</string>
+ </property>
<property name="title">
- <string>Status</string>
+ <string>Camera Settings</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_8">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <layout class="QFormLayout" name="formLayout_2">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_65">
- <property name="text">
- <string>Camera Info:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="caminfo_label_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
- <width>120</width>
+ <width>55</width>
<height>0</height>
</size>
</property>
<property name="text">
- <string/>
+ <string>Device</string>
</property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_17">
- <property name="text">
- <string>Extracted Points:</string>
+ <property name="buddy">
+ <cstring>camdevice_combo</cstring>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QLabel" name="pointinfo_label_2">
- <property name="minimumSize">
- <size>
- <width>50</width>
- <height>0</height>
- </size>
+ <item>
+ <widget class="QComboBox" name="camdevice_combo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- <property name="text">
- <string/>
+ <property name="toolTip">
+ <string>Camera device used as input</string>
</property>
</widget>
</item>
</layout>
</item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <layout class="QGridLayout" name="gridLayout_8">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_36">
+ <property name="minimumSize">
+ <size>
+ <width>55</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Resolution</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="5">
+ <widget class="QLabel" name="label_37">
+ <property name="text">
+ <string>FPS</string>
+ </property>
+ <property name="buddy">
+ <cstring>fps_spin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="6">
+ <widget class="QSpinBox" name="fps_spin">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Desired capture framerate</string>
+ </property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_41">
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="res_x_spin">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Desired capture width</string>
+ </property>
+ <property name="maximum">
+ <number>2000</number>
+ </property>
+ <property name="singleStep">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QSpinBox" name="res_y_spin">
+ <property name="toolTip">
+ <string>Desired capture height</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_34">
+ <property name="text">
+ <string>F/W</string>
+ </property>
+ <property name="buddy">
+ <cstring>f_dspin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="f_dspin">
+ <property name="toolTip">
+ <string>The camera's focal length devided by its sensor width</string>
+ </property>
+ <property name="decimals">
+ <number>2</number>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="7">
+ <spacer name="horizontalSpacer_9">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7"/>
+ </item>
</layout>
</widget>
</item>
- </layout>
- </widget>
- <widget class="QWidget" name="tab_2">
- <attribute name="title">
- <string>Camera</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QGroupBox" name="groupBox">
+ <widget class="QGroupBox" name="groupBox_4">
<property name="title">
- <string>Camera Settings</string>
+ <string>Camera Orientation</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_8">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
- <layout class="QFormLayout" name="formLayout_4">
+ <layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="label_4">
<property name="text">
- <string>Index</string>
+ <string>Pitch</string>
</property>
<property name="buddy">
- <cstring>camindex_spin</cstring>
+ <cstring>campitch_spin</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
- <widget class="QSpinBox" name="camindex_spin">
+ <widget class="QSpinBox" name="campitch_spin">
+ <property name="contextMenuPolicy">
+ <enum>Qt::DefaultContextMenu</enum>
+ </property>
<property name="toolTip">
- <string>Capture device index</string>
+ <string>The angle the camera is facing upwards</string>
+ </property>
+ <property name="minimum">
+ <number>-99</number>
</property>
</widget>
</item>
<item row="2" column="0">
- <widget class="QLabel" name="label_37">
+ <widget class="QLabel" name="label_20">
<property name="text">
- <string>FPS</string>
+ <string>Yaw</string>
</property>
<property name="buddy">
- <cstring>fps_spin</cstring>
+ <cstring>camyaw_spin</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
- <widget class="QSpinBox" name="fps_spin">
+ <widget class="QSpinBox" name="camyaw_spin">
+ <property name="contextMenuPolicy">
+ <enum>Qt::DefaultContextMenu</enum>
+ </property>
<property name="toolTip">
- <string>Desired capture framerate</string>
+ <string>The angle the camera is facing leftwards</string>
</property>
- <property name="maximum">
- <number>300</number>
+ <property name="minimum">
+ <number>-99</number>
</property>
</widget>
</item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_10">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_13">
- <item>
- <widget class="QLabel" name="label_36">
- <property name="text">
- <string>Resolution</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_9">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QSpinBox" name="res_x_spin">
- <property name="toolTip">
- <string>Desired capture width</string>
- </property>
- <property name="maximum">
- <number>2000</number>
- </property>
- <property name="singleStep">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_41">
- <property name="text">
- <string>x</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="res_y_spin">
- <property name="toolTip">
- <string>Desired capture height</string>
- </property>
- <property name="maximum">
- <number>2000</number>
- </property>
- <property name="singleStep">
- <number>10</number>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="2" column="2">
+ <widget class="QLabel" name="label_21">
+ <property name="text">
+ <string>deg (positve = leftwards)</string>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_9">
- <item>
- <widget class="QLabel" name="label_34">
- <property name="text">
- <string>(Focal length)/(Sensor width)</string>
- </property>
- <property name="buddy">
- <cstring>f_dspin</cstring>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QDoubleSpinBox" name="f_dspin">
- <property name="toolTip">
- <string>The camera's focal length devided by its sensor width</string>
- </property>
- <property name="decimals">
- <number>2</number>
- </property>
- <property name="singleStep">
- <double>0.100000000000000</double>
- </property>
- </widget>
- </item>
- </layout>
+ <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="2">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>deg (positive = upwards)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_19">
+ <property name="text">
+ <string>deg</string>
+ </property>
+ </widget>
+ </item>
+ <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>
</layout>
</item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_6">
- <item>
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Camera Pitch (upwards = positive)</string>
- </property>
- <property name="buddy">
- <cstring>campitch_spin</cstring>
- </property>
- </widget>
- </item>
- <item>
- <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>
- <property name="minimum">
- <number>-99</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>deg</string>
- </property>
- </widget>
- </item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
@@ -710,7 +686,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>0</width>
<height>20</height>
</size>
</property>
@@ -722,6 +698,19 @@
</widget>
</item>
<item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Point Extraction</string>
@@ -758,6 +747,39 @@
</layout>
</item>
<item>
+ <layout class="QHBoxLayout" name="horizontalLayout_secondary">
+ <item>
+ <widget class="QLabel" name="label_secondary">
+ <property name="text">
+ <string>Hysteresis</string>
+ </property>
+ <property name="buddy">
+ <cstring>threshold_secondary_slider</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="threshold_secondary_slider">
+ <property name="toolTip">
+ <string>Per pixel hysteresis width (leave left if there is little difference between dot and non-dot, move right for increased stability against pixel noise)</string>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_7">
@@ -825,81 +847,6 @@
</layout>
</widget>
</item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_5">
- <property name="title">
- <string>Status</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label_38">
- <property name="text">
- <string>Camera Info:</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>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Extracted Points:</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>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
@@ -946,7 +893,7 @@
<property name="minimumSize">
<size>
<width>150</width>
- <height>170</height>
+ <height>160</height>
</size>
</property>
<widget class="QLabel" name="label_44">
@@ -962,7 +909,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="ftnoir_tracker_pt.qrc">:/resources/clip_side.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/clip_side.png</pixmap>
</property>
</widget>
<widget class="QSpinBox" name="clip_theight_spin">
@@ -1085,7 +1032,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="ftnoir_tracker_pt.qrc">:/resources/clip_front.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/clip_front.png</pixmap>
</property>
</widget>
<widget class="QLabel" name="label_53">
@@ -1140,7 +1087,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="ftnoir_tracker_pt.qrc">:/resources/cap_side.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/cap_side.png</pixmap>
</property>
</widget>
<widget class="QSpinBox" name="cap_height_spin">
@@ -1250,7 +1197,7 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="ftnoir_tracker_pt.qrc">:/resources/cap_front.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/cap_front.png</pixmap>
</property>
</widget>
<widget class="QSpinBox" name="cap_width_spin">
@@ -1299,7 +1246,7 @@
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>20</height>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -1313,7 +1260,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1466,7 +1413,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1482,7 +1429,7 @@
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>20</height>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -1516,7 +1463,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1613,7 +1560,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>10</width>
<height>20</height>
</size>
</property>
@@ -1640,7 +1587,7 @@
</rect>
</property>
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;FTNoIR PointTracker Plugin&lt;br/&gt;Version 1.0&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;by Patrick Ruoff&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://ftnoirpt.sourceforge.net/&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline; color:#0000ff;&quot;&gt;Manual (external)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;FTNoIR PointTracker Plugin&lt;br/&gt;Version 1.1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;by Patrick Ruoff&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://ftnoirpt.sourceforge.net/&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline; color:#0000ff;&quot;&gt;Manual (external)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
@@ -1659,15 +1606,84 @@
<string/>
</property>
<property name="pixmap">
- <pixmap resource="ftnoir_tracker_pt.qrc">:/resources/logo_ir.png</pixmap>
+ <pixmap resource="ftnoir_tracker_pt.qrc">:/Resources/Logo_IR.png</pixmap>
</property>
</widget>
</widget>
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="groupBox_5">
+ <property name="title">
+ <string>Status</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_38">
+ <property name="text">
+ <string>Camera Info:</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>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Extracted Points:</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>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
+ <widget class="QPushButton" name="btnApply">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -1682,6 +1698,9 @@
</item>
<item>
<widget class="QPushButton" name="ok_button">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
<property name="text">
<string>Ok</string>
</property>
@@ -1689,6 +1708,9 @@
</item>
<item>
<widget class="QPushButton" name="cancel_button">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
<property name="text">
<string>Cancel</string>
</property>
@@ -1700,7 +1722,6 @@
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
- <tabstop>sleep_spin</tabstop>
<tabstop>reset_spin</tabstop>
<tabstop>chkEnableRoll</tabstop>
<tabstop>chkEnablePitch</tabstop>
@@ -1708,12 +1729,14 @@
<tabstop>chkEnableX</tabstop>
<tabstop>chkEnableY</tabstop>
<tabstop>chkEnableZ</tabstop>
- <tabstop>camindex_spin</tabstop>
+ <tabstop>camdevice_combo</tabstop>
<tabstop>res_x_spin</tabstop>
<tabstop>res_y_spin</tabstop>
<tabstop>fps_spin</tabstop>
<tabstop>f_dspin</tabstop>
+ <tabstop>camroll_combo</tabstop>
<tabstop>campitch_spin</tabstop>
+ <tabstop>camyaw_spin</tabstop>
<tabstop>threshold_slider</tabstop>
<tabstop>mindiam_spin</tabstop>
<tabstop>maxdiam_spin</tabstop>
@@ -1749,12 +1772,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>285</x>
- <y>105</y>
+ <x>172</x>
+ <y>110</y>
</hint>
<hint type="destinationlabel">
- <x>139</x>
- <y>111</y>
+ <x>351</x>
+ <y>112</y>
</hint>
</hints>
</connection>
diff --git a/ftnoir_tracker_pt/resources/logo_ir.png b/FTNoIR_Tracker_PT/Resources/Logo_IR.png
index 95032a25..95032a25 100644
--- a/ftnoir_tracker_pt/resources/logo_ir.png
+++ b/FTNoIR_Tracker_PT/Resources/Logo_IR.png
Binary files differ
diff --git a/ftnoir_tracker_pt/resources/cap_front.png b/FTNoIR_Tracker_PT/Resources/cap_front.png
index 14207a67..14207a67 100644
--- a/ftnoir_tracker_pt/resources/cap_front.png
+++ b/FTNoIR_Tracker_PT/Resources/cap_front.png
Binary files differ
diff --git a/ftnoir_tracker_pt/resources/cap_side.png b/FTNoIR_Tracker_PT/Resources/cap_side.png
index 5ad4ee65..5ad4ee65 100644
--- a/ftnoir_tracker_pt/resources/cap_side.png
+++ b/FTNoIR_Tracker_PT/Resources/cap_side.png
Binary files differ
diff --git a/ftnoir_tracker_pt/resources/clip_front.png b/FTNoIR_Tracker_PT/Resources/clip_front.png
index 04880138..04880138 100644
--- a/ftnoir_tracker_pt/resources/clip_front.png
+++ b/FTNoIR_Tracker_PT/Resources/clip_front.png
Binary files differ
diff --git a/ftnoir_tracker_pt/resources/clip_side.png b/FTNoIR_Tracker_PT/Resources/clip_side.png
index 72667ac7..72667ac7 100644
--- a/ftnoir_tracker_pt/resources/clip_side.png
+++ b/FTNoIR_Tracker_PT/Resources/clip_side.png
Binary files differ
diff --git a/FTNoIR_Tracker_PT/boost-compat.h b/FTNoIR_Tracker_PT/boost-compat.h
new file mode 100644
index 00000000..612f2c4d
--- /dev/null
+++ b/FTNoIR_Tracker_PT/boost-compat.h
@@ -0,0 +1,5 @@
+#pragma once
+#include <memory>
+namespace boost {
+ using std::shared_ptr;
+}
diff --git a/FTNoIR_Tracker_PT/camera.cpp b/FTNoIR_Tracker_PT/camera.cpp
new file mode 100644
index 00000000..754533c5
--- /dev/null
+++ b/FTNoIR_Tracker_PT/camera.cpp
@@ -0,0 +1,351 @@
+/* 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.
+ */
+
+ #if defined(OPENTRACK_API) && defined(_WIN32)
+#include <windows.h>
+#include <dshow.h>
+#endif
+
+#include "camera.h"
+#include <string>
+#include <QDebug>
+
+using namespace cv;
+
+#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__))
+#include <unistd.h>
+#endif
+
+#ifdef OPENTRACK_API
+void get_camera_device_names(std::vector<std::string>& device_names) {
+# if defined(_WIN32)
+ // Create the System Device Enumerator.
+ HRESULT hr;
+ ICreateDevEnum *pSysDevEnum = NULL;
+ hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
+ if (FAILED(hr))
+ {
+ return;
+ }
+ // Obtain a class enumerator for the video compressor category.
+ IEnumMoniker *pEnumCat = NULL;
+ hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
+
+ if (hr == S_OK) {
+ // Enumerate the monikers.
+ IMoniker *pMoniker = NULL;
+ ULONG cFetched;
+ while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) {
+ IPropertyBag *pPropBag;
+ hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
+ if (SUCCEEDED(hr)) {
+ // To retrieve the filter's friendly name, do the following:
+ VARIANT varName;
+ VariantInit(&varName);
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ if (SUCCEEDED(hr))
+ {
+ auto wstr = std::wstring(varName.bstrVal);
+ auto str = std::string(wstr.begin(), wstr.end());
+ device_names.push_back(str);
+ }
+ VariantClear(&varName);
+
+ ////// To create an instance of the filter, do the following:
+ ////IBaseFilter *pFilter;
+ ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
+ //// (void**)&pFilter);
+ // Now add the filter to the graph.
+ //Remember to release pFilter later.
+ pPropBag->Release();
+ }
+ pMoniker->Release();
+ }
+ pEnumCat->Release();
+ }
+ pSysDevEnum->Release();
+# else
+ for (int i = 0; i < 16; i++) {
+ char buf[128];
+ sprintf(buf, "/dev/video%d", i);
+ if (access(buf, R_OK | W_OK) == 0) {
+ device_names.push_back(std::string(buf));
+ }
+ }
+# endif
+}
+#else
+// ----------------------------------------------------------------------------
+void get_camera_device_names(std::vector<std::string>& device_names)
+{
+ videoInput VI;
+ VI.listDevices();
+ std::string device_name;
+ for(int index = 0; ; ++index) {
+ device_name = VI.getDeviceName(index);
+ if (device_name.empty()) break;
+ device_names.push_back(device_name);
+ }
+}
+#endif
+
+// ----------------------------------------------------------------------------
+void Camera::set_device_index(int index)
+{
+ if (desired_index != index)
+ {
+ desired_index = index;
+ _set_device_index();
+
+ // reset fps
+ dt_valid = 0;
+ dt_mean = 0;
+ active_index = index;
+ }
+}
+
+void Camera::set_f(float f)
+{
+ if (cam_desired.f != f)
+ {
+ cam_desired.f = f;
+ _set_f();
+ }
+}
+void Camera::set_fps(int fps)
+{
+ if (cam_desired.fps != fps)
+ {
+ cam_desired.fps = fps;
+ _set_fps();
+ }
+}
+
+void Camera::set_res(int x_res, int y_res)
+{
+ if (cam_desired.res_x != x_res || cam_desired.res_y != y_res)
+ {
+ cam_desired.res_x = x_res;
+ cam_desired.res_y = y_res;
+ _set_res();
+ _set_fps();
+ }
+}
+
+bool Camera::get_frame(float dt, cv::Mat* frame)
+{
+ bool new_frame = _get_frame(frame);
+ // measure fps of valid frames
+ const float dt_smoothing_const = 0.9;
+ dt_valid += dt;
+ if (new_frame)
+ {
+ dt_mean = dt_smoothing_const * dt_mean + (1.0 - dt_smoothing_const) * dt_valid;
+ cam_info.fps = 1.0 / dt_mean;
+ dt_valid = 0;
+ }
+ return new_frame;
+}
+
+// ----------------------------------------------------------------------------
+#ifdef OPENTRACK_API
+void CVCamera::start()
+{
+ cap = new VideoCapture(desired_index);
+ // extract camera info
+ if (cap->isOpened())
+ {
+ 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);
+ } else {
+ delete cap;
+ cap = nullptr;
+ }
+}
+
+void CVCamera::stop()
+{
+ if (cap)
+ {
+ cap->release();
+ delete cap;
+ }
+ active = false;
+}
+
+bool CVCamera::_get_frame(Mat* frame)
+{
+ if (cap && cap->isOpened())
+ {
+ Mat img;
+ /*
+ * XXX some Windows webcams fail to decode first
+ * frames and then some every once in a while
+ * -sh
+ */
+ for (int i = 0; i < 100 && !cap->read(img); i++)
+ ;;
+
+ if (img.empty())
+ return false;
+
+ *frame = img;
+ return true;
+ }
+ return false;
+}
+
+void CVCamera::_set_index()
+{
+ if (active) restart();
+}
+
+void CVCamera::_set_f()
+{
+ cam_info.f = cam_desired.f;
+}
+
+void CVCamera::_set_fps()
+{
+ if (cap) cap->set(CV_CAP_PROP_FPS, cam_desired.fps);
+}
+
+void CVCamera::_set_res()
+{
+ if (cap)
+ {
+ cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x);
+ cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y);
+ 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()
+{
+ if (cap)
+ {
+ cap->release();
+ delete cap;
+ }
+ 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
new file mode 100644
index 00000000..ea68c387
--- /dev/null
+++ b/FTNoIR_Tracker_PT/camera.h
@@ -0,0 +1,145 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <opencv2/opencv.hpp>
+#ifndef OPENTRACK_API
+# include <boost/shared_ptr.hpp>
+#else
+# include "FTNoIR_Tracker_PT/boost-compat.h"
+# include <opencv2/highgui/highgui.hpp>
+# include <opencv2/highgui/highgui_c.h>
+#endif
+#include <string>
+
+// ----------------------------------------------------------------------------
+void get_camera_device_names(std::vector<std::string>& device_names);
+
+
+// ----------------------------------------------------------------------------
+struct CamInfo
+{
+ CamInfo() : res_x(0), res_y(0), fps(0), f(1) {}
+
+ int res_x;
+ int res_y;
+ int fps;
+ float f; // (focal length) / (sensor width)
+};
+
+// ----------------------------------------------------------------------------
+// Base class for cameras, calculates the frame rate
+class Camera
+{
+public:
+ Camera() : dt_valid(0), dt_mean(0), desired_index(0), active_index(-1), active(false) {}
+ virtual ~Camera() {}
+
+ // start/stop capturing
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ void restart() { stop(); start(); }
+
+ // calls corresponding template methods and reinitializes frame rate calculation
+ void set_device_index(int index);
+ void set_f(float f);
+ void set_fps(int fps);
+ void set_res(int x_res, int y_res);
+
+ // gets a frame from the camera, dt: time since last call in seconds
+ bool get_frame(float dt, cv::Mat* frame);
+
+ // WARNING: returned references are valid as long as object
+ const CamInfo& get_info() const { return cam_info; }
+ const CamInfo& get_desired() const { return cam_desired; }
+
+protected:
+ // get a frame from the camera
+ virtual bool _get_frame(cv::Mat* frame) = 0;
+
+ // update the camera using cam_desired, write res and f to cam_info if successful
+ virtual void _set_device_index() = 0;
+ virtual void _set_f() = 0;
+ virtual void _set_fps() = 0;
+ virtual void _set_res() = 0;
+
+ float dt_valid;
+ float dt_mean;
+ int desired_index;
+ int active_index;
+ bool active;
+ CamInfo cam_info;
+ CamInfo cam_desired;
+};
+
+
+// ----------------------------------------------------------------------------
+// camera based on OpenCV's videoCapture
+#ifdef OPENTRACK_API
+class CVCamera : public Camera
+{
+public:
+ CVCamera() : cap(NULL) {}
+ ~CVCamera() { stop(); }
+
+ virtual void start();
+ virtual void stop();
+
+protected:
+ virtual bool _get_frame(cv::Mat* frame);
+ virtual void _set_index();
+ virtual void _set_f();
+ virtual void _set_fps();
+ virtual void _set_res();
+ virtual void _set_device_index();
+
+ cv::VideoCapture* cap;
+};
+#else
+// ----------------------------------------------------------------------------
+// Camera based on the videoInput library
+class VICamera : public Camera
+{
+public:
+ VICamera();
+ ~VICamera() { stop(); }
+
+ virtual void start();
+ virtual void stop();
+
+protected:
+ virtual bool _get_frame(cv::Mat* frame);
+ virtual void _set_device_index();
+ virtual void _set_f();
+ virtual void _set_fps();
+ virtual void _set_res();
+
+ videoInput VI;
+ cv::Mat new_frame;
+ unsigned char* frame_buffer;
+};
+#endif
+
+enum RotationType
+{
+ CLOCKWISE = 0,
+ 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/doc/index.htm b/FTNoIR_Tracker_PT/doc/index.htm
new file mode 100644
index 00000000..87b7356f
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/index.htm
@@ -0,0 +1,262 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<head>
+ <title>FTNoIR PointTracker Help</title>
+
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+
+ <meta name="author"
+ content="Patrick Ruoff (C14)"/>
+ <meta name="keywords"
+ content="facetracknoir infrared point model tracker plugin"/>
+ <meta name="description"
+ content="Pointtracker plugin for FaceTrackNoIR"/>
+
+ <link rel="shortcut icon" href="ptrack.ico" type="image/vnd.microsoft.icon" />
+ <link rel="stylesheet" type="text/css" href="style.css" />
+</head>
+
+<body>
+<div id="navbar">
+<ul class="navbar">
+<li class="navbar"><a class="navbar" href="#about">About</a></li>
+<li class="navbar"><a class="navbar" href="#settings">Settings</a></li>
+<li class="navbar"><a class="navbar" href="#setup">Filter Setup</a></li>
+<li class="navbar"><a class="navbar" href="#support">Support</a></li>
+<li class="navbar"><a class="navbar" href="#changelog">ChangeLog</a></li>
+<li class="navbar"><a class="navbar" href="#build_instructions">Build Instructions</a></li>
+</ul>
+</div>
+
+<div id="content">
+<div style="text-align:center"><h1>FaceTrackNoIR PointTracker Plugin</h1><img src="logo.png" alt="PointTracker Plugin Logo" /></div>
+
+<a class="nav" id="about"></a>
+<h2>About</h2>
+<div class="indent">
+<p>
+PointTracker is a plugin for the free head tracking software <a href="http://facetracknoir.sourceforge.net">FaceTrackNoIR</a>
+which introduces the capability to track a (typically IR-) point model comprising 3 bright points to FaceTrackNoIR,
+much like the popular free tracking software <a href="http://www.free-track.net/">Freetrack</a> does.<br/>
+It was created as a stable modular alternative to Freetrack, which has some stability issues with newer systems and seems to be no longer actively developped.
+</p>
+</div>
+
+<a class="nav" id="settings"></a>
+<h2>Settings</h2>
+<div class="indent">
+<p>
+This section desribes the various settings of the PointTracker plugin in detail.
+</p>
+
+<img src="settings1.png" alt="Settings Pane 1"/>
+<dl>
+<dt>Show VideoWidget</dt><dd>Whether the video widget is updated or not. It may save some performance to turn this off when not needed</dd>
+<dt>Sleep time</dt><dd>Time the tracking thread sleeps after each processed image. It's inverse should be below the framefrate you want to achieve.
+(check the framerate in the status region when tracker is active, in case the sleep time is too high, the framerate will decrease).
+Low values will result in more CPU-load.</dd>
+<dt>Dynamic Pose Resolution</dt><dd>Whether the point correspondence and pose ambiquity is resolved using a more sophisticated dynamic algorithm (constant velocity prediction) or a simple static resolution.
+Dynamic pose resolution can capture more extreme poses but may occasionally get stuck in a wrong pose estimates so that a reset of the internal state becomes neccessary.</dd>
+<dt>Auto-reset time</dt><dd>If no valid tracking result can be found when using dynamic pose resolution, the tracker will automatically reset its internal state (used for resolving the pose ambiguity and point correspondence)
+and return to a fail-safe initialization phase that assumes a neutral pose after this time.
+Decrease this time, if you get stuck in a wrong pose too often.</dd>
+<dt>Reset</dt><dd>Manually reset the trackers internal state used for dynamic pose resolution and return to a fail-safe initialization phase that assumes a neutral pose.
+You may use this in case you get stuck in a wrong pose.</dd>
+<dt>Enable Axis ...</dt><dd>Which axis to use for FTNoIR.</dd>
+</dl>
+
+<img src="settings2.png" alt="Settings Pane 2"/>
+<dl>
+<dt>Device</dt><dd>The camera used for tracking.</dd>
+<dt>Resolution</dt><dd>The desired capture resolution. If your camera does not support the entered resolution the true output resolution may be different or even invalid.
+You may check the true capture resolution in the status area while the tracker is running. A higher resolution results in more accurate point positions and will increase the
+stability of the tracking result, as long as the signal/noise ratio is sufficiently high.</dd>
+<dt>FPS</dt><dd>The desired capture framerate. Again, if your camera does not support the entered framerate, the true caputre framerate may be different or invalid.
+You may check the true processing framerate in the status area while the tracker is running.</dd>
+<dt>F/W</dt><dd>The focal length of the camera divided by the sensor width (of course in the same units).
+In case you don't have access to your camera's specifications, you can measure this yourself by placing a plane object of known width (for example a piece of cardboard) in front of the camera until it fills the whole image width.
+Then measure the distance between the object and the camera and divide by the object width.</dd>
+<dt>VideoWidget</dt><dd>Shows a resizable stand-alone video widget that shows the same content as the integrated video widget in FTNoIR.
+Update rate is only 10 fps and may lag behind a bit. Mainly useful during calibration of the point extraction. Same as for the integrated wiget, to save resources, this widget should only be shown when needed.</dd>
+<dt>Roll Pitch Yaw...</dt><dd>The orientation of the camera relative to the reference frame.
+If these angles are setup properly, the direction of translations may not be correct.
+Roll is treated in a special way since it is implemented as a frame rotation by +/- 90 deg that is transparent to the rest of the processing pipeline.
+</dd>
+<dt>Threshold</dt><dd>The threshold for point recognition. Areas above the threshold are shown in blue in the VideoWidget.
+Since point accuracy is best if the points are as big as possible in pixels, the theshold should be chosen as low as possible (stop before the contour of the points becomes "noisy").
+If small reflections are being falsely classified as points, increasing the minimum point diameter (see below) may help.</dd>
+<dt>Min Diameter</dt><dd>Minimum diameter of blobs to be classified as a pointmodel-point.</dd>
+<dt>Max Diameter</dt><dd>Maximum diameter of blobs to be classified as a pointmodel-point.</dd>
+<dt>Status</dt><dd>The tracker's status is shown in this area while the tracker is running.
+The FPS shown here correspond to the framerate of the whole tracker processing chain and may be lower than what your camera is able to provide, when<br/>
+1. The processing gets not enough CPU time<br/>
+2. The sleep time of the tracking thread is set too high<br/></dd>
+</dl>
+
+<img src="settings3.png" alt="Settings Pane 3"/>
+<dl>
+<dt>Model Selection and Dimensions ...</dt><dd>
+First select your model type (point, clip, custom), then enter the dimensions of your model in milimeters here.<br/>
+For the custom setting, the coordinates of the two remaining model points have to be entered (reference point M0 is at (0,0,0)) in a pose where the model roughly faces the camera.
+For orientation, the coordinates for the standard Freetrack clip are (0,40,-30), (0,-70,-80) and the ones for the cap (40,-60,-100), (-40,-60,-100).<br/>
+When using a custom point-model configuration, the following restrictions should be observed:<br/>
+The plane in which the 3 points lie should never be parallel to the image plane, M0-M1 and M0-M2 should be roughly perpendicular.</dd>
+
+<dt>Model Position</dt><dd>The vector from the model to the center of the head in the model frame. Can be calibrated automatically.</dd>
+<dt>Calibrate</dt><dd>In order to automatically calibrate the model-head offset, do the following:<br/>Press the Calibrate button, then look around while not moving your shoulder. (i.e. only rotation, no translation).
+Do not stay in one pose for too long. The current translation estimate will be updated in real time. As soon as the values stabilized sufficiently, press the Calibrate button again to stop the calibration process.</dd>
+</dl>
+</div>
+
+<a class="nav" id="setup"></a>
+<h2>Filter Setup</h2>
+<div class="indent">
+<p>
+This section desribes how the FTNoIR filter work and what the recommended settings for PointTracker are.
+</p>
+<p>
+Filtering is always a tradeoff between stability, accuracy and responsiveness.
+</p>
+<p>
+The <q>Smoothing</q> filter in FTNoIR is just a simple average over the last n samples.
+Since this filter produces input lag no matter how fast the head-movements are, it is recommended to turn it off by setting samples to 1.
+</p>
+<p>
+In the filter tab, it is recommended to select <q>Accela Filter Mk2</q>.
+Accela is a non-linear filter that works as follows:<br/>
+It looks at the difference between the new raw values <i>new_val</i> from the tracker and the last filtered value <i>old_val</i>
+and maps this difference via the customizable response function <i>f</i> via:<br/>
+</p>
+<p style="text-align: center">
+<i>new_val = old_val + f(new_val - old_val) / reduction_factor</i>
+</p>
+<p>
+So by setting <i>f(x) = reduction_factor * x</i>, one will get no filtering at all.<br/>
+If you set lower values for small x, small deviations (usually noise) will get dampened.
+This results in a dynamic dead-zone around the current position.
+</p>
+<p>
+The last two points are used by accela to extrapolate for large deviations.
+So in order to get a fast unfiltered response for large deviations, the line connecting the last two points should have a slope >= <i>reduction_factor</i>.
+</p>
+<p>
+More aggressive accela settings than the default FTNoIR accela settings are recommended in order to decrease the filtering lag and fully use the potential of point tracking.<br/>
+My current settings are:
+</p>
+<pre class="indent"><code>
+[Accela]
+Reduction=20
+
+[Curves-Accela-Scaling-Rotation]
+point-count=4
+point-0-x=0.1
+point-0-y=0
+point-1-x=1.43
+point-1-y=2.45
+point-2-x=2.0
+point-2-y=5.44
+point-3-x=2.06
+point-3-y=6
+</code></pre>
+<p>
+The curve is not too different from the standard one (except that I like a small dynamic dead zone for steady aiming, that's why the curve has a slope of 0 at the beginning).<br/>
+However, the reduction factor is decreased to a value of 20 (compared to the standard value of 100). This implies that each value of the curve is effectively 5 times higher than in standard FTNoIR (see formula above), which means higher responsiveness but can also lead to jitter/shaking.<br/>
+Keep in mind that there are no <q>best filter settings</q>. Since filtering is always a compromise it's a matter of personal taste and
+playing around with the filter settings is highly recommended.
+</p>
+</div>
+
+<a class="nav" id="support"></a>
+<h2>Support</h2>
+<div class="indent">
+<p>
+For questions/feedback about the plugin, post to the <a href="https://sourceforge.net/projects/facetracknoir/forums">FTNoIR-Forum</a>.<br/>
+In case you like this plugin and would like to support the author, you may consider making a donation.
+</p>
+<div style="text-align:center">
+<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+<fieldset class="blind">
+<input type="hidden" name="cmd" value="_s-xclick"/>
+<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHJwYJKoZIhvcNAQcEoIIHGDCCBxQCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYCa+2zPZ+6vFPqveJsBIjFLpy54m7tl0AdojRr/K5qa3QJDyRBhGwGAP2jRihkmZFE2oKlfLpkz7nrwOQY/wFEPkggO+cABxUfjcQVpIupHEtwdV0hMklLs0RmACJy802yfi1yTiCpJ4hvWN+VfUI3gOiZ9uRZ3L4iGXES7xtqJbDELMAkGBSsOAwIaBQAwgaQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIeopHzcJ8XBOAgYCYJFyTejSplEOwF21aQ01qQOads9Z+RUVI+hlvM/pHTjimaZPKSis3poAeqv6wKn40DpLNxDnmcT+Y9KXhrV+Gy4GZCPaeNzq2vquQ2ZVN0fTr84QVmKqPkjMBGmJAHSLCcZswUddemJgoD1uyvS0kNbchvxw7gDXJnJeBRNyXXKCCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTEyMDkyMzA5NTcwOFowIwYJKoZIhvcNAQkEMRYEFG/qW7uo4R4m5uFYegcZaZsTPAcUMA0GCSqGSIb3DQEBAQUABIGAGygLfrR6IQbG2xZY2OrwKkfmRwiwtnXpLBnSbnWb7XxUOMhvM6962RiKBQBGP0+XYw0S9yu8ZHx7tqz/3bcMfGjtz7PwixYx6Rm8Z29ja78aUy5FmU7fc9yAWFxLHptSliK1dJBPxdQa9J2YSDvPQPAj+AdB9sJvqJoMoxTFGM4=-----END PKCS7-----
+"/>
+<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" name="submit" alt="PayPal - The safer, easier way to pay online!"/>
+<img alt="" src="https://www.paypalobjects.com/de_DE/i/scr/pixel.gif" width="1" height="1"/>
+</fieldset>
+</form>
+</div>
+</div>
+
+<a class="nav" id="changelog"></a>
+<h2>ChangeLog</h2>
+<div class="indent">
+<h3>1.1</h3>
+<ul>
+<li>Added camera yaw and roll correction (intended for vertically mounted cameras)</li>
+<li>Improved point extraction algorithm, thanks to Michael Welter</li>
+<li>UI improvements: Select camera by device name, different VideoWidget architecture</li>
+<li>Bugfixes: Removed 99 FPS limitation</li>
+</ul>
+
+<h3>1.0</h3>
+<ul>
+<li>Added camera pitch correction</li>
+<li>Better communication with FTNoIR: output axis configuration, status report</li>
+</ul>
+
+<h3>1.0 beta</h3>
+<ul>
+<li>Switchted to videoInput library for capture. Desired capture resolution and fps can now be customized</li>
+<li>Introduced dynamic point-correspondence and POSIT-ambiguity resolution, which allows for the reconstruction of more extreme poses</li>
+<li>More convenient freetrack-like model dimension GUI</li>
+<li>Bugfixes: VideoWidget skipping frames, Timer resolution too low for accurate FPS measurement</li>
+</ul>
+</div>
+
+<a class="nav" id="build_instructions"></a>
+<h2>Build Instructions</h2>
+<div class="indent">
+<p>
+This section describes what you need to do in order to build PointTracker yourself.<br/>
+You can find the sources at the <a href="https://sourceforge.net/projects/ftnoirpt/">project site</a>
+or as part of the <a href="https://sourceforge.net/projects/facetracknoir/">FTNoIR sources</a>.
+</p>
+<p> The project was created with Visual Studio. </p>
+
+<h3>Dependencies</h3>
+<ul>
+<li>Qt 4.8.2 library</li>
+<li>Qt plugin for Visual studio</li>
+<li>OpenCV 2.4 prebuilt for Windows</li>
+<li>Boost 1.47</li>
+</ul>
+
+<h3>Details</h3>
+<div class="indent">
+<h4>Common</h4>
+<ul>
+<li>setup environment variable "QTDIR" (example value "D:\Devel\Libs\Qt\4.8.2")</li>
+<li>add "%QTDIR%\bin" to PATH</li>
+<li>setup environment variable "BOOST_DIR" (example value "D:\Devel\Libs\boost_1_47_0")</li>
+<li>setup environment variable "OPENCV_DIR" (example value "D:\Devel\Libs\opencv\build")</li>
+</ul>
+<h4>Debug</h4>
+<p>opencv linked dynamically:</p>
+<ul>
+<li>add "%OPENCV_DIR%\x86\vc9\bin" to PATH</li>
+</ul>
+<p>(in case of different Visual studio, change PATH and linker dependencies accordingly)</p>
+<h4>Release</h4>
+<p>opencv linked statically:</p>
+<ul>
+<li>custom build a statically linked version of opencv with the buil-option BUILD_WITH_STATIC_CRT set to OFF!</li>
+<li>copy resulting libaries to "%OPENCV_DIR%\x86\vc9\static_lib"</li>
+</ul>
+<p>(in case of different Visual studio, change PATH and linker dependencies accordingly)</p>
+</div>
+</div>
+
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/FTNoIR_Tracker_PT/doc/logo.png b/FTNoIR_Tracker_PT/doc/logo.png
new file mode 100644
index 00000000..95032a25
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/logo.png
Binary files differ
diff --git a/FTNoIR_Tracker_PT/doc/ptrack.ico b/FTNoIR_Tracker_PT/doc/ptrack.ico
new file mode 100644
index 00000000..c4b2aedc
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/ptrack.ico
Binary files differ
diff --git a/FTNoIR_Tracker_PT/doc/settings1.png b/FTNoIR_Tracker_PT/doc/settings1.png
new file mode 100644
index 00000000..35b84c5c
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/settings1.png
Binary files differ
diff --git a/FTNoIR_Tracker_PT/doc/settings2.png b/FTNoIR_Tracker_PT/doc/settings2.png
new file mode 100644
index 00000000..c6cfd1f3
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/settings2.png
Binary files differ
diff --git a/FTNoIR_Tracker_PT/doc/settings3.png b/FTNoIR_Tracker_PT/doc/settings3.png
new file mode 100644
index 00000000..5922403d
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/settings3.png
Binary files differ
diff --git a/FTNoIR_Tracker_PT/doc/style.css b/FTNoIR_Tracker_PT/doc/style.css
new file mode 100644
index 00000000..a8d3e333
--- /dev/null
+++ b/FTNoIR_Tracker_PT/doc/style.css
@@ -0,0 +1,131 @@
+body {
+ width: 1000px;
+ font-size: 13px;
+ color: #000000;
+ padding: 0;
+ margin: 0 auto;
+ background: #444444;
+ font-family: verdana,arial;
+}
+
+table {
+ border-width: 3px;
+ border-color: #0000FF;
+ border-style: ridge;
+ margin-top: 5px;
+ background-color: #E0E0FF;
+}
+
+table.blind {
+ border: none;
+ background-color: #E6E6E6;
+}
+
+fieldset.blind {
+ border: none;
+}
+
+h1 { font-size: 160%; }
+h2 { font-size: 140%; }
+h3 { font-size: 115%; }
+
+.indent {
+ margin-left: 25px;
+}
+
+p
+{
+ margin-left: 10px;
+}
+
+li
+{
+ margin: 10px;
+}
+
+
+dl
+{
+ /*width: 80%;*/
+ border-bottom: 1px solid #999;
+}
+
+dt
+{
+ padding-top: 5px;
+ font-weight: bold;
+ border-top: 1px solid #999;
+}
+
+dd
+{
+ padding: 5px;
+}
+
+
+hr {
+ color: #688938;
+}
+
+a:link, a:visited {
+ color: #0000BF;
+}
+a:hover {
+ color: #0000FF;
+}
+
+a.nav {
+ position: relative;
+ top: -30px;
+ display: block;
+ visibility: hidden;
+}
+
+#navbar {
+ width: 1000px;
+ height: 30px;
+ background-color:#1a1a1b;
+ position: fixed;
+ margin: 0 auto;
+ padding: 0;
+}
+
+#navbar ul
+{
+ list-style-type: none;
+ margin: 0 auto;
+ padding: 0;
+ overflow: hidden;
+}
+
+#navbar li
+{
+ margin: 0 auto;
+ padding: 5px;
+ float:left;
+}
+
+#navbar a:link,a:visited
+{
+ display:block;
+ width:150px;
+ font-weight:bold;
+ color:#e85d02;
+ text-align:center;
+ /*padding:4px;*/
+ text-decoration:none;
+ /*text-transform:uppercase;*/
+}
+
+#navbar a:hover,a:active
+{
+ color:#ffffff;
+}
+
+#content {
+ background-color:#ffffff;
+ padding: 15px;
+ padding-top: 40px;
+ padding-right: 40px;
+ margin: 0 auto;
+}
diff --git a/FTNoIR_Tracker_PT/frame_observer.cpp b/FTNoIR_Tracker_PT/frame_observer.cpp
new file mode 100644
index 00000000..281f3d57
--- /dev/null
+++ b/FTNoIR_Tracker_PT/frame_observer.cpp
@@ -0,0 +1,18 @@
+/* Copyright (c) 2013 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "frame_observer.h"
+
+//-----------------------------------------------------------------------------
+FrameProvider::~FrameProvider()
+{
+ QMutexLocker lock(&observer_mutex);
+ for (std::set<FrameObserver*>::iterator iter=frame_observers.begin(); iter!=frame_observers.end(); ++iter)
+ {
+ (*iter)->on_frame_provider_destroy();
+ }
+}
diff --git a/FTNoIR_Tracker_PT/frame_observer.h b/FTNoIR_Tracker_PT/frame_observer.h
new file mode 100644
index 00000000..585a6ee7
--- /dev/null
+++ b/FTNoIR_Tracker_PT/frame_observer.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2013 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 FRAME_OBSERVER_H
+#define FRAME_OBSERVER_H
+
+#include <QMutex>
+#include <opencv2/opencv.hpp>
+#ifndef OPENTRACK_API
+# include <boost/shared_ptr.hpp>
+#else
+# include "FTNoIR_Tracker_PT/boost-compat.h"
+#endif
+#include <set>
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+class FrameObserver;
+
+//-----------------------------------------------------------------------------
+// Provides means to copy frame and point information if it has observers
+// Instantiate a FrameObserver to get the information
+class FrameProvider
+{
+ friend class FrameObserver;
+public:
+ ~FrameProvider();
+
+protected:
+ virtual bool get_frame_and_points(cv::Mat& frame, boost::shared_ptr< std::vector<cv::Vec2f> >& points) = 0;
+
+ bool has_observers() const { QMutexLocker lock(&observer_mutex); return !frame_observers.empty(); }
+
+private:
+ mutable QMutex observer_mutex;
+ void add_observer(FrameObserver* obs) { QMutexLocker lock(&observer_mutex); frame_observers.insert(obs); }
+ void remove_observer(FrameObserver* obs) { QMutexLocker lock(&observer_mutex); frame_observers.erase(obs); }
+ std::set<FrameObserver*> frame_observers;
+};
+
+//-----------------------------------------------------------------------------
+// Used to get frame and point information from MutexedFrameProvider
+// Destroy instance if not interested anymore since a living
+// FrameObserver instance causes MutexedFrameProvider to provide the information,
+// potentially reducing its performance
+class FrameObserver
+{
+public:
+ FrameObserver(FrameProvider* provider) : provider(provider) {
+ provider->add_observer(this);
+ }
+
+ ~FrameObserver() {
+ if (provider) provider->remove_observer(this);
+ }
+
+ bool get_frame_and_points(cv::Mat& frame, boost::shared_ptr< std::vector<cv::Vec2f> >& points) {
+ return provider ? provider->get_frame_and_points(frame, points) : false;
+ }
+
+ void on_frame_provider_destroy() {
+ provider = NULL;
+ }
+
+protected:
+ FrameProvider* provider;
+
+private:
+ FrameObserver(const FrameObserver&);
+};
+
+#endif //FRAME_OBSERVER_H
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp
new file mode 100644
index 00000000..787a5128
--- /dev/null
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.cpp
@@ -0,0 +1,268 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "ftnoir_tracker_pt.h"
+#include <QHBoxLayout>
+#include <cmath>
+#include <QDebug>
+#include <QFile>
+#include <QCoreApplication>
+
+using namespace std;
+using namespace cv;
+using namespace boost;
+
+//#define PT_PERF_LOG //log performance
+
+const float rad2deg = 180.0/3.14159265;
+const float deg2rad = 1.0/rad2deg;
+
+//-----------------------------------------------------------------------------
+Tracker::Tracker()
+ : commands(0),
+ video_widget(NULL),
+ video_frame(NULL),
+ tracking_valid(false),
+ need_apply(false),
+ new_settings(nullptr)
+{
+ qDebug()<<"Tracker::Tracker";
+}
+
+Tracker::~Tracker()
+{
+ qDebug()<<"Tracker::~Tracker";
+ // terminate tracker thread
+ set_command(ABORT);
+ wait();
+ s.video_widget = false;
+ delete video_widget;
+ video_widget = NULL;
+ if (video_frame->layout()) delete video_frame->layout();
+}
+
+void Tracker::set_command(Command command)
+{
+ //QMutexLocker lock(&mutex);
+ commands |= command;
+}
+
+void Tracker::reset_command(Command command)
+{
+ //QMutexLocker lock(&mutex);
+ commands &= ~command;
+}
+
+void Tracker::run()
+{
+ qDebug()<<"Tracker:: Thread started";
+
+#ifdef PT_PERF_LOG
+ QFile log_file(QCoreApplication::applicationDirPath() + "/PointTrackerPerformance.txt");
+ if (!log_file.open(QIODevice::WriteOnly | QIODevice::Text)) return;
+ QTextStream log_stream(&log_file);
+#endif
+
+ time.start();
+ float dt;
+ bool new_frame;
+ forever
+ {
+ if (commands & ABORT) break;
+ if (commands & PAUSE) continue;
+ commands = 0;
+ apply_inner();
+ dt = time.start() / 1000.0;
+
+ 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, dt, true);
+ for (auto p : points)
+ {
+ auto p2 = cv::Point(p[0] * frame.cols + frame.cols/2, -p[1] * frame.cols + frame.rows/2);
+ cv::Scalar color(0, 255, 0);
+ cv::line(frame,
+ cv::Point(p2.x - 20, p2.y),
+ cv::Point(p2.x + 20, p2.y),
+ color,
+ 4);
+ cv::line(frame,
+ cv::Point(p2.x, p2.y - 20),
+ cv::Point(p2.x, p2.y + 20),
+ color,
+ 4);
+ }
+ tracking_valid = point_tracker.track(points, camera.get_info().f, dt);
+ video_widget->update_image(frame);
+ }
+#ifdef PT_PERF_LOG
+ log_stream<<"dt: "<<dt;
+ if (!frame.empty()) log_stream<<" fps: "<<camera.get_info().fps;
+ log_stream<<"\n";
+#endif
+ }
+
+ qDebug()<<"Tracker:: Thread stopping";
+}
+void Tracker::apply(settings& s)
+{
+ QMutexLocker lock(&mutex);
+ need_apply = true;
+ // caller guarantees object lifetime
+ new_settings = &s;
+}
+
+void Tracker::apply_inner()
+{
+ QMutexLocker lock(&mutex);
+ if (!need_apply)
+ return;
+ qDebug()<<"Tracker:: Applying settings";
+ auto& s = *new_settings;
+ new_settings = nullptr;
+ need_apply = false;
+ camera.set_device_index(s.cam_index);
+ camera.set_res(s.cam_res_x, s.cam_res_y);
+ camera.set_fps(s.cam_fps);
+ camera.set_f(s.cam_f);
+ 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;
+ {
+ cv::Vec3f M01(s.m01_x, s.m01_y, s.m01_z);
+ cv::Vec3f M02(s.m02_x, s.m02_y, s.m02_z);
+ point_tracker.point_model = boost::shared_ptr<PointModel>(new PointModel(M01, M02));
+ }
+ point_tracker.dynamic_pose_resolution = s.dyn_pose_res;
+ point_tracker.dt_reset = s.reset_time / 1000.0;
+ 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.get_pose();
+ FrameTrafo X_MH(Matx33f::eye(), t_MH);
+ X_GH_0 = R_GC * X_CM_0 * X_MH;
+}
+
+bool Tracker::get_frame_and_points(cv::Mat& frame_copy, boost::shared_ptr< std::vector<Vec2f> >& points)
+{
+ QMutexLocker lock(&mutex);
+ if (frame.empty()) return false;
+
+ // copy the frame and points from the tracker thread
+ frame_copy = frame.clone();
+ points = boost::shared_ptr< vector<Vec2f> >(new vector<Vec2f>(point_extractor.get_points()));
+ return true;
+}
+
+void Tracker::refreshVideo()
+{
+ if (video_widget) video_widget->update_frame_and_points();
+}
+
+void Tracker::StartTracker(QFrame *parent_window)
+{
+ this->video_frame = parent_window;
+ video_frame->setAttribute(Qt::WA_NativeWindow);
+ video_frame->show();
+ video_widget = new PTVideoWidget(video_frame, this);
+ QHBoxLayout* video_layout = new QHBoxLayout(parent_window);
+ video_layout->setContentsMargins(0, 0, 0, 0);
+ video_layout->addWidget(video_widget);
+ video_frame->setLayout(video_layout);
+ video_widget->resize(video_frame->width(), video_frame->height());
+ camera.start();
+ apply(s);
+ start();
+ reset_command(PAUSE);
+}
+
+#ifndef OPENTRACK_API
+void Tracker::StopTracker(bool exit)
+{
+ set_command(PAUSE);
+}
+#endif
+
+#ifdef OPENTRACK_API
+#define THeadPoseData double
+#endif
+
+void Tracker::GetHeadPoseData(THeadPoseData *data)
+{
+ {
+ QMutexLocker lock(&mutex);
+
+ if (!tracking_valid) return;
+
+ FrameTrafo X_CM = point_tracker.get_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;
+
+ // get translation(s)
+ if (s.bEnableX) data[TX] = t[0] / 10.0; // convert to cm
+ if (s.bEnableY) data[TY] = t[1] / 10.0;
+ if (s.bEnableZ) 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));
+
+ if (s.bEnableYaw) data[Yaw] = rad2deg * alpha;
+ if (s.bEnablePitch) data[Pitch] = - rad2deg * beta; // FTNoIR expects a minus here
+ if (s.bEnableRoll) data[Roll] = rad2deg * gamma;
+ }
+}
+
+//-----------------------------------------------------------------------------
+#ifdef OPENTRACK_API
+extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
+#else
+#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
+FTNOIR_TRACKER_BASE_EXPORT ITrackerPtr __stdcall GetTracker()
+#endif
+{
+ return new Tracker;
+}
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.h
new file mode 100644
index 00000000..47a9987b
--- /dev/null
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#ifndef FTNOIR_TRACKER_PT_H
+#define FTNOIR_TRACKER_PT_H
+
+#ifdef OPENTRACK_API
+# include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+# include "facetracknoir/global-settings.h"
+#endif
+#include "ftnoir_tracker_pt_settings.h"
+#include "frame_observer.h"
+#include "camera.h"
+#include "point_extractor.h"
+#include "point_tracker.h"
+#include "pt_video_widget.h"
+#include "facetracknoir/timer.hpp"
+
+#include <QThread>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QTime>
+#include <opencv2/opencv.hpp>
+#ifndef OPENTRACK_API
+# include <boost/shared_ptr.hpp>
+#else
+# include "FTNoIR_Tracker_PT/boost-compat.h"
+#endif
+#include <vector>
+
+//-----------------------------------------------------------------------------
+// Constantly processes the tracking chain in a separate thread
+class Tracker : public ITracker, QThread, public FrameProvider
+{
+public:
+ Tracker();
+ virtual ~Tracker();
+ virtual void StartTracker(QFrame* parent_window);
+ virtual void GetHeadPoseData(double* data);
+ virtual void refreshVideo();
+
+ void apply(settings& s);
+ void apply_inner();
+ void center();
+ void reset(); // reset the trackers internal state variables
+ void run();
+
+ void get_pose(FrameTrafo* X_CM) { QMutexLocker lock(&mutex); *X_CM = point_tracker.get_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(); }
+
+protected:
+ // --- MutexedFrameProvider interface ---
+ virtual bool get_frame_and_points(cv::Mat& frame, boost::shared_ptr< std::vector<cv::Vec2f> >& points);
+
+ // --- thread ---
+ QMutex mutex;
+ // thread commands
+ enum Command {
+ ABORT = 1<<0,
+ PAUSE = 1<<1
+ };
+ void set_command(Command command);
+ void reset_command(Command command);
+ 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;
+ bool tracking_valid, need_apply;
+
+ settings s;
+ settings* new_settings;
+ Timer time;
+};
+
+#undef VideoWidget
+
+#endif // FTNOIR_TRACKER_PT_H
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc
new file mode 100644
index 00000000..a8f9a1af
--- /dev/null
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>Resources/cap_front.png</file>
+ <file>Resources/cap_side.png</file>
+ <file>Resources/clip_front.png</file>
+ <file>Resources/clip_side.png</file>
+ <file>Resources/Logo_IR.png</file>
+ </qresource>
+</RCC>
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp
new file mode 100644
index 00000000..c103b78c
--- /dev/null
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.cpp
@@ -0,0 +1,321 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "ftnoir_tracker_pt_dialog.h"
+
+#include <QMessageBox>
+#include <QDebug>
+#include <opencv2/opencv.hpp>
+#ifndef OPENTRACK_API
+# include <boost/shared_ptr.hpp>
+#else
+# include "FTNoIR_Tracker_PT/boost-compat.h"
+#endif
+#include <vector>
+
+using namespace std;
+
+//-----------------------------------------------------------------------------
+TrackerDialog::TrackerDialog()
+ : tracker(NULL),
+ video_widget_dialog(NULL),
+ timer(this),
+ trans_calib_running(false)
+{
+ qDebug()<<"TrackerDialog::TrackerDialog";
+ setAttribute(Qt::WA_DeleteOnClose, false);
+
+ ui.setupUi( this );
+
+ vector<string> device_names;
+ get_camera_device_names(device_names);
+ for (vector<string>::iterator iter = device_names.begin(); iter != device_names.end(); ++iter)
+ {
+ 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.dyn_pose_res, ui.dynpose_check);
+ tie_setting(s.reset_time, ui.reset_spin);
+
+ tie_setting(s.cam_index, ui.camdevice_combo);
+ tie_setting(s.cam_f, ui.f_dspin);
+ 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);
+
+ tie_setting(s.bEnableYaw, ui.chkEnableYaw);
+ tie_setting(s.bEnablePitch, ui.chkEnablePitch);
+ tie_setting(s.bEnableRoll, ui.chkEnableRoll);
+ tie_setting(s.bEnableX, ui.chkEnableX);
+ tie_setting(s.bEnableY, ui.chkEnableY);
+ tie_setting(s.bEnableZ, ui.chkEnableZ);
+
+ tie_setting(s.min_point_size, ui.mindiam_spin);
+ tie_setting(s.max_point_size, ui.maxdiam_spin);
+
+ tie_setting(s.clip_by, ui.clip_bheight_spin);
+ tie_setting(s.clip_bz, ui.clip_blength_spin);
+ tie_setting(s.clip_ty, ui.clip_theight_spin);
+ tie_setting(s.clip_tz, ui.clip_tlength_spin);
+
+ tie_setting(s.cap_x, ui.cap_width_spin);
+ tie_setting(s.cap_y, ui.cap_height_spin);
+ tie_setting(s.cap_z, ui.cap_length_spin);
+
+ tie_setting(s.m01_x, ui.m1x_spin);
+ tie_setting(s.m01_y, ui.m1y_spin);
+ tie_setting(s.m01_z, ui.m1z_spin);
+
+ tie_setting(s.m02_x, ui.m2x_spin);
+ tie_setting(s.m02_y, ui.m2y_spin);
+ tie_setting(s.m02_z, ui.m2z_spin);
+
+ tie_setting(s.t_MH_x, ui.tx_spin);
+ tie_setting(s.t_MH_y, ui.ty_spin);
+ tie_setting(s.t_MH_z, ui.tz_spin);
+
+ connect( ui.tcalib_button,SIGNAL(toggled(bool)), this,SLOT(startstop_trans_calib(bool)) );
+ connect(ui.reset_button, SIGNAL(clicked()), this, SLOT(doReset()));
+
+ connect(ui.ok_button, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.cancel_button, SIGNAL(clicked()), this, SLOT(doCancel()));
+ connect(ui.btnApply, SIGNAL(clicked()), this, SLOT(doApply()));
+
+ 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(s.b.get(), SIGNAL(bundleChanged()), this, SLOT(do_apply_without_saving()));
+}
+
+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)
+{
+ if (start)
+ {
+ qDebug()<<"TrackerDialog:: Starting translation calibration";
+ trans_calib.reset();
+ trans_calib_running = true;
+ }
+ else
+ {
+ qDebug()<<"TrackerDialog:: Stoppping translation calibration";
+ trans_calib_running = false;
+ {
+ auto tmp = trans_calib.get_estimate();
+ s.t_MH_x = tmp[0];
+ s.t_MH_y = tmp[1];
+ s.t_MH_z = tmp[2];
+ }
+ settings_changed();
+ }
+}
+
+void TrackerDialog::trans_calib_step()
+{
+ if (tracker)
+ {
+ FrameTrafo X_CM;
+ tracker->get_pose(&X_CM);
+ 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::doCenter()
+{
+ if (tracker) tracker->center();
+}
+
+void TrackerDialog::doReset()
+{
+ if (tracker) tracker->reset();
+}
+
+void TrackerDialog::save()
+{
+ do_apply_without_saving();
+ s.b->save();
+}
+
+void TrackerDialog::doOK()
+{
+ save();
+ close();
+}
+
+void TrackerDialog::do_apply_without_saving()
+{
+ 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->revert();
+ close();
+}
+
+void TrackerDialog::widget_destroyed(QObject* obj)
+{
+ if (obj == video_widget_dialog) {
+ // widget was / will be already deleted by Qt
+ destroy_video_widget(false);
+ }
+}
+
+void TrackerDialog::create_video_widget()
+{
+ // this should not happen but better be sure
+ if (video_widget_dialog) destroy_video_widget();
+ if (!tracker) return;
+
+ video_widget_dialog = new VideoWidgetDialog(this, tracker);
+ video_widget_dialog->setAttribute( Qt::WA_DeleteOnClose );
+ connect( video_widget_dialog, SIGNAL(destroyed(QObject*)), this, SLOT(widget_destroyed(QObject*)) );
+ video_widget_dialog->show();
+}
+
+void TrackerDialog::destroy_video_widget(bool do_delete /*= true*/)
+{
+ if (video_widget_dialog) {
+ if (do_delete) delete video_widget_dialog;
+ video_widget_dialog = NULL;
+ }
+}
+
+void TrackerDialog::poll_tracker_info()
+{
+ if (tracker)
+ {
+ QString to_print;
+
+ // display caminfo
+ CamInfo info;
+ tracker->get_cam_info(&info);
+ to_print = QString::number(info.res_x)+"x"+QString::number(info.res_y)+" @ "+QString::number(info.fps)+" FPS";
+ ui.caminfo_label->setText(to_print);
+
+ // display pointinfo
+ int n_points = tracker->get_n_points();
+ to_print = QString::number(n_points);
+ if (n_points == 3)
+ to_print += " OK!";
+ else
+ to_print += " BAD!";
+ ui.pointinfo_label->setText(to_print);
+
+ // update calibration
+ if (trans_calib_running) trans_calib_step();
+
+ // update videowidget
+ if (video_widget_dialog) {
+ video_widget_dialog->get_video_widget()->update_frame_and_points();
+ }
+ }
+ else
+ {
+ QString to_print = "Tracker offline";
+ ui.caminfo_label->setText(to_print);
+ ui.pointinfo_label->setText(to_print);
+ }
+}
+
+void TrackerDialog::registerTracker(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);
+ ui.reset_button->setEnabled(true);
+}
+
+void TrackerDialog::unRegisterTracker()
+{
+ qDebug()<<"TrackerDialog:: Tracker un-registered";
+ tracker = NULL;
+ destroy_video_widget();
+ ui.tcalib_button->setEnabled(false);
+ //ui.center_button->setEnabled(false);
+ ui.reset_button->setEnabled(false);
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new TrackerDialog;
+}
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.h
new file mode 100644
index 00000000..0325160d
--- /dev/null
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dialog.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_PT_DIALOG_H
+#define FTNOIR_TRACKER_PT_DIALOG_H
+
+#ifdef OPENTRACK_API
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#else
+#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h"
+#endif
+#include "ftnoir_tracker_pt_settings.h"
+#include "ftnoir_tracker_pt.h"
+#include "trans_calib.h"
+#include "pt_video_widget.h"
+#include "ui_FTNoIR_PT_Controls.h"
+
+#include <QTimer>
+
+//-----------------------------------------------------------------------------
+// The dialog that shows up when the user presses "Settings"
+class TrackerDialog : public QWidget, Ui::UICPTClientControls, public ITrackerDialog
+{
+ Q_OBJECT
+public:
+ TrackerDialog();
+ void registerTracker(ITracker *tracker);
+ void unRegisterTracker();
+ void save();
+ void trans_calib_step();
+
+public slots:
+ void doCenter();
+ void doReset();
+ void doOK();
+ void doApply();
+ void doCancel();
+ void do_apply_without_saving();
+
+ void startstop_trans_calib(bool start);
+ void widget_destroyed(QObject* obj);
+ void create_video_widget();
+ void poll_tracker_info();
+ void set_model(int idx);
+
+protected:
+ void destroy_video_widget(bool do_delete = true);
+
+ void set_model_clip();
+ void set_model_cap();
+ void set_model_custom();
+
+ void settings_changed();
+
+ settings s;
+ Tracker* tracker;
+ VideoWidgetDialog* video_widget_dialog;
+ QTimer timer;
+
+ TranslationCalibrator trans_calib;
+ bool trans_calib_running;
+
+ Ui::UICPTClientControls ui;
+};
+
+#endif //FTNOIR_TRACKER_PT_DIALOG_H
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.cpp
index 22c4a33d..f3fbbef7 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.cpp
@@ -7,12 +7,11 @@
#include "ftnoir_tracker_pt_dll.h"
#include <QIcon>
-#include "facetracknoir/global-settings.h"
//-----------------------------------------------------------------------------
void TrackerDll::getFullName(QString *strToBeFilled)
{
- *strToBeFilled = "PointTracker 1.0";
+ *strToBeFilled = "PointTracker 1.1";
}
void TrackerDll::getShortName(QString *strToBeFilled)
@@ -27,14 +26,17 @@ void TrackerDll::getDescription(QString *strToBeFilled)
void TrackerDll::getIcon(QIcon *icon)
{
- *icon = QIcon(":/resources/icon.png");
+ *icon = QIcon(":/Resources/Logo_IR.png");
}
-//-----------------------------------------------------------------------------
-//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
-
+#ifdef OPENTRACK_API
+# include "facetracknoir/global-settings.h"
extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION 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_pt/ftnoir_tracker_pt_dll.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.h
index dde0bc9f..1d30e7e5 100644
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_dll.h
@@ -5,11 +5,20 @@
* copyright notice and this permission notice appear in all copies.
*/
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "facetracknoir/global-settings.h"
+#if defined(OPENTRACK_API)
+# include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+# include "facetracknoir/global-settings.h"
+#else
+# include "../ftnoir_tracker_base/ftnoir_tracker_base.h"
+#endif
//-----------------------------------------------------------------------------
-class TrackerDll : public Metadata
+class TrackerDll :
+#if defined(OPENTRACK_API)
+ public Metadata
+#else
+ public ITrackerDll
+#endif
{
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
diff --git a/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h
new file mode 100644
index 00000000..109090b3
--- /dev/null
+++ b/FTNoIR_Tracker_PT/ftnoir_tracker_pt_settings.h
@@ -0,0 +1,90 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#ifndef FTNOIR_TRACKER_PT_SETTINGS_H
+#define FTNOIR_TRACKER_PT_SETTINGS_H
+
+#include <opencv2/opencv.hpp>
+#include "point_tracker.h"
+
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings
+{
+ pbundle b;
+ value<int> cam_index,
+ cam_res_x,
+ cam_res_y,
+ cam_fps,
+ cam_roll,
+ cam_pitch,
+ cam_yaw,
+ threshold,
+ threshold_secondary,
+ min_point_size,
+ max_point_size;
+ value<double> cam_f;
+
+ value<int> m01_x, m01_y, m01_z;
+ value<int> m02_x, m02_y, m02_z;
+ value<bool> dyn_pose_res, video_widget;
+
+ value<int> t_MH_x, t_MH_y, t_MH_z;
+
+ value<int> reset_time;
+
+ value<bool> bEnableYaw, bEnablePitch, bEnableRoll;
+ value<bool> bEnableX, bEnableY, bEnableZ;
+
+ value<int> clip_ty, clip_tz, clip_by, clip_bz;
+ value<int> active_model_panel, cap_x, cap_y, cap_z;
+
+ settings() :
+ b(bundle("tracker-pt")),
+ cam_index(b, "camera-index", 0),
+ 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),
+ max_point_size(b, "max-point-size", 50),
+ cam_f(b, "camera-focal-length", 1),
+ m01_x(b, "m_01-x", 0),
+ m01_y(b, "m_01-y", 0),
+ m01_z(b, "m_01-z", 0),
+ m02_x(b, "m_02-x", 0),
+ m02_y(b, "m_02-y", 0),
+ m02_z(b, "m_02-z", 0),
+ dyn_pose_res(b, "dynamic-pose-resolution", false),
+ video_widget(b, "video-widget", true),
+ t_MH_x(b, "model-centroid-x", 0),
+ t_MH_y(b, "model-centroid-y", 0),
+ t_MH_z(b, "model-centroid-z", 0),
+ reset_time(b, "reset-time", 2000),
+ bEnableYaw(b, "enable-yaw", true),
+ bEnablePitch(b, "enable-pitch", true),
+ bEnableRoll(b, "enable-roll", true),
+ bEnableX(b, "enable-x", true),
+ bEnableY(b, "enable-y", true),
+ bEnableZ(b, "enable-z", true),
+ clip_ty(b, "clip-ty", 0),
+ clip_tz(b, "clip-tz", 0),
+ clip_by(b, "clip-by", 0),
+ clip_bz(b, "clip-bz", 0),
+ 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)
+ {}
+};
+
+#endif //FTNOIR_TRACKER_PT_SETTINGS_H
diff --git a/FTNoIR_Tracker_PT/point_extractor.cpp b/FTNoIR_Tracker_PT/point_extractor.cpp
new file mode 100644
index 00000000..d9ff0a5b
--- /dev/null
+++ b/FTNoIR_Tracker_PT/point_extractor.cpp
@@ -0,0 +1,163 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "point_extractor.h"
+#include <QDebug>
+
+
+using namespace cv;
+using namespace std;
+
+
+PointExtractor::PointExtractor(){
+ //if (!AllocConsole()){}
+ //else SetConsoleTitle("debug");
+ //freopen("CON", "w", stdout);
+ //freopen("CON", "w", stderr);
+}
+// ----------------------------------------------------------------------------
+const vector<Vec2f>& PointExtractor::extract_points(Mat frame, float dt, bool draw_output)
+{
+ const int W = frame.cols;
+ const int H = frame.rows;
+
+ if (frame_last.cols != W || frame_last.rows != H)
+ {
+ frame_last = cv::Mat();
+ }
+
+ // clear old points
+ points.clear();
+
+ // convert to grayscale
+ Mat frame_gray;
+ cvtColor(frame, frame_gray, CV_RGB2GRAY);
+
+ int secondary = threshold_secondary_val;
+
+ // mask for everything that passes the threshold (or: the upper threshold of the hysteresis)
+ Mat frame_bin;
+ // only used if draw_output
+ Mat frame_bin_copy;
+ // mask for everything that passes
+ Mat frame_bin_low;
+ // mask for lower-threshold && combined result of last, needs to remain in scope until drawing, but is only used if secondary != 0
+ Mat frame_last_and_low;
+
+ if(secondary==0){
+ threshold(frame_gray, frame_bin, threshold_val, 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 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);
+ threshold(frame_gray, frame_bin_low,std::max(float(1), t - (t*hyst)), 255, THRESH_BINARY);
+
+ if(draw_output) frame_bin.copyTo(frame_bin_copy);
+ if(frame_last.empty()){
+ frame_bin.copyTo(frame_last);
+ }else{
+ // keep pixels from last if they are above lower threshold
+ bitwise_and(frame_last, frame_bin_low, frame_last_and_low);
+ // union of pixels >= higher threshold and pixels >= lower threshold
+ bitwise_or(frame_bin, frame_last_and_low, frame_last);
+ frame_last.copyTo(frame_bin);
+ }
+ }
+ 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;
+
+ int blob_index = 1;
+ for (int y=0; y<H; y++)
+ {
+ if (blob_index >= 255) break;
+ for (int x=0; x<W; x++)
+ {
+ if (blob_index >= 255) break;
+
+ // find connected components with floodfill
+ if (frame_bin.at<unsigned char>(y,x) != 255) continue;
+ Rect rect;
+
+ floodFill(frame_bin, Point(x,y), Scalar(blob_index), &rect, Scalar(0), Scalar(0), FLOODFILL_FIXED_RANGE);
+ blob_index++;
+
+ // calculate the size of the connected component
+ unsigned int region_size = 0;
+ for (int i=rect.y; i < (rect.y+rect.height); i++)
+ {
+ for (int j=rect.x; j < (rect.x+rect.width); j++)
+ {
+ if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue;
+ region_size++;
+ }
+ }
+
+ if (region_size < region_size_min || region_size > region_size_max) continue;
+
+ // calculate the center of mass:
+ // mx = (sum_ij j*f(frame_grey_ij)) / (sum_ij f(frame_grey_ij))
+ // my = ...
+ // f maps from [threshold,256] -> [0, 1], lower values are mapped to 0
+ float m = 0;
+ float mx = 0;
+ float my = 0;
+ for (int i=rect.y; i < (rect.y+rect.height); i++)
+ {
+ for (int j=rect.x; j < (rect.x+rect.width); j++)
+ {
+ if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue;
+ float val;
+
+ if(secondary==0){
+ val = frame_gray.at<unsigned char>(i,j);
+ val = float(val - threshold_val)/(256 - threshold_val);
+ 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
+ val = frame_last.at<unsigned char>(i,j) / 256.;
+ }
+
+ m += val;
+ mx += j * val;
+ my += i * val;
+ }
+ }
+
+ // convert to centered camera coordinate system with y axis upwards
+ Vec2f c;
+ c[0] = (mx/m - W/2)/W;
+ c[1] = -(my/m - H/2)/W;
+ //qDebug()<<blob_index<<" => "<<c[0]<<" "<<c[1];
+ points.push_back(c);
+ }
+ }
+
+ // draw output image
+ if (draw_output) {
+ vector<Mat> channels;
+ if(secondary==0){
+ frame_bin.setTo(170, frame_bin);
+ channels.push_back(frame_gray + frame_bin);
+ channels.push_back(frame_gray - frame_bin);
+ channels.push_back(frame_gray - frame_bin);
+ }else{
+ frame_bin_copy.setTo(120, frame_bin_copy);
+ 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);
+ }
+ merge(channels, frame);
+ }
+
+ return points;
+}
diff --git a/ftnoir_tracker_pt/point_extractor.h b/FTNoIR_Tracker_PT/point_extractor.h
index b142d2bb..ff36f3ce 100644
--- a/ftnoir_tracker_pt/point_extractor.h
+++ b/FTNoIR_Tracker_PT/point_extractor.h
@@ -9,6 +9,7 @@
#define POINTEXTRACTOR_H
#include <opencv2/opencv.hpp>
+#include <opencv2/imgproc/imgproc_c.h>
// ----------------------------------------------------------------------------
// Extracts points from an opencv image
@@ -20,12 +21,15 @@ public:
// WARNING: returned reference is valid as long as object
const std::vector<cv::Vec2f>& extract_points(cv::Mat frame, float dt, bool draw_output);
const std::vector<cv::Vec2f>& get_points() { return points; }
+ PointExtractor();
int threshold_val;
+ int threshold_secondary_val;
int min_size, max_size;
protected:
std::vector<cv::Vec2f> points;
+ cv::Mat frame_last;
};
#endif //POINTEXTRACTOR_H
diff --git a/ftnoir_tracker_pt/point_tracker.cpp b/FTNoIR_Tracker_PT/point_tracker.cpp
index c08d6d83..dfefdaf8 100644
--- a/ftnoir_tracker_pt/point_tracker.cpp
+++ b/FTNoIR_Tracker_PT/point_tracker.cpp
@@ -14,6 +14,7 @@
#include <QDebug>
using namespace cv;
+using namespace boost;
using namespace std;
const float PI = 3.14159265358979323846f;
@@ -35,7 +36,8 @@ static void set_row(Matx33f& m, int i, const Vec3f& v)
// ----------------------------------------------------------------------------
PointModel::PointModel(Vec3f M01, Vec3f M02)
- : M01(M01), M02(M02)
+ : M01(M01),
+ M02(M02)
{
// calculate u
u = M01.cross(M02);
@@ -67,27 +69,46 @@ PointModel::PointModel(Vec3f M01, Vec3f M02)
get_d_order(points, d_order);
}
+#ifdef OPENTRACK_API
static bool d_vals_sort(const pair<float,int> a, const pair<float,int> b)
{
return a.first < b.first;
}
+#endif
void PointModel::get_d_order(const std::vector<cv::Vec2f>& points, int d_order[]) const
{
// get sort indices with respect to d scalar product
vector< pair<float,int> > d_vals;
- for (int i = 0; i<(int)points.size(); ++i)
+ for (int i = 0; i<points.size(); ++i)
d_vals.push_back(pair<float, int>(d.dot(points[i]), i));
- sort(d_vals.begin(), d_vals.end(), d_vals_sort);
-
- for (int i = 0; i<(int)points.size(); ++i)
+ struct
+ {
+ bool operator()(const pair<float, int>& a, const pair<float, int>& b) { return a.first < b.first; }
+ } comp;
+ std::sort(d_vals.begin(),
+ d_vals.end(),
+#ifdef OPENTRACK_API
+ d_vals_sort
+#else
+ comp
+#endif
+ );
+
+ for (int i = 0; i<points.size(); ++i)
d_order[i] = d_vals[i].second;
}
// ----------------------------------------------------------------------------
-PointTracker::PointTracker() : dynamic_pose_resolution(true), dt_reset(1), init_phase(true), dt_valid(0), v_t(0,0,0), v_r(0,0,0)
+PointTracker::PointTracker()
+ : init_phase(true),
+ dt_valid(0),
+ dt_reset(1),
+ v_t(0,0,0),
+ v_r(0,0,0),
+ dynamic_pose_resolution(true)
{
X_CM.t[2] = 1000; // default position: 1 m away from cam;
}
@@ -119,8 +140,15 @@ bool PointTracker::track(const vector<Vec2f>& points, float f, float dt)
reset();
}
+ bool no_model =
+#ifdef OPENTRACK_API
+ point_model.get() == NULL;
+#else
+ !point_model;
+#endif
+
// if there is a pointtracking problem, reset the velocities
- if (!point_model.get() || (int) points.size() != PointModel::N_POINTS)
+ if (no_model || points.size() != PointModel::N_POINTS)
{
//qDebug()<<"Wrong number of points!";
reset_velocities();
@@ -141,7 +169,7 @@ bool PointTracker::track(const vector<Vec2f>& points, float f, float dt)
return false;
}
- (void) POSIT(f);
+ int n_iter = POSIT(f);
//qDebug()<<"Number of POSIT iterations: "<<n_iter;
if (!init_phase)
@@ -239,8 +267,8 @@ int PointTracker::POSIT(float f)
// initial pose = last (predicted) pose
Vec3f k;
- get_row(X_CM.R, 2, k);
- float Z0 = X_CM.t[2];
+ get_row(R_expected, 2, k);
+ float Z0 = init_phase ? 1000 : X_CM.t[2];
float old_epsilon_1 = 0;
float old_epsilon_2 = 0;
diff --git a/ftnoir_tracker_pt/point_tracker.h b/FTNoIR_Tracker_PT/point_tracker.h
index 7eee580d..11034100 100644
--- a/ftnoir_tracker_pt/point_tracker.h
+++ b/FTNoIR_Tracker_PT/point_tracker.h
@@ -8,12 +8,16 @@
#ifndef POINTTRACKER_H
#define POINTTRACKER_H
-#include <memory>
#include <opencv2/opencv.hpp>
+#ifndef OPENTRACK_API
+# include <boost/shared_ptr.hpp>
+#else
+# include "FTNoIR_Tracker_PT/boost-compat.h"
+#endif
#include <list>
// ----------------------------------------------------------------------------
-// Afine frame trafo
+// Affine frame trafo
class FrameTrafo
{
public:
@@ -29,11 +33,22 @@ inline FrameTrafo operator*(const FrameTrafo& X, const FrameTrafo& Y)
return FrameTrafo(X.R*Y.R, X.R*Y.t + X.t);
}
+inline FrameTrafo operator*(const cv::Matx33f& X, const FrameTrafo& Y)
+{
+ return FrameTrafo(X*Y.R, X*Y.t);
+}
+
+inline FrameTrafo operator*(const FrameTrafo& X, const cv::Matx33f& Y)
+{
+ return FrameTrafo(X.R*Y, X.t);
+}
+
inline cv::Vec3f operator*(const FrameTrafo& X, const cv::Vec3f& v)
{
return X.R*v + X.t;
}
+
// ----------------------------------------------------------------------------
// Describes a 3-point model
// nomenclature as in
@@ -57,7 +72,7 @@ protected:
cv::Matx22f P;
- cv::Vec2f d; // discrimant vector for point correspondence
+ cv::Vec2f d; // discriminant 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;
@@ -76,7 +91,7 @@ public:
// f : (focal length)/(sensor width)
// dt : time since last call
bool track(const std::vector<cv::Vec2f>& points, float f, float dt);
- std::auto_ptr<PointModel> point_model;
+ boost::shared_ptr<PointModel> point_model;
bool dynamic_pose_resolution;
float dt_reset;
diff --git a/FTNoIR_Tracker_PT/pt_video_widget.cpp b/FTNoIR_Tracker_PT/pt_video_widget.cpp
new file mode 100644
index 00000000..02817cbf
--- /dev/null
+++ b/FTNoIR_Tracker_PT/pt_video_widget.cpp
@@ -0,0 +1,64 @@
+/* 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.
+ *
+ * 20130312, WVR: Add 7 lines to resizeGL after resize_frame. This should lower CPU-load.
+ */
+
+#include "pt_video_widget.h"
+
+#include <QDebug>
+#include <QHBoxLayout>
+
+using namespace cv;
+using namespace std;
+
+void PTVideoWidget::update_image(const cv::Mat& frame)
+{
+ QMutexLocker foo(&mtx);
+ _frame = frame.clone();
+ freshp = true;
+}
+
+// ----------------------------------------------------------------------------
+VideoWidgetDialog::VideoWidgetDialog(QWidget *parent, FrameProvider* provider)
+ : QDialog(parent),
+ video_widget(NULL)
+{
+ const int VIDEO_FRAME_WIDTH = 640;
+ const int VIDEO_FRAME_HEIGHT = 480;
+
+ video_widget = new PTVideoWidget(this, provider);
+
+ QHBoxLayout* layout = new QHBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(video_widget);
+ if (this->layout()) delete this->layout();
+ setLayout(layout);
+ resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT);
+}
+
+void PTVideoWidget::update_and_repaint()
+{
+ QMutexLocker foo(&mtx);
+ if (_frame.empty() || !freshp)
+ return;
+ freshp = false;
+ QImage qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888);
+ uchar* data = qframe.bits();
+ const int pitch = qframe.bytesPerLine();
+ for (int y = 0; y < _frame.rows; y++)
+ for (int x = 0; x < _frame.cols; x++)
+ {
+ const auto& elt = _frame.at<Vec3b>(y, x);
+ const cv::Scalar elt2 = static_cast<cv::Scalar>(elt);
+ data[y * pitch + x * 3 + 0] = elt2.val[2];
+ data[y * pitch + x * 3 + 1] = elt2.val[1];
+ data[y * pitch + x * 3 + 2] = elt2.val[0];
+ }
+ qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
+ texture = qframe;
+ update();
+}
diff --git a/FTNoIR_Tracker_PT/pt_video_widget.h b/FTNoIR_Tracker_PT/pt_video_widget.h
new file mode 100644
index 00000000..25d593c3
--- /dev/null
+++ b/FTNoIR_Tracker_PT/pt_video_widget.h
@@ -0,0 +1,71 @@
+/* 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 "frame_observer.h"
+#include <QObject>
+#include <QTime>
+#include <QDialog>
+#include <opencv2/opencv.hpp>
+#ifndef OPENTRACK_API
+# include <QGLWidget>
+# include <boost/shared_ptr.hpp>
+#else
+# include "FTNoIR_Tracker_PT/boost-compat.h"
+# if defined(_WIN32)
+# include <dshow.h>
+# endif
+#endif
+#include <QPainter>
+#include <QPaintEvent>
+#include <QTimer>
+
+class PTVideoWidget : public QWidget, public FrameObserver
+{
+ Q_OBJECT
+
+public:
+ PTVideoWidget(QWidget *parent, FrameProvider* provider) :
+ QWidget(parent),
+ /* to avoid linker errors */ FrameObserver(provider),
+ freshp(false)
+ {
+ connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint()));
+ timer.start(40);
+ }
+ void update_image(const cv::Mat &frame);
+ void update_frame_and_points() {}
+protected slots:
+ void paintEvent( QPaintEvent* e ) {
+ QMutexLocker foo(&mtx);
+ QPainter painter(this);
+ painter.drawImage(e->rect(), texture);
+ }
+ void update_and_repaint();
+private:
+ QMutex mtx;
+ QImage texture;
+ QTimer timer;
+ cv::Mat _frame;
+ bool freshp;
+};
+
+// ----------------------------------------------------------------------------
+// A VideoWidget embedded in a dialog frame
+class VideoWidgetDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ VideoWidgetDialog(QWidget *parent, FrameProvider* provider);
+ virtual ~VideoWidgetDialog() {}
+
+ PTVideoWidget* get_video_widget() { return video_widget; }
+
+private:
+ PTVideoWidget* video_widget;
+};
diff --git a/ftnoir_tracker_pt/trans_calib.cpp b/FTNoIR_Tracker_PT/trans_calib.cpp
index 9b75a1b6..9b75a1b6 100644
--- a/ftnoir_tracker_pt/trans_calib.cpp
+++ b/FTNoIR_Tracker_PT/trans_calib.cpp
diff --git a/ftnoir_tracker_pt/trans_calib.h b/FTNoIR_Tracker_PT/trans_calib.h
index 4024d011..f2521690 100644
--- a/ftnoir_tracker_pt/trans_calib.h
+++ b/FTNoIR_Tracker_PT/trans_calib.h
@@ -11,7 +11,7 @@
#include <opencv2/opencv.hpp>
//-----------------------------------------------------------------------------
-// calibrates the translation from head to model = t_MH
+// Calibrates the translation from head to model = t_MH
// by recursive least squares /
// kalman filter in information form with identity noise covariance
// measurement equation when head position = t_CH is fixed:
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..04704cfe
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+=======
+Windows binary builds are available at <https://www.dropbox.com/sh/544fbhsokdpy3n7/AAAKwl6BluqwT9Xn2slyp0dCa>
+
+Source code access available at <http://github.com/opentrack/opentrack/>
+
+--
+
+**opentrack** is an application dedicated to tracking user's head
+movements and relaying them 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>
+- Razer Hydra
+- Relaying via UDP from a different computer
+- Joystick analog axes (Windows only)
+
+# 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)
+- Wine freetrack glue protocol (Linux, OSX)
+- Tablet-like coordinate output (Windows)
+
+# Configuration
+
+**opentrack** offers output shaping, filtering, is buildable on
+MS Windows, MacOSX and GNU/Linux.
+
+Don't be afraid to submit an issue/feature request if the need arises.
+
+# Credits
+
+- Stanisław Halik
+- Chris Thompson (aka mm0zct)
+- Donovan Baarda
+- Ryan Spicer (OSX tester, contributor)
+- Patrick Ruoff (PT tracker)
+- FuraX49 (hatire arduino tracker)
+- Ulf Schreiber (PT tracker)
+- uglyDwarf (high CON)
+- George Trigonakis (tester)
+- Wim Vriend (historically)
+- Ron Hendriks (historically)
+
+# Licensing information
+
+The code originally licensed under GPLv3, new code is required to be
+compatible with it 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.
diff --git a/TODO.txt b/TODO.txt
new file mode 100644
index 00000000..e9eb232a
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,29 @@
+20131023 sh
+ Low-hanging fruit: Go through all forms and replace ok/cancel with
+ QButtonBox which works better with layouts.
+20131020 sh
+ Add unit testing by means of batch execution, protocol/filter that does
+ nothing, add separate executables for readers of specific protocols,
+ and run continuous integration every time commit happens that day.
+
+ Add statically-typed settings trees, convert result to qsettings-enabled
+ ini files. Use metadata props in order to get class name for ini section.
+ Required here are also arrays of settings. Use QList<T> for template
+ specialization.
+20131019 mm0zct
+ Ship more then one profile for configuring the curves etc.
+ There are two main user bases, HMD and traditional monitor+webcam users,
+ each wants a drastically different curve profile (HMD is 1:1 on all axes)
+ Also re:boost, I'd rather avoid extra library dependences if possible.
+
+ Rift tracker could do with positional estimation using intertial sensors.
+ Rift could do with a return-yaw-to-centre hotkey that's not the global all-axis option.
+ Hydra is really just a hack just now, could be improved a lot.
+
+ Add per-tracker hotkey support
+20131011 sh
+ low-hanging fruit: default saving profiles to a directory in user home,
+ not into global stuffies
+
+ as for build system, low-hanging fruit is writing functions/macrology
+ for all the repetition out there.
diff --git a/bin/NPClient.dll b/bin/NPClient.dll
index 2469db3c..bf971c03 100644..100755
--- a/bin/NPClient.dll
+++ b/bin/NPClient.dll
Binary files differ
diff --git a/bin/NPClient64.dll b/bin/NPClient64.dll
index 37bc6207..fd3164e5 100644..100755
--- a/bin/NPClient64.dll
+++ b/bin/NPClient64.dll
Binary files differ
diff --git a/bin/licence.rtf b/bin/licence.rtf
deleted file mode 100644
index c0337ab4..00000000
--- a/bin/licence.rtf
+++ /dev/null
@@ -1,361 +0,0 @@
-{\rtf1\ansi\deff1\adeflang1025
-{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\fmodern\fprq1\fcharset0 Nimbus Mono L{\*\falt Courier New};}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\fmodern\fprq1\fcharset0 Nimbus Mono L{\*\falt Courier New};}{\f4\froman\fprq2\fcharset0 Nimbus Roman No9 L{\*\falt Times New Roman};}{\f5\fnil\fprq2\fcharset0 SimSun;}{\f6\fnil\fprq2\fcharset0 Tahoma;}{\f7\fnil\fprq0\fcharset0 Tahoma;}}
-{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green0\blue128;\red128\green128\blue128;}
-{\stylesheet{\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031\snext1 Normal;}
-{\s2\sb240\sa120\keepn\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af6\afs28\lang1081\ltrch\dbch\af5\langfe2052\hich\f2\fs28\lang1031\loch\f2\fs28\lang1031\sbasedon1\snext3 Heading;}
-{\s3\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031\sbasedon1\snext3 Body Text;}
-{\s4\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af7\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031\sbasedon3\snext4 List;}
-{\s5\sb120\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af7\afs24\lang1081\ai\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\i\loch\f1\fs24\lang1031\i\sbasedon1\snext5 caption;}
-{\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af7\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031\sbasedon1\snext6 Index;}
-{\*\cs8\cf3\ul\ulc0\rtlch\af1\afs24\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs24\lang255\loch\f1\fs24\lang255 Internet link;}
-}
-{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment StarWriter}{\vern3200}}\deftab709
-{\*\pgdsctbl
-{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn18720\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Standard;}}
-{\*\pgdscno0}\paperh18720\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\pgwsxn12240\pghsxn18720\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
-\pard\plain \ltrpar\s1\cf0\qc{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs40\lang1081\ab\ltrch\dbch\af1\langfe2052\hich\f1\fs40\lang9226\b\loch\f1\fs40\lang9226\b {\rtlch \ltrch\loch\f1\fs40\lang9226\i0\b GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007}
-\par \pard\plain \ltrpar\s1\cf0\qc{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs36\lang1081\ab\ltrch\dbch\af1\langfe2052\hich\f1\fs36\lang9226\b\loch\f1\fs36\lang9226\b
-\par \pard\plain \ltrpar\s1\cf0\qc{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs20\lang9226\loch\f1\fs20\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0{\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 Copyright (C) 2007 Free Software Foundation, Inc. <}}{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0{\cf2\ul\ulc0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226{\field{\*\fldinst HYPERLINK "http://fsf.org/" }{\fldrslt \*\cs8\cf3\ul\ulc0\rtlch\ltrch\dbch\hich\f1\fs24\lang255\loch\f1\fs24\lang255 http://fsf.org/}{\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226}} >}}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Preamble}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 The GNU General Public License is a free, copyleft license for software and other kinds of works.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program-
--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 your programs, too.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code o
-r can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect
-the freedom of others.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them th
-ese terms so they know their rights.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Developers that use the GNU GPL protect your rights with two steps:}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be att
-ributed erroneously to authors of previous versions.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The
-systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems ar
-ise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents appli
-ed to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 The precise terms and conditions for copying, distribution and modification follow.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qc{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 TERMS AND CONDITIONS}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 0. Definitions.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 "This License" refers to version 3 of the GNU General Public License.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the ear
-lier work.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 A "covered work" means either the unmodified Program or a work based on the Program.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes
- copying, distribution (with or without modification), making available to the}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 public, and in some countries other activities as well.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work
-(except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list
-meets this criterion.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 1. Source Code.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that
-language.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the
- work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of
- the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not
- include the work's System Libraries, or general-purpose tools or generally available free}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries
- and dynamically linked subprograms that the work is specifically designed to require,}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 such as by intimate data communication or control flow between those subprograms and other parts of the work.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 The Corresponding Source for a work in source code form is that same work.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 2. Basic Permissions.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output
-from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 rights of fair use or other equivalent, as provided by copyright law.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for yo
-u, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 3. Protecting Users' Legal Rights From Anti-Circumvention Law.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention
- of such measures.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intent
-ion to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 4. Conveying Verbatim Copies.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and an
-y non-permissive terms added in accord with section 7 apply to the code;}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 5. Conveying Modified Source Versions.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 a) The work must carry prominent notices stating that you modified}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 it, and giving a relevant date.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 b) The work must carry prominent notices stating that it is released under this License and any conditions added under section }
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 7. This requirement modifies the requirement in section 4 to "keep intact all notices".}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution m
-edium, is called an "aggregate" if the compilation and its resulting copyright are not}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 6. Conveying Non-Source Forms.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that prod
-uct model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price
-no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in a
-ccord with subsection 6b.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy
- the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided
- you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requ
-irements.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whethe
-r a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the p
-articular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless s
-uch uses represent the only significant mode of use of the product.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding So
-urce. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient i
-n perpetuity or for a fixed term (regardless of how the transaction is characterized), the}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for examp
-le, the work has been installed in ROM).}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been
-modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special passwo
-rd or key for unpacking, reading or copying.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 7. Additional Terms.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this L
-icense, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.)
-You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 d) Limiting the use for publicity purposes of names of licensors or authors of the material; or}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions dire
-ctly impose on those licensors and authors.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that
-is a further restriction, you may remove that term. If a license document contains}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 8. Termination.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses grant
-ed under the third paragraph of section 11).}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the c
-opyright holder fails to notify you of the violation by some reasonable means}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 prior to 60 days after the cessation.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work
-) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive ne
-w licenses for the same material under section 10.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 9. Acceptance Not Required for Having Copies.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require accept
-ance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 10. Automatic Licensing of Downstream Recipients.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this
- License.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each pa
-rty to that transaction who receives a copy of the work also receives whatever}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reaso
-nable efforts.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not
-initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 11. Patents.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version".}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its co
-ntributor version, but do not include claims that would be infringed only as a}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor versio
-n.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" su
-ch a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other re
-adily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent lice
-nse, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 country that you have reason to believe are valid.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagat
-e, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 work and works based on it.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not con
-vey a covered work if you are a party to an arrangement with a third party that is}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you,
- a discriminatory patent license (a) in connection with copies of the covered work}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March
- 2007.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 12. No Surrender of Others' Freedom.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneo
-usly your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you conve
-y the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 13. Use with the GNU Affero General Public License.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The
- terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 combination as such.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 14. Revised Versions of this License.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of t
-hat numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 15. Disclaimer of Warranty.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, I
-NCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NE
-CESSARY SERVICING, REPAIR OR CORRECTION.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 16. Limitation of Liability.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CO
-NSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRA
-MS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 17. Interpretation of Sections 15 and 16.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in conne
-ction with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 END OF TERMS AND CONDITIONS}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 How to Apply These Terms to Your New Programs}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the f
-ull notice is found.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 <one line to give the program's name and a brief idea of what it does.>}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 Copyright (C) <year> <name of author>}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 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.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 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.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch\ltrch\dbch\hich\loch{\rtlch \ltrch\loch }}{{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0 You should have received a copy of the GNU General Public License along with this program. If not, see <}}{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0{\cf2\ul\ulc0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226{\field{\*\fldinst HYPERLINK "http://www.gnu.org/licenses/" }{\fldrslt \*\cs8\cf3\ul\ulc0\rtlch\ltrch\dbch\hich\f1\fs24\lang255\loch\f1\fs24\lang255 http://www.gnu.org/licenses/}{\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226}} >.}}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 Also add information on how to contact you by electronic and paper mail.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 <program> Copyright (C) <year> <name of author>}
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226 {\rtlch \ltrch\loch\f4\fs24\lang9226\i0\b0 The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box".}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang9226\loch\f1\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary.}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0{\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226 For more information on this, and how to apply and follow the GNU GPL, see <}}{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0{\cf2\ul\ulc0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226{\field{\*\fldinst HYPERLINK "http://www.gnu.org/licenses/" }{\fldrslt \*\cs8\cf3\ul\ulc0\rtlch\ltrch\dbch\hich\f1\fs24\lang255\loch\f1\fs24\lang255 http://www.gnu.org/licenses/}{\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226}} >.}}
-\par \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang1081\ltrch\dbch\af4\langfe2052\hich\f4\fs24\lang9226\loch\f4\fs24\lang9226
-\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang1081\ltrch\dbch\af1\langfe2052\hich\f1\fs24\lang1031\loch\f1\fs24\lang1031{\rtlch\ltrch\dbch\hich\loch{\rtlch \ltrch\loch }}{{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0 The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what y
-ou want to do, use the GNU Lesser General Public License instead of this License. But first, please read <}}{\rtlch \ltrch\loch\f1\fs24\lang1031\i0\b0{\cf2\ul\ulc0\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226{\field{\*\fldinst HYPERLINK "http://www.gnu.org/philosophy/why-not-lgpl.html" }{\fldrslt \*\cs8\cf3\ul\ulc0\rtlch\ltrch\dbch\hich\f1\fs24\lang255\loch\f1\fs24\lang255 http://www.gnu.org/philosophy/why-not-lgpl.html}{\rtlch\ltrch\dbch\hich\f4\lang9226\loch\f4\lang9226}} >.}}
-\par } \ No newline at end of file
diff --git a/bin/settings/default.ini b/bin/settings/default.ini
index 05ce3af4..e69de29b 100644
--- a/bin/settings/default.ini
+++ b/bin/settings/default.ini
@@ -1,130 +0,0 @@
-[Curves-rx]
-point-count=4
-point-0-x=0
-point-0-y=0
-point-1-x=5
-point-1-y=14
-point-2-x=12.222222328186
-point-2-y=75
-point-3-x=19
-point-3-y=158
-
-[Curves-ry]
-point-count=1
-point-0-x=19
-point-0-y=90
-
-[Curves-ry_alt]
-point-count=4
-point-0-x=0
-point-0-y=0
-point-1-x=4.88888883590698
-point-1-y=16
-point-2-x=8.88888931274414
-point-2-y=36
-point-3-x=12
-point-3-y=69
-
-[Curves-rz]
-point-count=1
-point-0-x=60
-point-0-y=60
-
-[Curves-tx]
-point-count=1
-point-0-x=59.8888893127441
-point-0-y=165
-
-[Curves-ty]
-point-count=1
-point-0-x=60
-point-0-y=165
-
-[Curves-tz]
-point-count=1
-point-0-x=60
-point-0-y=200
-
-[Tracking]
-Smooth=1
-invertYaw=false
-invertPitch=false
-invertRoll=false
-invertX=false
-invertY=false
-invertZ=false
-rx_alt=false
-ry_alt=true
-rz_alt=false
-tx_alt=false
-ty_alt=false
-tz_alt=false
-
-[GameProtocol]
-DLL=FTNoIR_Protocol_FT.dll
-
-[KB_Shortcuts]
-Keycode_Center=199
-Shift_Center=false
-Ctrl_Center=false
-Alt_Center=false
-Keycode_StartStop=207
-Shift_StartStop=false
-Ctrl_StartStop=false
-Alt_StartStop=false
-
-[PPJoy]
-Selection=1
-
-[FSUIPC]
-LocationOfDLL=C:/Program Files/Microsoft Games/Flight Simulator 9/Modules/FSUIPC.dll
-
-[TrackerSource]
-Selection=0
-DLL=FTNoIR_Tracker_SM.dll
-2ndDLL=None
-
-[Filter]
-DLL=FTNoIR_Filter_Accela.dll
-
-[SMTracker]
-FilterLevel=1
-EnableRoll=true
-EnablePitch=true
-EnableYaw=true
-EnableX=true
-EnableY=true
-EnableZ=true
-
-[Accela]
-Reduction=1000
-zoom-slowness=5
-smoothing-factor=1.5
-
-[Curves-Accela-Scaling-Rotation]
-point-count=6
-point-0-x=0
-point-0-y=0
-point-1-x=0.535433053970337
-point-1-y=0.29824560880661
-point-2-x=0.992125988006592
-point-2-y=0.736842095851898
-point-3-x=1.33070862293243
-point-3-y=1.59649121761322
-point-4-x=1.4960629940033
-point-4-y=3.29824566841125
-point-5-x=1.58267712593079
-point-5-y=8
-
-[Curves-Accela-Scaling-Translation]
-point-count=5
-point-0-x=0
-point-0-y=0
-point-1-x=0.346456706523895
-point-1-y=1
-point-2-x=0.559055089950562
-point-2-y=3.15789484977722
-point-3-x=0.700787425041199
-point-3-y=5.54385948181152
-point-4-x=0.795275568962097
-point-4-y=8 \ No newline at end of file
diff --git a/bin/settings/facetracknoir supported games.csv b/bin/settings/facetracknoir supported games.csv
index e5d3d6aa..91b9e6e6 100644
--- a/bin/settings/facetracknoir supported games.csv
+++ b/bin/settings/facetracknoir supported games.csv
@@ -1,9 +1,10 @@
-No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
+No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
1;18 Wheels of Steel: Haulin';FreeTrack20;V160;V;doc-uk;13601;000121F172F35116A02100
2;1944 D-Day;FreeTrack20;V160;;;15701;00022E542A6A0575F05200
497;2KMarinNEXT;FreeTrack20;V170;;;3425;0D614F6A0820D1EA8EE800
3;3D Instructor;FreeTrack20;V160;;;20490;00034B0FC367116611B100
4;3D Interactive;FreeTrack20;V160;;;20425;0004C6371D77135815A600
+505;3D Interieur Visualisation;FreeTrack20;V160;;;20815;01F9EDEE75DAC2968D9A00
5;3d Nav;FreeTrack20;V160;;;20235;000579EC0E26932651EA00
6;3D-Fahrschule Driving Simulator;FreeTrack20;V160;;;20020;000601075146E0E9625B00
7;3ds Max;FreeTrack20;V160;;;8601;00077A32A1A7523A4DE700
@@ -23,6 +24,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
21;Apache: Air Assault;FreeTrack20;V160;V;paleta77;1875;001591D997A2D912AAA200
22;Aprisoft Gartenplaner;FreeTrack20;V160;;;20014;0016F2F27A5762FA937A00
23;Aprisoft Traumhaus Designer;FreeTrack20;V160;;;20013;00174655E792BB825B9300
+498;ARI;FreeTrack20;V160;;;20795;01F23FB9A61044E206E200
24;ArmA;FreeTrack20;V160;V;EmBeES;10601;0018F2F27A57631A40F200
25;ArmA 2;FreeTrack20;V170;V;V4Friend, Ronski;7502;0019EB3616B3A44F05B900
26;ArmA 2 Operation Arrowhead;FreeTrack20;V160;V;vn88holden;0;001ABC224B7783DAF0D500
@@ -71,6 +73,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
65;Comanche;FreeTrack20;V160;;;2275;00414097C36A12BA32BA00
66;Combat Flight Simulator 3;FreeTrack20;V160;V;V4Friend;2304;00420EC5F763AB21CA7310
67;Combat Helo;FreeTrack20;V160;;;2001;004329DFA863FAE1EA7300
+515;Combined Arms;FreeTrack20;V160;;;1309;0203387EDB1A5AFEADB600
68;Commandos Strike Force;FreeTrack20;V160;;;8801;0044C1BBF892DB037A7200
69;Concept RS;FreeTrack20;V160;;;10701;004537971697736A72DA00
70;Condor: The Competitive Soaring Simulator;FreeTrack20;V160;V;MicheleF;5901;004670A8B762DA623A1300
@@ -89,6 +92,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
84;Dark Horizons Lore;FreeTrack20;V160;;;7901;005487801A852AA7385200
85;Dawn of Aces - Gold Edition;FreeTrack20;V170;;;1304;0055A9ED7700814190DE00
86;Dawn of Aces II;FreeTrack20;V160;;;1302;00566925967C2BB0285500
+513;Dawn of Aces/Red Baron;FreeTrack20;V160;;;1307;0201916C14F32918D9B800
87;DBS WalkAndFollow;FreeTrack20;V160;;;2525;005770A8B77008BDE89200
88;DCS: Black Shark;FreeTrack20;V170;V;EmBeES;1006;0058F688FC9B0556868F00
89;DCS: A-10C Warthog (32 and 64 bit);FreeTrack20;V170;V;fabri91, Shadow;1003;0059B6DCD15F5A572F6500
@@ -108,9 +112,11 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
102;Dungeons and Dragons Online;FreeTrack20;V170;;;1575;0066BD4D4DDC6BB6818800
103;DY Demo;FreeTrack20;V160;;;20345;006727D5047A15540F9D00
104;EADS Testing;FreeTrack20;V160;;;20303;00680288709760D5512900
+504;EAFIT;FreeTrack20;V160;;;20810;01F8D2675ABC163E99B000
105;Eagle Lander 3D;FreeTrack20;V160;;;11901;00697686E5A7B209C27900
106;EasyVR;FreeTrack20;V160;;;20220;006A68292872FAC4588100
107;ECA-Sindel;FreeTrack20;V160;;;20590;006BC5BEE479FD75FB8500
+508;Elite: Dangerous;FreeTrack20;V170;;;3475;0D93A9485EECA12E18BE00
481;Embers of Caerus;FreeTrack20;V170;;;3275;0CCB4134258D7E10119E00
108;EMS Simulations;FreeTrack20;V160;;;20390;006CA59E687D1589DE8500
109;Enemy Engaged 2;FreeTrack20;V160;;;2102;006D010873EA635AEDC800
@@ -163,6 +169,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
152;GameLab;FreeTrack20;V160;;;20555;00985485D891DB23092200
472;Games Farm;FreeTrack20;V160;;;3250;01D875C0981E627E5C7600
153;Gamma;FreeTrack20;V160;;;1050;009921007D1B9D38A76F00
+503;Garry's Mod;FreeTrack20;V160;;;12503;01F74EEB71FA7F37856900
483;Generic Robotics;FreeTrack20;V160;;;20750;01E3FE7B4F05872A415400
475;Glider Sim;FreeTrack20;V160;;;20720;01DB42130C4B0620871C00
154;Global Ground Support Deicing Simulation;FreeTrack20;V160;;;20330;009ACFE709237A3AA11F00
@@ -178,8 +185,10 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
164;Gun Commander;FreeTrack20;V160;;;2675;00A4E2D1D77E319FEE8600
165;Half Life 2;FreeTrack20;V160;;;7806;00A556BA018130AF365500
166;Halo;FreeTrack20;V160;;;3801;00A656BA018130AF3F9C00
+502;hapTEL;FreeTrack20;V160;;;20805;01F63ADE510A20446B6A00
167;Hardware Control Simulator, Railway Electronics;FreeTrack20;V160;;;20705;00A7F3E85B1A8930B42F00
168;Harrier Attack II;FreeTrack20;V160;;;1175;00A8F2F27A57D20A940900
+499;Harry's Hard Choices Interactive;FreeTrack20;V160;;;20800;01F33A21BAE3DB6D48A000
169;HAWX;FreeTrack20;V160;V;EmBeES ;0;00A9D615A9C8B088717000
170;Herissons (Paris France);FreeTrack20;V160;;;20001;00AAEA1CBED8C20B430B00
171;HOBI;FreeTrack20;V160;;;20335;00ABB253777F1779168900
@@ -207,6 +216,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
192;iRacing;FreeTrack20;V160;V;vn88holden ;14101;00C0103AF1AA730A236900
193;IREQ Robotic Camera Control;FreeTrack20;V160;;;20027;00C10448E0E8618521EB00
194;ISIC;FreeTrack20;V160;;;20680;00C2DEE3582F8F217E0B00
+506;ITCL;FreeTrack20;V160;;;20820;01FAD19412681DC9CC6100
195;IVD Online;FreeTrack20;V160;;;20535;00C390B57E1D7DDD883D00
196;J.J. Keller and Associates;FreeTrack20;V160;;;20002;00C4E482F57FE77CF46300
197;Janes F18;FreeTrack20;V160;;;9001;00C55F3D9577802AAF2E00
@@ -236,11 +246,13 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
220;Lore (Dark Horizons);FreeTrack20;V160;;;5302;00DCF478D27833DB62D500
221;Love;FreeTrack20;V160;;;3125;00DD71ED5E802AAB214800
222;Lucid Engine;FreeTrack20;V160;;;10501;00DE71ED5E803098259C00
+514;M4 Tank Brigade;FreeTrack20;V160;;;1308;02024ED5A3A26741604300
223;M4 Tank Platoon;FreeTrack20;V160;;;1306;00DFDCC441A8E036320900
224;Mach 1;FreeTrack20;V160;;;2575;00E0231518130942466000
225;ManuVAR;FreeTrack20;V160;;;20455;00E153FE1E901CB0448800
226;MaqSIM4;FreeTrack20;V160;;;20026;00E28F54A207D29B611700
227;Mech Tactical Sim;FreeTrack20;V160;;;9501;00E3F3E85B1A8E34A53300
+516;MechWarrior Online;FreeTrack20;V170;;;3026;0BD2E0DCBC723836CD2400
228;Mechwarrior Online;FreeTrack20;V170;;;3025;00E414954226DB5D8CE200
229;Medical Image Visualization;FreeTrack20;V160;;;20295;00E59343488532A5359B00
230;Meggitt Defense Systems;FreeTrack20;V160;;;20045;00E6926ED9122AB22AF300
@@ -321,6 +333,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
299;Rail Simulator 1;FreeTrack20;V160;;;1550;012BB253778929A0395900
300;Railway Work Simulator;FreeTrack20;V160;;;20225;012C91D998B1E9933B9100
301;RailWorks 2;FreeTrack20;V160;;;2750;012D3919C4972D9D299000
+507;RailWorks 5 (TS2014);FreeTrack20;V160;;;1551;01FB8B5232CB1502C95A00
302;Raydon Driving Simulator;FreeTrack20;V160;;;3701;012E5485D941DBE2FB5300
304;Real Time Visual;FreeTrack20;V160;;;9901;0130B1C664862297365500
305;RealFlight;FreeTrack20;V160;;;4001;0131AC6E87892E993A8B00
@@ -351,6 +364,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
329;RSD Demo;FreeTrack20;V160;;;2050;0149BF8C4EAA5871A85D00
330;RTMS Crane Sim;FreeTrack20;V160;;;20400;014AC93272841D91205200
331;RTT DeltaGen Plugin;FreeTrack20;V160;;;20195;014B90B5871B8DDD7D3400
+511;Sail;FreeTrack20;V160;;;3575;01FF2916D764159099F800
332;Sail Simulator 5;FreeTrack20;V160;;;1975;014CE2D1D78A1D9A3B6300
333;Sailors of the Sky;FreeTrack20;V160;;;10201;014D17BE02961FAF3AB100
334;Santa Cruz Watermill;FreeTrack20;V160;;;20290;014E88F5881EA32FA7E900
@@ -368,18 +382,22 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
346;Simax Simulator;FreeTrack20;V160;;;20021;015AAC156D9736A331AD00
347;Simball 4D;FreeTrack20;V160;;;20315;015BD6E585F99349F2AA00
348;Simbionix;FreeTrack20;V160;;;20485;015CE7A7FAA28528AE1D00
+518;SimCraft;FreeTrack20;V160;;;3650;02065BA013963203CB1900
349;SimCreator;FreeTrack20;V160;;;20520;015D3752FBC8935B001A00
350;Simlog Personal Simulator;FreeTrack20;V160;;;20635;015E42868C33A435B53100
351;SimQuest immersion system;FreeTrack20;V160;;;20023;015F6C69678C32A30FAE00
352;SimSol;FreeTrack20;V160;;;20034;01602315187389E0FB5300
491;Simumak;FreeTrack20;V160;;;20770;01EB119629980784DCE600
+510;Sir, You Are Being Hunted;FreeTrack20;V160;;;3550;01FEDAB345FA104ED4A100
353;Sirocco Racing;FreeTrack20;V160;;;5801;01612BCA748925A6369A00
354;Sky God: Military Freefall;FreeTrack20;V170;;;1526;01622C0104385FD1C44400
355;Soft fx Demo;FreeTrack20;V160;;;2125;01632E20238A2B99335200
356;Source Engine (Half-Life 2);FreeTrack20;V160;;;12502;0164E482F58829A739A600
357;Space Shuttle Mission 2007;FreeTrack20;V160;V;purewhitewings ;1225;0165662B03863D912F9700
+517;Spaze;FreeTrack20;V160;;;3625;020573F9D3ED8C43B8DC00
358;SRI;FreeTrack20;V160;;;20620;01663FD0FC9D8B218D8100
359;Stanford University;FreeTrack20;V160;;;20004;0167CE35BAF9933A62AA00
+500;Star Citizen;FreeTrack20;V170;;;3450;0D7AF4CE4E343EC6B4A200
360;Starshatter;FreeTrack20;V160;;;6401;0168F079578A3F9A3BB600
361;Steel Beasts 2;FreeTrack20;V160;;;11703;0169DCC441A9443A831A00
362;Steel Beasts Pro;FreeTrack20;V160;;;11701;016A8F54A20833CAA23900
@@ -405,6 +423,8 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
380;Telepresence;FreeTrack20;V160;;;20450;017CF478D278B33B02DA00
381;Tenstar Simulator;FreeTrack20;V160;;;20605;017D318F88A2EA62DBA200
382;Test Drive Unlimited;FreeTrack20;V160;;;13201;017E6F2699559730A84000
+509;Tetrahedral;FreeTrack20;V160;;;3525;01FDCFF1C56D6F757E8200
+501;The Crew;FreeTrack20;V170;;;1009;03F1F534E94F4834D9B100
488;The Gallery;FreeTrack20;V160;;;3350;01E8CE152EDE5FFD267700
383;The Sky Gods;FreeTrack20;V170;;;1525;017FDFF782DCCEEA27C200
384;theHunter;FreeTrack20;V170;;;2375;0180BFF3A86D34DA24C000
@@ -481,6 +501,7 @@ No;Game Name;Game protocol;Supported since;Verified;By;INTERNATIONAL_ID;FTN_ID
449;Wikid FJ;FreeTrack20;V160;;;20685;01C19BC3BDA98269B25A00
450;Wings of Prey;FreeTrack20;V160;V;V4Friend;1877;01C25909438736A133AC00
451;Wings of War;FreeTrack20;V160;;;7807;01C34B0FC38B36B42FB610
+512;Wings: Over Flanders Fields;FreeTrack20;V160;;;2326;02008AE39AAA4624B33C00
452;World Racing 2;FreeTrack20;V160;;;7201;01C41AAF68A2BA836AAE00
453;WWII Battle Tanks: T-34 vs. Tiger;FreeTrack20;V160;;;11102;01C5432C29C257F1963100
454;X Motor Racing;FreeTrack20;V160;;;1150;01C669259690E98629A900
diff --git a/cmake/FindQxt.cmake b/cmake/FindQxt.cmake
deleted file mode 100644
index 1ddfa0dd..00000000
--- a/cmake/FindQxt.cmake
+++ /dev/null
@@ -1,155 +0,0 @@
-#############
-## basic FindQxt.cmake
-## This is an *EXTREMELY BASIC* cmake find/config file for
-## those times you have a cmake project and wish to use
-## libQxt.
-##
-## It should be noted that at the time of writing, that
-## I (mschnee) have an extremely limited understanding of the
-## way Find*.cmake files work, but I have attempted to
-## emulate what FindQt4.cmake and a few others do.
-##
-## To enable a specific component, set your QXT_USE_${modname}:
-## SET(QXT_USE_QXTCORE TRUE)
-## SET(QXT_USE_QXTGUI FALSE)
-## Currently available components:
-## QxtCore, QxtGui, QxtNetwork, QxtWeb, QxtSql
-## Auto-including directories are enabled with INCLUDE_DIRECTORIES(), but
-## can be accessed if necessary via ${QXT_INCLUDE_DIRS}
-##
-## To add the libraries to your build, TARGET_LINK_LIBRARIES(), such as...
-## TARGET_LINK_LIBRARIES(YourTargetNameHere ${QXT_LIBRARIES})
-## ...or..
-## TARGET_LINK_LIBRARIES(YourTargetNameHere ${QT_LIBRARIES} ${QXT_LIBRARIES})
-################### TODO:
-## The purpose of this cmake file is to find what components
-## exist, regardless of how libQxt was build or configured, thus
-## it should search/find all possible options. As I am not aware
-## that any module requires anything special to be used, adding all
-## modules to ${QXT_MODULES} below should be sufficient.
-## Eventually, there should be version numbers, but
-## I am still too unfamiliar with cmake to determine how to do
-## version checks and comparisons.
-## At the moment, this cmake returns a failure if you
-## try to use a component that doesn't exist. I don't know how to
-## set up warnings.
-## It would be nice having a FindQxt.cmake and a UseQxt.cmake
-## file like done for Qt - one to check for everything in advance
-
-##############
-
-###### setup
-SET(QXT_MODULES QxtGui QxtWeb QxtZeroConf QxtNetwork QxtSql QxtBerkeley QxtCore)
-SET(QXT_FOUND_MODULES)
-FOREACH(mod ${QXT_MODULES})
- STRING(TOUPPER ${mod} U_MOD)
- SET(QXT_${U_MOD}_INCLUDE_DIR NOTFOUND)
- SET(QXT_${U_MOD}_LIB_DEBUG NOTFOUND)
- SET(QXT_${U_MOD}_LIB_RELEASE NOTFOUND)
- SET(QXT_FOUND_${U_MOD} FALSE)
-ENDFOREACH(mod)
-SET(QXT_QXTGUI_DEPENDSON QxtCore)
-SET(QXT_QXTWEB_DEPENDSON QxtCore QxtNetwork)
-SET(QXT_QXTZEROCONF_DEPENDSON QxtCore QxtNetwork)
-SET(QXT_QXTNETWORK_DEPENDSON QxtCore)
-SET(QXT_QXTQSQL_DEPENDSON QxtCore)
-SET(QXT_QXTBERKELEY_DEPENDSON QxtCore)
-
-FOREACH(mod ${QXT_MODULES})
- STRING(TOUPPER ${mod} U_MOD)
- IF(NOT ${U_MOD}_INCLUDE_DIR)
- FIND_PATH(QXT_${U_MOD}_INCLUDE_DIR NAME ${mod}
- PATH_SUFFIXES ${mod} include/${mod}
- qxt/include/${mod} include/qxt/${mod}
- Qxt/include/${mod} include/Qxt/${mod}
- PATHS
- ~/Library/Frameworks/
- /Library/Frameworks/
- /sw/
- /usr/local/
- /usr
- /opt/local/
- /opt/csw
- /opt
- "C:/Program Files/libqxt/include"
- "C:/Program Files (x86)/libqxt/include"
- NO_DEFAULT_PATH
- )
- FIND_LIBRARY(QXT_${U_MOD}_LIB_RELEASE NAME ${mod}
- PATH_SUFFIXES Qxt/lib64 Qxt/lib lib64 lib lib/${CMAKE_LIBRARY_ARCHITECTURE}
- PATHS
- /sw
- /usr/local
- /usr
- /opt/local
- /opt/csw
- /opt
- "C:/Program Files/libqxt"
- "C:/Program Files (x86)/libqxt"
- NO_DEFAULT_PATH
- )
- FIND_LIBRARY(QXT_${U_MOD}_LIB_DEBUG NAME ${mod}d
- PATH_SUFFIXES Qxt/lib64 Qxt/lib lib64 lib lib/${CMAKE_LIBRARY_ARCHITECTURE}
- PATHS
- /sw
- /usr/local
- /usr
- /opt/local
- /opt/csw
- /opt
- "C:/Program Files/libqxt/"
- "C:/Program Files (x86)/libqxt/"
- NO_DEFAULT_PATH
- )
- IF (QXT_${U_MOD}_LIB_RELEASE)
- SET(QXT_FOUND_MODULES "${QXT_FOUND_MODULES} ${mod}")
- ENDIF (QXT_${U_MOD}_LIB_RELEASE)
-
- IF (QXT_${U_MOD}_LIB_DEBUG)
- SET(QXT_FOUND_MODULES "${QXT_FOUND_MODULES} ${mod}")
- ENDIF (QXT_${U_MOD}_LIB_DEBUG)
- ENDIF()
-ENDFOREACH(mod)
-
-FOREACH(mod ${QXT_MODULES})
- STRING(TOUPPER ${mod} U_MOD)
- IF(QXT_${U_MOD}_INCLUDE_DIR AND QXT_${U_MOD}_LIB_RELEASE)
- SET(QXT_FOUND_${U_MOD} TRUE)
- ENDIF(QXT_${U_MOD}_INCLUDE_DIR AND QXT_${U_MOD}_LIB_RELEASE)
-ENDFOREACH(mod)
-
-
-##### find and include
-# To use a Qxt Library....
-# SET(QXT_FIND_COMPONENTS QxtCore, QxtGui)
-# ...and this will do the rest
-IF( QXT_FIND_COMPONENTS )
- FOREACH( component ${QXT_FIND_COMPONENTS} )
- STRING( TOUPPER ${component} _COMPONENT )
- SET(QXT_USE_${_COMPONENT}_COMPONENT TRUE)
- ENDFOREACH( component )
-ENDIF( QXT_FIND_COMPONENTS )
-
-SET(QXT_LIBRARIES "")
-SET(QXT_INCLUDE_DIRS "")
-
-# like FindQt4.cmake, in order of dependence
-FOREACH( module ${QXT_MODULES} )
- STRING(TOUPPER ${module} U_MOD)
- IF(QXT_USE_${U_MOD} OR QXT_DEPENDS_${U_MOD})
- IF(QXT_FOUND_${U_MOD})
- STRING(REPLACE "QXT" "" qxt_module_def "${U_MOD}")
- ADD_DEFINITIONS(-DQXT_${qxt_module_def}_LIB)
- SET(QXT_INCLUDE_DIRS ${QXT_INCLUDE_DIRS} ${QXT_${U_MOD}_INCLUDE_DIR})
- INCLUDE_DIRECTORIES(${QXT_${U_MOD}_INCLUDE_DIR})
- SET(QXT_LIBRARIES ${QXT_LIBRARIES} ${QXT_${U_MOD}_LIB_RELEASE})
- ELSE(QXT_FOUND_${U_MOD})
- MESSAGE("Could not find Qxt Module ${module}")
- RETURN()
- ENDIF(QXT_FOUND_${U_MOD})
- FOREACH(dep QXT_${U_MOD}_DEPENDSON)
- SET(QXT_DEPENDS_${dep} TRUE)
- ENDFOREACH(dep)
- ENDIF(QXT_USE_${U_MOD} OR QXT_DEPENDS_${U_MOD})
-ENDFOREACH(module)
-MESSAGE(STATUS "Found Qxt Libraries:${QXT_FOUND_MODULES}")
diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake
new file mode 100644
index 00000000..e16d8c37
--- /dev/null
+++ b/cmake/GetGitRevisionDescription.cmake
@@ -0,0 +1,123 @@
+# - Returns a version string from Git
+#
+# These functions force a re-configure on each git commit so that you can
+# trust the values of the variables in your build system.
+#
+# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
+#
+# Returns the refspec and sha hash of the current head revision
+#
+# git_describe(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe on the source tree, and adjusting
+# the output so that it tests false if an error occurs.
+#
+# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe --exact-match on the source tree,
+# and adjusting the output so that it tests false if there was no exact
+# matching tag.
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+if(__get_git_revision_description)
+ return()
+endif()
+set(__get_git_revision_description YES)
+
+# We must run the following at "include" time, not at function call time,
+# to find the path to this module rather than the path to a calling list file
+get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
+
+function(get_git_head_revision _refspecvar _hashvar)
+ set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
+ set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+ while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
+ set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
+ get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
+ if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
+ # We have reached the root directory, we are not in git
+ set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+ set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+ return()
+ endif()
+ set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+ endwhile()
+ set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
+ if(NOT EXISTS "${GIT_DATA}")
+ file(MAKE_DIRECTORY "${GIT_DATA}")
+ endif()
+
+ if(NOT EXISTS "${GIT_DIR}/HEAD")
+ return()
+ endif()
+ set(HEAD_FILE "${GIT_DATA}/HEAD")
+ configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
+
+ configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
+ "${GIT_DATA}/grabRef.cmake"
+ @ONLY)
+ include("${GIT_DATA}/grabRef.cmake")
+
+ set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
+ set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
+endfunction()
+
+function(git_describe _var)
+ if(NOT GIT_FOUND)
+ find_package(Git QUIET)
+ endif()
+ get_git_head_revision(refspec hash)
+ if(NOT GIT_FOUND)
+ set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
+ return()
+ endif()
+ if(NOT hash)
+ set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
+ return()
+ endif()
+
+ # TODO sanitize
+ #if((${ARGN}" MATCHES "&&") OR
+ # (ARGN MATCHES "||") OR
+ # (ARGN MATCHES "\\;"))
+ # message("Please report the following error to the project!")
+ # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
+ #endif()
+
+ #message(STATUS "Arguments to execute_process: ${ARGN}")
+
+ execute_process(COMMAND
+ "${GIT_EXECUTABLE}"
+ describe
+ ${hash}
+ ${ARGN}
+ WORKING_DIRECTORY
+ "${CMAKE_SOURCE_DIR}"
+ RESULT_VARIABLE
+ res
+ OUTPUT_VARIABLE
+ out
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT res EQUAL 0)
+ set(out "${out}-${res}-NOTFOUND")
+ endif()
+
+ set(${_var} "${out}" PARENT_SCOPE)
+endfunction()
+
+function(git_get_exact_tag _var)
+ git_describe(out ${ARGN})
+ set(${_var} "${out}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in
new file mode 100644
index 00000000..888ce13a
--- /dev/null
+++ b/cmake/GetGitRevisionDescription.cmake.in
@@ -0,0 +1,38 @@
+#
+# Internal file for GetGitRevisionDescription.cmake
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+set(HEAD_HASH)
+
+file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
+
+string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
+if(HEAD_CONTENTS MATCHES "ref")
+ # named branch
+ string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
+ if(EXISTS "@GIT_DIR@/${HEAD_REF}")
+ configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+ elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
+ configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+ set(HEAD_HASH "${HEAD_REF}")
+ endif()
+else()
+ # detached HEAD
+ configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
+endif()
+
+if(NOT HEAD_HASH)
+ file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
+ string(STRIP "${HEAD_HASH}" HEAD_HASH)
+endif()
diff --git a/compat/compat.cpp b/compat/compat.cpp
index 8eedc845..7b695617 100644
--- a/compat/compat.cpp
+++ b/compat/compat.cpp
@@ -6,8 +6,9 @@
*/
#define IN_FTNOIR_COMPAT
#include "compat.h"
+#include <string.h>
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize)
{
@@ -44,21 +45,14 @@ void PortableLockedShm::unlock()
}
#else
-PortableLockedShm::PortableLockedShm(const char *shmName, const char *mutexName, int mapSize) : size(mapSize)
+PortableLockedShm::PortableLockedShm(const char *shmName, const char* /*mutexName*/, int mapSize) : size(mapSize)
{
- char shm_filename[NAME_MAX];
- shm_filename[0] = '/';
- strncpy(shm_filename+1, shmName, NAME_MAX-2);
- sprintf(shm_filename + strlen(shm_filename), "%ld\n", (long) getuid());
- shm_filename[NAME_MAX-1] = '\0';
-
- //(void) shm_unlink(shm_filename);
-
- fd = shm_open(shm_filename, O_RDWR | O_CREAT, 0600);
- if (ftruncate(fd, mapSize) == 0)
- mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0);
- else
- mem = (void*) -1;
+ char filename[512] = {0};
+ strcpy(filename, "/");
+ strcat(filename, shmName);
+ fd = shm_open(filename, O_RDWR | O_CREAT, 0600);
+ (void) ftruncate(fd, mapSize);
+ mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)0);
}
PortableLockedShm::~PortableLockedShm()
@@ -79,6 +73,13 @@ void PortableLockedShm::unlock()
flock(fd, LOCK_UN);
}
+#endif
-
+bool PortableLockedShm::success()
+{
+#ifndef _WIN32
+ return (void*) mem != (void*) -1;
+#else
+ return (void*) mem != NULL;
#endif
+}
diff --git a/compat/compat.h b/compat/compat.h
index 7692b38a..0e488752 100644
--- a/compat/compat.h
+++ b/compat/compat.h
@@ -6,7 +6,7 @@
*/
#pragma once
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
#include <windows.h>
#else
#include <stdio.h>
@@ -19,10 +19,16 @@
#include <sys/types.h>
#endif
-#if defined(IN_FTNOIR_COMPAT) && (defined(_WIN32) || defined(__WIN32))
-# define COMPAT_EXPORT __declspec(dllexport)
+#if !defined(OPENTRACK_COMPAT_BUNDLED)
+# if defined(IN_FTNOIR_COMPAT) && defined(_WIN32)
+# define COMPAT_EXPORT __declspec(dllexport)
+# elif defined(_WIN32)
+# define COMPAT_EXPORT __declspec(dllimport)
+# else
+# define COMPAT_EXPORT __attribute__ ((visibility ("default")))
+# endif
#else
-# define COMPAT_EXPORT
+# define COMPAT_EXPORT
#endif
class COMPAT_EXPORT PortableLockedShm {
@@ -31,9 +37,10 @@ public:
~PortableLockedShm();
void lock();
void unlock();
+ bool success();
void* mem;
private:
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
HANDLE hMutex, hMapFile;
#else
int fd, size;
diff --git a/compat/qt-bug-appeasement.cpp b/compat/qt-bug-appeasement.cpp
new file mode 100644
index 00000000..9a86ac0a
--- /dev/null
+++ b/compat/qt-bug-appeasement.cpp
@@ -0,0 +1 @@
+#include "facetracknoir/qt-moc.h"
diff --git a/faceapi/build_options.h b/faceapi/build_options.h
deleted file mode 100644
index 6bc6a44c..00000000
--- a/faceapi/build_options.h
+++ /dev/null
@@ -1,8 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Build Options
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-//controls whether or not FaceAPI should use the callback or poll
-#define USE_HEADPOSE_CALLBACK 1
diff --git a/faceapi/ftnoir-faceapi-wrapper.exe.manifest b/faceapi/ftnoir-faceapi-wrapper.exe.manifest
deleted file mode 100644
index b6c98376..00000000
--- a/faceapi/ftnoir-faceapi-wrapper.exe.manifest
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.4053" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b">
- </assemblyIdentity>
- </dependentAssembly>
- </dependency>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b">
- </assemblyIdentity>
- </dependentAssembly>
- </dependency>
-</assembly> \ No newline at end of file
diff --git a/faceapi/ftnoir-faceapi-wrapper.rc b/faceapi/ftnoir-faceapi-wrapper.rc
deleted file mode 100644
index 54cbb863..00000000
--- a/faceapi/ftnoir-faceapi-wrapper.rc
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "winuser.h"
-2 RT_MANIFEST ftnoir-faceapi-wrapper.exe.manifest \ No newline at end of file
diff --git a/faceapi/lock.h b/faceapi/lock.h
deleted file mode 100644
index efe38605..00000000
--- a/faceapi/lock.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef SM_API_TESTAPPCONSOLE_LOCK_H
-#define SM_API_TESTAPPCONSOLE_LOCK_H
-
-#include "mutex.h"
-
-namespace sm
-{
- namespace faceapi
- {
- namespace samplecode
- {
- // A very simple scoped-lock class for sample code purposes.
- // It is recommended that you use the boost threads library.
- class Lock
- {
- public:
- Lock(const Mutex &mutex): _mutex(mutex)
- {
- _mutex.lock();
- }
- ~Lock()
- {
- _mutex.unlock();
- }
- private:
- // Noncopyable
- Lock(const Lock &);
- Lock &operator=(const Lock &);
- private:
- const Mutex &_mutex;
- };
- }
- }
-}
-#endif
diff --git a/faceapi/lockfree.h b/faceapi/lockfree.h
deleted file mode 100644
index ce7d2a64..00000000
--- a/faceapi/lockfree.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//lock free queue template class by Herb Sutter
-//Dr Dobbs Journal article http://www.drdobbs.com/cpp/210604448;jsessionid=OQGQPSMNL4X4XQE1GHPSKH4ATMY32JVN?pgno=1
-
-template <typename T> class LockFreeQueue
-{
-private:
- struct Node
- {
- Node( T val ) : value(val), next(nullptr) { }
- T value;
- Node* next;
- };
-
- Node* first; // for producer only
- Node* divider, last; // shared
-
- //not working in VC2008
- //atomic<Node*> divider, last; // shared
-
-public:
- LockFreeQueue()
- {
- // add dummy separator
- first = divider = last = new Node( T() );
- }
-
- ~LockFreeQueue()
- {
- while( first != nullptr )
- {
- // release the list
- Node* tmp = first;
- first = tmp->next;
- delete tmp;
- }
- }
-
- void Produce( const T& t )
- {
- last->next = new Node(t); // add the new item
- last = last->next; // publish it
-
- while( first != divider )
- {
- // trim unused nodes
- Node* tmp = first;
- first = first->next;
- delete tmp;
- }
- }
-
- bool Consume( T& result )
- {
- if( divider != last )
- {
- // if queue is nonempty
- result = divider->next->value; // copy it back
- divider = divider->next; // publish that we took it
- return true; // and report success
- }
-
- return false; // else report empty
- }
-};
-
diff --git a/faceapi/main.cpp b/faceapi/main.cpp
deleted file mode 100644
index 6cc93112..00000000
--- a/faceapi/main.cpp
+++ /dev/null
@@ -1,538 +0,0 @@
-/********************************************************************************
-* FaceTrackNoIR This program is a private project of the some enthusiastic *
-* gamers from Holland, who don't like to pay much for *
-* head-tracking. *
-* *
-* Copyright (C) 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/>. *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20130105 - WVR: Set engine state to TERMINATED, when EXIT.
- 20110501 - WVR: Added some command to be handled from FaceTrackNoIR (settings dialog).
- 20110322 - WVR: Somehow the video-widget of faceAPI version 3.2.6. does not
- work with FaceTrackNoIR (Qt issue?!). To be able to use
- release 3.2.6 of faceAPI anyway, this console-app is used.
- It exchanges data with FaceTrackNoIR via shared-memory...
-*/
-
-//Precompiled header
-#include "stdafx.h"
-
-//FaceAPI headers
-#include <sm_api.h>
-#include "ftnoir_tracker_base/ftnoir_tracker_sm_types.h"
-#include "utils.h"
-#include <exception>
-
-//local headers
-#include "build_options.h"
-
-//namespaces
-using namespace std;
-using namespace sm::faceapi::samplecode;
-
-//
-// global variables
-//
-HANDLE hSMMemMap = NULL;
-SMMemMap *pMemData;
-HANDLE hSMMutex;
-smEngineHeadPoseData new_head_pose;
-bool stopCommand = false;
-bool ftnoirConnected = false;
-
-//enums
-enum GROUP_ID
-{
- GROUP0=0,
-};
-
-enum EVENT_ID
-{
- EVENT_PING=0,
- EVENT_INIT,
-};
-
-enum INPUT_ID
-{
- INPUT0=0,
-};
-
-//function definitions
-void updateHeadPose(smEngineHeadPoseData* temp_head_pose);
-bool SMCreateMapping();
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//FaceAPI function implementations
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void STDCALL receiveLogMessage(void *, const char *buf, int /*buf_len*/)
-{
- Lock lock(g_mutex); // serialize logging calls from different threads to avoid garbled output.
- //cout << string(buf);
-}
-
-// Callback function for face-data
-void STDCALL receiveFaceData(void *, smEngineFaceData face_data, smCameraVideoFrame video_frame)
-{
- Lock lock(g_mutex);
-
- // Get info including data pointer to original image from camera
- smImageInfo video_frame_image_info;
- THROW_ON_ERROR(smImageGetInfo(video_frame.image_handle, &video_frame_image_info)); // reentrant, so ok
-
- // video_frame_image_info.plane_addr[*] now point to the image memory planes.
- // The memory is only valid until the end of this routine unless you call smImageAddRef(video_frame.image_handle).
- // So you can deep copy the image data here, or use smImageAddRef() and just copy the pointer.
- // If you use smImageAddRef() you are responsible for calling smImageDestroy() to avoid a memory leak later.
-
- // In this callback you will typically want to copy the smEngineFaceData data into your own data-structure.
- // Since the smEngineFaceData contains multiple pod types copying it is not atomic and
- // a mutex is required to avoid the race-condition with any thread simultaneously
- // reading from your data-structure.
- // Such a race condition will not crash your code but will create weird noise in the tracking data.
-
- if (g_do_face_data_printing)
- {
- //cout << video_frame << " " << face_data;
-
- // Save any face texture to a PNG file
- if (face_data.texture)
- {
- // Create a unique filename
- std::stringstream filename;
- filename << "face_" << video_frame.frame_num << ".png";
- // Try saving to a file
- if (saveToPNGFile(filename.str(), face_data.texture->image_info) == SM_API_OK)
- {
- cout << "Saved face-texture to " << filename.str() << std::endl;
- }
- else
- {
- cout << "Error saving face-texture to " << filename.str() << std::endl;
- }
- }
- }
-}
-
-// Callback function for head-pose
-void STDCALL receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVideoFrame video_frame)
-{
- Lock lock(g_mutex);
-
- // Get info including data pointer to original image from camera
- smImageInfo video_frame_image_info;
- THROW_ON_ERROR(smImageGetInfo(video_frame.image_handle, &video_frame_image_info)); // reentrant, so ok
-
- // video_frame_image_info.plane_addr[*] now point to the image memory planes.
- // The memory is only valid until the end of this routine unless you call smImageAddRef(video_frame.image_handle).
- // So you can deep copy the image data here, or use smImageAddRef() and just copy the pointer.
- // If you use smImageAddRef() you are responsible for calling smImageDestroy() to avoid a memory leak later.
-
- // In this callback you will typically want to copy the smEngineFaceData data into your own data-structure.
- // Since the smEngineFaceData contains multiple pod types copying it is not atomic and
- // a mutex is required to avoid the race-condition with any thread simultaneously
- // reading from your data-structure.
- // Such a race condition will not crash your code but will create weird noise in the tracking data.
-
- if (g_do_head_pose_printing)
- {
- //cout << video_frame << " " << head_pose << std::endl;
- }
-
- //make a copy of the new head pose data and send it to simconnect
- //when we get a simmconnect frame event the new offset will be applied to the camera
- updateHeadPose(&head_pose);
-}
-
-// Create the first available camera detected on the system, and return its handle
-smCameraHandle createFirstCamera()
-{
- // Detect cameras
- smCameraInfoList info_list;
- THROW_ON_ERROR(smCameraCreateInfoList(&info_list));
-
- if (info_list.num_cameras == 0)
- {
- throw std::exception();
- }
- else
- {
- cout << "The followings cameras were detected: " << endl;
- for (int i=0; i<info_list.num_cameras; ++i)
- {
- char buf[1024];
- cout << " " << i << ". Type: " << info_list.info[i].type;
- THROW_ON_ERROR(smStringWriteBuffer(info_list.info[i].model,buf,1024));
- cout << " Model: " << string(buf);
- cout << " Instance: " << info_list.info[i].instance_index << endl;
- // Print all the possible formats for the camera
- for (int j=0; j<info_list.info[i].num_formats; j++)
- {
- smCameraVideoFormat video_format = info_list.info[i].formats[j];
- cout << " - Format: ";
- cout << " res (" << video_format.res.w << "," << video_format.res.h << ")";
- cout << " image code " << video_format.format;
- cout << " framerate " << video_format.framerate << "(hz)";
- cout << " upside-down? " << (video_format.is_upside_down ? "y":"n") << endl;
- }
- }
- }
-
- // Create the first camera detected on the system
- smCameraHandle camera_handle = 0;
- THROW_ON_ERROR(smCameraCreate(&info_list.info[0], // Use first camera
- 0, // Use default settings for lens
- &camera_handle));
-
- // Destroy the info list
- smCameraDestroyInfoList(&info_list);
-
- return camera_handle;
-}
-
-// The main function: setup a tracking engine and show a video window, then loop on the keyboard.
-void run()
-{
- int state;
-
- // Capture control-C
-// signal(SIGINT, CtrlCHandler);
-
- // Make the console window a bit bigger (see utils.h)
- initConsole();
-
- #ifdef _DEBUG
- // Log API debugging information to a file
- THROW_ON_ERROR(smLoggingSetFileOutputEnable(SM_API_TRUE));
-
- // Hook up log message callback
- THROW_ON_ERROR(smLoggingRegisterCallback(0,receiveLogMessage));
- #endif
-
- // Get the version
- int major, minor, maint;
- THROW_ON_ERROR(smAPIVersion(&major, &minor, &maint));
- cout << endl << "API VERSION: " << major << "." << minor << "." << maint << "." << endl << endl;
- // Print detailed license info
- char *buff;
- int size;
- THROW_ON_ERROR(smAPILicenseInfoString(0,&size,SM_API_TRUE));
- buff = new char[size];
- THROW_ON_ERROR(smAPILicenseInfoString(buff,&size,SM_API_TRUE));
- cout << "LICENSE: " << buff << endl << endl;
- // Determine if non-commercial restrictions apply
- const bool non_commercial_license = smAPINonCommercialLicense() == SM_API_TRUE;
-
- // Initialize the API
- THROW_ON_ERROR(smAPIInit());
-
- #ifdef _DEBUG
- // Get the path to the logfile
- smStringHandle logfile_path_handle = 0;
- THROW_ON_ERROR(smStringCreate(&logfile_path_handle));
- THROW_ON_ERROR(smLoggingGetPath(logfile_path_handle));
- int buf_len = 0;
- unsigned short *buf = 0;
- THROW_ON_ERROR(smStringGetBufferW(logfile_path_handle,(wchar_t **)&buf,&buf_len));
- wcout << "Writing log to file: " << wstring((wchar_t *)buf) << endl;
- THROW_ON_ERROR(smStringDestroy(&logfile_path_handle));
- #endif
-
- // Register the WDM category of cameras
- THROW_ON_ERROR(smCameraRegisterType(SM_API_CAMERA_TYPE_WDM));
-
- smEngineHandle engine_handle = 0;
- smCameraHandle camera_handle = 0;
- if (non_commercial_license)
- {
- // Create a new Head-Tracker engine that uses the camera
- THROW_ON_ERROR(smEngineCreate(SM_API_ENGINE_LATEST_HEAD_TRACKER,&engine_handle));
- }
- else
- {
- // Print out a list of connected cameras, and choose the first camera on the system
- camera_handle = createFirstCamera();
- // Create a new Head-Tracker engine that uses the camera
- THROW_ON_ERROR(smEngineCreateWithCamera(SM_API_ENGINE_LATEST_HEAD_TRACKER,camera_handle,&engine_handle));
- }
-
- // Check license for particular engine version (always ok for non-commercial license)
- const bool engine_licensed = smEngineIsLicensed(engine_handle) == SM_API_OK;
-
- cout << "-----------------------------------------------------" << endl;
- cout << "Press 'r' to restart tracking" << endl;
- cout << "Press 'a' to toggle auto-restart mode" << endl;
- if (!non_commercial_license)
- {
- cout << "Press 'l' to toggle lip-tracking" << endl;
- cout << "Press 'e' to toggle eyebrow-tracking" << endl;
- }
- if (engine_licensed)
- {
- cout << "Press 'h' to toggle printing of head-pose data" << endl;
- cout << "Press 'f' to toggle printing of face-landmark data" << endl;
- }
- cout << "Press '1' to toggle face coordinate frame axes" << endl;
- cout << "Press '2' to toggle performance info" << endl;
- cout << "Press '3' to toggle face mask" << endl;
- cout << "Press '4' to toggle face landmarks" << endl;
- cout << "Press CTRL-C or 'q' to quit" << endl;
- cout << "-----------------------------------------------------" << endl;
-
- // Hook up callbacks to receive output data from engine.
- // These functions will return errors if the engine is not licensed.
- if (engine_licensed)
- {
- #if (USE_HEADPOSE_CALLBACK==1)
- #pragma message("Using Headpose Callback")
- THROW_ON_ERROR(smHTRegisterHeadPoseCallback(engine_handle,0,receiveHeadPose));
- #endif
- if (!non_commercial_license)
- {
- THROW_ON_ERROR(smHTRegisterFaceDataCallback(engine_handle,0,receiveFaceData));
- }
- }
- else
- {
- cout << "Engine is not licensed, cannot obtain any output data." << endl;
- }
-
- if (!non_commercial_license)
- {
- // Enable lip and eyebrow tracking
- THROW_ON_ERROR(smHTSetLipTrackingEnabled(engine_handle,SM_API_TRUE));
- THROW_ON_ERROR(smHTSetEyebrowTrackingEnabled(engine_handle,SM_API_TRUE));
- }
-
- // Create and show a video-display window
- // Set the initial filter-level, from the INI-file
- smVideoDisplayHandle video_display_handle = 0;
- if (pMemData) {
- THROW_ON_ERROR(smVideoDisplayCreate(engine_handle,&video_display_handle,(smWindowHandle) pMemData->handle,TRUE));
- THROW_ON_ERROR(smHTV2SetHeadPoseFilterLevel(engine_handle, pMemData->initial_filter_level));
- pMemData->handshake = 0;
- }
- else {
- THROW_ON_ERROR(smVideoDisplayCreate(engine_handle,&video_display_handle,0,TRUE));
- }
-
- // Setup the VideoDisplay
- THROW_ON_ERROR(smVideoDisplaySetFlags(video_display_handle,g_overlay_flags));
-
- // Get the handle to the window and change the title to "Hello World"
- smWindowHandle win_handle = 0;
- THROW_ON_ERROR(smVideoDisplayGetWindowHandle(video_display_handle,&win_handle));
- SetWindowText(win_handle, _T("faceAPI Video-widget"));
- MoveWindow(win_handle, 0, 0, 250, 180, true);
-
- // Loop on the keyboard
- while (processKeyPress(engine_handle, video_display_handle) && !stopCommand)
- {
- // Read and print the current head-pose (if not using the callback mechanism)
- #if (USE_HEADPOSE_CALLBACK==0)
- #pragma message("Polling Headpose Manually")
- if (engine_licensed)
- {
- smEngineHeadPoseData head_pose;
- Lock lock(g_mutex);
-
- THROW_ON_ERROR(smHTCurrentHeadPose(engine_handle,&head_pose));
- if (g_do_head_pose_printing)
- {
- std::cout << head_pose << std::endl;
- }
-
- }
- #endif
-
- // NOTE: If you have a windows event loop in your program you
- // will not need to call smAPIProcessEvents(). This manually redraws the video window.
- THROW_ON_ERROR(smAPIProcessEvents());
-
- // Prevent CPU overload in our simple loop.
- const int frame_period_ms = 10;
- Sleep(frame_period_ms);
-
- //
- // Process the command sent by FaceTrackNoIR.
- //
- if (ftnoirConnected && (pMemData != 0)) {
-
- //
- // Determine the trackers' state and send it to FaceTrackNoIR.
- //
- THROW_ON_ERROR(smEngineGetState(engine_handle, &state));
- pMemData->state = state;
- pMemData->handshake += 1;
-
- //
- // Check if FaceTrackNoIR is still 'in contact'.
- // FaceTrackNoIR will reset the handshake, every time in writes data.
- // If the value rises too high, this exe will stop itself...
- //
- if ( pMemData->handshake > 200) {
- stopCommand = TRUE;
- }
-
- //
- // Check if a command was issued and do something with it!
- //
- switch (pMemData->command) {
- case FT_SM_START:
-
- //
- // Only execute Start, if the engine is not yet tracking.
- //
- if (state != SM_API_ENGINE_STATE_HT_TRACKING) {
- THROW_ON_ERROR(smEngineStart(engine_handle)); // Start tracking
- }
- pMemData->command = 0; // Reset
- break;
-
- case FT_SM_STOP:
- THROW_ON_ERROR(smEngineStop(engine_handle)); // Stop tracking
- pMemData->command = 0; // Reset
- break;
-
- case FT_SM_EXIT:
- THROW_ON_ERROR(smEngineStop(engine_handle)); // Stop tracking
- stopCommand = TRUE;
- pMemData->command = 0; // Reset
- pMemData->state = SM_API_ENGINE_STATE_TERMINATED; // One last update, before quitting...
- break;
-
- case FT_SM_SET_PAR_FILTER:
- THROW_ON_ERROR(smHTV2SetHeadPoseFilterLevel(engine_handle, pMemData->par_val_int));
- pMemData->command = 0; // Reset
- break;
-
- case FT_SM_SHOW_CAM:
- THROW_ON_ERROR(smEngineShowCameraControlPanel(engine_handle));
- pMemData->command = 0; // Reset
- break;
-
- default:
- pMemData->command = 0; // Reset
- // should never be reached
- break;
- }
- }
- } // While(1)
-
- // Destroy engine
- THROW_ON_ERROR(smEngineDestroy(&engine_handle));
- // Destroy video display
- THROW_ON_ERROR(smVideoDisplayDestroy(&video_display_handle));
-
- if (ftnoirConnected) {
- if ( pMemData != NULL ) {
- UnmapViewOfFile ( pMemData );
- }
-
- if (hSMMutex != 0) {
- CloseHandle( hSMMutex );
- }
- hSMMutex = 0;
-
- if (hSMMemMap != 0) {
- CloseHandle( hSMMemMap );
- }
- hSMMemMap = 0;
- }
-
-} // run()
-
-// Application entry point
-int _tmain(int /*argc*/, _TCHAR** /*argv*/)
-{
- OutputDebugString(_T("_tmain() says: Starting Function\n"));
-
- try
- {
- if (SMCreateMapping()) {
- run();
- }
- }
- catch (exception &e)
- {
- cerr << e.what() << endl;
- }
-
- return smAPIQuit();
-}
-
-//
-// This is called exactly once for each FaceAPI callback and must be within an exclusive lock
-//
-void updateHeadPose(smEngineHeadPoseData* temp_head_pose)
-{
- //
- // Check if the pointer is OK and wait for the Mutex.
- //
- if ( (pMemData != NULL) && (WaitForSingleObject(hSMMutex, 100) == WAIT_OBJECT_0) ) {
-
- //
- // Copy the Raw measurements directly to the client.
- //
- if (temp_head_pose->confidence > 0.0f)
- {
- memcpy(&pMemData->data.new_pose,temp_head_pose,sizeof(smEngineHeadPoseData));
- }
- ReleaseMutex(hSMMutex);
- }
-};
-
-//
-// Create a memory-mapping to the faceAPI data.
-// It contains the tracking data, a command-code from FaceTrackNoIR
-//
-//
-bool SMCreateMapping()
-{
- OutputDebugString(_T("FTCreateMapping says: Starting Function\n"));
-
- //
- // A FileMapping is used to create 'shared memory' between the faceAPI and FaceTrackNoIR.
- // FaceTrackNoIR creates the mapping, this program only opens it.
- // If it's not there: the program was apparently started by the user instead of FaceTrackNoIR...
- //
- // Open an existing FileMapping, Read/Write access
- //
- hSMMemMap = OpenFileMappingA( FILE_MAP_WRITE , false , (LPCSTR) SM_MM_DATA );
- if ( ( hSMMemMap != 0 ) ) {
- ftnoirConnected = true;
- OutputDebugString(_T("FTCreateMapping says: FileMapping opened successfully...\n"));
- pMemData = (SMMemMap *) MapViewOfFile(hSMMemMap, FILE_MAP_WRITE, 0, 0, sizeof(TFaceData));
- if (pMemData != NULL) {
- OutputDebugString(_T("FTCreateMapping says: MapViewOfFile OK.\n"));
- pMemData->state = 0;
- }
- hSMMutex = CreateMutexA(NULL, false, SM_MUTEX);
- }
- else {
- OutputDebugString(_T("FTCreateMapping says: FileMapping not opened...FaceTrackNoIR not connected!\n"));
- ftnoirConnected = false;
- pMemData = 0;
- }
-
- return true;
-}
diff --git a/faceapi/mutex.h b/faceapi/mutex.h
deleted file mode 100644
index a4f84705..00000000
--- a/faceapi/mutex.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef SM_API_TESTAPPCONSOLE_MUTEX_H
-#define SM_API_TESTAPPCONSOLE_MUTEX_H
-
-#include <exception>
-
-namespace sm
-{
- namespace faceapi
- {
- namespace samplecode
- {
- // A very simple mutex class for sample code purposes.
- // It is recommended that you use the boost threads library.
- class Mutex
- {
- public:
- Mutex()
- {
- if (!InitializeCriticalSectionAndSpinCount(&_cs,0x80000400))
- {
- throw std::exception();
- }
- }
- ~Mutex()
- {
- DeleteCriticalSection(&_cs);
- }
- void lock() const
- {
- EnterCriticalSection(&_cs);
- }
- void unlock() const
- {
- LeaveCriticalSection(&_cs);
- }
- private:
- // Noncopyable
- Mutex(const Mutex &);
- Mutex &operator=(const Mutex &);
- private:
- mutable CRITICAL_SECTION _cs;
- };
- }
- }
-}
-#endif
diff --git a/faceapi/stdafx.cpp b/faceapi/stdafx.cpp
deleted file mode 100644
index b4263f59..00000000
--- a/faceapi/stdafx.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// stdafx.cpp : source file that includes just the standard includes
-// TestAppConsole.pch will be the pre-compiled header
-// stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
-
-// TODO: reference any additional headers you need in STDAFX.H
-// and not in this file
diff --git a/faceapi/stdafx.h b/faceapi/stdafx.h
deleted file mode 100644
index 1fdab0b1..00000000
--- a/faceapi/stdafx.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
-#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
-#endif
-
-#include <stdio.h>
-#include <tchar.h>
-
-#ifndef _MSC_VER
-
-#include <inttypes.h>
-
-typedef uint64_t u_int64_t;
-typedef uint32_t u_int32_t;
-typedef uint16_t u_int16_t;
-typedef uint8_t u_int8_t;
-#endif
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <cassert>
-#include <conio.h>
-#include <sm_api_configure.h>
-#ifdef SM_API
-# undef SM_API
-#endif
-#ifdef STDCALL
-# undef STDCALL
-#endif
-
-#define SM_API(type) type __declspec(dllimport) __stdcall
-#define STDCALL __stdcall
-
-#include <sm_api.h>
diff --git a/faceapi/utils.h b/faceapi/utils.h
deleted file mode 100644
index 5d25e9a7..00000000
--- a/faceapi/utils.h
+++ /dev/null
@@ -1,349 +0,0 @@
-#ifndef SM_API_TESTAPPCONSOLE_UTILS_H
-#define SM_API_TESTAPPCONSOLE_UTILS_H
-
-#include "lock.h"
-#include <exception>
-#include <iostream>
-
-#define THROW_ON_ERROR(x) \
-{ \
- smReturnCode result = (x); \
- if (result < 0) \
- { \
- std::stringstream s; \
- s << "API error code: " << result; \
- std::cerr << s; \
- throw std::exception(); \
- } \
-}
-
-namespace sm
-{
- namespace faceapi
- {
- namespace samplecode
- {
- // Global variables
- Mutex g_mutex;
- bool g_ctrl_c_detected(false);
- bool g_do_head_pose_printing(false);
- bool g_do_face_data_printing(false);
- unsigned short g_overlay_flags(SM_API_VIDEO_DISPLAY_HEAD_MESH | SM_API_VIDEO_DISPLAY_PERFORMANCE);
-
- // CTRL-C handler function
- void __cdecl CtrlCHandler(int)
- {
- Lock lock(g_mutex);
- std::cout << "Ctrl-C detected, stopping..." << std::endl;
- g_ctrl_c_detected = true;
- }
-
- // Radians to degrees conversion
- float rad2deg(float rad)
- {
- return rad*57.2957795f;
- }
-
- void toggleFlag(unsigned short &val, unsigned short flag)
- {
- if (val & flag)
- {
- val = val & ~flag;
- }
- else
- {
- val = val | flag;
- }
- }
-
- // Save an image to PNG file
- smReturnCode saveToPNGFile(const std::string& filepath, smImageInfo image_info)
- {
- smBool ok;
- smReturnCode error;
-
- // Create an API string
- smStringHandle filepath_handle = 0;
- ok = (error = smStringCreate(&filepath_handle)) == SM_API_OK;
- ok = ok && (error = smStringReadBuffer(filepath_handle,filepath.c_str(),filepath.size())) == SM_API_OK;
-
- // Create an API image
- smImageHandle image_handle = 0;
- smImageMemoryCopyMode copy_mode = SM_API_IMAGE_MEMORYCOPYMODE_AUTO;
- ok = ok && (error = smImageCreateFromInfo(&image_info,&copy_mode,&image_handle)) == SM_API_OK;
-
- // Save the image as PNG
- ok = ok && (error = smImageSaveToPNG(image_handle,filepath_handle)) == SM_API_OK;
-
- // Destroy the image and string
- smStringDestroy(&filepath_handle);
- smImageDestroy(&image_handle);
- return error;
- }
-
- // Stream operators for printing
-
- std::ostream &operator<<(std::ostream & os, const smSize2i &s)
- {
- return os << "[" << s.h << "," << s.h << "]";
- }
-
- std::ostream &operator<<(std::ostream & os, const smCoord3f &pos)
- {
- return os << "(" << pos.x << "," << pos.y << "," << pos.z << ")";
- }
-
- std::ostream &operator<<(std::ostream & os, const smRotEuler &rot)
- {
- return os << "(" << rad2deg(rot.x_rads) << "," << rad2deg(rot.y_rads) << "," << rad2deg(rot.z_rads) << ")";
- }
-
- std::ostream &operator<<(std::ostream & os, const smPixel &p)
- {
- return os << "[" << static_cast<int>(p.x) << "," << static_cast<int>(p.y) << "]";
- }
-
- std::ostream &operator<<(std::ostream & os, const smFaceTexCoord &ftc)
- {
- return os << "{" << ftc.u << "," << ftc.v << "}";
- }
-
- std::ostream &operator<<(std::ostream & os, const smFaceLandmark &lm)
- {
- return os << "id "<< lm.id << " fc" << lm.fc << " ftc" << lm.ftc << " pc" << lm.pc << " wc" << lm.wc;
- }
-
- std::ostream &operator<<(std::ostream & os, const smImageInfo &im)
- {
- os << "format ";
- switch (im.format)
- {
- case SM_API_IMAGECODE_GRAY_8U:
- os << "GRAY_8U";
- break;
- case SM_API_IMAGECODE_GRAY_16U:
- os << "GRAY_16U";
- break;
- case SM_API_IMAGECODE_YUY2:
- os << "YUY2";
- break;
- case SM_API_IMAGECODE_I420:
- os << "I420";
- break;
- case SM_API_IMAGECODE_BGRA_32U:
- os << "BGRA_32U";
- break;
- case SM_API_IMAGECODE_ARGB_32U:
- os << "ARGB_32U";
- break;
- case SM_API_IMAGECODE_BGR_24U:
- os << "BGR_24U";
- break;
- case SM_API_IMAGECODE_RGB_24U:
- os << "RGB_24U";
- break;
- default:
- os << "unknown";
- break;
- }
- os << " res" << im.res;
- os << " plane_addr(" << static_cast<void *>(im.plane_addr[0]) << ","
- << static_cast<void *>(im.plane_addr[1]) << ","
- << static_cast<void *>(im.plane_addr[2]) << ","
- << static_cast<void *>(im.plane_addr[3]) << ")";
- os << " step_bytes(" << im.step_bytes[0] << "," << im.step_bytes[1] << "," << im.step_bytes[2] << "," << im.step_bytes[3] << ")";
- os << " user_data " << im.user_data;
- return os;
- }
-
- std::ostream &operator<<(std::ostream & os, const smFaceTexture &t)
- {
- os << "type ";
- switch (t.type)
- {
- case SM_ORTHOGRAPHIC_PROJECTION:
- os << "orthographic";
- break;
- default:
- os << "unknown";
- break;
- }
- os << " origin" << t.origin << " scale" << t.scale << std::endl;
- os << " image_info " << t.image_info << std::endl;
- os << " num_mask_landmarks " << t.num_mask_landmarks << std::endl;
- for (int i=0; i<t.num_mask_landmarks; i++)
- {
- os << " " << t.mask_landmarks[i] << std::endl;
- }
- return os;
- }
-
- // Stream operator for printing face landmarks
- std::ostream &operator<<(std::ostream &os, const smEngineFaceData &face_data)
- {
- fixed(os);
- showpos(os);
- os.precision(2);
- os << "Face Data: "
- << "origin_wc" << face_data.origin_wc << " "
- << "num_landmarks " << face_data.num_landmarks
- << std::endl;
- for (int i=0; i<face_data.num_landmarks; i++)
- {
- os << " " << face_data.landmarks[i] << std::endl;
- }
- // Print any face texture info
- if (face_data.texture)
- {
- os << "Face Texture: " << *face_data.texture;
- }
- return os;
- }
-
- // Stream operator for printing head-pose data
- std::ostream &operator<<(std::ostream & os, const smEngineHeadPoseData &head_pose)
- {
- fixed(os);
- showpos(os);
- os.precision(2);
- return os << "Head Pose: "
- << "head_pos" << head_pose.head_pos << " "
- << "head_rot" << head_pose.head_rot << " "
- << "left_eye_pos" << head_pose.left_eye_pos << " "
- << "right_eye_pos" << head_pose.right_eye_pos << " "
- << "confidence " << head_pose.confidence;
- }
-
- std::ostream &operator<<(std::ostream & os, const smCameraVideoFrame &vf)
- {
- fixed(os);
- showpos(os);
- os.precision(2);
- return os << "Framenum: " << vf.frame_num;
- }
-
- // Handles keyboard events: return false if quit.
- bool processKeyPress(smEngineHandle engine_handle, smVideoDisplayHandle video_display_handle)
- {
- Lock lock(g_mutex);
- if (g_ctrl_c_detected)
- {
- return false;
- }
- if (!_kbhit())
- {
- return true;
- }
- int key = _getch();
- switch (key)
- {
- case 'q':
- return false;
- case 'r':
- {
- // Manually restart the tracking
- THROW_ON_ERROR(smEngineStart(engine_handle));
- std::cout << "Restarting tracking" << std::endl;
- }
- return true;
- case 'a':
- {
- // Toggle auto-restart mode
- int on;
- THROW_ON_ERROR(smHTGetAutoRestartMode(engine_handle,&on));
- THROW_ON_ERROR(smHTSetAutoRestartMode(engine_handle,!on));
- std::cout << "Autorestart-mode is " << (on?"on":"off") << std::endl;
- }
- return true;
- case '1':
- toggleFlag(g_overlay_flags,SM_API_VIDEO_DISPLAY_REFERENCE_FRAME);
- THROW_ON_ERROR(smVideoDisplaySetFlags(video_display_handle,g_overlay_flags));
- return true;
- case '2':
- toggleFlag(g_overlay_flags,SM_API_VIDEO_DISPLAY_PERFORMANCE);
- THROW_ON_ERROR(smVideoDisplaySetFlags(video_display_handle,g_overlay_flags));
- return true;
- case '3':
- toggleFlag(g_overlay_flags,SM_API_VIDEO_DISPLAY_HEAD_MESH);
- THROW_ON_ERROR(smVideoDisplaySetFlags(video_display_handle,g_overlay_flags));
- return true;
- case '4':
- toggleFlag(g_overlay_flags,SM_API_VIDEO_DISPLAY_LANDMARKS);
- THROW_ON_ERROR(smVideoDisplaySetFlags(video_display_handle,g_overlay_flags));
- return true;
- case 'l':
- if (smAPINonCommercialLicense() == SM_API_TRUE)
- {
- return false;
- }
- else
- {
- int on;
- THROW_ON_ERROR(smHTGetLipTrackingEnabled(engine_handle,&on));
- THROW_ON_ERROR(smHTSetLipTrackingEnabled(engine_handle,!on));
- }
- return true;
- case 'e':
- if (smAPINonCommercialLicense() == SM_API_TRUE)
- {
- return false;
- }
- else
- {
- int on;
- THROW_ON_ERROR(smHTGetEyebrowTrackingEnabled(engine_handle,&on));
- THROW_ON_ERROR(smHTSetEyebrowTrackingEnabled(engine_handle,!on));
- }
- return true;
- case 'h':
- if (smEngineIsLicensed(engine_handle) != SM_API_OK)
- {
- return false;
- }
- else
- {
- g_do_head_pose_printing = !g_do_head_pose_printing;
- std::cout << "HeadPose printing is " << (g_do_head_pose_printing?"on":"off") << std::endl;
- }
- return true;
- case 'f':
- if (smEngineIsLicensed(engine_handle) != SM_API_OK)
- {
- return false;
- }
- else
- {
- g_do_face_data_printing = !g_do_face_data_printing;
- std::cout << "FaceData printing is " << (g_do_face_data_printing?"on":"off") << std::endl;
- }
- return true;
- default:
- return true;
- }
- }
-
- // Setup console window geometry / font etc
- void initConsole()
- {
- HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
- // Buffer of 255 x 1024
- COORD buffer_size;
- buffer_size.X = 255;
- buffer_size.Y = 1024;
- SetConsoleScreenBufferSize(console_handle, buffer_size);
- // Window size of 120 x 50
- SMALL_RECT window_size;
- window_size.Left = 0;
- window_size.Right = 120;
- window_size.Top = 0;
- window_size.Bottom = 50;
- SetConsoleWindowInfo(console_handle,TRUE,&window_size);
- // Green text
- SetConsoleTextAttribute(console_handle, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
-// ShowWindow(GetConsoleWindow(), SW_HIDE);
- }
- }
- }
-}
-
-#endif
diff --git a/facetracknoir/clientfiles/FlightGear/Nasal/headtracker.xml b/facetracknoir/clientfiles/FlightGear/Nasal/headtracker.xml
deleted file mode 100644
index d8bd1d0a..00000000
--- a/facetracknoir/clientfiles/FlightGear/Nasal/headtracker.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0"?>
-
-<PropertyList>
- <nasal>
- <headtracker>
- <script>
- var Value = {
- new: func(prop) {
- var m = { parents: [Value] };
- m.prop = props.globals.getNode(prop, 1);
- m.value = 0;
- return m;
- },
- apply: func(value) {
- me.prop.setDoubleValue(me.prop.getValue() - me.value + value);
- me.value = value;
- },
- };
-
-
- var x = Value.new("/sim/current-view/x-offset-m");
- var y = Value.new("/sim/current-view/y-offset-m");
- var z = Value.new("/sim/current-view/z-offset-m");
- var h = Value.new("/sim/current-view/heading-offset-deg");
- var p = Value.new("/sim/current-view/pitch-offset-deg");
- var r = Value.new("/sim/current-view/roll-offset-deg");
-
-
- var resetting = 0;
- var status = nil;
-
- var reset = func {
- if (status != 1) {
- setprop("/sim/headtracker/control", 1);
- resetting = 1;
- view.resetViewPos();
- view.resetViewDir();
- x.value = y.value = z.value = h.value = p.value = r.value = 0;
- }
- }
-
- setlistener("/sim/headtracker/status", func(n) {
- var s = n.getValue();
- if (!status and s) {
- setprop("/sim/headtracker/control", 0);
- resetting = 0;
- }
- status = s;
- }, 1, 0);
-
-
- var loop = func {
- if (!view.index and !resetting) {
- x.apply(getprop("/sim/headtracker/x-m"));
- y.apply(getprop("/sim/headtracker/y-m"));
- z.apply(getprop("/sim/headtracker/z-m"));
-
- h.apply(getprop("/sim/headtracker/heading-deg"));
- p.apply(getprop("/sim/headtracker/pitch-deg"));
- r.apply(-1 * getprop("/sim/headtracker/roll-deg"));
- }
- settimer(loop, 0);
- }
-
- loop();
-
- </script>
- </headtracker>
- </nasal>
-
- <sim>
- <headtracker>
- <x-m type="double">0</x-m>
- <y-m type="double">0</y-m>
- <z-m type="double">0</z-m>
- <heading-deg type="double">0</heading-deg>
- <pitch-deg type="double">0</pitch-deg>
- <roll-deg type="double">0</roll-deg>
- <status type="int">0</status>
- <control type="int">0</control>
- </headtracker>
- </sim>
-</PropertyList>
diff --git a/facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml b/facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml
index cd1d0dad..8c14119a 100644
--- a/facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml
+++ b/facetracknoir/clientfiles/FlightGear/Protocol/headtracker.xml
@@ -11,57 +11,44 @@
<chunk>
<name>x</name>
<type>double</type>
- <node>/sim/headtracker/x-m</node>
+ <node>/sim/current-view/x-offset-m</node>
</chunk>
<chunk>
<name>y</name>
<type>double</type>
- <node>/sim/headtracker/y-m</node>
+ <node>/sim/current-view/y-offset-m</node>
</chunk>
<chunk>
<name>z</name>
<type>double</type>
- <node>/sim/headtracker/z-m</node>
+ <node>/sim/current-view/z-offset-m</node>
</chunk>
<chunk>
<name>heading</name>
<type>double</type>
- <node>/sim/headtracker/heading-deg</node>
+ <node>/sim/current-view/heading-offset-deg</node>
</chunk>
<chunk>
<name>pitch</name>
<type>double</type>
- <node>/sim/headtracker/pitch-deg</node>
+ <node>/sim/current-view/pitch-offset-deg</node>
</chunk>
<chunk>
<name>roll</name>
<type>double</type>
- <node>/sim/headtracker/roll-deg</node>
+ <node>/sim/current-view/roll-offset-deg</node>
</chunk>
<chunk>
<name>status</name>
<type>int</type>
- <node>/sim/headtracker/status</node>
+ <node>/sim/current-view/headtracker-debug-status</node>
</chunk>
</input>
-
- <output>
- <binary_mode>true</binary_mode>
- <binary_footer>none</binary_footer>
- <byte_order>host</byte_order>
- <record_length>4</record_length>
-
- <chunk>
- <name>control</name>
- <type>int</type>
- <node>/sim/headtracker/control</node>
- </chunk>
- </output>
</generic>
</PropertyList>
diff --git a/facetracknoir/clientfiles/FlightGear/readme.txt b/facetracknoir/clientfiles/FlightGear/readme.txt
index 75cbbcd2..0b3d9dfe 100644
--- a/facetracknoir/clientfiles/FlightGear/readme.txt
+++ b/facetracknoir/clientfiles/FlightGear/readme.txt
@@ -1,19 +1,8 @@
-FaceTrackNoIR for FlightGear.
-
-FaceTrackNoIR was made compatible with FlightGear with the help of Melchior Franz, who initially made a Linux headtracker. FaceTrackNoIR sends UDP-packets to FlightGear which contain 6DOF-data. The script and protocol provided by Melchior take care of receiving the data and moving 'the head' in-game.
-
-To make the FlightGear script work, copy the files in the subfolders to the corresponding folders in the FlightGear installation folder. Start FlightGear with the batch-file 'start_fg.bat'.
-
-
-Please let us know if you like the program, if you have ideas for improvements or any questions you might have.
-
-
-
-The FaceTrackNoIR team:
-
-Wim Vriend
-Ron Hendriks
-
-
-
-Disclaimer: For usage of 3rd party software like FlightGear, the FaceTrackNoIR team is not responsible. Use it at your own risk. \ No newline at end of file
+Copy Protocol/headtracker.xml to fgdata/Protocol/headtracker.xml
+
+$ fgfs --generic=socket,in,25,localhost,5542,udp,headtracker
+
+Adjust paths as necessary.
+
+cheers,
+-sh 20131008
diff --git a/facetracknoir/clientfiles/FlightGear/win32/start_fg.bat b/facetracknoir/clientfiles/FlightGear/win32/start_fg.bat
deleted file mode 100644
index cd9829b5..00000000
--- a/facetracknoir/clientfiles/FlightGear/win32/start_fg.bat
+++ /dev/null
@@ -1 +0,0 @@
-fgfs --generic=socket,in,25,localhost,5550,udp,headtracker --generic=socket,out,10,localhost,5551,udp,headtracker --prop:browser=/sim/headtracker "c:\Program Files\FlightGear\data\Nasal\headtracker.xml" \ No newline at end of file
diff --git a/facetracknoir/clientfiles/aruco/test3.jpg b/facetracknoir/clientfiles/aruco/test3.jpg
new file mode 100644
index 00000000..2ff6dbd0
--- /dev/null
+++ b/facetracknoir/clientfiles/aruco/test3.jpg
Binary files differ
diff --git a/facetracknoir/clientfiles/vjoy/VJoy.dll b/facetracknoir/clientfiles/vjoy/VJoy.dll
new file mode 100644
index 00000000..e3446675
--- /dev/null
+++ b/facetracknoir/clientfiles/vjoy/VJoy.dll
Binary files differ
diff --git a/facetracknoir/curve-config.cpp b/facetracknoir/curve-config.cpp
new file mode 100644
index 00000000..2bff009a
--- /dev/null
+++ b/facetracknoir/curve-config.cpp
@@ -0,0 +1,117 @@
+#include "facetracknoir/facetracknoir.h"
+#include "facetracknoir/curve-config.h"
+#include <QDebug>
+#include <QCheckBox>
+CurveConfigurationDialog::CurveConfigurationDialog(FaceTrackNoIR *ftnoir, QWidget *parent) :
+ QWidget( parent, Qt::Dialog ), mainApp(ftnoir)
+{
+ ui.setupUi( this );
+ setFont(qApp->font());
+
+ QPoint offsetpos(120, 30);
+ this->move(parent->pos() + offsetpos);
+
+ // Connect Qt signals to member-functions
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ tie_setting(mainApp->s.a_x.altp, ui.tx_altp);
+ tie_setting(mainApp->s.a_y.altp, ui.ty_altp);
+ tie_setting(mainApp->s.a_z.altp, ui.tz_altp);
+ tie_setting(mainApp->s.a_yaw.altp, ui.rx_altp);
+ tie_setting(mainApp->s.a_pitch.altp, ui.ry_altp);
+ tie_setting(mainApp->s.a_roll.altp, ui.rz_altp);
+
+ tie_setting(mainApp->s.tcomp_p, ui.tcomp_enable);
+ tie_setting(mainApp->s.tcomp_tz, ui.tcomp_rz);
+
+ tie_setting(mainApp->s.a_x.zero, ui.pos_tx);
+ tie_setting(mainApp->s.a_y.zero, ui.pos_ty);
+ tie_setting(mainApp->s.a_z.zero, ui.pos_tz);
+ tie_setting(mainApp->s.a_yaw.zero, ui.pos_rx);
+ tie_setting(mainApp->s.a_pitch.zero, ui.pos_ry);
+ tie_setting(mainApp->s.a_roll.zero, ui.pos_rz);
+
+ tie_setting(mainApp->s.a_yaw.invert, ui.chkInvertYaw);
+ tie_setting(mainApp->s.a_pitch.invert, ui.chkInvertPitch);
+ tie_setting(mainApp->s.a_roll.invert, ui.chkInvertRoll);
+ tie_setting(mainApp->s.a_x.invert, ui.chkInvertX);
+ tie_setting(mainApp->s.a_y.invert, ui.chkInvertY);
+ tie_setting(mainApp->s.a_z.invert, ui.chkInvertZ);
+
+ // Load the settings from the current .INI-file
+ loadSettings();
+}
+
+void CurveConfigurationDialog::doOK() {
+ save();
+ this->close();
+}
+
+void CurveConfigurationDialog::doCancel() {
+ mainApp->b->revert();
+ loadSettings();
+ close();
+}
+
+//
+// Load the current Settings from the currently 'active' INI-file.
+//
+void CurveConfigurationDialog::loadSettings() {
+ QFunctionConfigurator* configs[6] = {
+ ui.txconfig,
+ ui.tyconfig,
+ ui.tzconfig,
+ ui.rxconfig,
+ ui.ryconfig,
+ ui.rzconfig
+ };
+
+ QFunctionConfigurator* alt_configs[6] = {
+ ui.txconfig_alt,
+ ui.tyconfig_alt,
+ ui.tzconfig_alt,
+ ui.rxconfig_alt,
+ ui.ryconfig_alt,
+ ui.rzconfig_alt
+ };
+
+ QSettings settings("opentrack");
+ QString currentFile = settings.value("SettingsFile",
+ QCoreApplication::applicationDirPath() + "/settings/default.ini" )
+ .toString();
+
+ for (int i = 0; i < 6; i++)
+ {
+ configs[i]->setConfig(&mainApp->axis(i).curve);
+ alt_configs[i]->setConfig(&mainApp->axis(i).curveAlt);
+ }
+}
+
+//
+// Save the current Settings to the currently 'active' INI-file.
+//
+void CurveConfigurationDialog::save() {
+
+ qDebug() << "save() says: started";
+
+ QSettings settings("opentrack");
+ QString currentFile =
+ settings.value("SettingsFile",
+ QCoreApplication::applicationDirPath() + "/settings/default.ini" )
+ .toString();
+
+ ui.rxconfig->saveSettings(currentFile);
+ ui.ryconfig->saveSettings(currentFile);
+ ui.rzconfig->saveSettings(currentFile);
+ ui.txconfig->saveSettings(currentFile);
+ ui.tyconfig->saveSettings(currentFile);
+ ui.tzconfig->saveSettings(currentFile);
+
+ ui.txconfig_alt->saveSettings(currentFile);
+ ui.tyconfig_alt->saveSettings(currentFile);
+ ui.tzconfig_alt->saveSettings(currentFile);
+ ui.rxconfig_alt->saveSettings(currentFile);
+ ui.ryconfig_alt->saveSettings(currentFile);
+ ui.rzconfig_alt->saveSettings(currentFile);
+}
diff --git a/facetracknoir/curve-config.h b/facetracknoir/curve-config.h
new file mode 100644
index 00000000..0949cdc4
--- /dev/null
+++ b/facetracknoir/curve-config.h
@@ -0,0 +1,22 @@
+#pragma once
+#include <QWidget>
+#include <QPalette>
+#include "ui_ftnoir_curves.h"
+
+class FaceTrackNoIR;
+
+class CurveConfigurationDialog: public QWidget
+{
+ Q_OBJECT
+public:
+ CurveConfigurationDialog( FaceTrackNoIR *ftnoir, QWidget *parent );
+ void loadSettings();
+private:
+ Ui::UICCurveConfigurationDialog ui;
+ void save();
+ FaceTrackNoIR *mainApp;
+
+private slots:
+ void doOK();
+ void doCancel();
+};
diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp
index bb0cef11..98c8c2c2 100644
--- a/facetracknoir/facetracknoir.cpp
+++ b/facetracknoir/facetracknoir.cpp
@@ -1,1604 +1,695 @@
-/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20130101 - WVR: Added "None" to filter-listbox to remove "use advanced filtering".
- 20121209 - WVR: Pre-v170 DLLs will not be added to the Listbox. Initial selection was changed (made case-insensitive).
- 20121014 - WVR: Added second Tracker Source for Arduino solution. The two will be mutually exclusive.
- 20120929 - WVR: Disable button Filter-settings when StartTracker.
- 20120918 - WVR: When AutoStart is TRUE, the program is not directly minimized any more.
- This now depends on the AutoMinimize time. Fixed the 'not showing' of the MIB.
- Also disable combo and buttons after 'Start'.
- 20120917 - WVR: Added Mouse-buttons to ShortKeys.
- 20120717 - WVR: FunctionConfig is now used for the Curves, instead of BezierConfig.
- 20120427 - WVR: The Protocol-code was already in separate DLLs, but the ListBox was still filled 'statically'. Now, a Dir() of the
- EXE-folder is done, to locate Protocol-DLLs. The Icons were also moved to the DLLs
- 20120317 - WVR: The Filter and Tracker-code was moved to separate DLLs. The calling-method
- was changed accordingly. The save() and LoadSettings() functions were adapted.
- The face-tracker member-functions NotifyZeroed and refreshVideo were added, as
- requested by Stanislaw.
- 20110813 - WVR: Changed the presentation of the raw inputs: now a decimal digit will even show when '0'.
- 20110404 - WVR: Migrated the FlightGear protocol to a separate DLL. The rest must follow...
- 20110401 - WVR: The about-dialog was shown 'misplaced'. It was corrected.
- 20110328 - WVR: Added the display for output-pose.
- 20110207 - WVR: RadioButtons for 'Stop engine' added. It is now possible to choose Stop or Keep tracking.
- 20110109 - WVR: Added minimizeTaskBar option added. It is now possible to choose minimized or tray.
-*/
-#include "facetracknoir.h"
-#include "tracker.h"
-#include <ftnoir_tracker_ht/ht-api.h>
-#include <QDebug>
-
-#if defined(__WIN32) || defined(_WIN32)
-# include <windows.h>
-#endif
-
-#if defined(__APPLE__)
-# define SONAME "dylib"
-#elif defined(_WIN32) || defined(__WIN32)
-# define SONAME "dll"
-#else
-# define SONAME "so"
-#endif
-
-#include <iostream>
-
-#if defined(__WIN32) || defined(_WIN32)
-#undef DIRECTINPUT_VERSION
-#define DIRECTINPUT_VERSION 0x0800
-#include <dshow.h>
-#include <dinput.h>
-
-KeybindingWorkerDummy::~KeybindingWorkerDummy() {
- if (dinkeyboard) {
- dinkeyboard->Unacquire();
- dinkeyboard->Release();
- }
- if (din)
- din->Release();
-}
-
-KeybindingWorkerDummy::KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter)
-: kCenter(keyCenter), window(w), should_quit(true), din(0), dinkeyboard(0)
-{
- if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) {
- qDebug() << "setup DirectInput8 Creation failed!" << GetLastError();
- return;
- }
- if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) {
- din->Release();
- din = 0;
- qDebug() << "setup CreateDevice function failed!" << GetLastError();
- return;
- }
- if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) {
- qDebug() << "setup SetDataFormat function failed!" << GetLastError();
- dinkeyboard->Release();
- dinkeyboard = 0;
- din->Release();
- din = 0;
- return;
- }
-
- if (dinkeyboard->SetCooperativeLevel(window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) {
- dinkeyboard->Release();
- din->Release();
- din = 0;
- dinkeyboard = 0;
- qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError();
- return;
- }
- if (dinkeyboard->Acquire() != DI_OK)
- {
- dinkeyboard->Release();
- din->Release();
- din = 0;
- dinkeyboard = 0;
- qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError();
- return;
- }
- should_quit = false;
-}
-
-#define PROCESS_KEY(k, s) \
- if (isKeyPressed(&k, keystate) && (!k.ever_pressed ? (k.timer.start(), k.ever_pressed = true) : k.timer.restart() > 100)) \
- window.s();
-
-static bool isKeyPressed( const Key *key, const BYTE *keystate ) {
- bool shift;
- bool ctrl;
- bool alt;
-
- if (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) );
-
- //
- // If one of the modifiers is needed and not pressed, return false.
- //
- if (key->shift && !shift) return false;
- if (key->ctrl && !ctrl) return false;
- if (key->alt && !alt) return false;
-
- //
- // All is well!
- //
- return true;
- }
- return false;
-}
-
-void KeybindingWorkerDummy::run() {
- BYTE keystate[256];
- while (!should_quit)
- {
- if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) {
- qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError();
- Sleep(25);
- continue;
- }
-
- PROCESS_KEY(kCenter, shortcutRecentered);
-
- Sleep(25);
- }
-}
-#else
-#endif
-
-#ifdef _MSC_VER
-# define LIB_PREFIX ""
-#else
-# define LIB_PREFIX "lib"
-#endif
-
-//
-// Setup the Main Dialog
-//
-FaceTrackNoIR::FaceTrackNoIR(QWidget *parent, Qt::WFlags flags) :
- #if defined(__WIN32) || defined(_WIN32)
- keybindingWorker(NULL),
- #else
- keyCenter(0),
- #endif
- QMainWindow(parent, flags),
- pTrackerDialog(NULL),
- pSecondTrackerDialog(NULL),
- pProtocolDialog(NULL),
- pFilterDialog(NULL),
- looping(false),
- timUpdateHeadPose(this)
-{
- ui.setupUi(this);
- cameraDetected = false;
-
- //
- // Initialize Widget handles, to prevent memory-access errors.
- //
- _keyboard_shortcuts = 0;
- _curve_config = 0;
-
- tracker = 0;
-
- setupFaceTrackNoIR();
-
- //Q_INIT_RESOURCE(PoseWidget);
-
- ui.lblX->setVisible(false);
- ui.lblY->setVisible(false);
- ui.lblZ->setVisible(false);
- ui.lblRotX->setVisible(false);
- ui.lblRotY->setVisible(false);
- ui.lblRotZ->setVisible(false);
-
- ui.lcdNumOutputPosX->setVisible(false);
- ui.lcdNumOutputPosY->setVisible(false);
- ui.lcdNumOutputPosZ->setVisible(false);
- ui.lcdNumOutputRotX->setVisible(false);
- ui.lcdNumOutputRotY->setVisible(false);
- ui.lcdNumOutputRotZ->setVisible(false);
-}
-
-/** sets up all objects and connections to buttons */
-void FaceTrackNoIR::setupFaceTrackNoIR() {
- // if we simply place a global variable with THeadPoseData,
- // it gets initialized and pulls in QSettings before
- // main() starts. program can and will crash.
-
- ui.headPoseWidget->show();
- ui.video_frame->hide();
-
- // menu objects will be connected with the functions in FaceTrackNoIR class
- connect(ui.btnLoad, SIGNAL(clicked()), this, SLOT(open()));
- connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save()));
- connect(ui.btnSaveAs, SIGNAL(clicked()), this, SLOT(saveAs()));
-
- connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration()));
- connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(showKeyboardShortcuts()));
- connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings()));
- connect(ui.btnShowSecondTrackerSettings, SIGNAL(clicked()), this, SLOT(showSecondTrackerSettings()));
- connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showServerControls()));
- connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterControls()));
-
- // Connect checkboxes
- connect(ui.chkInvertYaw, SIGNAL(stateChanged(int)), this, SLOT(setInvertYaw(int)));
- connect(ui.chkInvertRoll, SIGNAL(stateChanged(int)), this, SLOT(setInvertRoll(int)));
- connect(ui.chkInvertPitch, SIGNAL(stateChanged(int)), this, SLOT(setInvertPitch(int)));
- connect(ui.chkInvertX, SIGNAL(stateChanged(int)), this, SLOT(setInvertX(int)));
- connect(ui.chkInvertY, SIGNAL(stateChanged(int)), this, SLOT(setInvertY(int)));
- connect(ui.chkInvertZ, SIGNAL(stateChanged(int)), this, SLOT(setInvertZ(int)));
-
- // button methods connect with methods in this class
- connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker()));
- connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker()));
-
- //read the camera-name, using DirectShow
- GetCameraNameDX();
-
- //Create the system-tray and connect the events for that.
- createIconGroupBox();
-
- //Load the tracker-settings, from the INI-file
- loadSettings();
-
- connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int)));
- connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int)));
- connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int)));
- connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int)));
-
- //Setup the timer for showing the headpose.
- connect(&timUpdateHeadPose, SIGNAL(timeout()), this, SLOT(showHeadPose()));
- ui.txtTracking->setVisible(false);
- settingsDirty = false;
-}
-
-/** destructor stops the engine and quits the faceapi **/
-FaceTrackNoIR::~FaceTrackNoIR() {
-
- //
- // Stop the tracker, by simulating a button-push
- //
- stopTracker();
- save();
-}
-
-//
-// Update the Settings, after a value has changed. This way, the Tracker does not have to re-start.
-//
-void FaceTrackNoIR::updateSettings() {
- if ( tracker != NULL ) {
- tracker->loadSettings();
- }
-}
-
-//
-// Get a pointer to the video-widget, to use in the DLL
-//
-QFrame *FaceTrackNoIR::get_video_widget() {
- return ui.video_frame;
-}
-
-/** read the name of the first video-capturing device at start up **/
-/** FaceAPI can only use this first one... **/
-void FaceTrackNoIR::GetCameraNameDX() {
-#if defined(_WIN32)
- ui.cameraName->setText("No video-capturing device was found in your system: check if it's connected!");
-
- // Create the System Device Enumerator.
- HRESULT hr;
- ICreateDevEnum *pSysDevEnum = NULL;
- hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
- if (FAILED(hr))
- {
- qDebug() << "GetWDM says: CoCreateInstance Failed!";
- return;
- }
-
- qDebug() << "GetWDM says: CoCreateInstance succeeded!";
-
- // Obtain a class enumerator for the video compressor category.
- IEnumMoniker *pEnumCat = NULL;
- hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
-
- if (hr == S_OK) {
- qDebug() << "GetWDM says: CreateClassEnumerator succeeded!";
-
- // Enumerate the monikers.
- IMoniker *pMoniker = NULL;
- ULONG cFetched;
- if (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) {
- IPropertyBag *pPropBag;
- hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
- if (SUCCEEDED(hr)) {
- // To retrieve the filter's friendly name, do the following:
- VARIANT varName;
- VariantInit(&varName);
- hr = pPropBag->Read(L"FriendlyName", &varName, 0);
- if (SUCCEEDED(hr))
- {
- // Display the name in your UI somehow.
- QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal));
- qDebug() << "GetWDM says: Moniker found:" << str;
- ui.cameraName->setText(str);
- }
- VariantClear(&varName);
-
- ////// To create an instance of the filter, do the following:
- ////IBaseFilter *pFilter;
- ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
- //// (void**)&pFilter);
- // Now add the filter to the graph.
- //Remember to release pFilter later.
- pPropBag->Release();
- }
- pMoniker->Release();
- }
- pEnumCat->Release();
- }
- pSysDevEnum->Release();
-#endif
-}
-
-//
-// Open an INI-file with the QFileDialog
-// If succesfull, the settings in it will be read
-//
-void FaceTrackNoIR::open() {
- QFileDialog dialog(this);
- dialog.setFileMode(QFileDialog::ExistingFile);
-
- QString fileName = dialog.getOpenFileName(
- this,
- tr("Select one FTNoir settings file"),
- QCoreApplication::applicationDirPath() + "/Settings/",
- tr("Settings file (*.ini);;All Files (*)"),
- NULL);
-
- //
- // If a file was selected, save it's name and read it's contents.
- //
- if (! fileName.isEmpty() ) {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath());
- loadSettings();
- }
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FaceTrackNoIR::save() {
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "Tracking" );
- iniFile.setValue ( "invertYaw", ui.chkInvertYaw->isChecked() );
- iniFile.setValue ( "invertPitch", ui.chkInvertPitch->isChecked() );
- iniFile.setValue ( "invertRoll", ui.chkInvertRoll->isChecked() );
- iniFile.setValue ( "invertX", ui.chkInvertX->isChecked() );
- iniFile.setValue ( "invertY", ui.chkInvertY->isChecked() );
- iniFile.setValue ( "invertZ", ui.chkInvertZ->isChecked() );
- iniFile.endGroup ();
-
- iniFile.beginGroup ( "GameProtocol" );
- {
- DynamicLibrary* proto = dlopen_protocols.value( ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL);
- iniFile.setValue ( "DLL", proto == NULL ? "" : proto->filename);
- }
- iniFile.endGroup ();
-
- iniFile.beginGroup ( "TrackerSource" );
- {
- DynamicLibrary* tracker = dlopen_trackers.value( ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
- iniFile.setValue ( "DLL", tracker == NULL ? "" : tracker->filename);
- }
- {
- DynamicLibrary* tracker = dlopen_trackers.value( ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL);
- iniFile.setValue ( "2ndDLL", tracker == NULL ? "" : tracker->filename);
- }
- iniFile.endGroup ();
-
- //
- // Save the name of the filter in the INI-file.
- //
- iniFile.beginGroup ( "Filter" );
- {
- DynamicLibrary* filter = dlopen_filters.value( ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
- iniFile.setValue ( "DLL", filter == NULL ? "" : filter->filename);
- }
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Get the new name of the INI-file and save the settings to it.
-//
-// The user may choose to overwrite an existing file. This will be deleted, before copying the current file to it.
-//
-void FaceTrackNoIR::saveAs()
-{
- //
- // Get the current filename of the INI-file.
- //
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
-
- //
- // Get the new filename of the INI-file.
- //
- QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"),
- oldFile,
-// QCoreApplication::applicationDirPath() + "/Settings",
- tr("Settings file (*.ini);;All Files (*)"));
- if (!fileName.isEmpty()) {
-
- //
- // Remove the file, if it already exists.
- //
- QFileInfo newFileInfo ( fileName );
- if ((newFileInfo.exists()) && (oldFile != fileName)) {
- QFile newFileFile ( fileName );
- newFileFile.remove();
- }
-
- //
- // Copy the current INI-file to the new name.
- //
- QFileInfo oldFileInfo ( oldFile );
- if (oldFileInfo.exists()) {
- QFile oldFileFile ( oldFile );
- oldFileFile.copy( fileName );
- }
-
- //
- // Write the new name to the Registry and save the other INI-values.
- //
- settings.setValue ("SettingsFile", fileName);
- save();
-
- //
- // Reload the settings, to get the GUI right again...
- //
- loadSettings();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FaceTrackNoIR::loadSettings() {
- looping = true;
- qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- qDebug() << "Config file now" << currentFile;
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- //
- // Put the filename in the window-title.
- //
- QFileInfo pathInfo ( currentFile );
- setWindowTitle ( "opentrack (1.8 alpha) - " + pathInfo.fileName() );
-
- //
- // Get a List of all the INI-files in the (currently active) Settings-folder.
- //
- QDir settingsDir( pathInfo.dir() );
- QStringList filters;
- filters << "*.ini";
- iniFileList.clear();
- iniFileList = settingsDir.entryList( filters, QDir::Files, QDir::Name );
-
- //
- // Add strings to the Listbox.
- //
- ui.iconcomboProfile->clear();
- for ( int i = 0; i < iniFileList.size(); i++) {
- ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), iniFileList.at(i));
- if (iniFileList.at(i) == pathInfo.fileName()) {
- ui.iconcomboProfile->setItemIcon(i, QIcon(":/images/settingsopen16.png"));
- ui.iconcomboProfile->setCurrentIndex( i );
- }
- }
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Tracking" );
- ui.chkInvertYaw->setChecked (iniFile.value ( "invertYaw", 0 ).toBool());
- ui.chkInvertPitch->setChecked (iniFile.value ( "invertPitch", 0 ).toBool());
- ui.chkInvertRoll->setChecked (iniFile.value ( "invertRoll", 0 ).toBool());
- ui.chkInvertX->setChecked (iniFile.value ( "invertX", 0 ).toBool());
- ui.chkInvertY->setChecked (iniFile.value ( "invertY", 0 ).toBool());
- ui.chkInvertZ->setChecked (iniFile.value ( "invertZ", 0 ).toBool());
- iniFile.endGroup ();
-
- // Read the currently selected Protocol from the INI-file.
- // If the setting "DLL" isn't found (pre-1.7 version of INI), then the setting 'Selection' is evaluated.
- //
- iniFile.beginGroup ( "GameProtocol" );
- QString selectedProtocolName = iniFile.value ( "DLL", "" ).toString();
- iniFile.endGroup ();
-
- //
- // Find the Index of the DLL and set the selection.
- //
- for ( int i = 0; i < dlopen_protocols.size(); i++) {
- if (dlopen_protocols.at(i)->filename.compare( selectedProtocolName, Qt::CaseInsensitive ) == 0) {
- ui.iconcomboProtocol->setCurrentIndex( i );
- break;
- }
- }
-
- //
- // Read the currently selected Tracker from the INI-file.
- // If the setting "DLL" isn't found (pre-1.7 version), then the setting 'Selection' is evaluated.
- //
- iniFile.beginGroup ( "TrackerSource" );
- QString selectedTrackerName = iniFile.value ( "DLL", "" ).toString();
- qDebug() << "loadSettings says: selectedTrackerName = " << selectedTrackerName;
- QString secondTrackerName = iniFile.value ( "2ndDLL", "None" ).toString();
- qDebug() << "loadSettings says: secondTrackerName = " << secondTrackerName;
- iniFile.endGroup ();
-
- for ( int i = 0; i < dlopen_trackers.size(); i++) {
- DynamicLibrary* foo = dlopen_trackers.at(i);
- if (foo && foo->filename.compare( selectedTrackerName, Qt::CaseInsensitive ) == 0) {
- ui.iconcomboTrackerSource->setCurrentIndex( i );
- }
- if (foo && foo->filename.compare( secondTrackerName, Qt::CaseInsensitive ) == 0) {
- ui.cbxSecondTrackerSource->setCurrentIndex( i + 1 );
- }
- }
-
- //
- // Read the currently selected Filter from the INI-file.
- //
- iniFile.beginGroup ( "Filter" );
- QString selectedFilterName = iniFile.value ( "DLL", "" ).toString();
- qDebug() << "createIconGroupBox says: selectedFilterName = " << selectedFilterName;
- iniFile.endGroup ();
-
- //
- // Find the Index of the DLL and set the selection.
- //
- for ( int i = 0; i < dlopen_filters.size(); i++) {
- DynamicLibrary* foo = dlopen_filters.at(i);
- if (foo && foo->filename.compare( selectedFilterName, Qt::CaseInsensitive ) == 0) {
- ui.iconcomboFilter->setCurrentIndex( i );
- break;
- }
- }
-
- settingsDirty = false;
- looping = false;
-}
-
-/** start tracking the face **/
-void FaceTrackNoIR::startTracker( ) {
- bindKeyboardShortcuts();
-
- //
- // Disable buttons
- //
- ui.iconcomboProfile->setEnabled ( false );
- ui.btnLoad->setEnabled ( false );
- ui.btnSave->setEnabled ( false );
- ui.btnSaveAs->setEnabled ( false );
- ui.btnShowFilterControls->setEnabled ( false );
-
- //
- // Create the Tracker and setup
- //
-
- if (Libraries)
- delete Libraries;
- Libraries = new SelectedLibraries(this);
-
- if (!Libraries->correct)
- {
- QMessageBox::warning(this, "Something went wrong", "Tracking can't be initialized, probably protocol prerequisites missing", QMessageBox::Ok, QMessageBox::NoButton);
- stopTracker();
- return;
- }
-
-#if defined(_WIN32) || defined(__WIN32)
- keybindingWorker = new KeybindingWorker(*this, keyCenter);
- keybindingWorker->start();
-#endif
-
- if (tracker) {
- tracker->wait();
- delete tracker;
- }
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- for (int i = 0; i < 6; i++)
- {
- axis(i).curve.loadSettings(iniFile);
- axis(i).curveAlt.loadSettings(iniFile);
- }
-
- static const char* names[] = {
- "tx_alt",
- "ty_alt",
- "tz_alt",
- "rx_alt",
- "ry_alt",
- "rz_alt",
- };
-
- static const char* invert_names[] = {
- "invertX",
- "invertY",
- "invertZ",
- "invertYaw",
- "invertPitch",
- "invertRoll"
- };
-
- iniFile.beginGroup("Tracking");
-
- for (int i = 0; i < 6; i++) {
- axis(i).altp = iniFile.value(names[i], false).toBool();
- axis(i).invert = iniFile.value(invert_names[i], false).toBool() ? 1 : -1;
- }
-
- iniFile.endGroup();
-
- tracker = new Tracker ( this );
-
- //
- // Setup the Tracker and send the settings.
- // This is necessary, because the events are only triggered 'on change'
- //
- tracker->setInvertAxis(Yaw, ui.chkInvertYaw->isChecked() );
- tracker->setInvertAxis(Pitch, ui.chkInvertPitch->isChecked() );
- tracker->setInvertAxis(Roll, ui.chkInvertRoll->isChecked() );
- tracker->setInvertAxis(TX, ui.chkInvertX->isChecked() );
- tracker->setInvertAxis(TY, ui.chkInvertY->isChecked() );
- tracker->setInvertAxis(TZ, ui.chkInvertZ->isChecked() );
-
- tracker->start();
-
- //
- // Register the Tracker instance with the Tracker Dialog (if open)
- //
- if (pTrackerDialog && Libraries->pTracker) {
- pTrackerDialog->registerTracker( Libraries->pTracker );
- }
-
- ui.headPoseWidget->show();
-
- //
- ui.btnStartTracker->setEnabled ( false );
- ui.btnStopTracker->setEnabled ( true );
-
- // Enable/disable Protocol-server Settings
- ui.iconcomboTrackerSource->setEnabled ( false );
- ui.cbxSecondTrackerSource->setEnabled ( false );
- ui.iconcomboProtocol->setEnabled ( false );
- ui.btnShowServerControls->setEnabled ( false );
- ui.iconcomboFilter->setEnabled ( false );
-
- //
- // Update the camera-name, FaceAPI can only use the 1st one found!
- //
- GetCameraNameDX();
-
- //
- // Start the timer to update the head-pose (digits and 'man in black')
- //
- timUpdateHeadPose.start(40);
-
- ui.lblX->setVisible(true);
- ui.lblY->setVisible(true);
- ui.lblZ->setVisible(true);
- ui.lblRotX->setVisible(true);
- ui.lblRotY->setVisible(true);
- ui.lblRotZ->setVisible(true);
-
- ui.lcdNumOutputPosX->setVisible(true);
- ui.lcdNumOutputPosY->setVisible(true);
- ui.lcdNumOutputPosZ->setVisible(true);
- ui.lcdNumOutputRotX->setVisible(true);
- ui.lcdNumOutputRotY->setVisible(true);
- ui.lcdNumOutputRotZ->setVisible(true);
-}
-
-/** stop tracking the face **/
-void FaceTrackNoIR::stopTracker( ) {
- ui.game_name->setText("Not connected");
-#if defined(_WIN32) || defined(__WIN32)
- if (keybindingWorker)
- {
- keybindingWorker->should_quit = true;
- keybindingWorker->wait();
- delete keybindingWorker;
- keybindingWorker = NULL;
- }
-#endif
- //
- // Stop displaying the head-pose.
- //
- timUpdateHeadPose.stop();
- ui.pose_display->rotateBy(0, 0, 0);
-
- ui.lblX->setVisible(false);
- ui.lblY->setVisible(false);
- ui.lblZ->setVisible(false);
- ui.lblRotX->setVisible(false);
- ui.lblRotY->setVisible(false);
- ui.lblRotZ->setVisible(false);
-
- ui.lcdNumOutputPosX->setVisible(false);
- ui.lcdNumOutputPosY->setVisible(false);
- ui.lcdNumOutputPosZ->setVisible(false);
- ui.lcdNumOutputRotX->setVisible(false);
- ui.lcdNumOutputRotY->setVisible(false);
- ui.lcdNumOutputRotZ->setVisible(false);
- ui.txtTracking->setVisible(false);
-
- //
- // Delete the tracker (after stopping things and all).
- //
- if ( tracker ) {
- qDebug() << "Done with tracking";
- tracker->should_quit = true;
- tracker->wait();
-
- qDebug() << "stopTracker says: Deleting tracker!";
- delete tracker;
- qDebug() << "stopTracker says: Tracker deleted!";
- tracker = 0;
- if (Libraries) {
- delete Libraries;
- Libraries = NULL;
- }
- }
-
- //
- // UnRegister the Tracker instance with the Tracker Dialog (if open)
- //
- if (pTrackerDialog) {
- pTrackerDialog->unRegisterTracker();
- }
- if (pProtocolDialog) {
- pProtocolDialog->unRegisterProtocol();
- }
- ui.btnStartTracker->setEnabled ( true );
- ui.btnStopTracker->setEnabled ( false );
-// ui.btnShowEngineControls->setEnabled ( false );
- ui.iconcomboProtocol->setEnabled ( true );
- ui.iconcomboTrackerSource->setEnabled ( true );
- ui.cbxSecondTrackerSource->setEnabled ( true );
- ui.iconcomboFilter->setEnabled ( true );
-
- // Enable/disable Protocol-server Settings
- ui.btnShowServerControls->setEnabled ( true );
- ui.video_frame->hide();
-
- //
- ui.iconcomboProfile->setEnabled ( true );
- ui.btnLoad->setEnabled ( true );
- ui.btnSave->setEnabled ( true );
- ui.btnSaveAs->setEnabled ( true );
- ui.btnShowFilterControls->setEnabled ( true );
-}
-
-/** set the invert from the checkbox **/
-void FaceTrackNoIR::setInvertAxis(Axis axis, int invert ) {
- if (tracker)
- tracker->setInvertAxis (axis, (invert != 0)?true:false );
- settingsDirty = true;
-}
-
-/** Show the headpose in the widget (triggered by timer) **/
-void FaceTrackNoIR::showHeadPose() {
- double newdata[6];
-
- ui.lblX->setVisible(true);
- ui.lblY->setVisible(true);
- ui.lblZ->setVisible(true);
- ui.lblRotX->setVisible(true);
- ui.lblRotY->setVisible(true);
- ui.lblRotZ->setVisible(true);
-
- ui.lcdNumOutputPosX->setVisible(true);
- ui.lcdNumOutputPosY->setVisible(true);
- ui.lcdNumOutputPosZ->setVisible(true);
- ui.lcdNumOutputRotX->setVisible(true);
- ui.lcdNumOutputRotY->setVisible(true);
- ui.lcdNumOutputRotZ->setVisible(true);
-
- //
- // Get the pose and also display it.
- // Updating the pose from within the Tracker-class caused crashes...
- //
- tracker->getHeadPose(newdata);
- ui.lcdNumX->display(QString("%1").arg(newdata[TX], 0, 'f', 1));
- ui.lcdNumY->display(QString("%1").arg(newdata[TY], 0, 'f', 1));
- ui.lcdNumZ->display(QString("%1").arg(newdata[TZ], 0, 'f', 1));
-
-
- ui.lcdNumRotX->display(QString("%1").arg(newdata[Yaw], 0, 'f', 1));
- ui.lcdNumRotY->display(QString("%1").arg(newdata[Pitch], 0, 'f', 1));
- ui.lcdNumRotZ->display(QString("%1").arg(newdata[Roll], 0, 'f', 1));
-
- ui.txtTracking->setVisible(tracker->getTrackingActive());
-
- //
- // Get the output-pose and also display it.
- //
- tracker->getOutputHeadPose(newdata);
-
- ui.pose_display->rotateBy(newdata[Yaw], newdata[Roll], newdata[Pitch]);
-
- ui.lcdNumOutputPosX->display(QString("%1").arg(newdata[TX], 0, 'f', 1));
- ui.lcdNumOutputPosY->display(QString("%1").arg(newdata[TY], 0, 'f', 1));
- ui.lcdNumOutputPosZ->display(QString("%1").arg(newdata[TZ], 0, 'f', 1));
-
-
- ui.lcdNumOutputRotX->display(QString("%1").arg(newdata[Yaw], 0, 'f', 1));
- ui.lcdNumOutputRotY->display(QString("%1").arg(newdata[Pitch], 0, 'f', 1));
- ui.lcdNumOutputRotZ->display(QString("%1").arg(newdata[Roll], 0, 'f', 1));
-
- //
- // Update the curves in the curve-configurator. This shows the ball with the red lines.
- //
- if (_curve_config) {
- _curve_config->update();
- }
- if (Libraries->pProtocol)
- {
- QString name = Libraries->pProtocol->getGameName();
- ui.game_name->setText(name);
- }
-}
-
-/** toggles Video Widget **/
-void FaceTrackNoIR::showVideoWidget() {
- if(ui.video_frame->isHidden())
- ui.video_frame->show();
- else
- ui.video_frame->hide();
-}
-
-/** toggles Video Widget **/
-void FaceTrackNoIR::showHeadPoseWidget() {
- if(ui.headPoseWidget->isHidden())
- ui.headPoseWidget->show();
- else
- ui.headPoseWidget->hide();
-}
-
-/** toggles Engine Controls Dialog **/
-void FaceTrackNoIR::showTrackerSettings() {
- if (pTrackerDialog) {
- delete pTrackerDialog;
- pTrackerDialog = NULL;
- }
-
- DynamicLibrary* lib = dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
-
- if (lib) {
- pTrackerDialog = (ITrackerDialog*) lib->Dialog();
- if (pTrackerDialog) {
- pTrackerDialog->Initialize(this);
- if (Libraries && Libraries->pTracker)
- pTrackerDialog->registerTracker(Libraries->pTracker);
- }
- }
-}
-
-// Show the Settings dialog for the secondary Tracker
-void FaceTrackNoIR::showSecondTrackerSettings() {
- if (pSecondTrackerDialog) {
- delete pSecondTrackerDialog;
- pSecondTrackerDialog = NULL;
- }
-
- DynamicLibrary* lib = dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL);
-
- if (lib) {
- pSecondTrackerDialog = (ITrackerDialog*) lib->Dialog();
- if (pSecondTrackerDialog) {
- pSecondTrackerDialog->Initialize(this);
- if (Libraries && Libraries->pSecondTracker)
- pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker);
- }
- }
-}
-
-/** toggles Server Controls Dialog **/
-void FaceTrackNoIR::showServerControls() {
- if (pProtocolDialog) {
- delete pProtocolDialog;
- pProtocolDialog = NULL;
- }
-
- DynamicLibrary* lib = dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL);
-
- if (lib && lib->Dialog) {
- pProtocolDialog = (IProtocolDialog*) lib->Dialog();
- if (pProtocolDialog) {
- pProtocolDialog->Initialize(this);
- }
- }
-}
-
-/** toggles Filter Controls Dialog **/
-void FaceTrackNoIR::showFilterControls() {
- if (pFilterDialog) {
- delete pFilterDialog;
- pFilterDialog = NULL;
- }
-
- DynamicLibrary* lib = dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
-
- if (lib && lib->Dialog) {
- pFilterDialog = (IFilterDialog*) lib->Dialog();
- if (pFilterDialog) {
- pFilterDialog->Initialize(this, Libraries ? Libraries->pFilter : NULL);
- }
- }
-}
-/** toggles Keyboard Shortcut Dialog **/
-void FaceTrackNoIR::showKeyboardShortcuts() {
-
- // Create if new
- if (!_keyboard_shortcuts)
- {
- _keyboard_shortcuts = new KeyboardShortcutDialog( this, this, Qt::Dialog );
- }
-
- // Show if already created
- if (_keyboard_shortcuts) {
- _keyboard_shortcuts->show();
- _keyboard_shortcuts->raise();
- }
-}
-
-/** toggles Curve Configuration Dialog **/
-void FaceTrackNoIR::showCurveConfiguration() {
-
- // Create if new
- if (!_curve_config)
- {
- _curve_config = new CurveConfigurationDialog( this, this, Qt::Dialog );
- }
-
- // Show if already created
- if (_curve_config) {
- _curve_config->show();
- _curve_config->raise();
- }
-}
-
-/** exit application **/
-void FaceTrackNoIR::exit() {
- QCoreApplication::exit(0);
-}
-
-//
-// Setup the icons for the comboBoxes
-//
-void FaceTrackNoIR::createIconGroupBox()
-{
- QDir settingsDir( QCoreApplication::applicationDirPath() );
-
- {
- QStringList protocols = settingsDir.entryList( QStringList() << (LIB_PREFIX "opentrack-proto-*." SONAME), QDir::Files, QDir::Name );
- for ( int i = 0; i < protocols.size(); i++) {
- QIcon icon;
- QString longName;
- QString str = protocols.at(i);
- DynamicLibrary* lib = new DynamicLibrary(str);
- qDebug() << "Loading" << str;
- std::cout.flush();
- Metadata* meta;
- if (!lib->Metadata || ((meta = lib->Metadata()), !meta))
- {
- delete lib;
- continue;
- }
- meta->getFullName(&longName);
- meta->getIcon(&icon);
- delete meta;
- dlopen_protocols.push_back(lib);
- ui.iconcomboProtocol->addItem(icon, longName);
- }
- }
-
- {
- ui.cbxSecondTrackerSource->addItem(QIcon(), "None");
- QStringList trackers = settingsDir.entryList( QStringList() << (LIB_PREFIX "opentrack-tracker-*." SONAME), QDir::Files, QDir::Name );
- for ( int i = 0; i < trackers.size(); i++) {
- QIcon icon;
- QString longName;
- QString str = trackers.at(i);
- DynamicLibrary* lib = new DynamicLibrary(str);
- qDebug() << "Loading" << str;
- std::cout.flush();
- Metadata* meta;
- if (!lib->Metadata || ((meta = lib->Metadata()), !meta))
- {
- delete lib;
- continue;
- }
- meta->getFullName(&longName);
- meta->getIcon(&icon);
- delete meta;
- dlopen_trackers.push_back(lib);
- ui.iconcomboTrackerSource->addItem(icon, longName);
- ui.cbxSecondTrackerSource->addItem(icon, longName);
- }
- }
-
- {
- dlopen_filters.push_back((DynamicLibrary*) NULL);
- ui.iconcomboFilter->addItem(QIcon(), "None");
- QStringList filters = settingsDir.entryList( QStringList() << (LIB_PREFIX "opentrack-filter-*." SONAME), QDir::Files, QDir::Name );
- for ( int i = 0; i < filters.size(); i++) {
- QIcon icon;
- QString fullName;
- QString str = filters.at(i);
- DynamicLibrary* lib = new DynamicLibrary(str);
- qDebug() << "Loading" << str;
- std::cout.flush();
- Metadata* meta;
- if (!lib->Metadata || ((meta = lib->Metadata()), !meta))
- {
- delete lib;
- continue;
- }
- meta->getFullName(&fullName);
- meta->getIcon(&icon);
- delete meta;
- dlopen_filters.push_back(lib);
- ui.iconcomboFilter->addItem(icon, fullName);
- }
- }
-
- connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int)));
- connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int)));
- connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int)));
- connect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int)));
-}
-
-//
-// Handle changes of the Protocol selection
-//
-void FaceTrackNoIR::protocolSelected(int index)
-{
- settingsDirty = true;
- ui.btnShowServerControls->setEnabled ( true );
-
- //setWindowIcon(QIcon(":/images/FaceTrackNoIR.png"));
- //breaks with transparency -sh
- //ui.btnShowServerControls->setIcon(icon);]
-}
-
-//
-// Handle changes of the Tracking Source selection
-//
-void FaceTrackNoIR::trackingSourceSelected(int index)
-{
- settingsDirty = true;
- ui.btnShowEngineControls->setEnabled ( true );
-}
-
-//
-// Handle changes of the Profile selection
-//
-void FaceTrackNoIR::profileSelected(int index)
-{
- if (looping)
- return;
- //
- // Read the current INI-file setting, to get the folder in which it's located...
- //
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QFileInfo pathInfo ( currentFile );
-
- //
- // Save the name of the INI-file in the Registry.
- //
- settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + iniFileList.value(ui.iconcomboProfile->currentIndex(), ""));
- loadSettings();
-}
-
-//
-// Handle changes of the Filter selection
-//
-void FaceTrackNoIR::filterSelected(int index)
-{
- settingsDirty = true;
-
- //QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- //QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- //QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- ui.btnShowFilterControls->setEnabled ( true );
-}
-
-//**************************************************************************************************//
-//**************************************************************************************************//
-//
-// Constructor for Keyboard-shortcuts-dialog
-//
-KeyboardShortcutDialog::KeyboardShortcutDialog( FaceTrackNoIR *ftnoir, QWidget *parent, Qt::WindowFlags f ) :
-QWidget( parent , f)
-{
- ui.setupUi( this );
-
- QPoint offsetpos(100, 100);
- this->move(parent->pos() + offsetpos);
-
- mainApp = ftnoir; // Preserve a pointer to FTNoIR
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
-
- connect(ui.cbxCenterKey, SIGNAL(currentIndexChanged(int)), this, SLOT(keyChanged( int )));
- connect(ui.chkCenterShift, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int)));
- connect(ui.chkCenterCtrl, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int)));
- connect(ui.chkCenterAlt, SIGNAL(stateChanged(int)), this, SLOT(keyChanged(int)));
-
- // Clear the Lists with key-descriptions and keycodes and build the Lists
- // The strings will all be added to the ListBoxes for each Shortkey
- //
-
- // Add strings to the Listboxes.
- //
-
- for ( int i = 0; i < global_key_sequences.size(); i++) {
- ui.cbxCenterKey->addItem(global_key_sequences.at(i));
- }
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-KeyboardShortcutDialog::~KeyboardShortcutDialog() {
- qDebug() << "~KeyboardShortcutDialog() says: started";
-}
-
-//
-// OK clicked on server-dialog
-//
-void KeyboardShortcutDialog::doOK() {
- save();
- this->close();
- mainApp->bindKeyboardShortcuts();
-}
-
-// override show event
-void KeyboardShortcutDialog::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void KeyboardShortcutDialog::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-void FaceTrackNoIR::bindKeyboardShortcuts()
-{
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
- iniFile.beginGroup ( "KB_Shortcuts" );
- int idxCenter = iniFile.value("Key_index_Center", 0).toInt();
-
-#if !defined(_WIN32) && !defined(__WIN32)
- if (keyCenter) {
- delete keyCenter;
- keyCenter = NULL;
- }
-
- if (idxCenter > 0)
- {
- QString seq(global_key_sequences.value(idxCenter, ""));
- if (!seq.isEmpty())
- {
- if (iniFile.value("Shift_Center", false).toBool())
- seq = "Shift+" + seq;
- if (iniFile.value("Alt_Center", false).toBool())
- seq = "Alt+" + seq;
- if (iniFile.value("Ctrl_Center", false).toBool())
- seq = "Ctrl+" + seq;
- keyCenter = new QxtGlobalShortcut(QKeySequence(seq));
- connect(keyCenter, SIGNAL(activated()), this, SLOT(shortcutRecentered()));
- }
- }
-
-#else
- keyCenter.keycode = 0;
- keyCenter.shift = keyCenter.alt = keyCenter.ctrl = 0;
- if (idxCenter > 0 && idxCenter < global_windows_key_sequences.size())
- keyCenter.keycode = global_windows_key_sequences[idxCenter];
- keyCenter.shift = iniFile.value("Shift_Center", false).toBool();
- keyCenter.alt = iniFile.value("Alt_Center", false).toBool();
- keyCenter.ctrl = iniFile.value("Ctrl_Center", false).toBool();
-#endif
- iniFile.endGroup ();
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void KeyboardShortcutDialog::loadSettings() {
- qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "KB_Shortcuts" );
-
- ui.chkCenterShift->setChecked (iniFile.value ( "Shift_Center", 0 ).toBool());
- ui.chkCenterCtrl->setChecked (iniFile.value ( "Ctrl_Center", 0 ).toBool());
- ui.chkCenterAlt->setChecked (iniFile.value ( "Alt_Center", 0 ).toBool());
-
- ui.cbxCenterKey->setCurrentIndex(iniFile.value("Key_index_Center", 0).toInt());
-
- iniFile.endGroup ();
-
- settingsDirty = false;
-
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void KeyboardShortcutDialog::save() {
-
- qDebug() << "save() says: started";
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "KB_Shortcuts" );
- iniFile.setValue ( "Key_index_Center", ui.cbxCenterKey->currentIndex() );
- iniFile.setValue ( "Shift_Center", ui.chkCenterShift->isChecked() );
- iniFile.setValue ( "Ctrl_Center", ui.chkCenterCtrl->isChecked() );
- iniFile.setValue ( "Alt_Center", ui.chkCenterAlt->isChecked() );
-
- iniFile.endGroup ();
-
- settingsDirty = false;
-
- //
- // Send a message to the main program, to update the Settings (for the tracker)
- //
- mainApp->updateSettings();
-}
-
-//**************************************************************************************************//
-//**************************************************************************************************//
-//
-// Constructor for Curve-configuration-dialog
-//
-CurveConfigurationDialog::CurveConfigurationDialog( FaceTrackNoIR *ftnoir, QWidget *parent, Qt::WindowFlags f ) :
-QWidget( parent , f)
-{
- ui.setupUi( this );
-
- QPoint offsetpos(120, 30);
- this->move(parent->pos() + offsetpos);
-
- mainApp = ftnoir; // Preserve a pointer to FTNoIR
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
-
- QFunctionConfigurator* configs[6] = {
- ui.txconfig,
- ui.tyconfig,
- ui.tzconfig,
- ui.rxconfig,
- ui.ryconfig,
- ui.rzconfig
- };
-
- QFunctionConfigurator* alt_configs[6] = {
- ui.txconfig_alt,
- ui.tyconfig_alt,
- ui.tzconfig_alt,
- ui.rxconfig_alt,
- ui.ryconfig_alt,
- ui.rzconfig_alt
- };
-
- QCheckBox* checkboxes[6] = {
- ui.rx_altp,
- ui.ry_altp,
- ui.rz_altp,
- ui.tx_altp,
- ui.ty_altp,
- ui.tz_altp
- };
-
- for (int i = 0; i < 6; i++)
- {
- configs[i]->setConfig(&mainApp->axis(i).curve, currentFile);
- alt_configs[i]->setConfig(&mainApp->axis(i).curveAlt, currentFile);
- connect(configs[i], SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool)));
- connect(alt_configs[i], SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool)));
- connect(checkboxes[i], SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int)));
- }
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-CurveConfigurationDialog::~CurveConfigurationDialog() {
- qDebug() << "~CurveConfigurationDialog() says: started";
-}
-
-//
-// OK clicked on server-dialog
-//
-void CurveConfigurationDialog::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void CurveConfigurationDialog::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void CurveConfigurationDialog::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void CurveConfigurationDialog::loadSettings() {
- qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- static const char* names[] = {
- "tx_alt",
- "ty_alt",
- "tz_alt",
- "rx_alt",
- "ry_alt",
- "rz_alt"
- };
-
- iniFile.beginGroup("Tracking");
-
- for (int i = 0; i < 6; i++)
- mainApp->axis(i).altp = iniFile.value(names[i], false).toBool();
-
- QCheckBox* widgets[] = {
- ui.tx_altp,
- ui.ty_altp,
- ui.tz_altp,
- ui.rx_altp,
- ui.ry_altp,
- ui.rz_altp
- };
-
- for (int i = 0; i < 6; i++)
- widgets[i]->setChecked(mainApp->axis(i).altp);
-
- QDoubleSpinBox* widgets2[] = {
- ui.pos_tx,
- ui.pos_ty,
- ui.pos_tz,
- ui.pos_tx,
- ui.pos_ry,
- ui.pos_rz
- };
-
- const char* names2[] = {
- "zero_tx",
- "zero_ty",
- "zero_tz",
- "zero_rx",
- "zero_ry",
- "zero_rz"
- };
-
- for (int i = 0; i < 6; i++)
- widgets2[i]->setValue(iniFile.value(names2[i], 0).toDouble());
-
- iniFile.endGroup();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void CurveConfigurationDialog::save() {
-
- qDebug() << "save() says: started";
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
-
- ui.rxconfig->saveSettings(currentFile);
- ui.ryconfig->saveSettings(currentFile);
- ui.rzconfig->saveSettings(currentFile);
- ui.txconfig->saveSettings(currentFile);
- ui.tyconfig->saveSettings(currentFile);
- ui.tzconfig->saveSettings(currentFile);
-
- ui.txconfig_alt->saveSettings(currentFile);
- ui.tyconfig_alt->saveSettings(currentFile);
- ui.tzconfig_alt->saveSettings(currentFile);
- ui.rxconfig_alt->saveSettings(currentFile);
- ui.ryconfig_alt->saveSettings(currentFile);
- ui.rzconfig_alt->saveSettings(currentFile);
-
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup("Tracking");
-
- iniFile.setValue("rx_alt", ui.rx_altp->checkState() != Qt::Unchecked);
- iniFile.setValue("ry_alt", ui.ry_altp->checkState() != Qt::Unchecked);
- iniFile.setValue("rz_alt", ui.rz_altp->checkState() != Qt::Unchecked);
- iniFile.setValue("tx_alt", ui.tx_altp->checkState() != Qt::Unchecked);
- iniFile.setValue("ty_alt", ui.ty_altp->checkState() != Qt::Unchecked);
- iniFile.setValue("tz_alt", ui.tz_altp->checkState() != Qt::Unchecked);
-
- QDoubleSpinBox* widgets2[] = {
- ui.pos_tx,
- ui.pos_ty,
- ui.pos_tz,
- ui.pos_tx,
- ui.pos_ry,
- ui.pos_rz
- };
-
- const char* names2[] = {
- "zero_tx",
- "zero_ty",
- "zero_tz",
- "zero_rx",
- "zero_ry",
- "zero_rz"
- };
-
- for (int i = 0; i < 6; i++)
- iniFile.setValue(names2[i], widgets2[i]->value());
-
- iniFile.endGroup();
-
- settingsDirty = false;
-
- //
- // Send a message to the main program, to update the Settings (for the tracker)
- //
- mainApp->updateSettings();
-}
-
-void FaceTrackNoIR::shortcutRecentered()
-{
- if (tracker)
- {
-#if defined(__WIN32) || defined(_WIN32)
- MessageBeep(MB_OK);
-#else
- QApplication::beep();
-#endif
- qDebug() << "Center";
- tracker->do_center = true;
- }
-}
+/********************************************************************************
+* 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 "shortcuts.h"
+#include "tracker.h"
+#include "curve-config.h"
+#include "opentrack-version.h"
+#include <QDebug>
+
+#if defined(_WIN32)
+# include <windows.h>
+# include <dshow.h>
+#endif
+
+#if defined(__APPLE__)
+# define SONAME "dylib"
+#elif defined(_WIN32)
+# define SONAME "dll"
+#else
+# define SONAME "so"
+#endif
+
+#include <iostream>
+
+#ifdef _MSC_VER
+# define LIB_PREFIX ""
+#else
+# define LIB_PREFIX "lib"
+#endif
+
+#if defined(__unix) || defined(__linux) || defined(__APPLE__)
+# include <unistd.h>
+#endif
+
+static bool get_metadata(DynamicLibrary* lib, QString& longName, QIcon& icon)
+{
+ Metadata* meta;
+ if (!lib->Metadata || ((meta = lib->Metadata()), !meta))
+ return false;
+ meta->getFullName(&longName);
+ meta->getIcon(&icon);
+ delete meta;
+ return true;
+}
+
+static void fill_combobox(const QString& filter, QList<DynamicLibrary*>& list, QComboBox* cbx, QComboBox* cbx2)
+{
+ QDir settingsDir( QCoreApplication::applicationDirPath() );
+ QStringList filenames = settingsDir.entryList( QStringList() << (LIB_PREFIX + filter + SONAME), QDir::Files, QDir::Name );
+ for ( int i = 0; i < filenames.size(); i++) {
+ QIcon icon;
+ QString longName;
+ QString str = filenames.at(i);
+ DynamicLibrary* lib = new DynamicLibrary(str);
+ qDebug() << "Loading" << str;
+ std::cout.flush();
+ if (!get_metadata(lib, longName, icon))
+ {
+ delete lib;
+ continue;
+ }
+ list.push_back(lib);
+ cbx->addItem(icon, longName);
+ if (cbx2)
+ cbx2->addItem(icon, longName);
+ }
+}
+
+FaceTrackNoIR::FaceTrackNoIR(QWidget *parent) :
+ QMainWindow(parent),
+#if defined(_WIN32)
+ keybindingWorker(NULL),
+#else
+ keyCenter(this),
+ keyToggle(this),
+#endif
+ 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}),
+ timUpdateHeadPose(this),
+ pTrackerDialog(NULL),
+ pSecondTrackerDialog(NULL),
+ pProtocolDialog(NULL),
+ pFilterDialog(NULL),
+ kbd_quit(QKeySequence("Ctrl+Q"), this),
+ looping(false)
+{
+ ui.setupUi(this);
+ setFixedSize(size());
+
+ _keyboard_shortcuts = 0;
+ _curve_config = 0;
+
+ tracker = 0;
+
+ CurveConfigurationDialog* ccd;
+
+ if (!_curve_config)
+ {
+ ccd = new CurveConfigurationDialog( this, this );
+ _curve_config = ccd;
+ } else {
+ ccd = dynamic_cast<CurveConfigurationDialog*>(_curve_config);
+ }
+
+ QDir::setCurrent(QCoreApplication::applicationDirPath());
+
+ fill_profile_cbx();
+
+ connect(ui.btnLoad, SIGNAL(clicked()), this, SLOT(open()));
+ connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save()));
+ connect(ui.btnSaveAs, SIGNAL(clicked()), this, SLOT(saveAs()));
+
+ connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration()));
+ connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(showKeyboardShortcuts()));
+ connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings()));
+ connect(ui.btnShowSecondTrackerSettings, SIGNAL(clicked()), this, SLOT(showSecondTrackerSettings()));
+ connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showServerControls()));
+ connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterControls()));
+
+ ui.cbxSecondTrackerSource->addItem(QIcon(), "");
+ dlopen_filters.push_back((DynamicLibrary*) NULL);
+ ui.iconcomboFilter->addItem(QIcon(), "");
+
+ fill_combobox("opentrack-proto-*.", dlopen_protocols, ui.iconcomboProtocol, NULL);
+ fill_combobox("opentrack-tracker-*.", dlopen_trackers, ui.iconcomboTrackerSource, ui.cbxSecondTrackerSource);
+ fill_combobox("opentrack-filter-*.", dlopen_filters, ui.iconcomboFilter, NULL);
+
+ tie_setting(s.tracker_dll, ui.iconcomboTrackerSource);
+ tie_setting(s.tracker2_dll, ui.cbxSecondTrackerSource);
+ tie_setting(s.protocol_dll, ui.iconcomboProtocol);
+ tie_setting(s.filter_dll, ui.iconcomboFilter);
+
+ connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker()));
+ connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker()));
+
+ GetCameraNameDX();
+
+ connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int)));
+ connect(&timUpdateHeadPose, SIGNAL(timeout()), this, SLOT(showHeadPose()));
+
+#ifndef _WIN32
+ connect(&keyCenter, SIGNAL(activated()), this, SLOT(shortcutRecentered()));
+ connect(&keyToggle, SIGNAL(activated()), this, SLOT(shortcutToggled()));
+#endif
+
+ connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit()));
+ kbd_quit.setEnabled(true);
+}
+
+FaceTrackNoIR::~FaceTrackNoIR() {
+
+ stopTracker();
+ save();
+ if (Libraries)
+ delete Libraries;
+}
+
+QFrame* FaceTrackNoIR::get_video_widget() {
+ return ui.video_frame;
+}
+
+void FaceTrackNoIR::GetCameraNameDX() {
+#if defined(_WIN32)
+ ui.cameraName->setText("No video-capturing device was found in your system: check if it's connected!");
+
+ // Create the System Device Enumerator.
+ HRESULT hr;
+ ICreateDevEnum *pSysDevEnum = NULL;
+ hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
+ if (FAILED(hr))
+ {
+ qDebug() << "GetWDM says: CoCreateInstance Failed!";
+ return;
+ }
+
+ qDebug() << "GetWDM says: CoCreateInstance succeeded!";
+
+ // Obtain a class enumerator for the video compressor category.
+ IEnumMoniker *pEnumCat = NULL;
+ hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
+
+ if (hr == S_OK) {
+ qDebug() << "GetWDM says: CreateClassEnumerator succeeded!";
+
+ IMoniker *pMoniker = NULL;
+ ULONG cFetched;
+ if (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) {
+ IPropertyBag *pPropBag;
+ hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
+ if (SUCCEEDED(hr)) {
+ VARIANT varName;
+ VariantInit(&varName);
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ if (SUCCEEDED(hr))
+ {
+ QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal));
+ qDebug() << "GetWDM says: Moniker found:" << str;
+ ui.cameraName->setText(str);
+ }
+ VariantClear(&varName);
+
+ pPropBag->Release();
+ }
+ pMoniker->Release();
+ }
+ pEnumCat->Release();
+ }
+ pSysDevEnum->Release();
+#else
+ for (int i = 0; i < 16; i++) {
+ char buf[128];
+ sprintf(buf, "/dev/video%d", i);
+ if (access(buf, R_OK | W_OK) == 0) {
+ ui.cameraName->setText(QString(buf));
+ break;
+ }
+ }
+#endif
+}
+
+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);
+
+ if (! fileName.isEmpty() ) {
+ {
+ QSettings settings("opentrack");
+ settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath());
+ }
+ looping = true;
+ fill_profile_cbx();
+ loadSettings();
+ looping = false;
+ }
+}
+
+void FaceTrackNoIR::save() {
+ b->save();
+
+ QSettings settings("opentrack");
+
+ QString currentFile =
+ settings.value("SettingsFile",
+ QCoreApplication::applicationDirPath() + "/settings/default.ini")
+ .toString();
+
+#if defined(__unix) || defined(__linux)
+ QByteArray bytes = QFile::encodeName(currentFile);
+ const char* filename_as_asciiz = bytes.constData();
+
+ if (access(filename_as_asciiz, R_OK | W_OK))
+ {
+ QMessageBox::warning(this, "Something went wrong", "Check permissions and ownership for your .ini file!", QMessageBox::Ok, QMessageBox::NoButton);
+ }
+#endif
+}
+
+void FaceTrackNoIR::saveAs()
+{
+ looping = true;
+ QSettings settings("opentrack");
+ QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+
+ 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();
+ }
+
+ looping = false;
+ fill_profile_cbx();
+}
+
+void FaceTrackNoIR::loadSettings() {
+ b->reload();
+ (dynamic_cast<CurveConfigurationDialog*>(_curve_config))->loadSettings();
+}
+
+void FaceTrackNoIR::updateButtonState(bool running)
+{
+ bool e = !running;
+ ui.iconcomboProfile->setEnabled ( e );
+ ui.btnLoad->setEnabled ( e );
+ ui.btnSaveAs->setEnabled ( e );
+ ui.btnStartTracker->setEnabled ( e );
+ ui.btnStopTracker->setEnabled ( running );
+ ui.iconcomboProtocol->setEnabled ( e );
+ ui.btnShowServerControls->setEnabled ( e );
+ ui.iconcomboFilter->setEnabled ( e );
+ ui.iconcomboTrackerSource->setEnabled(e);
+ ui.cbxSecondTrackerSource->setEnabled(e);
+
+ ui.btnStartTracker->setEnabled(e);
+ ui.btnStopTracker->setEnabled(running);
+}
+
+void FaceTrackNoIR::startTracker( ) {
+ b->save();
+ loadSettings();
+ bindKeyboardShortcuts();
+
+ if (Libraries)
+ delete Libraries;
+ Libraries = new SelectedLibraries(this);
+
+ if (!Libraries->correct)
+ {
+ QMessageBox::warning(this, "Something went wrong", "Tracking can't be initialized, probably protocol prerequisites missing", QMessageBox::Ok, QMessageBox::NoButton);
+ stopTracker();
+ return;
+ }
+
+#if defined(_WIN32)
+ keybindingWorker = new KeybindingWorker(*this, keyCenter, keyToggle);
+ keybindingWorker->start();
+#endif
+
+ if (tracker) {
+ delete tracker;
+ }
+
+ {
+ QSettings settings("opentrack");
+ QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat );
+
+ for (int i = 0; i < 6; i++)
+ {
+ axis(i).curve.loadSettings(iniFile);
+ axis(i).curveAlt.loadSettings(iniFile);
+ }
+ }
+
+ tracker = new Tracker ( this, s );
+
+ if (pTrackerDialog && Libraries->pTracker) {
+ pTrackerDialog->registerTracker( Libraries->pTracker );
+ }
+
+ if (pFilterDialog && Libraries->pFilter)
+ pFilterDialog->registerFilter(Libraries->pFilter);
+
+ tracker->start();
+
+ ui.video_frame->show();
+
+ timUpdateHeadPose.start(50);
+
+ updateButtonState(true);
+}
+
+void FaceTrackNoIR::stopTracker( ) {
+ ui.game_name->setText("Not connected");
+#if defined(_WIN32)
+ if (keybindingWorker)
+ {
+ keybindingWorker->should_quit = true;
+ keybindingWorker->wait();
+ delete keybindingWorker;
+ keybindingWorker = NULL;
+ }
+#endif
+ timUpdateHeadPose.stop();
+ ui.pose_display->rotateBy(0, 0, 0);
+
+ if (pTrackerDialog) {
+ pTrackerDialog->unRegisterTracker();
+ delete pTrackerDialog;
+ pTrackerDialog = nullptr;
+ }
+ if (pProtocolDialog) {
+ pProtocolDialog->unRegisterProtocol();
+ delete pProtocolDialog;
+ pProtocolDialog = nullptr;
+ }
+ if (pFilterDialog)
+ {
+ pFilterDialog->unregisterFilter();
+ delete pFilterDialog;
+ pFilterDialog = nullptr;
+ }
+ if (pSecondTrackerDialog)
+ {
+ pSecondTrackerDialog->unRegisterTracker();
+ delete pSecondTrackerDialog;
+ pSecondTrackerDialog = nullptr;
+ }
+
+ if ( tracker ) {
+ delete tracker;
+ tracker = 0;
+ if (Libraries) {
+ delete Libraries;
+ Libraries = NULL;
+ }
+ }
+ updateButtonState(false);
+}
+
+void FaceTrackNoIR::showHeadPose() {
+ double newdata[6];
+
+ tracker->getHeadPose(newdata);
+ ui.lcdNumX->display(newdata[TX]);
+ ui.lcdNumY->display(newdata[TY]);
+ ui.lcdNumZ->display(newdata[TZ]);
+
+
+ ui.lcdNumRotX->display(newdata[Yaw]);
+ ui.lcdNumRotY->display(newdata[Pitch]);
+ ui.lcdNumRotZ->display(newdata[Roll]);
+
+ tracker->getOutputHeadPose(newdata);
+
+ ui.pose_display->rotateBy(newdata[Yaw], newdata[Roll], newdata[Pitch]);
+
+ ui.lcdNumOutputPosX->display(newdata[TX]);
+ ui.lcdNumOutputPosY->display(newdata[TY]);
+ ui.lcdNumOutputPosZ->display(newdata[TZ]);
+
+ ui.lcdNumOutputRotX->display(newdata[Yaw]);
+ ui.lcdNumOutputRotY->display(newdata[Pitch]);
+ ui.lcdNumOutputRotZ->display(newdata[Roll]);
+
+ if (_curve_config) {
+ _curve_config->update();
+ }
+ if (Libraries->pProtocol)
+ {
+ const QString name = Libraries->pProtocol->getGameName();
+ ui.game_name->setText(name);
+ }
+}
+
+void FaceTrackNoIR::showTrackerSettings() {
+ if (pTrackerDialog) {
+ delete pTrackerDialog;
+ pTrackerDialog = NULL;
+ }
+
+ DynamicLibrary* lib = dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
+
+ if (lib) {
+ pTrackerDialog = (ITrackerDialog*) lib->Dialog();
+ if (pTrackerDialog) {
+ auto foo = dynamic_cast<QWidget*>(pTrackerDialog);
+ foo->setFixedSize(foo->size());
+ if (Libraries && Libraries->pTracker)
+ pTrackerDialog->registerTracker(Libraries->pTracker);
+ dynamic_cast<QWidget*>(pTrackerDialog)->show();
+ }
+ }
+}
+
+void FaceTrackNoIR::showSecondTrackerSettings() {
+ if (pSecondTrackerDialog) {
+ delete pSecondTrackerDialog;
+ pSecondTrackerDialog = NULL;
+ }
+
+ DynamicLibrary* lib = dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL);
+
+ if (lib) {
+ pSecondTrackerDialog = (ITrackerDialog*) lib->Dialog();
+ if (pSecondTrackerDialog) {
+ auto foo = dynamic_cast<QWidget*>(pSecondTrackerDialog);
+ foo->setFixedSize(foo->size());
+ if (Libraries && Libraries->pSecondTracker)
+ pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker);
+ dynamic_cast<QWidget*>(pSecondTrackerDialog)->show();
+ }
+ }
+}
+
+void FaceTrackNoIR::showServerControls() {
+ if (pProtocolDialog) {
+ delete pProtocolDialog;
+ pProtocolDialog = NULL;
+ }
+
+ DynamicLibrary* lib = dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL);
+
+ if (lib && lib->Dialog) {
+ pProtocolDialog = (IProtocolDialog*) lib->Dialog();
+ if (pProtocolDialog) {
+ auto foo = dynamic_cast<QWidget*>(pProtocolDialog);
+ foo->setFixedSize(foo->size());
+ dynamic_cast<QWidget*>(pProtocolDialog)->show();
+ }
+ }
+}
+
+void FaceTrackNoIR::showFilterControls() {
+ if (pFilterDialog) {
+ delete pFilterDialog;
+ pFilterDialog = NULL;
+ }
+
+ DynamicLibrary* lib = dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
+
+ if (lib && lib->Dialog) {
+ pFilterDialog = (IFilterDialog*) lib->Dialog();
+ if (pFilterDialog) {
+ auto foo = dynamic_cast<QWidget*>(pFilterDialog);
+ foo->setFixedSize(foo->size());
+ if (Libraries && Libraries->pFilter)
+ pFilterDialog->registerFilter(Libraries->pFilter);
+ dynamic_cast<QWidget*>(pFilterDialog)->show();
+ }
+ }
+}
+void FaceTrackNoIR::showKeyboardShortcuts() {
+
+ if (!_keyboard_shortcuts)
+ {
+ _keyboard_shortcuts = new KeyboardShortcutDialog( this, this );
+ }
+
+ _keyboard_shortcuts->show();
+ _keyboard_shortcuts->raise();
+}
+void FaceTrackNoIR::showCurveConfiguration() {
+
+ if (!_curve_config)
+ {
+ _curve_config = new CurveConfigurationDialog( this, this );
+ }
+
+ if (_curve_config) {
+ _curve_config->show();
+ _curve_config->raise();
+ }
+}
+
+void FaceTrackNoIR::exit() {
+ QCoreApplication::exit(0);
+}
+
+void FaceTrackNoIR::fill_profile_cbx()
+{
+ if (looping)
+ return;
+ QSettings settings("opentrack");
+ QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ qDebug() << "Config file now" << currentFile;
+ QFileInfo pathInfo ( currentFile );
+ setWindowTitle(QString( OPENTRACK_VERSION " :: ") + pathInfo.fileName());
+ QDir settingsDir( pathInfo.dir() );
+ QStringList filters;
+ filters << "*.ini";
+ auto iniFileList = settingsDir.entryList( filters, QDir::Files, QDir::Name );
+ ui.iconcomboProfile->clear();
+ for ( int i = 0; i < iniFileList.size(); i++) {
+ ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), iniFileList.at(i));
+ if (iniFileList.at(i) == pathInfo.fileName()) {
+ ui.iconcomboProfile->setCurrentIndex( i );
+ }
+ }
+}
+
+void FaceTrackNoIR::profileSelected(int index)
+{
+ 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));
+ loadSettings();
+}
+
+#if !defined(_WIN32)
+void FaceTrackNoIR::bind_keyboard_shortcut(QxtGlobalShortcut& key, key_opts& k)
+{
+ key.setShortcut(QKeySequence::fromString(""));
+ key.setDisabled();
+ const int idx = k.key_index;
+ if (idx > 0)
+ {
+ QString seq(global_key_sequences.value(idx, ""));
+ if (!seq.isEmpty())
+ {
+ if (k.shift)
+ seq = "Shift+" + seq;
+ if (k.alt)
+ seq = "Alt+" + seq;
+ if (k.ctrl)
+ seq = "Ctrl+" + seq;
+ key.setShortcut(QKeySequence::fromString(seq, QKeySequence::PortableText));
+ key.setEnabled();
+ } else {
+ key.setDisabled();
+ }
+ }
+}
+#else
+static void bind_keyboard_shortcut(Key& key, key_opts& k)
+{
+ int idx = k.key_index;
+ if (idx > 0)
+ {
+ 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;
+ }
+}
+#endif
+
+void FaceTrackNoIR::bindKeyboardShortcuts()
+{
+#if !defined(_WIN32)
+ bind_keyboard_shortcut(keyCenter, s.center_key);
+ bind_keyboard_shortcut(keyToggle, s.toggle_key);
+#else
+ bind_keyboard_shortcut(keyCenter, s.center_key);
+ bind_keyboard_shortcut(keyToggle, s.toggle_key);
+#endif
+ if (tracker) /* running already */
+ {
+#if defined(_WIN32)
+ if (keybindingWorker)
+ {
+ keybindingWorker->should_quit = true;
+ keybindingWorker->wait();
+ delete keybindingWorker;
+ keybindingWorker = NULL;
+ }
+ keybindingWorker = new KeybindingWorker(*this, keyCenter, keyToggle);
+ keybindingWorker->start();
+#endif
+ }
+}
+
+void FaceTrackNoIR::shortcutRecentered()
+{
+ QApplication::beep();
+
+ qDebug() << "Center";
+ if (tracker)
+ tracker->do_center = true;
+}
+
+void FaceTrackNoIR::shortcutToggled()
+{
+ QApplication::beep();
+ qDebug() << "Toggle";
+ if (tracker)
+ tracker->enabled = !tracker->enabled;
+}
diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/facetracknoir.h
index fd9c06a7..50a6e0ec 100644
--- a/facetracknoir/facetracknoir.h
+++ b/facetracknoir/facetracknoir.h
@@ -1,297 +1,165 @@
-/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-
-#ifndef FaceTrackNoIR_H
-#define FaceTrackNoIR_H
-
-#undef FTNOIR_PROTOCOL_BASE_LIB
-#undef FTNOIR_TRACKER_BASE_LIB
-#undef FTNOIR_FILTER_BASE_LIB
-#define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_IMPORT
-#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT
-#define FTNOIR_FILTER_BASE_EXPORT Q_DECL_IMPORT
-
-#include <QtGui/QMainWindow>
-#include <QApplication>
-#include <QFileDialog>
-#include <QListView>
-#include <QPainter>
-#include <QWidget>
-#include <QDialog>
-#include <QUrl>
-#include <QList>
-#include <QKeySequence>
-#include <QtGui>
-#include <QString>
-#if !defined(_WIN32) && !defined(__WIN32)
-# include <qxtglobalshortcut.h>
-#else
-# include <windows.h>
-#endif
-#include <QThread>
-#include <QDebug>
-#include <QElapsedTimer>
-
-
-#include "ui_facetracknoir.h"
-#include "ui_ftnoir_keyboardshortcuts.h"
-#include "ui_ftnoir_curves.h"
-
-#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "ftnoir_filter_base/ftnoir_filter_base.h"
-
-#include "global-settings.h"
-#include "tracker.h"
-
-class Tracker; // pre-define class to avoid circular includes
-class FaceTrackNoIR;
-
-class KeybindingWorker;
-
-#if defined(__WIN32) || defined(_WIN32)
-extern QList<int> global_windows_key_sequences;
-#undef DIRECTINPUT_VERSION
-#define DIRECTINPUT_VERSION 0x0800
-#include <dinput.h>
-struct Key {
- BYTE keycode;
- bool shift;
- bool ctrl;
- bool alt;
- bool ever_pressed;
- QElapsedTimer timer;
-public:
- Key() : keycode(0), shift(false), ctrl(false), alt(false), ever_pressed(false)
- {
- }
-};
-#else
-typedef unsigned char BYTE;
-struct Key { int foo; };
-#endif
-
-class FaceTrackNoIR : public QMainWindow, IDynamicLibraryProvider
-{
- Q_OBJECT
-
-public:
- FaceTrackNoIR(QWidget *parent = 0, Qt::WFlags flags = 0);
- ~FaceTrackNoIR();
-
- void updateSettings(); // Update the settings (let Tracker read INI-file).
-
- QFrame *get_video_widget(); // Get a pointer to the video-widget, to use in the DLL
- Tracker *tracker;
- void bindKeyboardShortcuts();
- DynamicLibrary* current_tracker1() {
- return dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
- }
- DynamicLibrary* current_tracker2() {
- return dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL);
- }
- DynamicLibrary* current_protocol() {
- return dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL);
- }
- DynamicLibrary* current_filter() {
- return dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
- }
- THeadPoseDOF& axis(int idx) {
- return *pose.axes[idx];
- }
-
-#if defined(_WIN32) || defined(__WIN32)
- Key keyCenter;
- KeybindingWorker* keybindingWorker;
-#else
- QxtGlobalShortcut* keyCenter;
-#endif
-public slots:
- void shortcutRecentered();
-
-private:
- HeadPoseData pose;
- Ui::FaceTrackNoIRClass ui;
- QTimer timUpdateHeadPose; // Timer to display headpose
- QStringList iniFileList; // List of INI-files, that are present in the Settings folder
-
- ITrackerDialog* pTrackerDialog; // Pointer to Tracker dialog instance (in DLL)
- ITrackerDialog* pSecondTrackerDialog; // Pointer to the second Tracker dialog instance (in DLL)
- IProtocolDialog* pProtocolDialog; // Pointer to Protocol dialog instance (in DLL)
- IFilterDialog* pFilterDialog; // Pointer to Filter dialog instance (in DLL)
-
- /** Widget variables **/
- QWidget *_keyboard_shortcuts;
- QWidget *_curve_config;
-
- void createIconGroupBox();
-// void createMessageGroupBox();
-
- /** helper **/
- bool cameraDetected;
- bool settingsDirty;
-
- void GetCameraNameDX();
- void loadSettings();
- void setupFaceTrackNoIR();
-
- QList<DynamicLibrary*> dlopen_filters;
- QList<DynamicLibrary*> dlopen_trackers;
- QList<DynamicLibrary*> dlopen_protocols;
-
- bool looping;
-
- private slots:
- //file menu
- void open();
- void save();
- void saveAs();
- void exit();
-// void setIcon(int index);
- void profileSelected(int index);
- void protocolSelected(int index);
- void filterSelected(int index);
- void trackingSourceSelected(int index);
-
- void showVideoWidget();
- void showHeadPoseWidget();
- void showTrackerSettings();
- void showSecondTrackerSettings();
-
- void showServerControls();
- void showFilterControls();
- void showKeyboardShortcuts();
- void showCurveConfiguration();
-
- void setInvertAxis( Axis axis, int invert );
- void setInvertYaw(int invert) {
- setInvertAxis(Yaw, invert);
- }
- void setInvertPitch(int invert) {
- setInvertAxis(Pitch, invert);
- }
- void setInvertRoll(int invert) {
- setInvertAxis(Roll, invert);
- }
- void setInvertX(int invert) {
- setInvertAxis(TX, invert);
- }
- void setInvertY(int invert) {
- setInvertAxis(TY, invert);
- }
- void setInvertZ(int invert) {
- setInvertAxis(TZ, invert);
- }
- void showHeadPose();
-
- void startTracker();
- void stopTracker();
-
-};
-
-class KeyboardShortcutDialog: public QWidget
-{
- Q_OBJECT
-public:
-
- explicit KeyboardShortcutDialog( FaceTrackNoIR *ftnoir, QWidget *parent=0, Qt::WindowFlags f=0 );
- virtual ~KeyboardShortcutDialog();
- void showEvent ( QShowEvent * event );
-
-private:
- Ui::UICKeyboardShortcutDialog ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FaceTrackNoIR *mainApp;
-
-private slots:
- void doOK();
- void doCancel();
- void keyChanged( int index ) { settingsDirty = true; }
- void keyChanged( bool index ) { settingsDirty = true; }
-};
-
-// Widget that has controls for Keyboard shortcuts.
-class CurveConfigurationDialog: public QWidget
-{
- Q_OBJECT
-public:
-
- explicit CurveConfigurationDialog( FaceTrackNoIR *ftnoir, QWidget *parent=0, Qt::WindowFlags f=0 );
- virtual ~CurveConfigurationDialog();
- void showEvent ( QShowEvent * event );
-
-private:
- Ui::UICCurveConfigurationDialog ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FaceTrackNoIR *mainApp;
-
-private slots:
- void doOK();
- void doCancel();
- void curveChanged( bool change ) { settingsDirty = true; }
- void curveChanged( int change ) { settingsDirty = true; }
-};
-
-#endif // FaceTrackNoIR_H
-
-extern QList<QString> global_key_sequences;
-#if defined(__WIN32) || defined(_WIN32)
-class KeybindingWorkerDummy {
-private:
- LPDIRECTINPUT8 din;
- LPDIRECTINPUTDEVICE8 dinkeyboard;
- Key kCenter;
- FaceTrackNoIR& window;
-public:
- volatile bool should_quit;
- ~KeybindingWorkerDummy();
- KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter);
- void run();
-};
-#else
-class KeybindingWorkerDummy {
-public:
- KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter);
- void run() {}
-};
-#endif
-
-class KeybindingWorker : public QThread, public KeybindingWorkerDummy {
- Q_OBJECT
-public:
- KeybindingWorker(FaceTrackNoIR& w, Key keyCenter) : KeybindingWorkerDummy(w, keyCenter)
- {
- }
- void run() {
- KeybindingWorkerDummy::run();
- }
-};
+/********************************************************************************
+* 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/>. *
+*********************************************************************************/
+
+#ifndef FaceTrackNoIR_H
+#define FaceTrackNoIR_H
+
+#include <QMainWindow>
+#include <QApplication>
+#include <QFileDialog>
+#include <QListView>
+#include <QPainter>
+#include <QWidget>
+#include <QDialog>
+#include <QUrl>
+#include <QList>
+#include <QKeySequence>
+#include <QtGui>
+#include <QString>
+#include <QByteArray>
+#include <QShortcut>
+#include <vector>
+#if !defined(_WIN32)
+# include "qxt-mini/QxtGlobalShortcut"
+#else
+# include <windows.h>
+#endif
+#include <QThread>
+#include <QDebug>
+
+#include "ui_facetracknoir.h"
+
+#include "facetracknoir/options.h"
+using namespace options;
+
+#include "facetracknoir/main-settings.hpp"
+
+#include "global-settings.h"
+#include "tracker.h"
+#include "facetracknoir/shortcuts.h"
+
+#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "ftnoir_filter_base/ftnoir_filter_base.h"
+
+#include "opentrack-version.h"
+
+class Tracker; // pre-define class to avoid circular includes
+class FaceTrackNoIR;
+
+class KeybindingWorker;
+
+class FaceTrackNoIR : public QMainWindow, IDynamicLibraryProvider
+{
+ Q_OBJECT
+
+public:
+ FaceTrackNoIR(QWidget *parent = 0);
+ ~FaceTrackNoIR();
+
+ QFrame *get_video_widget(); // Get a pointer to the video-widget, to use in the DLL
+ Tracker *tracker;
+ void bindKeyboardShortcuts();
+ DynamicLibrary* current_tracker1() {
+ return dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL);
+ }
+ DynamicLibrary* current_tracker2() {
+ return dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL);
+ }
+ DynamicLibrary* current_protocol() {
+ return dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL);
+ }
+ DynamicLibrary* current_filter() {
+ return dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL);
+ }
+ THeadPoseDOF& axis(int idx) {
+ return *pose.axes[idx];
+ }
+
+#if defined(_WIN32)
+ Key keyCenter;
+ Key keyToggle;
+ KeybindingWorker* keybindingWorker;
+#else
+ QxtGlobalShortcut keyCenter;
+ QxtGlobalShortcut keyToggle;
+#endif
+ pbundle b;
+ main_settings s;
+public slots:
+ void shortcutRecentered();
+ void shortcutToggled();
+
+private:
+ HeadPoseData pose;
+ Ui::OpentrackUI ui;
+ QTimer timUpdateHeadPose; // Timer to display headpose
+
+ ITrackerDialog* pTrackerDialog; // Pointer to Tracker dialog instance (in DLL)
+ ITrackerDialog* pSecondTrackerDialog; // Pointer to the second Tracker dialog instance (in DLL)
+ IProtocolDialog* pProtocolDialog; // Pointer to Protocol dialog instance (in DLL)
+ IFilterDialog* pFilterDialog; // Pointer to Filter dialog instance (in DLL)
+
+ QWidget *_keyboard_shortcuts;
+ QWidget *_curve_config;
+
+ void createIconGroupBox();
+
+ void GetCameraNameDX();
+ void loadSettings();
+ void updateButtonState(bool);
+
+ QList<DynamicLibrary*> dlopen_filters;
+ QList<DynamicLibrary*> dlopen_trackers;
+ QList<DynamicLibrary*> dlopen_protocols;
+ QShortcut kbd_quit;
+
+#ifndef _WIN32
+ void bind_keyboard_shortcut(QxtGlobalShortcut&, key_opts& k);
+#endif
+ void fill_profile_cbx();
+ bool looping;
+
+private slots:
+ void open();
+ void save();
+ void saveAs();
+ void exit();
+ void profileSelected(int index);
+
+ void showTrackerSettings();
+ void showSecondTrackerSettings();
+
+ void showServerControls();
+ void showFilterControls();
+ void showKeyboardShortcuts();
+ void showCurveConfiguration();
+
+ void showHeadPose();
+
+ void startTracker();
+ void stopTracker();
+};
+
+#endif // FaceTrackNoIR_H
diff --git a/facetracknoir/facetracknoir.ico b/facetracknoir/facetracknoir.ico
index 5115066c..5cac8da1 100644
--- a/facetracknoir/facetracknoir.ico
+++ b/facetracknoir/facetracknoir.ico
Binary files differ
diff --git a/facetracknoir/facetracknoir.ui b/facetracknoir/facetracknoir.ui
index ee5fb5b0..b257ae30 100644
--- a/facetracknoir/facetracknoir.ui
+++ b/facetracknoir/facetracknoir.ui
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>WVR</author>
- <class>FaceTrackNoIRClass</class>
- <widget class="QMainWindow" name="FaceTrackNoIRClass">
+ <class>OpentrackUI</class>
+ <widget class="QMainWindow" name="OpentrackUI">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
@@ -10,125 +10,41 @@
<rect>
<x>0</x>
<y>0</y>
- <width>874</width>
- <height>380</height>
+ <width>790</width>
+ <height>500</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>874</width>
- <height>380</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>874</width>
- <height>380</height>
+ <width>65536</width>
+ <height>65536</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="windowTitle">
- <string>FaceTrackNoIR</string>
+ <string>opentrack</string>
</property>
<property name="windowIcon">
- <iconset resource="../ftnoir_protocol_ftn/ftn-protocol.qrc">
+ <iconset resource="main-facetracknoir.qrc">
<normaloff>:/images/facetracknoir.png</normaloff>:/images/facetracknoir.png</iconset>
</property>
<property name="toolTip">
<string/>
</property>
- <property name="styleSheet">
- <string notr="true">/* Customize any plain widget that is a child of a QMainWindow. */
-QMainWindow &gt; .QWidget {
- background-color: rgb(100, 100, 100);
-}
-
-/* Set the selection colors for all widgets. */
-QWidget {
- selection-color: black;
- selection-background-color: Silver;
- color: black;
-}
-
-/* Specials for individual widget(s) */
-QWidget#widget {
-/* background-color: #484848;*/
- background-color: #595959;
- border-left: 1px solid #000;
-}
-
-/* Specials for individual widget(s) */
-QWidget#widget4logo {
- background-color: #000000;
-}
-
-/* Specials for individual widget(s) */
-QWidget#headPoseWidget {
- background-color: #595959;
-}
-
-QWidget#widget4video {
-/* background-color: #595959;*/
-}
-
-QWidget#Leftwidget {
- background-color: ;
-}
-
-QWidget#widgetTop {
- background-color: #595959;
- border-bottom: 1px solid #000;
-}
-
-/* Make text in message boxes selectable. */
-QMessageBox {
- /* LinksAccessibleByMouse | TextSelectableByMouse */
- messagebox-text-interaction-flags: 5;
-}
-
-/* Make the entire row selected in item views. */
-QAbstractItemView {
- show-decoration-selected: 1;
-}
-
-/* Nice WindowsXP-style password character for password line edits. */
-QLineEdit[echoMode=&quot;2&quot;] {
- lineedit-password-character: 9679;
-}
-
-/* Customize tooltips. */
-QToolTip {
- background-color: rgb(170, 255, 127);
- opacity: 200;
-}
-
-/* Customize push buttons and comboboxes. Our read-only combobox
- is very similar to a push button, so they share the same border image. */
-
-QPushButton {
- min-width: 4em;
-}
-
-QCheckBox {
- background:none;
-}
-
-QPushButton:disabled {
- color: rgb(128, 128, 128);
-}
-
-QGroupBox {
- color: rgb(255, 255, 255);
-}</string>
- </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -143,1888 +59,819 @@ QGroupBox {
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>874</width>
- <height>380</height>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65535</width>
+ <height>65535</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
- <widget class="QWidget" name="widget" native="true">
- <property name="enabled">
- <bool>true</bool>
- </property>
+ <widget class="QFrame" name="video_frame">
<property name="geometry">
<rect>
- <x>250</x>
- <y>0</y>
- <width>671</width>
- <height>431</height>
+ <x>10</x>
+ <y>130</y>
+ <width>320</width>
+ <height>240</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>400</width>
- <height>419</height>
+ <width>250</width>
+ <height>187</height>
</size>
</property>
- <property name="palette">
- <palette>
- <active>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Button">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Text">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="ButtonText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Base">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Window">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Highlight">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>192</red>
- <green>192</green>
- <blue>192</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="HighlightedText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="AlternateBase">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>72</red>
- <green>72</green>
- <blue>72</blue>
- </color>
- </brush>
- </colorrole>
- </active>
- <inactive>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Button">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Text">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="ButtonText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Base">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Window">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Highlight">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>192</red>
- <green>192</green>
- <blue>192</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="HighlightedText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="AlternateBase">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>72</red>
- <green>72</green>
- <blue>72</blue>
- </color>
- </brush>
- </colorrole>
- </inactive>
- <disabled>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Button">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Text">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="ButtonText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Base">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Window">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>89</red>
- <green>89</green>
- <blue>89</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="Highlight">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>192</red>
- <green>192</green>
- <blue>192</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="HighlightedText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>0</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- <colorrole role="AlternateBase">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>72</red>
- <green>72</green>
- <blue>72</blue>
- </color>
- </brush>
- </colorrole>
- </disabled>
- </palette>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
</property>
- <property name="locale">
- <locale language="English" country="UnitedStates"/>
+ <property name="lineWidth">
+ <number>0</number>
</property>
- <widget class="QLabel" name="cameraName">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>10</y>
- <width>400</width>
- <height>25</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>400</width>
- <height>25</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>600</width>
- <height>30</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QGroupBox" name="groupBox_4">
- <property name="geometry">
- <rect>
- <x>320</x>
- <y>70</y>
- <width>221</width>
- <height>121</height>
- </rect>
- </property>
- <property name="title">
- <string>Axis inversion</string>
- </property>
- <widget class="QLabel" name="lblInvert1_2">
- <property name="geometry">
- <rect>
- <x>169</x>
- <y>24</y>
- <width>30</width>
- <height>16</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>30</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Invert</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblInvert1_3">
- <property name="geometry">
- <rect>
- <x>72</x>
- <y>24</y>
- <width>30</width>
- <height>16</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>30</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Invert</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblSensX">
- <property name="geometry">
- <rect>
- <x>108</x>
- <y>52</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </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="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>X</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblSensPitch">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>71</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </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="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Pitch</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkInvertPitch">
- <property name="geometry">
- <rect>
- <x>72</x>
- <y>71</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QLabel" name="lblSensY">
- <property name="geometry">
- <rect>
- <x>108</x>
- <y>71</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </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="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Y</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblSensZ">
- <property name="geometry">
- <rect>
- <x>108</x>
- <y>90</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </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="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Z</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkInvertZ">
- <property name="geometry">
- <rect>
- <x>169</x>
- <y>90</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkInvertY">
- <property name="geometry">
- <rect>
- <x>169</x>
- <y>71</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkInvertRoll">
- <property name="geometry">
- <rect>
- <x>72</x>
- <y>90</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkInvertX">
- <property name="geometry">
- <rect>
- <x>169</x>
- <y>52</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QLabel" name="lblSensYaw">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>52</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </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="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Yaw</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkInvertYaw">
- <property name="geometry">
- <rect>
- <x>72</x>
- <y>52</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- <widget class="QLabel" name="lblSensRoll">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>90</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </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="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Roll</string>
- </property>
- </widget>
- </widget>
- <widget class="QGroupBox" name="groupProfile">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>70</y>
- <width>271</width>
- <height>120</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>206</width>
- <height>120</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>65535</width>
- <height>65535</height>
- </size>
- </property>
- <property name="title">
- <string>Profile</string>
- </property>
- <widget class="QComboBox" name="iconcomboProfile">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="currentIndex">
- <number>-1</number>
- </property>
- <property name="maxVisibleItems">
- <number>10</number>
- </property>
- </widget>
- <widget class="QPushButton" name="btnSaveAs">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>80</y>
- <width>251</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Save the INI-file under another name</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Save As ...</string>
- </property>
- </widget>
- <widget class="QPushButton" name="btnLoad">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>50</y>
- <width>111</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Load an INI-file from a folder</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Load</string>
- </property>
- </widget>
- <widget class="QPushButton" name="btnSave">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>50</y>
- <width>131</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Save the current INI-file</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </widget>
- <widget class="QLabel" name="game_name">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>40</y>
- <width>411</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ccc;
-background:none;</string>
- </property>
- <property name="text">
- <string>Not connected</string>
- </property>
- </widget>
- <widget class="QGroupBox" name="groupGameProtocol">
- <property name="geometry">
- <rect>
- <x>440</x>
- <y>201</y>
- <width>180</width>
- <height>80</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>180</width>
- <height>80</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>180</width>
- <height>80</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="title">
- <string>Game protocol</string>
- </property>
- <widget class="QComboBox" name="iconcomboProtocol">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>161</width>
- <height>22</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="currentIndex">
- <number>-1</number>
- </property>
- <property name="maxVisibleItems">
- <number>7</number>
- </property>
- </widget>
- <widget class="QPushButton" name="btnShowServerControls">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>50</y>
- <width>161</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Change game protocol settings</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </widget>
- <widget class="QGroupBox" name="groupTrackerSource">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>201</y>
- <width>200</width>
- <height>80</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>200</width>
- <height>80</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>200</width>
- <height>80</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="title">
- <string>Tracker Source(1st = Master)</string>
- </property>
- <widget class="QComboBox" name="iconcomboTrackerSource">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>180</width>
- <height>22</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="currentIndex">
- <number>-1</number>
- </property>
- <property name="maxVisibleItems">
- <number>42</number>
- </property>
- </widget>
- <widget class="QPushButton" name="btnShowEngineControls">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>50</y>
- <width>180</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Change tracker settings</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </widget>
- <widget class="QGroupBox" name="groupFilter">
- <property name="geometry">
- <rect>
- <x>230</x>
- <y>201</y>
- <width>200</width>
- <height>80</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>200</width>
- <height>70</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>200</width>
- <height>80</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="title">
- <string>Filter</string>
- </property>
- <widget class="QComboBox" name="iconcomboFilter">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>180</width>
- <height>22</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="currentIndex">
- <number>-1</number>
- </property>
- <property name="maxVisibleItems">
- <number>7</number>
- </property>
- </widget>
- <widget class="QPushButton" name="btnShowFilterControls">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>50</y>
- <width>180</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Change game protocol settings</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </widget>
- <widget class="QGroupBox" name="groupBox_3">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>289</y>
- <width>200</width>
- <height>80</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>200</width>
- <height>80</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>200</width>
- <height>80</height>
- </size>
- </property>
- <property name="title">
- <string>Tracker Source (2nd)</string>
- </property>
- <widget class="QPushButton" name="btnShowSecondTrackerSettings">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>50</y>
- <width>180</width>
- <height>23</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Change tracker settings</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- <widget class="QComboBox" name="cbxSecondTrackerSource">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>180</width>
- <height>22</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="currentIndex">
- <number>-1</number>
- </property>
- <property name="maxVisibleItems">
- <number>42</number>
- </property>
- </widget>
- </widget>
- <widget class="QGroupBox" name="groupStartStop">
- <property name="geometry">
- <rect>
- <x>230</x>
- <y>289</y>
- <width>200</width>
- <height>80</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>200</width>
- <height>80</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>80</height>
- </size>
- </property>
- <property name="title">
- <string>GO!</string>
- </property>
- <widget class="QPushButton" name="btnStartTracker">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>30</y>
- <width>81</width>
- <height>21</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Start the Tracker</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Start</string>
- </property>
- </widget>
- <widget class="QPushButton" name="btnStopTracker">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>100</x>
- <y>30</y>
- <width>81</width>
- <height>21</height>
- </rect>
- </property>
- <property name="toolTip">
- <string>Stop the Tracker</string>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="text">
- <string>Stop</string>
- </property>
- </widget>
- </widget>
- <widget class="QPushButton" name="btnShortcuts">
+ <widget class="QWidget" name="widget4video" native="true">
<property name="geometry">
<rect>
- <x>440</x>
- <y>288</y>
- <width>181</width>
- <height>38</height>
+ <x>0</x>
+ <y>0</y>
+ <width>320</width>
+ <height>240</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>54</width>
- <height>38</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>200</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="cursor">
- <cursorShape>PointingHandCursor</cursorShape>
- </property>
- <property name="toolTip">
- <string>Edit the Keyboard and mouse shortcuts</string>
- </property>
- <property name="text">
- <string>Shortcuts</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>24</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- <widget class="QPushButton" name="btnEditCurves">
- <property name="geometry">
- <rect>
- <x>440</x>
- <y>332</y>
- <width>181</width>
- <height>38</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>54</width>
- <height>38</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>200</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="cursor">
- <cursorShape>PointingHandCursor</cursorShape>
- </property>
- <property name="toolTip">
- <string>Edit the Curve settings</string>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="text">
- <string>Curves</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>120</width>
- <height>24</height>
+ <width>65536</width>
+ <height>65536</height>
</size>
</property>
</widget>
</widget>
- <widget class="QFrame" name="video_frame">
+ <widget class="QGroupBox" name="groupBox4logo">
<property name="geometry">
<rect>
- <x>0</x>
- <y>89</y>
- <width>250</width>
- <height>187</height>
+ <x>100</x>
+ <y>10</y>
+ <width>229</width>
+ <height>121</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="title">
+ <string notr="true"/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_8">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinimumSize</enum>
+ </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>
+ <property name="horizontalSpacing">
+ <number>10</number>
+ </property>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblZ">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>5</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="lblX">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </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="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>5</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="lblRotX">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLCDNumber" name="lcdNumOutputPosY">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>5</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLCDNumber" name="lcdNumOutputPosZ">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>5</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="lblRotZ">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblY">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="lblRotY">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </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="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>5</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QLCDNumber" name="lcdNumOutputRotZ">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>13</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </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>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>5</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="GLWidget" name="pose_display" native="true">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>81</width>
+ <height>100</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>250</width>
- <height>187</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>250</width>
- <height>187</height>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QGroupBox" name="groupGameProtocol">
+ <property name="geometry">
+ <rect>
+ <x>350</x>
+ <y>270</y>
+ <width>191</width>
+ <height>91</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>180</width>
+ <height>80</height>
</size>
</property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
</property>
- <property name="frameShadow">
- <enum>QFrame::Plain</enum>
+ <property name="styleSheet">
+ <string notr="true"/>
</property>
- <property name="lineWidth">
- <number>0</number>
+ <property name="title">
+ <string>Game protocol</string>
</property>
- <widget class="QWidget" name="widget4video" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>250</width>
- <height>187</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>250</width>
- <height>187</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>250</width>
- <height>187</height>
- </size>
- </property>
- </widget>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_6" rowstretch="6,6" columnstretch="6" rowminimumheight="6,6" columnminimumwidth="6">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="iconcomboProtocol">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ <property name="maxVisibleItems">
+ <number>7</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="btnShowServerControls">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Change game protocol settings</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Settings</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
- <widget class="QWidget" name="headPoseWidget" native="true">
+ <widget class="QPushButton" name="btnEditCurves">
<property name="geometry">
<rect>
- <x>0</x>
- <y>275</y>
- <width>261</width>
- <height>141</height>
+ <x>580</x>
+ <y>390</y>
+ <width>171</width>
+ <height>38</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>62</width>
+ <height>38</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="cursor">
+ <cursorShape>PointingHandCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Edit the Curve settings</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <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>98</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLabel" name="game_name">
+ <property name="geometry">
+ <rect>
+ <x>370</x>
+ <y>40</y>
+ <width>411</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Not connected</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox" name="groupFilter">
+ <property name="geometry">
+ <rect>
+ <x>580</x>
+ <y>210</y>
+ <width>171</width>
+ <height>91</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
- <height>100</height>
+ <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>16777215</width>
- <height>160</height>
+ <width>65536</width>
+ <height>65536</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
- <widget class="QGroupBox" name="groupBox">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>231</width>
- <height>169</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="title">
- <string>Raw Input</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <widget class="QLCDNumber" name="lcdNumRotZ">
- <property name="geometry">
- <rect>
- <x>150</x>
- <y>60</y>
- <width>71</width>
- <height>21</height>
- </rect>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="numDigits">
- <number>6</number>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumRotX">
- <property name="geometry">
- <rect>
- <x>150</x>
- <y>20</y>
- <width>71</width>
- <height>21</height>
- </rect>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="numDigits">
- <number>6</number>
- </property>
- </widget>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>21</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">border:none;
-color:white</string>
- </property>
- <property name="text">
- <string>X</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_5">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>21</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">border:none;
-color:white;</string>
- </property>
- <property name="text">
- <string>Y</string>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumZ">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>60</y>
- <width>61</width>
- <height>21</height>
- </rect>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- </widget>
- <widget class="QLabel" name="label_6">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>60</y>
- <width>21</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color:white;
-border:none;</string>
- </property>
- <property name="text">
- <string>Z</string>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumY">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>40</y>
- <width>61</width>
- <height>21</height>
- </rect>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- </widget>
- <widget class="QLabel" name="label_7">
- <property name="geometry">
- <rect>
- <x>108</x>
- <y>58</y>
- <width>31</width>
- <height>20</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">border:none;
-color:white;</string>
- </property>
- <property name="text">
- <string>roll</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_8">
- <property name="geometry">
- <rect>
- <x>109</x>
- <y>38</y>
- <width>31</width>
- <height>20</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color:white;
-border:none;</string>
- </property>
- <property name="text">
- <string>pitch</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_9">
- <property name="geometry">
- <rect>
- <x>108</x>
- <y>18</y>
- <width>31</width>
- <height>20</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">border:none;
-color:white;</string>
- </property>
- <property name="text">
- <string>yaw</string>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumRotY">
- <property name="geometry">
- <rect>
- <x>150</x>
- <y>40</y>
- <width>71</width>
- <height>21</height>
- </rect>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="numDigits">
- <number>6</number>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumX">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>20</y>
- <width>61</width>
- <height>21</height>
- </rect>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- </widget>
- </widget>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>0</y>
- <width>231</width>
- <height>50</height>
- </rect>
- </property>
- <property name="title">
- <string>Status</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <widget class="QLabel" name="txtTracking">
- <property name="geometry">
- <rect>
- <x>110</x>
- <y>10</y>
- <width>101</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">border:none;
-color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>Tracking</string>
- </property>
- </widget>
- </widget>
+ <property name="title">
+ <string>Filter</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QComboBox" name="iconcomboFilter">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ <property name="maxVisibleItems">
+ <number>7</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="btnShowFilterControls">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Change game protocol settings</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Settings</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
- <widget class="QWidget" name="widget4logo" native="true">
+ <widget class="QGroupBox" name="groupTrackerSource">
<property name="geometry">
<rect>
- <x>90</x>
- <y>0</y>
- <width>160</width>
- <height>90</height>
+ <x>350</x>
+ <y>60</y>
+ <width>191</width>
+ <height>91</height>
</rect>
</property>
<property name="minimumSize">
<size>
- <width>160</width>
- <height>90</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>16777215</width>
- <height>90</height>
+ <width>65536</width>
+ <height>65536</height>
</size>
</property>
- <widget class="QLCDNumber" name="lcdNumOutputRotX">
- <property name="geometry">
- <rect>
- <x>101</x>
- <y>19</y>
- <width>50</width>
- <height>21</height>
- </rect>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumOutputRotY">
- <property name="geometry">
- <rect>
- <x>101</x>
- <y>37</y>
- <width>50</width>
- <height>21</height>
- </rect>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumOutputRotZ">
- <property name="geometry">
- <rect>
- <x>101</x>
- <y>55</y>
- <width>50</width>
- <height>21</height>
- </rect>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumOutputPosX">
- <property name="geometry">
- <rect>
- <x>17</x>
- <y>19</y>
- <width>50</width>
- <height>21</height>
- </rect>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumOutputPosY">
- <property name="geometry">
- <rect>
- <x>17</x>
- <y>37</y>
- <width>50</width>
- <height>21</height>
- </rect>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- <widget class="QLCDNumber" name="lcdNumOutputPosZ">
- <property name="geometry">
- <rect>
- <x>17</x>
- <y>55</y>
- <width>50</width>
- <height>21</height>
- </rect>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="numDigits">
- <number>5</number>
- </property>
- <property name="segmentStyle">
- <enum>QLCDNumber::Flat</enum>
- </property>
- </widget>
- <widget class="QLabel" name="lblX">
- <property name="geometry">
- <rect>
- <x>9</x>
- <y>20</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>X</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblY">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>Y</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblZ">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>59</y>
- <width>16</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>Z</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblRotZ">
- <property name="geometry">
- <rect>
- <x>69</x>
- <y>59</y>
- <width>20</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>roll</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblRotX">
- <property name="geometry">
- <rect>
- <x>71</x>
- <y>20</y>
- <width>20</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>yaw</string>
- </property>
- </widget>
- <widget class="QLabel" name="lblRotY">
- <property name="geometry">
- <rect>
- <x>69</x>
- <y>40</y>
- <width>25</width>
- <height>16</height>
- </rect>
- </property>
- <property name="styleSheet">
- <string notr="true">color: rgb(0, 255, 0);</string>
- </property>
- <property name="text">
- <string>pitch</string>
- </property>
- </widget>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="title">
+ <string>Main tracker</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <widget class="QComboBox" name="iconcomboTrackerSource">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ <property name="maxVisibleItems">
+ <number>42</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnShowEngineControls">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Change tracker settings</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Settings</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
- <widget class="GLWidget" name="pose_display" native="true">
+ <widget class="QLabel" name="cameraName">
<property name="geometry">
<rect>
- <x>0</x>
- <y>0</y>
- <width>90</width>
- <height>90</height>
+ <x>370</x>
+ <y>10</y>
+ <width>411</width>
+ <height>25</height>
</rect>
</property>
<property name="sizePolicy">
@@ -2039,6 +886,829 @@ color: rgb(0, 255, 0);</string>
<height>0</height>
</size>
</property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="geometry">
+ <rect>
+ <x>350</x>
+ <y>160</y>
+ <width>191</width>
+ <height>91</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="title">
+ <string>Auxiliary tracker</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <widget class="QComboBox" name="cbxSecondTrackerSource">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ <property name="maxVisibleItems">
+ <number>42</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnShowSecondTrackerSettings">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Change tracker settings</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Settings</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QGroupBox" name="groupStartStop">
+ <property name="geometry">
+ <rect>
+ <x>350</x>
+ <y>400</y>
+ <width>190</width>
+ <height>65</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="title">
+ <string>GO!</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_9" rowstretch="0" columnstretch="0,0" rowminimumheight="0" columnminimumwidth="0,0">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinimumSize</enum>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QPushButton" name="btnStartTracker">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Start the Tracker</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Start</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="btnStopTracker">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Stop the Tracker</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QPushButton" name="btnShortcuts">
+ <property name="geometry">
+ <rect>
+ <x>580</x>
+ <y>340</y>
+ <width>171</width>
+ <height>38</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>62</width>
+ <height>38</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="cursor">
+ <cursorShape>PointingHandCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Edit the Keyboard and mouse shortcuts</string>
+ </property>
+ <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>
+ <widget class="QGroupBox" name="groupProfile">
+ <property name="geometry">
+ <rect>
+ <x>550</x>
+ <y>60</y>
+ <width>231</width>
+ <height>123</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="title">
+ <string>Profile</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5" rowstretch="6,6,6" columnstretch="6,6" rowminimumheight="6,6,6" columnminimumwidth="6,6">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0" colspan="2">
+ <widget class="QComboBox" name="iconcomboProfile">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ <property name="maxVisibleItems">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="btnLoad">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Load an INI-file from a folder</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Load</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="btnSave">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Save the current INI-file</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QPushButton" name="btnSaveAs">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Save the INI-file under another name</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string>Save As ...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>380</y>
+ <width>141</width>
+ <height>106</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Raw translation</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignHCenter</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMaximumSize</enum>
+ </property>
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::FieldsStayAtSizeHint</enum>
+ </property>
+ <property name="rowWrapPolicy">
+ <enum>QFormLayout::DontWrapRows</enum>
+ </property>
+ <property name="labelAlignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ <property name="formAlignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </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="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>TX</string>
+ </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="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>false</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="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLCDNumber" name="lcdNumY">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>false</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="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>TZ</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="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>380</y>
+ <width>161</width>
+ <height>111</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Raw rotation</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignHCenter</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMaximumSize</enum>
+ </property>
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::FieldsStayAtSizeHint</enum>
+ </property>
+ <property name="rowWrapPolicy">
+ <enum>QFormLayout::DontWrapRows</enum>
+ </property>
+ <property name="labelAlignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ <property name="formAlignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </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="QLabel" name="label_9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLCDNumber" name="lcdNumRotX">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>false</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="label_8">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLCDNumber" name="lcdNumRotY">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>false</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="label_7">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLCDNumber" name="lcdNumRotZ">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="smallDecimalPoint">
+ <bool>false</bool>
+ </property>
+ <property name="digitCount">
+ <number>4</number>
+ </property>
+ <property name="segmentStyle">
+ <enum>QLCDNumber::Flat</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ <zorder>lcdNumRotZ</zorder>
+ <zorder>label_8</zorder>
+ <zorder>label_7</zorder>
+ <zorder>lcdNumRotY</zorder>
+ <zorder>lcdNumRotX</zorder>
+ <zorder>label_9</zorder>
</widget>
</widget>
</widget>
@@ -2050,15 +1720,7 @@ color: rgb(0, 255, 0);</string>
<header>glwidget.h</header>
</customwidget>
</customwidgets>
- <tabstops>
- <tabstop>iconcomboTrackerSource</tabstop>
- <tabstop>btnStartTracker</tabstop>
- <tabstop>btnStopTracker</tabstop>
- <tabstop>btnShowEngineControls</tabstop>
- <tabstop>iconcomboProtocol</tabstop>
- </tabstops>
<resources>
- <include location="../ftnoir_protocol_ftn/ftn-protocol.qrc"/>
<include location="main-facetracknoir.qrc"/>
</resources>
<connections/>
diff --git a/facetracknoir/ftnoir_curves.ui b/facetracknoir/ftnoir_curves.ui
index 9dc79326..195083b9 100644
--- a/facetracknoir/ftnoir_curves.ui
+++ b/facetracknoir/ftnoir_curves.ui
@@ -6,12 +6,18 @@
<rect>
<x>0</x>
<y>0</y>
- <width>1050</width>
- <height>667</height>
+ <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>FaceTrackNoIR tracking curves</string>
+ <string>Mapping properties</string>
</property>
<property name="windowIcon">
<iconset>
@@ -20,891 +26,919 @@
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
<property name="styleSheet">
- <string notr="true">background-color: rgb(240, 240, 240);
-/*
-QWidget#widgetTop {
-background-color: #595959;
-border-bottom: 1px solid #000;
-}
-*/
-
-/* Make text in message boxes selectable. */
-QMessageBox {
-/* LinksAccessibleByMouse | TextSelectableByMouse */
-messagebox-text-interaction-flags: 5;
-}
-/* Make the entire row selected in item views. */
-QAbstractItemView {
-show-decoration-selected: 1;
-}
-
-/* Nice WindowsXP-style password character for password line edits. */
-QLineEdit[echoMode=&quot;2&quot;] {
-lineedit-password-character: 9679;
-}
-
-/* Customize tooltips. */
-QToolTip {
-background-color: rgb(170, 255, 127);
-opacity: 200;
-}
-
-/* Customize push buttons and comboboxes. Our read-only combobox
-is very similar to a push button, so they share the same border image. */
-
-QPushButton {
-min-width: 4em;
-}
-
-QPushButton:disabled {
-color: rgb(128, 128, 128);
-}
-
-QGroupBox {
-color: rgb(255, 255, 255);
-}</string>
+ <string notr="true">background-color: #ccc;</string>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string>rx</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="rxconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>921</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>5</number>
- </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>0</x>
- <y>280</y>
- <width>166</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Use alternative</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="rxconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>340</y>
- <width>921</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>5</number>
- </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>
- <widget class="QWidget" name="tab2">
- <attribute name="title">
- <string>ry</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="ryconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>595</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>90</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>90</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>10</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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>0</x>
- <y>280</y>
- <width>199</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Use alternative</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="ryconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>340</y>
- <width>1013</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>90</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>90</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>10</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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="tab3">
- <attribute name="title">
- <string>rz</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="rzconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>595</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>5</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>1</number>
- </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>0</x>
- <y>280</y>
- <width>271</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Use alternative</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="rzconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>340</y>
- <width>595</width>
- <height>240</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>180</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>5</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>1</number>
- </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="tab4">
- <attribute name="title">
- <string>tx</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="txconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>555</width>
- <height>270</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>7</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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>0</x>
- <y>280</y>
- <width>228</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Use alternative</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="txconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>310</y>
- <width>555</width>
- <height>160</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>7</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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="tab5">
- <attribute name="title">
- <string>ty</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="tyconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>555</width>
- <height>160</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>7</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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>0</x>
- <y>280</y>
- <width>229</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Use alternative</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="tyconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>310</y>
- <width>555</width>
- <height>160</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>7</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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="tab6">
- <attribute name="title">
- <string>tz</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="tzconfig" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>555</width>
- <height>160</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>7</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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>0</x>
- <y>280</y>
- <width>263</width>
- <height>21</height>
- </rect>
- </property>
- <property name="text">
- <string>Use alternative</string>
- </property>
- </widget>
- <widget class="QFunctionConfigurator" name="tzconfig_alt" native="true">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>310</y>
- <width>555</width>
- <height>160</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>100</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>7</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>2</number>
- </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="tab_2">
- <attribute name="title">
- <string>Positions</string>
- </attribute>
- <widget class="QLabel" name="label">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>44</y>
- <width>35</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>RY</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_2">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>34</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>RX</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_3">
- <property name="geometry">
- <rect>
- <x>9</x>
- <y>75</y>
- <width>33</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>RZ</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="pos_rx">
- <property name="geometry">
- <rect>
- <x>50</x>
- <y>10</y>
- <width>131</width>
- <height>22</height>
- </rect>
- </property>
- <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>
- <widget class="QDoubleSpinBox" name="pos_ry">
- <property name="geometry">
- <rect>
- <x>50</x>
- <y>40</y>
- <width>131</width>
- <height>22</height>
- </rect>
- </property>
- <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>
- <widget class="QDoubleSpinBox" name="pos_rz">
- <property name="geometry">
- <rect>
- <x>49</x>
- <y>71</y>
- <width>131</width>
- <height>22</height>
- </rect>
- </property>
- <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>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>209</x>
- <y>10</y>
- <width>32</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="pos_tx">
- <property name="geometry">
- <rect>
- <x>249</x>
- <y>10</y>
- <width>152</width>
- <height>22</height>
- </rect>
- </property>
- <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>
- <widget class="QDoubleSpinBox" name="pos_ty">
- <property name="geometry">
- <rect>
- <x>249</x>
- <y>40</y>
- <width>152</width>
- <height>22</height>
- </rect>
- </property>
- <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>
- <widget class="QDoubleSpinBox" name="pos_tz">
- <property name="geometry">
- <rect>
- <x>248</x>
- <y>71</y>
- <width>154</width>
- <height>22</height>
- </rect>
- </property>
- <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>
- <widget class="QLabel" name="label_5">
- <property name="geometry">
- <rect>
- <x>209</x>
- <y>44</y>
- <width>32</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_6">
- <property name="geometry">
- <rect>
- <x>208</x>
- <y>75</y>
- <width>35</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </widget>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="styleSheet">
+ <string notr="true">background-color: #ccc;</string>
+ </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="maxInputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>5</number>
+ </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>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="1">
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="2">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
+ <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="maxInputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>5</number>
+ </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="maxInputEGU" stdset="0">
+ <number>90</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>90</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>10</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>90</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>90</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>10</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>5</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>1</number>
+ </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="maxInputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>180</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>5</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>1</number>
+ </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="maxInputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>28</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>28</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>28</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>28</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>28</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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="maxInputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="maxOutputEGU" stdset="0">
+ <number>100</number>
+ </property>
+ <property name="pixPerEGU_Input" stdset="0">
+ <number>28</number>
+ </property>
+ <property name="pixPerEGU_Output" stdset="0">
+ <number>2</number>
+ </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">
+ <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="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>
+ <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="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="1" column="2">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>TY</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="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="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>
+ </layout>
</widget>
</item>
- <item>
- <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>0</width>
- <height>0</height>
- </size>
- </property>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="title">
+ <string>Translation compensation</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <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>Enablement</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <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>
+ <item row="2" column="0">
+ <widget class="QGroupBox" name="groupBox_4">
<property name="maximumSize">
<size>
- <width>100</width>
- <height>16777215</height>
+ <width>65536</width>
+ <height>65536</height>
</size>
</property>
- <property name="text">
- <string>Cancel</string>
- </property>
+ <property name="font">
+ <font>
+ <kerning>true</kerning>
+ </font>
+ </property>
+ <property name="title">
+ <string>Axis inversion</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="6,6,6" columnstretch="6,6" rowminimumheight="6,6,6" columnminimumwidth="6,6">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinAndMaxSize</enum>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="chkInvertYaw">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="chkInvertX">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="chkInvertPitch">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="chkInvertY">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="chkInvertRoll">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="chkInvertZ">
+ <property name="maximumSize">
+ <size>
+ <width>65536</width>
+ <height>65536</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background:none;</string>
+ </property>
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
</layout>
- </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>
@@ -915,25 +949,25 @@ color: rgb(255, 255, 255);
<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/>
- <designerdata>
- <property name="gridDeltaX">
- <number>10</number>
- </property>
- <property name="gridDeltaY">
- <number>10</number>
- </property>
- <property name="gridSnapX">
- <bool>false</bool>
- </property>
- <property name="gridSnapY">
- <bool>false</bool>
- </property>
- <property name="gridVisible">
- <bool>true</bool>
- </property>
- </designerdata>
<slots>
<slot>startEngineClicked()</slot>
<slot>stopEngineClicked()</slot>
diff --git a/facetracknoir/ftnoir_keyboardshortcuts.ui b/facetracknoir/ftnoir_keyboardshortcuts.ui
index e70b7536..94d11734 100644
--- a/facetracknoir/ftnoir_keyboardshortcuts.ui
+++ b/facetracknoir/ftnoir_keyboardshortcuts.ui
@@ -6,16 +6,22 @@
<rect>
<x>0</x>
<y>0</y>
- <width>289</width>
- <height>81</height>
+ <width>371</width>
+ <height>131</height>
</rect>
</property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="windowTitle">
- <string>FaceTrackNoIR Keyboard and Mouse shortcuts</string>
+ <string>Keyboard shortcuts</string>
</property>
<property name="windowIcon">
<iconset>
- <normaloff>images/FaceTrackNoIR.png</normaloff>images/FaceTrackNoIR.png</iconset>
+ <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -23,194 +29,176 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <widget class="QPushButton" name="btnCancel">
- <property name="geometry">
- <rect>
- <x>180</x>
- <y>50</y>
- <width>100</width>
- <height>23</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- <widget class="QPushButton" name="btnOK">
- <property name="geometry">
- <rect>
- <x>74</x>
- <y>50</y>
- <width>100</width>
- <height>23</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QComboBox" name="cbxCenterKey">
- <property name="geometry">
- <rect>
- <x>179</x>
- <y>19</y>
- <width>101</width>
- <height>20</height>
- </rect>
- </property>
- <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>
- <widget class="QLabel" name="textLabel2_4">
- <property name="geometry">
- <rect>
- <x>210</x>
- <y>0</y>
- <width>46</width>
- <height>16</height>
- </rect>
- </property>
- <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>
- <widget class="QCheckBox" name="chkCenterAlt">
- <property name="geometry">
- <rect>
- <x>141</x>
- <y>21</y>
- <width>36</width>
- <height>17</height>
- </rect>
- </property>
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Alt</string>
- </property>
- </widget>
- <widget class="QLabel" name="textLabel2_3">
- <property name="geometry">
- <rect>
- <x>5</x>
- <y>23</y>
- <width>33</width>
- <height>16</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" 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>
- <widget class="QCheckBox" name="chkCenterCtrl">
- <property name="geometry">
- <rect>
- <x>95</x>
- <y>21</y>
- <width>40</width>
- <height>17</height>
- </rect>
- </property>
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Ctrl</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="chkCenterShift">
- <property name="geometry">
- <rect>
- <x>44</x>
- <y>21</y>
- <width>45</width>
- <height>17</height>
- </rect>
- </property>
- <property name="maximumSize">
- <size>
- <width>50</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Shift</string>
- </property>
- </widget>
+ <layout class="QGridLayout" name="gridLayout">
+ <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="1" column="0">
+ <widget class="QLabel" name="textLabel2_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" 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="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="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="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="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>
+ <item row="2" column="0">
+ <widget class="QLabel" name="textLabel2_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" 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="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="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="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="3" column="3" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
<resources/>
<connections/>
diff --git a/facetracknoir/global-settings.cpp b/facetracknoir/global-settings.cpp
index f605b591..3b627860 100644
--- a/facetracknoir/global-settings.cpp
+++ b/facetracknoir/global-settings.cpp
@@ -1,6 +1,6 @@
#include "global-settings.h"
-#if !(defined(__WIN32) || defined(_WIN32))
+#if !(defined(_WIN32))
# include <dlfcn.h>
#endif
@@ -9,13 +9,6 @@ SelectedLibraries* Libraries = NULL;
SelectedLibraries::~SelectedLibraries()
{
if (pTracker) {
- pTracker->WaitForExit();
- }
- if (pSecondTracker) {
- pSecondTracker->WaitForExit();
- }
-
- if (pTracker) {
delete pTracker;
pTracker = NULL;
}
@@ -91,8 +84,8 @@ SelectedLibraries::SelectedLibraries(IDynamicLibraryProvider* mainApp) :
DynamicLibrary::DynamicLibrary(const QString& filename)
{
this->filename = filename;
+#if defined(_WIN32)
QString fullPath = QCoreApplication::applicationDirPath() + "/" + this->filename;
-#if defined(__WIN32) || defined(_WIN32)
handle = new QLibrary(fullPath);
Dialog = (SETTINGS_FUNCTION) handle->resolve(MAYBE_STDCALL_UNDERSCORE "GetDialog" CALLING_CONVENTION_SUFFIX_VOID_FUNCTION);
Constructor = (NULLARY_DYNAMIC_FUNCTION) handle->resolve(MAYBE_STDCALL_UNDERSCORE "GetConstructor" CALLING_CONVENTION_SUFFIX_VOID_FUNCTION);
@@ -102,6 +95,8 @@ DynamicLibrary::DynamicLibrary(const QString& filename)
handle = dlopen(latin1.constData(), RTLD_NOW |
# ifdef __linux
RTLD_DEEPBIND
+# elif defined(__APPLE__)
+ RTLD_LOCAL|RTLD_FIRST|RTLD_NOW
# else
0
# endif
@@ -128,7 +123,7 @@ DynamicLibrary::DynamicLibrary(const QString& filename)
DynamicLibrary::~DynamicLibrary()
{
-#if defined(__WIN32) || defined(_WIN32)
+#if defined(_WIN32)
handle->unload();
#else
if (handle)
diff --git a/facetracknoir/global-settings.h b/facetracknoir/global-settings.h
index 29a8da62..6b04b73b 100644
--- a/facetracknoir/global-settings.h
+++ b/facetracknoir/global-settings.h
@@ -1,6 +1,6 @@
#pragma once
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
# define CALLING_CONVENTION_SUFFIX_VOID_FUNCTION "@0"
# ifdef _MSC_VER
# define MAYBE_STDCALL_UNDERSCORE "_"
@@ -12,6 +12,14 @@
# define MAYBE_STDCALL_UNDERSCORE ""
#endif
+#ifdef _MSC_VER
+# define virt_override
+#else
+# define virt_override override
+#endif
+
+#include <cstdio>
+
#include <QWidget>
#include <QDebug>
#include <QString>
@@ -21,7 +29,7 @@
#include "ftnoir_filter_base/ftnoir_filter_base.h"
#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
# define CALLING_CONVENTION __stdcall
#else
# define CALLING_CONVENTION
@@ -57,7 +65,7 @@ public:
METADATA_FUNCTION Metadata;
QString filename;
private:
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
QLibrary* handle;
#else
void* handle;
diff --git a/facetracknoir/global-shortcuts.cpp b/facetracknoir/global-shortcuts.cpp
index 286200c0..1c10b160 100644
--- a/facetracknoir/global-shortcuts.cpp
+++ b/facetracknoir/global-shortcuts.cpp
@@ -1,9 +1,12 @@
#include "facetracknoir/facetracknoir.h"
-#if defined(__WIN32) || defined(_WIN32)
-#include <windows.h>
-#include <strmif.h>
-#include <dshow.h>
+#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
diff --git a/facetracknoir/images/facetracknoir.png b/facetracknoir/images/facetracknoir.png
index b57724e0..41b54524 100644
--- a/facetracknoir/images/facetracknoir.png
+++ b/facetracknoir/images/facetracknoir.png
Binary files differ
diff --git a/facetracknoir/images/settingsopen16.png b/facetracknoir/images/settingsopen16.png
deleted file mode 100644
index 5bf65f0d..00000000
--- a/facetracknoir/images/settingsopen16.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/main-facetracknoir.qrc b/facetracknoir/main-facetracknoir.qrc
index eb5ad991..6cb2e300 100644
--- a/facetracknoir/main-facetracknoir.qrc
+++ b/facetracknoir/main-facetracknoir.qrc
@@ -2,7 +2,6 @@
<qresource prefix="/">
<file>uielements/tools.png</file>
<file>images/settings16.png</file>
- <file>images/settingsopen16.png</file>
<file>uielements/curves.png</file>
<file>images/facetracknoir.png</file>
</qresource>
diff --git a/facetracknoir/main-settings.hpp b/facetracknoir/main-settings.hpp
new file mode 100644
index 00000000..c9b5ff66
--- /dev/null
+++ b/facetracknoir/main-settings.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <QString>
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct key_opts {
+ value<int> key_index;
+ value<bool> ctrl, alt, shift;
+ key_opts(pbundle b, const QString& name) :
+ key_index(b, QString("key-index-%1").arg(name), 0),
+ ctrl(b, QString("key-ctrl-%1").arg(name), 0),
+ alt(b, QString("key-alt-%1").arg(name), 0),
+ shift(b, QString("key-shift-%1").arg(name), 0)
+ {}
+};
+
+struct axis_opts {
+ value<double> zero;
+ value<bool> invert, altp;
+ axis_opts(pbundle b, QString pfx) :
+ zero(b, n(pfx, "zero-pos"), 0),
+ invert(b, n(pfx, "invert-axis"), false),
+ altp(b, n(pfx, "alt-axis-sign"), false)
+ {}
+private:
+ static inline QString n(QString pfx, QString name) {
+ return QString("%1-%2").arg(pfx, name);
+ }
+};
+
+struct main_settings {
+ pbundle b;
+ key_opts center_key;
+ key_opts toggle_key;
+ 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),
+ center_key(b, "center"),
+ toggle_key(b, "toggle"),
+ tracker_dll(b, "tracker-dll", ""),
+ tracker2_dll(b, "tracker2-dll", ""),
+ filter_dll(b, "filter-dll", ""),
+ protocol_dll(b, "protocol-dll", ""),
+ a_x(b, "x"),
+ a_y(b, "y"),
+ a_z(b, "z"),
+ a_yaw(b, "yaw"),
+ a_pitch(b, "pitch"),
+ a_roll(b, "roll"),
+ tcomp_p(b, "compensate-translation", true),
+ tcomp_tz(b, "compensate-translation-disable-z-axis", false)
+ {}
+};
diff --git a/facetracknoir/main.cpp b/facetracknoir/main.cpp
index fd0ca1cc..3143a093 100644
--- a/facetracknoir/main.cpp
+++ b/facetracknoir/main.cpp
@@ -1,62 +1,72 @@
-/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20100520 - WVR: Added class FaceApp, to override winEventFilter. It receives
- messages from the Game.
-*/
-
-#include "facetracknoir.h"
-#include "tracker.h"
-#include <QtGui/QApplication>
-#include <QDesktopWidget>
-#include <QDebug>
-#include <QList>
-
-#if defined(_WIN32)
-#include <windows.h>
-//#pragma comment(linker, "/SUBSYSTEM:console /ENTRY:mainCRTStartup")
-#endif
-int main(int argc, char** argv)
-{
-#if defined(_WIN32)
- (void) timeBeginPeriod(1);
-#endif
- QApplication app(argc, argv);
- QFont font;
- font.setFamily(font.defaultFamily());
- font.setPointSize(9);
- app.setFont(font);
- FaceTrackNoIR w;
- //
- // Create the Main Window and DeskTop and Exec!
- //
- QDesktopWidget desktop;
- w.move(desktop.screenGeometry().width()/2-w.width()/2, 100);
- w.show();
- qApp->exec();
-
- return 0;
-}
-
+/********************************************************************************
+* FaceTrackNoIR This program is a private project of the some enthusiastic *
+* gamers from Holland, who don't like to pay much for *
+* head-tracking. *
+* *
+* Copyright (C) 2010 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* *
+* Homepage *
+* *
+* 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 "tracker.h"
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QDebug>
+#include <QList>
+#include <QDir>
+#include <QStringList>
+#include <memory>
+
+#if defined(_WIN32) && defined(_MSC_VER)
+# include <windows.h>
+# ifdef OPENTRACK_BREAKPAD
+# include <exception_handler.h>
+using namespace google_breakpad;
+bool dumpCallback(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ bool succeeded)
+{
+ MessageBoxA(GetDesktopWindow(),
+ "Generating crash dump!\r\n"
+ "Please send the .dmp file to <sthalik@misaki.pl> to help us improve the code.",
+ "opentrack crashed :(",
+ MB_OK | MB_ICONERROR);
+ return succeeded;
+}
+
+# endif
+#endif
+
+int main(int argc, char** argv)
+{
+#if defined(OPENTRACK_BREAKPAD) && defined(_MSC_VER)
+ auto handler = new ExceptionHandler(L".", nullptr, dumpCallback, nullptr, -1);
+#endif
+ QApplication::setAttribute(Qt::AA_X11InitThreads, true);
+ QApplication app(argc, argv);
+ auto w = std::make_shared<FaceTrackNoIR>();
+
+ w->show();
+ app.exec();
+
+ return 0;
+}
+
diff --git a/facetracknoir/mingw-version-script.txt b/facetracknoir/mingw-version-script.txt
new file mode 100644
index 00000000..fe20ad37
--- /dev/null
+++ b/facetracknoir/mingw-version-script.txt
@@ -0,0 +1,8 @@
+{
+ global:
+ GetDialog?0;
+ GetConstructor?0;
+ GetMetadata?0;
+ local:
+ *;
+};
diff --git a/facetracknoir/options.h b/facetracknoir/options.h
new file mode 100644
index 00000000..3fd0e767
--- /dev/null
+++ b/facetracknoir/options.h
@@ -0,0 +1,319 @@
+/* Copyright (c) 2013 Stanislaw Halik
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#pragma once
+
+#include <QObject>
+#include <QSettings>
+#include <QMap>
+#include <QString>
+#include <QVariant>
+#include <QMutex>
+#include <QMutexLocker>
+#include <memory>
+#include <cassert>
+#include <QWidget>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QDoubleSpinBox>
+#include <QSpinBox>
+#include <QSlider>
+#include <QLineEdit>
+#include <QLabel>
+#include <QCoreApplication>
+
+#ifdef __GNUC__
+# define ov override
+#else
+# define ov
+#endif
+
+#include <QDebug>
+
+namespace options {
+ template<typename T>
+ inline T qcruft_to_t (const QVariant& t);
+
+ template<>
+ inline int qcruft_to_t<int>(const QVariant& t)
+ {
+ return t.toInt();
+ }
+
+ template<>
+ inline QString qcruft_to_t<QString>(const QVariant& t)
+ {
+ return t.toString();
+ }
+
+ template<>
+ inline bool qcruft_to_t<bool>(const QVariant& t)
+ {
+ return t.toBool();
+ }
+
+ template<>
+ inline double qcruft_to_t<double>(const QVariant& t)
+ {
+ return t.toDouble();
+ }
+
+ template<>
+ inline QVariant qcruft_to_t<QVariant>(const QVariant& t)
+ {
+ return t;
+ }
+
+ // snapshot of qsettings group at given time
+ class group {
+ private:
+ QMap<QString, QVariant> map;
+ QString name;
+ public:
+ group(const QString& name) : name(name)
+ {
+ QSettings settings(group::org);
+ QString currentFile =
+ settings.value("SettingsFile",
+ QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings iniFile(currentFile, QSettings::IniFormat);
+ iniFile.beginGroup(name);
+ for (auto& k : iniFile.childKeys())
+ map[k] = iniFile.value(k);
+ iniFile.endGroup();
+ }
+ static constexpr const char* org = "opentrack";
+ void save() {
+ QSettings settings(group::org);
+ QString currentFile =
+ settings.value("SettingsFile",
+ QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings s(currentFile, QSettings::IniFormat);
+ s.beginGroup(name);
+ for (auto& k : map.keys())
+ s.setValue(k, map[k]);
+ s.endGroup();
+ }
+ template<typename T>
+ T get(const QString& k) {
+ return qcruft_to_t<T>(map.value(k));
+ }
+
+ void put(const QString& s, const QVariant& d)
+ {
+ map[s] = d;
+ }
+ bool contains(const QString& s)
+ {
+ return map.contains(s);
+ }
+ };
+
+ class impl_bundle : public QObject {
+ Q_OBJECT
+ private:
+ QMutex mtx;
+ const QString group_name;
+ group saved;
+ group transient;
+ impl_bundle(const impl_bundle&) = delete;
+ impl_bundle& operator=(const impl_bundle&) = delete;
+ bool modified;
+ public:
+ impl_bundle(const QString& group_name) :
+ mtx(QMutex::Recursive),
+ group_name(group_name),
+ saved(group_name),
+ transient(saved),
+ modified(false)
+ {
+ }
+ void reload() {
+ QMutexLocker l(&mtx);
+ saved = group(group_name);
+ transient = saved;
+ emit reloaded();
+ }
+
+ std::shared_ptr<impl_bundle> make(const QString& name) {
+ return std::make_shared<impl_bundle>(name);
+ }
+ void store(const QString& name, const QVariant& datum)
+ {
+ QMutexLocker l(&mtx);
+ if (!transient.contains(name) || datum != transient.get<QVariant>(name))
+ {
+ if (!modified)
+ qDebug() << name << transient.get<QVariant>(name) << datum;
+ modified = true;
+ transient.put(name, datum);
+ emit bundleChanged();
+ }
+ }
+ bool contains(const QString& name)
+ {
+ QMutexLocker l(&mtx);
+ return transient.contains(name);
+ }
+ template<typename T>
+ T get(const QString& name) {
+ QMutexLocker l(&mtx);
+ return transient.get<T>(name);
+ }
+ void save()
+ {
+ QMutexLocker l(&mtx);
+ modified = false;
+ saved = transient;
+ transient.save();
+ }
+ void revert()
+ {
+ QMutexLocker l(&mtx);
+ modified = false;
+ transient = saved;
+ emit bundleChanged();
+ }
+
+ bool modifiedp() {
+ QMutexLocker l(&mtx);
+ return modified;
+ }
+ signals:
+ void bundleChanged();
+ void reloaded();
+ };
+
+ typedef std::shared_ptr<impl_bundle> pbundle;
+
+ class base_value : public QObject {
+ Q_OBJECT
+ public:
+ base_value(pbundle b, const QString& name) : b(b), self_name(name) {
+ connect(b.get(), SIGNAL(reloaded()), this, SLOT(reread_value()));
+ }
+ protected:
+ virtual QVariant operator=(const QVariant& datum) = 0;
+ pbundle b;
+ QString self_name;
+ public slots:
+ void reread_value()
+ {
+ this->operator=(b->get<QVariant>(self_name));
+ }
+ public slots:
+#define DEFINE_SLOT(t) void setValue(t datum) { this->operator=(qVariantFromValue(datum)); }
+ DEFINE_SLOT(double)
+ DEFINE_SLOT(int)
+ DEFINE_SLOT(QString)
+ DEFINE_SLOT(bool)
+ signals:
+#define DEFINE_SIGNAL(t) void valueChanged(t);
+ DEFINE_SIGNAL(double)
+ DEFINE_SIGNAL(int)
+ DEFINE_SIGNAL(QString)
+ DEFINE_SIGNAL(bool)
+ };
+
+ template<typename T>
+ class value : public base_value {
+ protected:
+ QVariant operator=(const QVariant& datum) {
+ auto foo = qcruft_to_t<T>(datum);
+ b->store(self_name, qVariantFromValue<T>(foo));
+ emit valueChanged(foo);
+ return datum;
+ }
+ public:
+ static constexpr const Qt::ConnectionType QT_CONNTYPE = Qt::UniqueConnection;
+ static constexpr const Qt::ConnectionType OPT_CONNTYPE = Qt::UniqueConnection;
+ value(pbundle b, const QString& name, T def) :
+ base_value(b, name)
+ {
+ if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid)
+ {
+ this->operator=(qVariantFromValue<T>(def));
+ }
+ }
+ operator T() { return b->get<T>(self_name); }
+ QVariant operator=(const T& datum)
+ {
+ return this->operator =(qVariantFromValue<T>(datum));
+ }
+ };
+
+ template<typename T, typename Q>
+ inline void tie_setting(value<T>&, Q*);
+
+ template<>
+ inline void tie_setting(value<int>& v, QComboBox* cb)
+ {
+ cb->setCurrentIndex(v);
+ base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<QString>& v, QComboBox* cb)
+ {
+ cb->setCurrentText(v);
+ v = cb->currentText();
+ base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<bool>& v, QCheckBox* cb)
+ {
+ cb->setChecked(v);
+ base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<double>& v, QDoubleSpinBox* dsb)
+ {
+ dsb->setValue(v);
+ base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<int>& v, QSpinBox* sb)
+ {
+ sb->setValue(v);
+ base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<int>& v, QSlider* sl)
+ {
+ sl->setValue(v);
+ base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<QString>& v, QLineEdit* le)
+ {
+ le->setText(v);
+ base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.QT_CONNTYPE);
+ base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.OPT_CONNTYPE);
+ }
+
+ template<>
+ inline void tie_setting(value<QString>& v, QLabel* lb)
+ {
+ lb->setText(v);
+ base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.OPT_CONNTYPE);
+ }
+
+ inline pbundle bundle(const QString& group) {
+ return std::make_shared<impl_bundle>(group);
+ }
+}
diff --git a/facetracknoir/qt-moc.h b/facetracknoir/qt-moc.h
new file mode 100644
index 00000000..8ccfffe8
--- /dev/null
+++ b/facetracknoir/qt-moc.h
@@ -0,0 +1,10 @@
+#include <QObject>
+
+// this file exists only such that cmake qt automoc is appeased
+
+class AutomocMe : public QObject {
+ Q_OBJECT
+private:
+ virtual void foo() = 0;
+ AutomocMe() {}
+};
diff --git a/facetracknoir/rotation.h b/facetracknoir/rotation.h
index dd70ca77..22f35abb 100644
--- a/facetracknoir/rotation.h
+++ b/facetracknoir/rotation.h
@@ -1,64 +1,64 @@
-/* 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 ROTATION_H
-#define ROTATION_H
-#include <cmath>
-// ----------------------------------------------------------------------------
-class Rotation {
-
-public:
- Rotation() : a(1.0),b(0.0),c(0.0),d(0.0) {}
- Rotation(double yaw, double pitch, double roll) { fromEuler(yaw, pitch, roll); }
- Rotation(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {}
-
- Rotation inv(){ // inverse
- return Rotation(a,-b,-c, -d);
- }
-
-
- // conversions
- // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
- void fromEuler(double yaw, double pitch, double roll)
- {
-
- double sin_phi = sin(roll/2.0);
- double cos_phi = cos(roll/2.0);
- double sin_the = sin(pitch/2.0);
- double cos_the = cos(pitch/2.0);
- double sin_psi = sin(yaw/2.0);
- double cos_psi = cos(yaw/2.0);
-
- 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 toEuler(double& yaw, double& pitch, double& roll)
- {
- roll = atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c));
- pitch = asin(2.0*(a*c - b*d));
- yaw = atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d));
- }
-
- const Rotation operator*(const Rotation& B)
- {
- const Rotation& A = *this;
- return Rotation(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);
- }
-
-protected:
- double a,b,c,d; // quaternion coefficients
-};
-
-
-
-#endif //ROTATION_H
+/* 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 ROTATION_H
+#define ROTATION_H
+#include <cmath>
+// ----------------------------------------------------------------------------
+class RotationType {
+
+public:
+ RotationType() : a(1.0),b(0.0),c(0.0),d(0.0) {}
+ RotationType(double yaw, double pitch, double roll) { fromEuler(yaw, pitch, roll); }
+ RotationType(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {}
+
+ RotationType inv(){ // inverse
+ return RotationType(a,-b,-c, -d);
+ }
+
+
+ // conversions
+ // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
+ void fromEuler(double yaw, double pitch, double roll)
+ {
+
+ double sin_phi = sin(roll/2.0);
+ double cos_phi = cos(roll/2.0);
+ double sin_the = sin(pitch/2.0);
+ double cos_the = cos(pitch/2.0);
+ double sin_psi = sin(yaw/2.0);
+ double cos_psi = cos(yaw/2.0);
+
+ 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 toEuler(double& yaw, double& pitch, double& roll) const
+ {
+ roll = atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c));
+ pitch = asin(2.0*(a*c - b*d));
+ yaw = atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d));
+ }
+
+ const RotationType operator*(const RotationType& B) const
+ {
+ const RotationType& A = *this;
+ return RotationType(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);
+ }
+
+protected:
+ double a,b,c,d; // quaternion coefficients
+};
+
+
+
+#endif //ROTATION_H
diff --git a/facetracknoir/shortcuts.cpp b/facetracknoir/shortcuts.cpp
new file mode 100644
index 00000000..a905be57
--- /dev/null
+++ b/facetracknoir/shortcuts.cpp
@@ -0,0 +1,150 @@
+#include "facetracknoir/facetracknoir.h"
+#include "facetracknoir/shortcuts.h"
+
+KeyboardShortcutDialog::KeyboardShortcutDialog( FaceTrackNoIR *ftnoir, QWidget *parent )
+ : QWidget( parent, Qt::Dialog)
+{
+ ui.setupUi( this );
+
+ QPoint offsetpos(100, 100);
+ this->move(parent->pos() + offsetpos);
+
+ mainApp = ftnoir; // Preserve a pointer to FTNoIR
+
+ // Connect Qt signals to member-functions
+ 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(mainApp->s.center_key.key_index, ui.cbxCenterKey);
+ tie_setting(mainApp->s.center_key.alt, ui.chkCenterAlt);
+ tie_setting(mainApp->s.center_key.shift, ui.chkCenterShift);
+ tie_setting(mainApp->s.center_key.ctrl, ui.chkCenterCtrl);
+
+ tie_setting(mainApp->s.toggle_key.key_index, ui.cbxToggleKey);
+ tie_setting(mainApp->s.toggle_key.alt, ui.chkToggleAlt);
+ tie_setting(mainApp->s.toggle_key.shift, ui.chkToggleShift);
+ tie_setting(mainApp->s.toggle_key.ctrl, ui.chkToggleCtrl);
+}
+
+//
+// OK clicked on server-dialog
+//
+void KeyboardShortcutDialog::doOK() {
+ mainApp->b->save();
+ this->close();
+ if (mainApp->tracker)
+ mainApp->bindKeyboardShortcuts();
+}
+
+void KeyboardShortcutDialog::doCancel() {
+ mainApp->b->revert();
+ close();
+}
+
+#if defined(_WIN32)
+#include <windows.h>
+
+KeybindingWorkerImpl::~KeybindingWorkerImpl() {
+ if (dinkeyboard) {
+ dinkeyboard->Unacquire();
+ dinkeyboard->Release();
+ }
+ if (din)
+ din->Release();
+}
+
+KeybindingWorkerImpl::KeybindingWorkerImpl(FaceTrackNoIR& w, Key keyCenter, Key keyToggle)
+: din(0), dinkeyboard(0), kCenter(keyCenter), kToggle(keyToggle), window(w), should_quit(true)
+{
+ if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) {
+ qDebug() << "setup DirectInput8 Creation failed!" << GetLastError();
+ return;
+ }
+ if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) {
+ din->Release();
+ din = 0;
+ qDebug() << "setup CreateDevice function failed!" << GetLastError();
+ return;
+ }
+ if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) {
+ qDebug() << "setup SetDataFormat function failed!" << GetLastError();
+ dinkeyboard->Release();
+ dinkeyboard = 0;
+ din->Release();
+ din = 0;
+ return;
+ }
+
+ if (dinkeyboard->SetCooperativeLevel((HWND) window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) {
+ dinkeyboard->Release();
+ din->Release();
+ din = 0;
+ dinkeyboard = 0;
+ qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError();
+ return;
+ }
+ if (dinkeyboard->Acquire() != DI_OK)
+ {
+ dinkeyboard->Release();
+ din->Release();
+ din = 0;
+ dinkeyboard = 0;
+ qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError();
+ return;
+ }
+ should_quit = false;
+}
+
+static bool isKeyPressed( const Key *key, const BYTE *keystate ) {
+ bool shift;
+ bool ctrl;
+ bool alt;
+
+ if (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) );
+
+ //
+ // If one of the modifiers is needed and not pressed, return false.
+ //
+ if (key->shift && !shift) return false;
+ if (key->ctrl && !ctrl) return false;
+ if (key->alt && !alt) return false;
+
+ //
+ // All is well!
+ //
+ return true;
+ }
+ 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)) \
+ window.s();
+
+void KeybindingWorkerImpl::run() {
+ BYTE keystate[256];
+ while (!should_quit)
+ {
+ if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) {
+ qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError();
+ Sleep(25);
+ continue;
+ }
+
+ PROCESS_KEY(kCenter, shortcutRecentered);
+ PROCESS_KEY(kToggle, shortcutToggled);
+
+ Sleep(25);
+ }
+}
+
+#else
+#endif
diff --git a/facetracknoir/shortcuts.h b/facetracknoir/shortcuts.h
new file mode 100644
index 00000000..f8c34be7
--- /dev/null
+++ b/facetracknoir/shortcuts.h
@@ -0,0 +1,85 @@
+#pragma once
+#include <QWidget>
+#include <QElapsedTimer>
+#include <QThread>
+#include <QMessageBox>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QSettings>
+#include "ui_ftnoir_keyboardshortcuts.h"
+
+class FaceTrackNoIR;
+
+class KeyboardShortcutDialog: public QWidget
+{
+ Q_OBJECT
+public:
+
+ KeyboardShortcutDialog( FaceTrackNoIR *ftnoir, QWidget *parent );
+private:
+ Ui::UICKeyboardShortcutDialog ui;
+ FaceTrackNoIR *mainApp;
+
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+extern QList<QString> global_key_sequences;
+
+#if defined(_WIN32)
+extern QList<int> global_windows_key_sequences;
+# undef DIRECTINPUT_VERSION
+# define DIRECTINPUT_VERSION 0x0800
+# include <windows.h>
+# include <dinput.h>
+
+struct Key {
+ BYTE keycode;
+ bool shift;
+ bool ctrl;
+ bool alt;
+ bool ever_pressed;
+ QElapsedTimer timer;
+public:
+ Key() : keycode(0), shift(false), ctrl(false), alt(false), ever_pressed(false)
+ {
+ }
+};
+#else
+typedef unsigned char BYTE;
+struct Key { int foo; };
+#endif
+
+#if defined(_WIN32)
+class KeybindingWorkerImpl {
+private:
+ LPDIRECTINPUT8 din;
+ LPDIRECTINPUTDEVICE8 dinkeyboard;
+ Key kCenter;
+ Key kToggle;
+ FaceTrackNoIR& window;
+public:
+ volatile bool should_quit;
+ ~KeybindingWorkerImpl();
+ KeybindingWorkerImpl(FaceTrackNoIR& w, Key keyCenter, Key keyToggle);
+ void run();
+};
+#else
+class KeybindingWorkerImpl {
+public:
+ KeybindingWorkerImpl(FaceTrackNoIR& w, Key keyCenter, Key keyToggle);
+ void run() {}
+};
+#endif
+
+class KeybindingWorker : public QThread, public KeybindingWorkerImpl {
+ Q_OBJECT
+public:
+ KeybindingWorker(FaceTrackNoIR& w, Key keyCenter, Key keyToggle) : KeybindingWorkerImpl(w, keyCenter, keyToggle)
+ {
+ }
+ void run() {
+ KeybindingWorkerImpl::run();
+ }
+};
diff --git a/facetracknoir/timer.hpp b/facetracknoir/timer.hpp
new file mode 100644
index 00000000..623836db
--- /dev/null
+++ b/facetracknoir/timer.hpp
@@ -0,0 +1,66 @@
+#pragma once
+#include <time.h>
+#if defined (_WIN32)
+# include <windows.h>
+# define CLOCK_MONOTONIC 0
+static inline void clock_gettime(int, struct timespec* ts)
+{
+ static LARGE_INTEGER freq;
+
+ if (!freq.QuadPart)
+ (void) QueryPerformanceFrequency(&freq);
+
+ LARGE_INTEGER d;
+
+ (void) QueryPerformanceCounter(&d);
+
+ d.QuadPart *= 1000000000L;
+ d.QuadPart /= freq.QuadPart;
+
+ ts->tv_sec = d.QuadPart / 1000000000L;
+ ts->tv_nsec = d.QuadPart % 1000000000L;
+}
+
+#else
+# if defined(__MACH__)
+# define CLOCK_MONOTONIC 0
+# include <inttypes.h>
+# include <mach/mach_time.h>
+static inline void clock_gettime(int, struct timespec* ts)
+{
+ static mach_timebase_info_data_t sTimebaseInfo;
+ uint64_t state, nsec;
+ if ( sTimebaseInfo.denom == 0 ) {
+ (void) mach_timebase_info(&sTimebaseInfo);
+ }
+ state = mach_absolute_time();
+ nsec = state * sTimebaseInfo.numer / sTimebaseInfo.denom;
+ ts->tv_sec = nsec / 1000000000L;
+ ts->tv_nsec = nsec % 1000000000L;
+}
+# endif
+#endif
+class Timer {
+private:
+ struct timespec state;
+ int conv(const struct timespec& cur)
+ {
+ return (cur.tv_sec - state.tv_sec) * 1000L + (cur.tv_nsec - state.tv_nsec) / 1000000L;
+ }
+public:
+ Timer() {
+ start();
+ }
+ int start() {
+ struct timespec cur;
+ (void) clock_gettime(CLOCK_MONOTONIC, &cur);
+ int ret = conv(cur);
+ state = cur;
+ return ret;
+ }
+ int elapsed() {
+ struct timespec cur;
+ (void) clock_gettime(CLOCK_MONOTONIC, &cur);
+ return conv(cur);
+ }
+};
diff --git a/facetracknoir/tracker.cpp b/facetracknoir/tracker.cpp
index 7eedfea1..ebc8246d 100644
--- a/facetracknoir/tracker.cpp
+++ b/facetracknoir/tracker.cpp
@@ -1,210 +1,173 @@
-/********************************************************************************
-* 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) 2012 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage: http://facetracknoir.sourceforge.net/home/default.htm *
-* *
-* 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/>. *
-*********************************************************************************/
+/* Copyright (c) 2012-2013 Stanislaw Halik <sthalik@misaki.pl>
+ *
+ * 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.
+ */
+
/*
- Modifications (last one on top):
- 20121215 - WVR: Fixed crash after message: protocol not installed correctly... by terminating the thread.
- 20120921 - WVR: Fixed centering when no filter is selected.
- 20120917 - WVR: Added Mouse-buttons to ShortKeys.
- 20120827 - WVR: Signal tracking = false to Curve-widget(s) when quitting run(). Also when Alternative Pitch curve is used.
- 20120805 - WVR: The FunctionConfig-widget is used to configure the Curves. It was tweaked some more, because the Accela filter now also
- uses the Curve(s). ToDo: make the ranges configurable by the user. Development on the Toradex IMU makes us realize, that
- a fixed input-range may not be so handy after all..
- 20120427 - WVR: The Protocol-code was already in separate DLLs, but the ListBox was still filled �statically�. Now, a Dir() of the
- EXE-folder is done, to locate Protocol-DLLs. The Icons were also moved to the DLLs
- 20120317 - WVR: The Filter and Tracker-code was moved to separate DLLs. The calling-method
- was changed accordingly.
- The face-tracker member-functions NotifyZeroed and refreshVideo were added, as
- requested by Stanislaw.
- 20110411 - WVR: Finished moving all Protocols to separate C++ projects. Every protocol now
- has it's own Class, that's inside it's own DLL. This reduces the size of the program,
- makes it more structured and enables a more sophisticated installer.
- 20110328 - WVR: Changed the camera-structs into class-instances. This makes initialisation
- easier and hopefully solves the remaining 'start-up problem'.
- 20110313 - WVR: Removed 'set_initial'. Less is more.
- 20110109 - WVR: Added setZero option to define behaviour after STOP tracking via shortkey.
- 20110104 - WVR: Removed a few nasty bugs (it was impossible to stop tracker without crash).
- 20101224 - WVR: Removed the QThread inheritance of the Base Class for the protocol-servers.
- Again, this drastically simplifies the code in the protocols.
- 20101217 - WVR: Created Base Class for the protocol-servers. This drastically simplifies
- the code needed here.
- 20101024 - WVR: Added shortkey to disable/enable one or more axis during tracking.
- 20101021 - WVR: Added FSUIPC server for FS2004.
- 20101011 - WVR: Added SimConnect server.
- 20101007 - WVR: Created 6DOF-curves and drastically changed the tracker for that.
- Also eliminated a 'glitch' in the process.
- 20100607 - WVR: Re-installed Rotation Neutral Zone and improved reaction
- after 'start/stop'. MessageBeep when confidence is back...
- 20100604 - WVR: Created structure for DOF-data and changed timing of
- ReceiveHeadPose end run().
- 20100602 - WVR: Implemented EWMA-filtering, according to the example of
- Melchior Franz. Works like a charm...
- 20100601 - WVR: Added DirectInput keyboard-handling. '=' used for center,
- 'BACK' for start (+center)/stop.
- 20100517 - WVR: Added upstream command(s) from FlightGear
- 20100523 - WVR: Checkboxes to invert 6DOF's was implemented. Multiply by
- 1 or (-1).
-*/
+ * this file appeared originally in facetracknoir, was rewritten completely
+ * following opentrack fork.
+ *
+ * originally written by Wim Vriend.
+ */
+
#include "tracker.h"
#include "facetracknoir.h"
+#include <opencv2/core/core.hpp>
+#include <cmath>
+#include <algorithm>
+
+#if defined(_WIN32)
+# include <windows.h>
+#endif
-/** constructor **/
-Tracker::Tracker( FaceTrackNoIR *parent ) :
- confid(false),
+Tracker::Tracker(FaceTrackNoIR *parent , main_settings& s) :
+ mainApp(parent),
+ s(s),
should_quit(false),
- do_center(false)
+ do_center(false),
+ enabled(true)
{
- // Retieve the pointer to the parent
- mainApp = parent;
- // Load the settings from the INI-file
- loadSettings();
}
Tracker::~Tracker()
{
+ should_quit = true;
+ wait();
}
static void get_curve(double pos, double& out, THeadPoseDOF& axis) {
- bool altp = (pos < 0) && axis.altp;
+ bool altp = (pos < 0) && axis.opts.altp;
if (altp) {
- out = axis.invert * axis.curveAlt.getValue(pos);
+ out = (axis.opts.invert ? -1 : 1) * axis.curveAlt.getValue(pos);
axis.curve.setTrackingActive( false );
axis.curveAlt.setTrackingActive( true );
}
else {
- out = axis.invert * axis.curve.getValue(pos);
+ out = (axis.opts.invert ? -1 : 1) * axis.curve.getValue(pos);
axis.curve.setTrackingActive( true );
axis.curveAlt.setTrackingActive( false );
}
- out += axis.zero;
+ out += axis.opts.zero;
+}
+
+static void t_compensate(double* input, double* output, bool rz)
+{
+ const auto H = input[Yaw] * M_PI / -180;
+ const auto P = input[Pitch] * M_PI / -180;
+ const auto B = input[Roll] * M_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,
+ };
+
+ cv::Mat rmat(3, 3, CV_64F, foo);
+ const cv::Mat tvec(3, 1, CV_64F, input);
+ cv::Mat ret = rmat * tvec;
+
+ const int max = !rz ? 3 : 2;
+
+ for (int i = 0; i < max; i++)
+ output[i] = ret.at<double>(i);
}
/** QThread run method @override **/
void Tracker::run() {
- T6DOF current_camera; // Used for filtering
- T6DOF target_camera;
- T6DOF new_camera;
-
- /** Direct Input variables **/
T6DOF offset_camera;
- T6DOF gameoutput_camera;
-
- bool bTracker1Confid = false;
- bool bTracker2Confid = false;
-
- double newpose[6];
- double last_post_filter[6];
-
- forever
- {
+
+ double newpose[6] = {0};
+ int sleep_ms = 15;
+
+ if (Libraries->pTracker)
+ sleep_ms = std::min(sleep_ms, 1000 / Libraries->pTracker->preferredHz());
+
+ if (Libraries->pSecondTracker)
+ sleep_ms = std::min(sleep_ms, 1000 / Libraries->pSecondTracker->preferredHz());
+
+ qDebug() << "tracker Hz:" << 1000 / sleep_ms;
+
+#if defined(_WIN32)
+ (void) timeBeginPeriod(1);
+#endif
+
+ for (;;)
+ {
if (should_quit)
break;
- for (int i = 0; i < 6; i++)
- newpose[i] = 0;
-
- //
- // The second tracker serves as 'secondary'. So if an axis is written by the second tracker it CAN be overwritten by the Primary tracker.
- // This is enforced by the sequence below.
- //
if (Libraries->pSecondTracker) {
- bTracker2Confid = Libraries->pSecondTracker->GiveHeadPoseData(newpose);
+ Libraries->pSecondTracker->GetHeadPoseData(newpose);
}
if (Libraries->pTracker) {
- bTracker1Confid = Libraries->pTracker->GiveHeadPoseData(newpose);
+ Libraries->pTracker->GetHeadPoseData(newpose);
}
{
QMutexLocker foo(&mtx);
- confid = bTracker1Confid || bTracker2Confid;
-
- if ( confid ) {
- for (int i = 0; i < 6; i++)
- mainApp->axis(i).headPos = newpose[i];
- }
-
- //
- // If Center is pressed, copy the current values to the offsets.
- //
+
+ for (int i = 0; i < 6; i++)
+ mainApp->axis(i).headPos = newpose[i];
+
if (do_center) {
- //
- // Only copy valid values
- //
- if (confid) {
- for (int i = 0; i < 6; i++)
- offset_camera.axes[i] = mainApp->axis(i).headPos;
- }
-
- Tracker::do_center = false;
-
- if (Libraries->pTracker)
- Libraries->pTracker->NotifyCenter();
-
- if (Libraries->pSecondTracker)
- Libraries->pSecondTracker->NotifyCenter();
-
+ for (int i = 0; i < 6; i++)
+ offset_camera.axes[i] = mainApp->axis(i).headPos;
+
+ do_center = false;
+
if (Libraries->pFilter)
- Libraries->pFilter->Initialize();
+ Libraries->pFilter->reset();
}
-
- if (getTrackingActive()) {
- // get values
+
+ T6DOF target_camera, target_camera2, new_camera;
+
+ if (enabled)
+ {
for (int i = 0; i < 6; i++)
target_camera.axes[i] = mainApp->axis(i).headPos;
-
- // do the centering
- target_camera = target_camera - offset_camera;
-
- //
- // Use advanced filtering, when a filter was selected.
- //
- if (Libraries->pFilter) {
- for (int i = 0; i < 6; i++)
- last_post_filter[i] = gameoutput_camera.axes[i];
- Libraries->pFilter->FilterHeadPoseData(current_camera.axes, target_camera.axes, new_camera.axes, last_post_filter);
- }
- else {
- new_camera = target_camera;
- }
-
- for (int i = 0; i < 6; i++) {
- get_curve(new_camera.axes[i], output_camera.axes[i], mainApp->axis(i));
- }
-
- //
- // Send the headpose to the game
- //
- if (Libraries->pProtocol) {
- gameoutput_camera = output_camera;
- Libraries->pProtocol->sendHeadposeToGame( gameoutput_camera.axes, newpose ); // degrees & centimeters
- }
+
+ target_camera2 = target_camera - offset_camera;
+ }
+
+ if (Libraries->pFilter) {
+ Libraries->pFilter->FilterHeadPoseData(target_camera2.axes, new_camera.axes);
+ } else {
+ new_camera = target_camera2;
+ }
+
+ for (int i = 0; i < 6; i++) {
+ get_curve(new_camera.axes[i], output_camera.axes[i], mainApp->axis(i));
+ }
+
+ if (mainApp->s.tcomp_p)
+ t_compensate(output_camera.axes, output_camera.axes, mainApp->s.tcomp_tz);
+
+ if (Libraries->pProtocol) {
+ Libraries->pProtocol->sendHeadposeToGame( output_camera.axes ); // degrees & centimeters
}
}
-
- //for lower cpu load
- msleep(1);
+
+ msleep(sleep_ms);
}
+#if defined(_WIN32)
+ (void) timeEndPeriod(1);
+#endif
for (int i = 0; i < 6; i++)
{
@@ -213,9 +176,6 @@ void Tracker::run() {
}
}
-//
-// Get the raw headpose, so it can be displayed.
-//
void Tracker::getHeadPose( double *data ) {
QMutexLocker foo(&mtx);
for (int i = 0; i < 6; i++)
@@ -224,42 +184,8 @@ void Tracker::getHeadPose( double *data ) {
}
}
-//
-// Get the output-headpose, so it can be displayed.
-//
void Tracker::getOutputHeadPose( double *data ) {
QMutexLocker foo(&mtx);
for (int i = 0; i < 6; i++)
data[i] = output_camera.axes[i];
}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void Tracker::loadSettings() {
- qDebug() << "Tracker::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup("Tracking");
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- const char* names2[] = {
- "zero_tx",
- "zero_ty",
- "zero_tz",
- "zero_rx",
- "zero_ry",
- "zero_rz"
- };
-
- for (int i = 0; i < 6; i++)
- mainApp->axis(i).zero = iniFile.value(names2[i], 0).toDouble();
-
- iniFile.endGroup();
-}
-
-void Tracker::setInvertAxis(Axis axis, bool invert) { mainApp->axis(axis).invert = invert?-1.0f:1.0f; }
diff --git a/facetracknoir/tracker.h b/facetracknoir/tracker.h
index f452395d..a33d8e0d 100644
--- a/facetracknoir/tracker.h
+++ b/facetracknoir/tracker.h
@@ -1,152 +1,100 @@
-/********************************************************************************
-* 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 - 2012 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/>. *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20120717 - WVR: FunctionConfig is now used for the Curves, instead of BezierConfig.
-*/
-#ifndef __TRACKER_H__
-#define __TRACKER_H__
-
-#include <QThread>
-#include <QMessageBox>
-#include <QLineEdit>
-#include <QPoint>
-#include <QWaitCondition>
-#include <QList>
-#include <QPainterPath>
-#include <QDebug>
-#include <QMutex>
-#include "global-settings.h"
-#include <ftnoir_tracker_base/ftnoir_tracker_types.h>
-
-//#define DIRECTINPUT_VERSION 0x0800
-//#include <Dinput.h>
-#undef FTNOIR_PROTOCOL_BASE_LIB
-#undef FTNOIR_TRACKER_BASE_LIB
-#undef FTNOIR_FILTER_BASE_LIB
-#undef FTNOIR_PROTOCOL_BASE_EXPORT
-#undef FTNOIR_TRACKER_BASE_EXPORT
-#undef FTNOIR_FILTER_BASE_EXPORT
-#define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_IMPORT
-#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT
-#define FTNOIR_FILTER_BASE_EXPORT Q_DECL_IMPORT
-
-#include <qfunctionconfigurator/functionconfig.h>
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#include "ftnoir_filter_base/ftnoir_filter_base.h"
-#include "tracker_types.h"
-
-class FaceTrackNoIR; // pre-define parent-class to avoid circular includes
-
-//
-// Structure to hold all variables concerning one of 6 DOF's
-//
-class THeadPoseDOF {
-private:
- THeadPoseDOF(const THeadPoseDOF &) {}
-public:
- THeadPoseDOF() :
- headPos(0),
- invert(0),
- altp(false),
- zero(0)
- {
- }
-
- THeadPoseDOF(QString primary,
- QString secondary,
- int maxInput1,
- int maxOutput1,
- int maxInput2,
- int maxOutput2) :
- curve(primary, maxInput1, maxOutput1),
- curveAlt(secondary, maxInput2, maxOutput2),
- headPos(0),
- invert(1),
- zero(0)
- {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
- curve.loadSettings(iniFile);
- curveAlt.loadSettings(iniFile);
-
- iniFile.beginGroup("Tracking");
- altp = iniFile.value(secondary).toBool();
- iniFile.endGroup();
- }
- double headPos; // Current position (from faceTracker, radials or meters)
- float invert; // Invert measured value (= 1.0f or -1.0f)
- FunctionConfig curve; // Function to translate input -> output
- FunctionConfig curveAlt;
- bool altp;
- double zero;
-};
-
-class Tracker : public QThread {
- Q_OBJECT
-
-private:
- FaceTrackNoIR *mainApp;
- QMutex mtx;
-
-protected:
- // qthread override run method
- void run();
-
-public:
- Tracker( FaceTrackNoIR *parent );
- ~Tracker();
- void loadSettings(); // Load settings from the INI-file
- bool getTrackingActive() { return confid; }
-
- void setInvertAxis(Axis axis, bool invert);
-
- void getHeadPose(double *data); // Return the current headpose data
- void getOutputHeadPose(double *data); // Return the current (processed) headpose data
-
- volatile bool should_quit;
- // following are now protected by hTrackMutex
- volatile bool do_center; // Center head-position, using the shortkey
- // Flags to start/stop/reset tracking
- volatile bool confid; // Tracker data is OK;
-
- T6DOF output_camera;
-};
-
-class HeadPoseData {
-public:
- THeadPoseDOF* axes[6];
- HeadPoseData()
- {
- axes[TX] = new THeadPoseDOF("tx","tx_alt", 100, 100, 100, 100);
- axes[TY] = new THeadPoseDOF("ty","ty_alt", 100, 100, 100, 100);
- axes[TZ] = new THeadPoseDOF("tz","tz_alt", 100, 100, 100, 100);
- axes[Yaw] = new THeadPoseDOF("rx", "rx_alt", 180, 180, 180, 180);
- axes[Pitch] = new THeadPoseDOF("ry", "ry_alt", 90, 90, 90, 90);
- axes[Roll] = new THeadPoseDOF("rz", "rz_alt", 180, 180, 180, 180);
- }
-};
-
-#endif
+#ifndef __TRACKER_H__
+#define __TRACKER_H__
+
+#include <QThread>
+#include <QMessageBox>
+#include <QLineEdit>
+#include <QPoint>
+#include <QWaitCondition>
+#include <QList>
+#include <QPainterPath>
+#include <QDebug>
+#include <QMutex>
+#include "global-settings.h"
+#include <ftnoir_tracker_base/ftnoir_tracker_types.h>
+#include <vector>
+
+#include <qfunctionconfigurator/functionconfig.h>
+#include "tracker_types.h"
+#include "facetracknoir/main-settings.hpp"
+#include "facetracknoir/options.h"
+using namespace options;
+
+class FaceTrackNoIR; // pre-define parent-class to avoid circular includes
+
+class THeadPoseDOF {
+private:
+ THeadPoseDOF(const THeadPoseDOF &) = delete;
+ THeadPoseDOF& operator=(const THeadPoseDOF&) = delete;
+public:
+ THeadPoseDOF(QString primary,
+ QString secondary,
+ int maxInput1,
+ int maxOutput1,
+ int maxInput2,
+ int maxOutput2,
+ axis_opts* opts) :
+ headPos(0),
+ curve(primary, maxInput1, maxOutput1),
+ curveAlt(secondary, maxInput2, maxOutput2),
+ opts(*opts)
+ {
+ QSettings settings("opentrack");
+ QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat );
+ curve.loadSettings(iniFile);
+ curveAlt.loadSettings(iniFile);
+ }
+ volatile double headPos;
+ FunctionConfig curve;
+ FunctionConfig curveAlt;
+ axis_opts& opts;
+};
+
+class Tracker : protected QThread {
+ Q_OBJECT
+
+private:
+ FaceTrackNoIR *mainApp;
+ QMutex mtx;
+ main_settings& s;
+ volatile bool should_quit;
+protected:
+ void run();
+
+public:
+ Tracker( FaceTrackNoIR *parent, main_settings& s);
+ ~Tracker();
+
+ void getHeadPose(double *data);
+ void getOutputHeadPose(double *data);
+ volatile bool do_center;
+ volatile bool enabled;
+
+ T6DOF output_camera;
+
+ void start() { QThread::start(); }
+};
+
+class HeadPoseData {
+public:
+ THeadPoseDOF* axes[6];
+ HeadPoseData(std::vector<axis_opts*> opts)
+ {
+ axes[TX] = new THeadPoseDOF("tx","tx_alt", 100, 100, 100, 100, opts[TX]);
+ axes[TY] = new THeadPoseDOF("ty","ty_alt", 100, 100, 100, 100, opts[TY]);
+ axes[TZ] = new THeadPoseDOF("tz","tz_alt", 100, 100, 100, 100, opts[TZ]);
+ axes[Yaw] = new THeadPoseDOF("rx", "rx_alt", 180, 180, 180, 180, opts[Yaw]);
+ axes[Pitch] = new THeadPoseDOF("ry", "ry_alt", 90, 90, 90, 90, opts[Pitch]);
+ axes[Roll] = new THeadPoseDOF("rz", "rz_alt", 180, 180, 180, 180, opts[Roll]);
+ }
+ ~HeadPoseData()
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ delete axes[i];
+ }
+ }
+};
+
+#endif
diff --git a/facetracknoir/tracker_types.cpp b/facetracknoir/tracker_types.cpp
index 11adc985..dec4ff81 100644
--- a/facetracknoir/tracker_types.cpp
+++ b/facetracknoir/tracker_types.cpp
@@ -1,44 +1,44 @@
-#include "tracker_types.h"
-#include "rotation.h"
-
-#define PI 3.14159265358979323846264
-#define D2R PI/180.0
-#define R2D 180.0/PI
-
-T6DOF operator-(const T6DOF& A, const T6DOF& B)
-{
- Rotation R_A(A.axes[Yaw]*D2R, A.axes[Pitch]*D2R, A.axes[Roll]*D2R);
- Rotation R_B(B.axes[Yaw]*D2R, B.axes[Pitch]*D2R, B.axes[Roll]*D2R);
- Rotation R_C = R_A * R_B.inv();
-
- T6DOF C;
- R_C.toEuler(C.axes[Yaw], C.axes[Pitch], C.axes[Roll]);
- C.axes[Yaw] *= R2D;
- C.axes[Pitch] *= R2D;
- C.axes[Roll] *= R2D;
-
- C.axes[TX] = A.axes[TX] - B.axes[TX];
- C.axes[TY] = A.axes[TY] - B.axes[TY];
- C.axes[TZ] = A.axes[TZ] - B.axes[TZ];
- //C.frame_number?
- return C;
-}
-
-T6DOF operator+(const T6DOF& A, const T6DOF& B)
-{
- Rotation R_A(A.axes[Yaw]*D2R, A.axes[Pitch]*D2R, A.axes[Roll]*D2R);
- Rotation R_B(B.axes[Yaw]*D2R, B.axes[Pitch]*D2R, B.axes[Roll]*D2R);
- Rotation R_C = R_A * R_B;
-
- T6DOF C;
- R_C.toEuler(C.axes[Yaw], C.axes[Pitch], C.axes[Roll]);
- C.axes[Yaw] *= R2D;
- C.axes[Pitch] *= R2D;
- C.axes[Roll] *= R2D;
-
- C.axes[TX] = A.axes[TX] + B.axes[TX];
- C.axes[TY] = A.axes[TY] + B.axes[TY];
- C.axes[TZ] = A.axes[TZ] + B.axes[TZ];
- //C.frame_number?
- return C;
-}
+#include "tracker_types.h"
+#include "rotation.h"
+
+#define PI 3.14159265358979323846264
+#define D2R PI/180.0
+#define R2D 180.0/PI
+
+T6DOF operator-(const T6DOF& A, const T6DOF& B)
+{
+ RotationType R_A(A.axes[Yaw]*D2R, A.axes[Pitch]*D2R, A.axes[Roll]*D2R);
+ RotationType R_B(B.axes[Yaw]*D2R, B.axes[Pitch]*D2R, B.axes[Roll]*D2R);
+ RotationType R_C = R_A * R_B.inv();
+
+ T6DOF C;
+ R_C.toEuler(C.axes[Yaw], C.axes[Pitch], C.axes[Roll]);
+ C.axes[Yaw] *= R2D;
+ C.axes[Pitch] *= R2D;
+ C.axes[Roll] *= R2D;
+
+ C.axes[TX] = A.axes[TX] - B.axes[TX];
+ C.axes[TY] = A.axes[TY] - B.axes[TY];
+ C.axes[TZ] = A.axes[TZ] - B.axes[TZ];
+ //C.frame_number?
+ return C;
+}
+
+T6DOF operator+(const T6DOF& A, const T6DOF& B)
+{
+ RotationType R_A(A.axes[Yaw]*D2R, A.axes[Pitch]*D2R, A.axes[Roll]*D2R);
+ RotationType R_B(B.axes[Yaw]*D2R, B.axes[Pitch]*D2R, B.axes[Roll]*D2R);
+ RotationType R_C = R_A * R_B;
+
+ T6DOF C;
+ R_C.toEuler(C.axes[Yaw], C.axes[Pitch], C.axes[Roll]);
+ C.axes[Yaw] *= R2D;
+ C.axes[Pitch] *= R2D;
+ C.axes[Roll] *= R2D;
+
+ C.axes[TX] = A.axes[TX] + B.axes[TX];
+ C.axes[TY] = A.axes[TY] + B.axes[TY];
+ C.axes[TZ] = A.axes[TZ] + B.axes[TZ];
+ //C.frame_number?
+ return C;
+}
diff --git a/facetracknoir/tracker_types.h b/facetracknoir/tracker_types.h
index d77a0b87..a367371e 100644
--- a/facetracknoir/tracker_types.h
+++ b/facetracknoir/tracker_types.h
@@ -1,46 +1,19 @@
-/********************************************************************************
-* 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 - 2012 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/>. *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20120924 - C14: Moved tracker types only used by Tracker to this file (should not be part of public interface)
- Modified operators to represent correct frame transitions
-*/
-#ifndef __TRACKER_TYPES_H__
-#define __TRACKER_TYPES_H__
-
-#include "ftnoir_tracker_base/ftnoir_tracker_types.h"
-
-struct T6DOF {
-public:
- double axes[6];
-
- T6DOF() {
- for (int i = 0; i < 6; i++)
- axes[i] = 0;
- }
-};
-
-T6DOF operator-(const T6DOF& A, const T6DOF& B); // get new pose with respect to reference pose B
-T6DOF operator+(const T6DOF& A, const T6DOF& B); // get new pose with respect to reference pose B^-1
-
-#endif //__TRACKER_TYPES_H__
+#ifndef __TRACKER_TYPES_H__
+#define __TRACKER_TYPES_H__
+
+#include "ftnoir_tracker_base/ftnoir_tracker_types.h"
+
+struct T6DOF {
+public:
+ double axes[6];
+
+ T6DOF() {
+ for (int i = 0; i < 6; i++)
+ axes[i] = 0;
+ }
+};
+
+T6DOF operator-(const T6DOF& A, const T6DOF& B); // get new pose with respect to reference pose B
+T6DOF operator+(const T6DOF& A, const T6DOF& B); // get new pose with respect to reference pose B^-1
+
+#endif //__TRACKER_TYPES_H__
diff --git a/facetracknoir/uielements/logo_facetracknoir_32px.jpg b/facetracknoir/uielements/logo_facetracknoir_32px.jpg
deleted file mode 100644
index 73ead853..00000000
--- a/facetracknoir/uielements/logo_facetracknoir_32px.jpg
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logo_facetracknoir_32px.png b/facetracknoir/uielements/logo_facetracknoir_32px.png
deleted file mode 100644
index c4e63c76..00000000
--- a/facetracknoir/uielements/logo_facetracknoir_32px.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logo_noir.png b/facetracknoir/uielements/logo_noir.png
deleted file mode 100644
index bb654a07..00000000
--- a/facetracknoir/uielements/logo_noir.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logo_noir_small.png b/facetracknoir/uielements/logo_noir_small.png
deleted file mode 100644
index 5d49e0b1..00000000
--- a/facetracknoir/uielements/logo_noir_small.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logo_noir_small_target.png b/facetracknoir/uielements/logo_noir_small_target.png
deleted file mode 100644
index 4bbaf41f..00000000
--- a/facetracknoir/uielements/logo_noir_small_target.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logo_noir_small_target90px.png b/facetracknoir/uielements/logo_noir_small_target90px.png
deleted file mode 100644
index ecaa4e12..00000000
--- a/facetracknoir/uielements/logo_noir_small_target90px.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logofacetracknoir.png b/facetracknoir/uielements/logofacetracknoir.png
deleted file mode 100644
index a1a3407b..00000000
--- a/facetracknoir/uielements/logofacetracknoir.png
+++ /dev/null
Binary files differ
diff --git a/facetracknoir/uielements/logofacetracknoir60px.png b/facetracknoir/uielements/logofacetracknoir60px.png
deleted file mode 100644
index f01f6024..00000000
--- a/facetracknoir/uielements/logofacetracknoir60px.png
+++ /dev/null
Binary files differ
diff --git a/freetrackclient/freetrackclient.cpp b/freetrackclient/freetrackclient.cpp
index 98544e2d..395f017d 100644
--- a/freetrackclient/freetrackclient.cpp
+++ b/freetrackclient/freetrackclient.cpp
@@ -1,36 +1,22 @@
-/********************************************************************************
-* FreeTrackClientDll Implements the FreeTrack 2.0 interface for FT-enabled *
-* games. *
-* It uses the FreeTrack protocol (memory mapping) to *
-* receive data from FaceTrackNoIR (or FreeTrack, or ...). *
-* *
-* Copyright (C) 2013 Wim Vriend (Developing) *
-* Ron Hendriks (Testing and Research) *
-* *
-* Homepage <http://facetracknoir.sourceforge.net/home/default.htm> *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
-
- 20130208 - WVR: The old DLL from FreeTrack seems to crash ArmA2. And we need 64-bit support.
-
-*/
-
-#define FT_EXPORT(t) extern "C" t __declspec(dllexport) __stdcall
+/***********************************************************************************
+ * * FTTypes FTTypes contains the specific type definitions for the *
+ * * FreeTrack protocol. *
+ * * It was loosely translated from FTTypes.pas *
+ * * which was created by the FreeTrack-team. *
+ * * *
+ * * Wim Vriend (Developing) *
+ * * Ron Hendriks (Testing and Research) *
+ * * *
+ * * Homepage <http://facetracknoir.sourceforge.net/home/default.htm> *
+ * * *
+ * * 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. *
+ * * *
+ * * *
+ * * The FreeTrackClient sources were translated from the original Delphi sources *
+ * * created by the FreeTrack developers. *
+ */
#define NP_AXIS_MAX 16383
#include <stdarg.h>
@@ -38,18 +24,19 @@
#include <stdio.h>
#include <string.h>
#include <windows.h>
-#include <tchar.h>
+//#include <tchar.h>
-#include "ftnoir_protocol_ft\fttypes.h"
+#include "ftnoir_protocol_ft/fttypes.h"
+
+#define FT_EXPORT(t) extern "C" __declspec(dllexport) t __stdcall
//
// Functions to create/open the file-mapping
// and to destroy it again.
//
-bool FTCreateMapping();
-void FTDestroyMapping();
-float scale2AnalogLimits( float x, float min_x, float max_x );
-float getDegreesFromRads ( float rads );
+static float scale2AnalogLimits( float x, float min_x, float max_x );
+static float getDegreesFromRads ( float rads );
+FT_EXPORT(bool) FTCreateMapping(void);
#if 0
static FILE *debug_stream = fopen("c:\\FreeTrackClient.log", "a");
@@ -64,8 +51,8 @@ static FILE *debug_stream = fopen("c:\\FreeTrackClient.log", "a");
static HANDLE hFTMemMap = 0;
static FTMemMap *pMemData = 0;
static HANDLE hFTMutex = 0;
-static char* dllVersion = "1.0.0.0";
-static char* dllProvider = "FreeTrack";
+static const char* dllVersion = "1.0.0.0";
+static const char* dllProvider = "FreeTrack";
static unsigned short gameid = 0;
@@ -98,13 +85,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
/******************************************************************
* FTGetData (FreeTrackClient.1)
*/
+
#pragma comment(linker, "/export:FTGetData@4=FTGetData")
FT_EXPORT(bool) FTGetData(PFreetrackData data)
{
- static int frame = 0;
static int prevDataID = 0;
static int dlyTrackingOff = 0;
- static int tracking = 0;
+
// dbg_report("NP_GetData called.");
if (FTCreateMapping() == false) return false;
@@ -123,7 +110,6 @@ FT_EXPORT(bool) FTGetData(PFreetrackData data)
dlyTrackingOff++;
if (dlyTrackingOff > 20) {
dlyTrackingOff = 100;
- tracking = false;
}
}
prevDataID = pMemData->data.DataID;
@@ -167,7 +153,7 @@ FT_EXPORT(void) FTReportName( int name )
* FTGetDllVersion (FreeTrackClient.3)
*/
#pragma comment(linker, "/export:FTGetDllVersion@0=FTGetDllVersion")
-extern "C" __declspec( dllexport ) char* FTGetDllVersion(void)
+FT_EXPORT(const char*) FTGetDllVersion(void)
{
dbg_report("FTGetDllVersion request.\n");
@@ -178,7 +164,7 @@ extern "C" __declspec( dllexport ) char* FTGetDllVersion(void)
* FTProvider (FreeTrackClient.4)
*/
#pragma comment(linker, "/export:FTProvider@0=FTProvider")
-extern "C" __declspec( dllexport ) char* FTProvider(void)
+FT_EXPORT(const char*) FTProvider(void)
{
dbg_report("FTProvider request.\n");
@@ -190,10 +176,8 @@ extern "C" __declspec( dllexport ) char* FTProvider(void)
// It contains the tracking data, a handle to the main-window and the program-name of the Game!
//
//
-bool FTCreateMapping()
+FT_EXPORT(bool) FTCreateMapping(void)
{
- bool bMappingExists = false;
-
//
// Memory-mapping already exists!
//
@@ -217,7 +201,6 @@ bool FTCreateMapping()
if ( ( hFTMemMap != 0 ) && ( GetLastError() == ERROR_ALREADY_EXISTS ) ) {
dbg_report("FTCreateMapping: Mapping already exists.\n");
- bMappingExists = true; // So the server was (probably) already started!
CloseHandle( hFTMemMap );
hFTMemMap = 0;
}
@@ -240,7 +223,7 @@ bool FTCreateMapping()
//
// Destory the FileMapping to the shared memory
//
-void FTDestroyMapping()
+FT_EXPORT(void) FTDestroyMapping(void)
{
if ( pMemData != NULL ) {
UnmapViewOfFile ( pMemData );
@@ -255,14 +238,14 @@ void FTDestroyMapping()
//
// 4 convenience
//
-float getDegreesFromRads ( float rads ) {
+static float getDegreesFromRads ( float rads ) {
return (rads * 57.295781f);
}
//
// Scale the measured value to the TIR values
//
-float scale2AnalogLimits( float x, float min_x, float max_x ) {
+static float scale2AnalogLimits( float x, float min_x, float max_x ) {
double y;
double local_x;
diff --git a/freetrackclient/freetrackclient.def b/freetrackclient/freetrackclient.def
new file mode 100644
index 00000000..155648dd
--- /dev/null
+++ b/freetrackclient/freetrackclient.def
@@ -0,0 +1,6 @@
+LIBRARY freetrackclient.dll
+EXPORTS
+FTGetData@4 = FTGetData
+FTReportName@4 = FTReportName
+FTGetDllVersion@0 = FTGetDllVersion
+FTProvider@0 = FTProvider
diff --git a/freetrackclient/ftclient.h b/freetrackclient/ftclient.h
deleted file mode 100644
index 406e1237..00000000
--- a/freetrackclient/ftclient.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/** @file
- @brief
-*/
-#pragma once
-#ifndef INCLUDED_FTCLIENT_H
-#define INCLUDED_FTCLIENT_H
-
-
-
-
-
-
-#include "Windows.h"
-#include "SysUtils.h"
-#include "FTTypes.h"
-
-/*__stdcall*/ bool FTGetData(PFreetrackData data);
-/*__stdcall*/ void FTReportName(PAnsiChar name);
-/*__stdcall*/ char* FTGetDllVersion();
-/*__stdcall*/ char* FTProvider();
-
-
-bool OpenMapping();
-void DestroyMapping();
-
-
-
-
-#endif//INCLUDED_FTCLIENT_H
-//END
diff --git a/ftnoir_csv/csv.cpp b/ftnoir_csv/csv.cpp
index 26b675fc..66823d24 100644
--- a/ftnoir_csv/csv.cpp
+++ b/ftnoir_csv/csv.cpp
@@ -136,9 +136,9 @@ void CSV::getGameData( const int id, unsigned char* table, QString& gamename)
//
if (gameLine.count() > 6) {
if (gameLine.at(6).compare( gameID, Qt::CaseInsensitive ) == 0) {
- QByteArray id = gameLine.at(7).toAscii();
- int tmp[8];
- int fuzz[3];
+ QByteArray id = gameLine.at(7).toLatin1();
+ unsigned int tmp[8];
+ unsigned int fuzz[3];
if (gameLine.at(3) == QString("V160"))
{
qDebug() << "no table";
@@ -155,7 +155,7 @@ void CSV::getGameData( const int id, unsigned char* table, QString& gamename)
tmp + 6,
tmp + 5,
tmp + 4,
- fuzz + 1) != 11 || ((fuzz[2] << 8) | fuzz[0]) != gameLine.at(0).toInt())
+ fuzz + 1) != 11)
{
qDebug() << "scanf failed" << fuzz[0] << fuzz[1] << fuzz[2];
}
@@ -177,4 +177,4 @@ void CSV::getGameData( const int id, unsigned char* table, QString& gamename)
//
qDebug() << "Unknown game connected" << gameID;
file.close();
-} \ No newline at end of file
+}
diff --git a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui
index 1478254e..c544263d 100644
--- a/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui
+++ b/ftnoir_filter_accela/ftnoir_accela_filtercontrols.ui
@@ -3,22 +3,40 @@
<class>AccelaUICFilterControls</class>
<widget class="QWidget" name="AccelaUICFilterControls">
<property name="windowModality">
- <enum>Qt::ApplicationModal</enum>
+ <enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>868</width>
- <height>729</height>
+ <width>261</width>
+ <height>330</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>Filter settings</string>
+ <string>Accela filter settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>images/FaceTrackNoIR.png</normaloff>images/FaceTrackNoIR.png</iconset>
+ <iconset resource="../ftnoir_filter_ewma2/ewma-filter.qrc">
+ <normaloff>:/images/filter-16.png</normaloff>:/images/filter-16.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -29,515 +47,360 @@
<property name="styleSheet">
<string notr="true"/>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="enabled">
- <bool>true</bool>
+ <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="Preferred">
+ <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
- <width>850</width>
- <height>650</height>
+ <width>25</width>
+ <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>300</width>
- <height>650</height>
+ <width>150</width>
+ <height>16777215</height>
</size>
</property>
- <property name="currentIndex">
+ <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>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;Accela by &lt;a href=&quot;https://github.com/sthalik&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;Stanisław Halik&lt;/span&gt;&lt;/a&gt;&lt;br/&gt;Help from &lt;a href=&quot;https://github.com/dbaarda&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;Donovan Baarda&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;2012-2013&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="margin">
<number>0</number>
</property>
- <widget class="QWidget" name="tab_3">
- <attribute name="title">
- <string>Preset</string>
- </attribute>
- <widget class="QLabel" name="label_2">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>111</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Rotation smoothing</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_3">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>111</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Translation smoothing</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="rotationCircle">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>10</y>
- <width>81</width>
- <height>22</height>
- </rect>
- </property>
- <property name="minimum">
- <double>0.100000000000000</double>
- </property>
- <property name="maximum">
- <double>10.000000000000000</double>
- </property>
- <property name="value">
- <double>3.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="translationCircle">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>40</y>
- <width>81</width>
- <height>22</height>
- </rect>
- </property>
- <property name="minimum">
- <double>0.100000000000000</double>
- </property>
- <property name="maximum">
- <double>10.000000000000000</double>
- </property>
- <property name="value">
- <double>0.750000000000000</double>
- </property>
- </widget>
- <widget class="QPushButton" name="resetCircle">
- <property name="geometry">
- <rect>
- <x>140</x>
- <y>70</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>Set curves</string>
- </property>
- </widget>
- <widget class="QPushButton" name="removeAllButton">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>70</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>Remove all</string>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string>Rotation</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="scalingConfig" native="true">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>10</y>
- <width>819</width>
- <height>571</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>10</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>10</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>57</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>57</number>
- </property>
- <property name="gridDistEGU_Input" stdset="0">
- <number>1</number>
- </property>
- <property name="gridDistEGU_Output" stdset="0">
- <number>1</number>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>255</red>
- <green>170</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>192</red>
- <green>192</green>
- <blue>192</blue>
- </color>
- </property>
- <property name="stringInputEGU" stdset="0">
- <string>Input</string>
- </property>
- <property name="stringOutputEGU" stdset="0">
- <string>Output</string>
- </property>
- <property name="stringCaption" stdset="0">
- <string>Translation</string>
- </property>
- </widget>
- </widget>
- <widget class="QWidget" name="tab_2">
- <attribute name="title">
- <string>Translation</string>
- </attribute>
- <widget class="QFunctionConfigurator" name="translationScalingConfig" native="true">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>10</y>
- <width>819</width>
- <height>581</height>
- </rect>
- </property>
- <property name="maxInputEGU" stdset="0">
- <number>10</number>
- </property>
- <property name="maxOutputEGU" stdset="0">
- <number>10</number>
- </property>
- <property name="pixPerEGU_Input" stdset="0">
- <number>57</number>
- </property>
- <property name="pixPerEGU_Output" stdset="0">
- <number>57</number>
- </property>
- <property name="gridDistEGU_Input" stdset="0">
- <number>1</number>
- </property>
- <property name="gridDistEGU_Output" stdset="0">
- <number>1</number>
- </property>
- <property name="colorBezier" stdset="0">
- <color>
- <red>85</red>
- <green>255</green>
- <blue>0</blue>
- </color>
- </property>
- <property name="colorBackground" stdset="0">
- <color>
- <red>192</red>
- <green>192</green>
- <blue>192</blue>
- </color>
- </property>
- <property name="stringInputEGU" stdset="0">
- <string>Input</string>
- </property>
- <property name="stringOutputEGU" stdset="0">
- <string>Output</string>
- </property>
- </widget>
- </widget>
+ <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>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="lblSensYaw_4">
- <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>Reduction factor:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSlider" name="slideReduction">
- <property name="minimumSize">
- <size>
- <width>50</width>
- <height>15</height>
- </size>
- </property>
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>1000</number>
- </property>
- <property name="pageStep">
- <number>5</number>
- </property>
- <property name="value">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::NoTicks</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="spinReduction">
- <property name="minimumSize">
- <size>
- <width>35</width>
- <height>22</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="readOnly">
- <bool>false</bool>
- </property>
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>1000</number>
- </property>
- <property name="value">
- <number>100</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="lblSensYaw_5">
- <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>Zoom slowness:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSlider" name="slideZoom">
- <property name="minimumSize">
- <size>
- <width>50</width>
- <height>15</height>
- </size>
- </property>
- <property name="minimum">
- <number>0</number>
- </property>
- <property name="maximum">
- <number>200</number>
- </property>
- <property name="pageStep">
- <number>1</number>
- </property>
- <property name="value">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="tickPosition">
- <enum>QSlider::NoTicks</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="spinZoom">
- <property name="minimumSize">
- <size>
- <width>35</width>
- <height>22</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">background:none;</string>
- </property>
- <property name="readOnly">
- <bool>false</bool>
- </property>
- <property name="minimum">
- <number>0</number>
- </property>
- <property name="maximum">
- <number>200</number>
- </property>
- <property name="value">
- <number>100</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <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>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="spacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnOK">
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnCancel">
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="9" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </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>
+ </widget>
</item>
</layout>
</widget>
- <customwidgets>
- <customwidget>
- <class>QFunctionConfigurator</class>
- <extends>QWidget</extends>
- <header>qfunctionconfigurator.h</header>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections>
- <connection>
- <sender>slideReduction</sender>
- <signal>valueChanged(int)</signal>
- <receiver>spinReduction</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>219</x>
- <y>620</y>
- </hint>
- <hint type="destinationlabel">
- <x>310</x>
- <y>622</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>spinReduction</sender>
- <signal>valueChanged(int)</signal>
- <receiver>slideReduction</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>315</x>
- <y>613</y>
- </hint>
- <hint type="destinationlabel">
- <x>170</x>
- <y>621</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>slideZoom</sender>
- <signal>valueChanged(int)</signal>
- <receiver>spinZoom</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>547</x>
- <y>602</y>
- </hint>
- <hint type="destinationlabel">
- <x>667</x>
- <y>602</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>spinZoom</sender>
- <signal>valueChanged(int)</signal>
- <receiver>slideZoom</receiver>
- <slot>setValue(int)</slot>
- <hints>
- <hint type="sourcelabel">
- <x>663</x>
- <y>602</y>
- </hint>
- <hint type="destinationlabel">
- <x>537</x>
- <y>602</y>
- </hint>
- </hints>
- </connection>
- </connections>
+ <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"/>
+ </resources>
+ <connections/>
<slots>
<slot>startEngineClicked()</slot>
<slot>stopEngineClicked()</slot>
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.cpp b/ftnoir_filter_accela/ftnoir_filter_accela.cpp
index 0aea2f78..31cb94bd 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela.cpp
+++ b/ftnoir_filter_accela/ftnoir_filter_accela.cpp
@@ -1,140 +1,104 @@
-/* Copyright (c) 2012 Stanislaw Halik
+/* Copyright (c) 2012-2013 Stanislaw Halik
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*/
-/*
- Modifications (last one on top):
- 20120807 - WVR: FunctionConfig is now also used for the Filter. The extrapolation was adapted from Stanislaw.
- Additional changes: I have added two parameters to the constructor of FunctionConfig and
- renamed 3 member-functions (getFilterFullName is now called getFullName).
-*/
#include "ftnoir_filter_accela/ftnoir_filter_accela.h"
-#include "math.h"
+#include <algorithm>
+#include <cmath>
#include <QDebug>
-#include <float.h>
+#include <QMutexLocker>
#include "facetracknoir/global-settings.h"
+using namespace std;
-#if !defined(_WIN32) && !defined(__WIN32)
-# define _isnan isnan
-#endif
-
-FTNoIR_Filter::FTNoIR_Filter() :
- functionConfig("Accela-Scaling-Rotation", 10, 10),
- translationFunctionConfig("Accela-Scaling-Translation", 10, 10)
+FTNoIR_Filter::FTNoIR_Filter() : first_run(true)
{
- first_run = true;
- kMagicNumber = 1000;
- loadSettings(); // Load the Settings
}
-FTNoIR_Filter::~FTNoIR_Filter()
+static inline double parabola(const double a, const double x, const double dz, const double expt)
{
-
+ const double sign = x > 0 ? 1 : -1;
+ const double a1 = 1./a;
+ return a1 * pow(std::max<double>(fabs(x) - dz, 0), expt) * sign;
}
-void FTNoIR_Filter::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- functionConfig.loadSettings(iniFile);
- translationFunctionConfig.loadSettings(iniFile);
-
- iniFile.beginGroup ( "Accela" );
- kMagicNumber = iniFile.value ( "Reduction", 1000 ).toFloat();
- kZoomSlowness = iniFile.value("zoom-slowness", 0).toFloat();
- iniFile.endGroup ();
+template<typename T>
+static inline T clamp(const T min, const T max, const T value)
+{
+ if (value < min)
+ return min;
+ if (value > max)
+ return max;
+ return value;
}
-void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position,
- double *target_camera_position,
- double *new_camera_position,
- double *last_post_filter_values)
+void FTNoIR_Filter::FilterHeadPoseData(const double* target_camera_position,
+ double *new_camera_position)
{
- double target[6];
- double prev_output[6];
- float output[6];
-
- for (int i = 0; i < 6; i++)
- {
- prev_output[i] = current_camera_position[i];
- target[i] = target_camera_position[i];
- }
-
if (first_run)
{
for (int i = 0; i < 6; i++)
{
- new_camera_position[i] = target[i];
- current_camera_position[i] = target[i];
+ new_camera_position[i] = target_camera_position[i];
+ last_input[i] = target_camera_position[i];
+ for (int j = 0; j < 3; j++)
+ last_output[j][i] = target_camera_position[i];
}
- first_run=false;
+ timer.start();
+ frame_delta = 1;
+ first_run = false;
return;
}
- for (int i=0;i<6;i++)
- {
- if (_isnan(target[i]))
- return;
-
- if (_isnan(prev_output[i]))
- return;
-
- double e2 = target[i];
- double start = prev_output[i];
- double vec = e2 - start;
- int sign = vec < 0 ? -1 : 1;
- double x = fabs(vec);
- QList<QPointF> points = (i >= 3 ? functionConfig : translationFunctionConfig).getPoints();
- int extrapolatep = 0;
- double ratio;
- double maxx;
- double add;
- // linear extrapolation of a spline
- if (points.size() > 1) {
- QPointF last = points[points.size() - 1];
- QPointF penultimate = points[points.size() - 2];
- ratio = (last.y() - penultimate.y()) / (last.x() - penultimate.x());
- extrapolatep = 1;
- add = last.y();
- maxx = last.x();
- }
- double foo = extrapolatep && x > maxx ? add + ratio * (x - maxx) : (i >= 3 ? functionConfig : translationFunctionConfig).getValue(x);
- // the idea is that "empty" updates without new head pose data are still
- // useful for filtering, as skipping them would result in jerky output.
- // the magic "100" is the amount of calls to the filter by FTNOIR per sec.
- // WVR: Added kMagicNumber for Patrick
- double velocity = foo / kMagicNumber * (1 / std::max(1.0, 1 + kZoomSlowness * -last_post_filter_values[TZ] / 100));
- double sum = start + velocity * sign;
- bool done = (sign > 0 ? sum >= e2 : sum <= e2);
- if (done) {
- output[i] = e2;
- } else {
- output[i] = sum;
- }
-
- if (_isnan(output[i]))
- return;
- }
+ bool new_frame = false;
for (int i = 0; i < 6; i++)
{
- new_camera_position[i] = output[i];
- current_camera_position[i] = output[i];
+ if (target_camera_position[i] != last_input[i])
+ {
+ new_frame = true;
+ break;
+ }
}
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Filter object.
-// Export both decorated and undecorated names.
-// GetFilter - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetFilter@0 - Common name decoration for __stdcall functions in C language.
+ if (new_frame)
+ {
+ for (int i = 0; i < 6; i++)
+ last_input[i] = target_camera_position[i];
+ frame_delta = timer.start();
+ } else {
+ auto d = timer.elapsed();
+ double c = clamp(0.0, 1.0, d / (double) frame_delta);
+ for (int i = 0; i < 6; i++)
+ new_camera_position[i] =
+ last_output[1][i] + (last_output[0][i] - last_output[1][i]) * c;
+ return;
+ }
+
+ 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];
+ new_camera_position[i] = done ? target_camera_position[i] : result;
+ last_output[2][i] = last_output[1][i];
+ last_output[1][i] = last_output[0][i];
+ last_output[0][i] = new_camera_position[i];
+ }
+}
extern "C" FTNOIR_FILTER_BASE_EXPORT IFilter* CALLING_CONVENTION GetConstructor()
{
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.h b/ftnoir_filter_accela/ftnoir_filter_accela.h
index 6e98c797..f56ae57c 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela.h
+++ b/ftnoir_filter_accela/ftnoir_filter_accela.h
@@ -1,66 +1,58 @@
-/********************************************************************************
-* 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 *
-* *
-* 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
-#ifndef INCLUDED_FTN_FILTER_H
-#define INCLUDED_FTN_FILTER_H
-
-#undef FTNOIR_TRACKER_BASE_LIB
-#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT
-
#include "ftnoir_filter_base/ftnoir_filter_base.h"
#include "ui_ftnoir_accela_filtercontrols.h"
-#include <qfunctionconfigurator/functionconfig.h>
#include "facetracknoir/global-settings.h"
+#include <QMutex>
+#include "facetracknoir/timer.hpp"
+
+#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 <facetracknoir/options.h>
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<double> rotation_alpha,
+ translation_alpha,
+ second_order_alpha,
+ third_order_alpha,
+ rot_deadzone,
+ trans_deadzone,
+ expt;
+ 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)
+ {}
+};
-//
-// Macro to determine array-size
-//
-#define NUM_OF(x) (sizeof (x) / sizeof *(x))
-
-//*******************************************************************************************************
-// FaceTrackNoIR Filter class.
-//*******************************************************************************************************
-class FTNOIR_FILTER_BASE_EXPORT FTNoIR_Filter : public IFilter
+class FTNoIR_Filter : public IFilter
{
public:
FTNoIR_Filter();
- ~FTNoIR_Filter();
- void FilterHeadPoseData(double *current_camera_position, double *target_camera_position, double *new_camera_position, double *last_post_filter_values);
- void Initialize() {
+ void FilterHeadPoseData(const double* target_camera_position, double *new_camera_position);
+ void reset() {
first_run = true;
}
+ void receiveSettings() {
+ s.b->reload();
+ }
private:
- void loadSettings(); // Load the settings from the INI-file
- double newHeadPose[6]; // Structure with new headpose
-
- bool first_run;
- double kMagicNumber, kZoomSlowness; // Stanislaws' magic number (should be 100 according to him...)
-
- FunctionConfig functionConfig;
- FunctionConfig translationFunctionConfig;
+ settings s;
+ bool first_run;
+ double last_input[6];
+ double last_output[3][6];
+ Timer timer;
+ qint64 frame_delta;
};
//*******************************************************************************************************
@@ -68,54 +60,30 @@ private:
//*******************************************************************************************************
// Widget that has controls for FTNoIR protocol filter-settings.
-class FTNOIR_FILTER_BASE_EXPORT FilterControls: public QWidget, public IFilterDialog
+class FilterControls: public QWidget, public IFilterDialog
{
Q_OBJECT
public:
-
- explicit FilterControls();
- virtual ~FilterControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent, IFilter *ptr);
-
+ FilterControls();
+ void registerFilter(IFilter* filter);
+ void unregisterFilter();
private:
Ui::AccelaUICFilterControls ui;
- void loadSettings();
+ void discard();
void save();
-
- /** helper **/
- bool settingsDirty;
-
- IFilter* pFilter; // If the filter was active when the dialog was opened, this will hold a pointer to the Filter instance
- FunctionConfig functionConfig;
- FunctionConfig translationFunctionConfig;
-
+ FTNoIR_Filter* accela_filter;
+ settings s;
private slots:
void doOK();
void doCancel();
- void settingChanged(bool) { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
- void resetCircle();
- void removeAll();
};
-//*******************************************************************************************************
-// FaceTrackNoIR Filter DLL. Functions used to get general info on the Filter
-//*******************************************************************************************************
class FTNoIR_FilterDll : public Metadata
{
public:
- FTNoIR_FilterDll();
- ~FTNoIR_FilterDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Filter Mk2"); }
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Mk2"); }
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Accela filter Mk2"); }
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Filter Mk4"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Mk4"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Accela filter Mk4"); }
void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); }
};
-
-
-#endif //INCLUDED_FTN_FILTER_H
-//END
-
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp
index 1de51b10..ca321891 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp
+++ b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp
@@ -1,250 +1,58 @@
-/********************************************************************************
-* 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) 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20130102 - WVR: Added 'reduction factor' to accommodate Patrick's need for speed.
-*/
-#include "ftnoir_filter_accela/ftnoir_filter_accela.h"
-#include <math.h>
-#include <QDebug>
-#include <algorithm>
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Filter Settings-dialog.
-//*******************************************************************************************************
-//
-// Constructor for server-settings-dialog
-//
-FilterControls::FilterControls() :
- QWidget(),
- functionConfig("Accela-Scaling-Rotation", 10, 10),
- translationFunctionConfig("Accela-Scaling-Translation", 10, 10)
-{
- ui.setupUi( this );
-
- // Load the settings from the current .INI-file
- loadSettings();
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.scalingConfig, SIGNAL(CurveChanged(bool)), this, SLOT(settingChanged(bool)));
- connect(ui.translationScalingConfig, SIGNAL(CurveChanged(bool)), this, SLOT(settingChanged(bool)));
- connect(ui.resetCircle, SIGNAL(clicked()), this, SLOT(resetCircle()));
- connect(ui.removeAllButton, SIGNAL(clicked()), this, SLOT(removeAll()));
-
- // Connect slider for reduction
- //connect(ui.slideReduction, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int)));
-
- qDebug() << "FilterControls() says: started";
-}
-
-//
-// Destructor for server-dialog
-//
-FilterControls::~FilterControls() {
- qDebug() << "~FilterControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void FilterControls::Initialize(QWidget *parent, IFilter* ptr) {
-
- //
- // The dialog can be opened, while the Tracker is running.
- // In that case, ptr will point to the active Filter-instance.
- // This can be used to update settings, while Tracking and may also be handy to display logging-data and such...
- //
- pFilter = ptr;
- loadSettings();
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void FilterControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void FilterControls::showEvent ( QShowEvent * event ) {
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void FilterControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FilterControls::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Filter::loadSettings2 says: iniFile = " << currentFile;
-
- //qDebug() << "FTNoIR_Filter::loadSettings2 says: size = " << NUM_OF(defScaleRotation);
-
- ui.translationScalingConfig->setConfig(&translationFunctionConfig, currentFile);
- ui.scalingConfig->setConfig(&functionConfig, currentFile);
-
- iniFile.beginGroup ( "Accela" );
- ui.slideReduction->setValue (iniFile.value ( "Reduction", 1000 ).toInt());
- ui.slideZoom->setValue(iniFile.value("zoom-slowness", 0).toInt());
- ui.rotationCircle->setValue(iniFile.value("preset-rotation", 3).toDouble());
- ui.translationCircle->setValue(iniFile.value("preset-translation", 0.75).toDouble());
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-void FilterControls::removeAll() {
- translationFunctionConfig.removeAllPoints();
- functionConfig.removeAllPoints();
-}
-
-void FilterControls::resetCircle()
-{
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
- iniFile.beginGroup ( "Accela" );
- iniFile.setValue("preset-rotation", ui.rotationCircle->value());
- iniFile.setValue("preset-translation", ui.translationCircle->value());
- iniFile.endGroup();
-
- // essentially unit circles elongated on the X axis
- double elongations[] = {
- ui.rotationCircle->value(), ui.translationCircle->value()
- };
-
- FunctionConfig* configs[] = {
- &functionConfig, &translationFunctionConfig
- };
-
- QFunctionConfigurator* widgets[] = {
- ui.scalingConfig, ui.translationScalingConfig
- };
-
- for (int i = 0; i < 2; i++)
- {
- FunctionConfig& cfg = *configs[i];
- double sz = elongations[i];
-
- cfg.removeAllPoints();
-
- for (double x = 0; x <= sz+1e-2; x += 1e-1)
- {
- double sq = sz*sz-x*x;
- double val;
- if (sq <= 1e-4)
- val = 0;
- else
- val = std::min<double>(sqrt(sq), sz);
-
- cfg.addPoint(QPointF(x, 10*(sz-val)/sz));
- }
-
- cfg.saveSettings(iniFile);
-
- widgets[i]->setConfig(&cfg, currentFile);
- }
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FilterControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Filter::save() says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Accela" );
- iniFile.setValue ( "Reduction", ui.slideReduction->value() );
- iniFile.setValue("zoom-slowness", ui.slideZoom->value());
- iniFile.endGroup ();
-
- functionConfig.saveSettings(iniFile);
- translationFunctionConfig.saveSettings(iniFile);
-
- settingsDirty = false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Filter-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetFilterDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetFilterDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetFilterDialog=_GetFilterDialog@0")
-
-extern "C" FTNOIR_FILTER_BASE_EXPORT IFilterDialog* CALLING_CONVENTION GetDialog()
-{
- return new FilterControls;
-}
+#include "ftnoir_filter_accela/ftnoir_filter_accela.h"
+#include <cmath>
+#include <QDebug>
+#include <algorithm>
+#include <QDoubleSpinBox>
+#include "facetracknoir/global-settings.h"
+
+FilterControls::FilterControls() :
+ accela_filter(nullptr)
+{
+ ui.setupUi( this );
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ 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);
+}
+
+void FilterControls::registerFilter(IFilter* filter)
+{
+ accela_filter = (FTNoIR_Filter*) filter;
+}
+
+void FilterControls::unregisterFilter()
+{
+ accela_filter = NULL;
+}
+
+void FilterControls::doOK() {
+ save();
+ this->close();
+}
+
+void FilterControls::doCancel() {
+ discard();
+ close();
+}
+
+void FilterControls::discard()
+{
+ s.b->revert();
+}
+
+void FilterControls::save() {
+ s.b->save();
+ if (accela_filter)
+ accela_filter->receiveSettings();
+}
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT IFilterDialog* CALLING_CONVENTION GetDialog()
+{
+ return new FilterControls;
+}
diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp
index 3ae273df..a024e789 100644
--- a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp
+++ b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp
@@ -1,57 +1,7 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The FilterDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_filter_accela.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_FilterDll::FTNoIR_FilterDll() {
-}
-
-FTNoIR_FilterDll::~FTNoIR_FilterDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Filter object.
-
-// Export both decorated and undecorated names.
-// GetFilterDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetFilterDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetFilterDll=_GetFilterDll@0")
-
-extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_FilterDll;
-}
+#include "ftnoir_filter_accela.h"
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_FilterDll;
+}
diff --git a/ftnoir_filter_base/ftnoir_filter_base.h b/ftnoir_filter_base/ftnoir_filter_base.h
index b38fc226..fbb0441d 100644
--- a/ftnoir_filter_base/ftnoir_filter_base.h
+++ b/ftnoir_filter_base/ftnoir_filter_base.h
@@ -10,53 +10,20 @@
#include <QMessageBox>
#include <QSettings>
-////////////////////////////////////////////////////////////////////////////////
-#ifdef __cplusplus
-# define EXTERN_C extern "C"
-#else
-# define EXTERN_C
-#endif // __cplusplus
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
struct IFilter
{
- virtual ~IFilter() {}
- virtual void FilterHeadPoseData(double *current_camera_position, double *target_camera_position, double *new_camera_position, double *last_post_filter) = 0;
- virtual void Initialize() = 0;
+ virtual ~IFilter() = 0;
+ virtual void FilterHeadPoseData(const double *target_camera_position, double *new_camera_position) = 0;
+ virtual void reset() = 0;
};
-// Factory function that creates instances of the Filter object.
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
-struct IFilterDll
-{
- virtual ~IFilterDll() {}
-
- virtual void getFullName(QString *strToBeFilled) = 0;
- virtual void getShortName(QString *strToBeFilled) = 0;
- virtual void getDescription(QString *strToBeFilled) = 0;
- virtual void getIcon(QIcon *icon) = 0;
-};
+inline IFilter::~IFilter() { }
struct IFilterDialog
{
virtual ~IFilterDialog() {}
- virtual void Initialize(QWidget *parent, IFilter* ptr) = 0;
-
- virtual void getFullName(QString *strToBeFilled) {};
- virtual void getShortName(QString *strToBeFilled) {};
- virtual void getDescription(QString *strToBeFilled) {};
- virtual void getIcon(QIcon *icon) {};
+ virtual void registerFilter(IFilter* tracker) = 0;
+ virtual void unregisterFilter() = 0;
};
#endif // FTNOIR_FILTER_BASE_H
diff --git a/ftnoir_filter_base/ftnoir_filter_base_global.h b/ftnoir_filter_base/ftnoir_filter_base_global.h
index a923f6cf..a1a13315 100644
--- a/ftnoir_filter_base/ftnoir_filter_base_global.h
+++ b/ftnoir_filter_base/ftnoir_filter_base_global.h
@@ -1,12 +1,16 @@
-#ifndef FTNOIR_FILTER_BASE_GLOBAL_H
-#define FTNOIR_FILTER_BASE_GLOBAL_H
-
-#include <QtGlobal>
-
-#ifdef FTNOIR_FILTER_BASE_LIB
-# define FTNOIR_FILTER_BASE_EXPORT Q_DECL_EXPORT
-#else
-# define FTNOIR_FILTER_BASE_EXPORT Q_DECL_IMPORT
-#endif
-
-#endif // FTNOIR_FILTER_BASE_GLOBAL_H
+#ifndef FTNOIR_FILTER_BASE_GLOBAL_H
+#define FTNOIR_FILTER_BASE_GLOBAL_H
+
+#include <QtGlobal>
+
+#ifndef OPENTRACK_MAIN
+# if !defined(_MSC_VER)
+# define FTNOIR_FILTER_BASE_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define FTNOIR_FILTER_BASE_EXPORT Q_DECL_EXPORT
+#endif
+#else
+# define FTNOIR_FILTER_BASE_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // FTNOIR_FILTER_BASE_GLOBAL_H
diff --git a/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui b/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui
index 0f31bcd3..8ee633cc 100644
--- a/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui
+++ b/ftnoir_filter_ewma2/ftnoir_ewma_filtercontrols.ui
@@ -2,11 +2,14 @@
<ui version="4.0">
<class>UICFilterControls</class>
<widget class="QWidget" name="UICFilterControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>371</width>
+ <width>477</width>
<height>380</height>
</rect>
</property>
@@ -17,12 +20,11 @@
</size>
</property>
<property name="windowTitle">
- <string>EWMA2 Filter settings FaceTrackNoIR</string>
+ <string>EWMA2 filter settings</string>
</property>
<property name="windowIcon">
- <iconset>
- images/facetracknoir.png
- </iconset>
+ <iconset resource="ewma-filter.qrc">
+ <normaloff>:/images/filter-16.png</normaloff>:/images/filter-16.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -480,7 +482,9 @@ p, li { white-space: pre-wrap; }
<tabstop>btnOK</tabstop>
<tabstop>btnCancel</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="ewma-filter.qrc"/>
+ </resources>
<connections>
<connection>
<sender>minSmooth</sender>
diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp
index 8e9196ba..e2196a01 100644
--- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp
+++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp
@@ -28,6 +28,7 @@
#include <QWidget>
#include "facetracknoir/global-settings.h"
#include <algorithm>
+#include <QMutexLocker>
//#define LOG_OUTPUT
///////////////////////////////////////////////////////////////////////////////
@@ -43,48 +44,22 @@
//
///////////////////////////////////////////////////////////////////////////////
-FTNoIR_Filter::FTNoIR_Filter()
-{
- first_run = true;
+FTNoIR_Filter::FTNoIR_Filter() :
+ first_run(true),
// Deltas are smoothed over the last 3 frames (0.1sec at 30fps).
- delta_smoothing = 1.0 / 3.0;
+ delta_smoothing(1.0/3.0),
// Noise is smoothed over the last 3600 frames (~2mins at 30fps).
- noise_smoothing = 1.0 / 3600.0;
- loadSettings(); // Load the Settings
-}
-
-FTNoIR_Filter::~FTNoIR_Filter()
+ noise_smoothing(1.0/3600.0)
{
}
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Filter::loadSettings() {
- qDebug() << "FTNoIR_Filter::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Filter::loadSettings says: iniFile = " << currentFile;
-
- //
- // The EWMA2-filter-settings are in the Tracking group: this is because they used to be on the Main Form of FaceTrackNoIR
- //
- iniFile.beginGroup ( "Tracking" );
- // TODO(abo): change UI to have range 1-120 frames.
- kMinSmoothing = iniFile.value ( "minSmooth", 2 ).toInt();
- kMaxSmoothing = iniFile.value ( "maxSmooth", 15 ).toInt();
- // TODO(abo): change powCurve to a float with default=1.0.
- kSmoothingScaleCurve = iniFile.value ( "powCurve", 10 ).toInt();
- iniFile.endGroup ();
+void FTNoIR_Filter::receiveSettings()
+{
+ s.b->reload();
}
-void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position,
- double *target_camera_position,
- double *new_camera_position,
- double *last_post_filter)
+void FTNoIR_Filter::FilterHeadPoseData(const double *target_camera_position,
+ double *new_camera_position)
{
double new_delta, new_noise, norm_noise;
double alpha;
@@ -113,7 +88,7 @@ void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position,
norm_noise = std::min<double>(new_noise/(9.0*noise[i]), 1.0);
// Calculate the alpha from the normalized noise.
// TODO(abo): change kSmoothingScaleCurve to a float where 1.0 is sqrt(norm_noise).
- alpha = 1.0/(kMinSmoothing+(1.0-pow(norm_noise,kSmoothingScaleCurve/20.0))*(kMaxSmoothing-kMinSmoothing));
+ alpha = 1.0/(s.kMinSmoothing+(1.0-pow(norm_noise,s.kSmoothingScaleCurve/20.0))*(s.kMaxSmoothing-s.kMinSmoothing));
new_camera_position[i] = alpha*target_camera_position[i] + (1.0-alpha)*current_camera_position[i];
}
diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h
index 72dc6f0a..e49b7a6d 100644
--- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h
+++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h
@@ -30,37 +30,38 @@
#include "facetracknoir/global-settings.h"
#include "ui_ftnoir_ewma_filtercontrols.h"
#include <QWidget>
+#include <QMutex>
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> kMinSmoothing, kMaxSmoothing, kSmoothingScaleCurve;
+ settings() :
+ b(bundle("ewma-filter")),
+ kMinSmoothing(b, "min-smoothing", 15),
+ kMaxSmoothing(b, "max-smoothing", 50),
+ kSmoothingScaleCurve(b, "smoothing-scale-curve", 10)
+ {}
+};
+
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// EWMA Filter: Exponentially Weighted Moving Average filter with dynamic smoothing parameter
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FTNoIR_Filter : public IFilter
{
public:
FTNoIR_Filter();
- ~FTNoIR_Filter();
- void Initialize() {}
-
- void FilterHeadPoseData(double *current_camera_position,
- double *target_camera_position,
- double *new_camera_position,
- double *last_post_filter);
-
+ void reset() {}
+ void FilterHeadPoseData(const double *target_camera_position,
+ double *new_camera_position);
+ void receiveSettings();
private:
- void loadSettings(); // Load the settings from the INI-file
- double newHeadPose; // Structure with new headpose
-
bool first_run;
double delta_smoothing;
double noise_smoothing;
double delta[6];
double noise[6];
-
- double kMinSmoothing;
- double kMaxSmoothing;
- double kSmoothingScaleCurve;
+ double current_camera_position[6];
+ settings s;
};
//*******************************************************************************************************
@@ -72,26 +73,19 @@ class FilterControls: public QWidget, public IFilterDialog
{
Q_OBJECT
public:
- explicit FilterControls();
- virtual ~FilterControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent, IFilter* ptr);
+ FilterControls();
+ void registerFilter(IFilter* flt);
+ void unregisterFilter();
private:
Ui::UICFilterControls ui;
- void loadSettings();
void save();
-
- /** helper **/
- bool settingsDirty;
-
- IFilter* pFilter; // If the filter was active when the dialog was opened, this will hold a pointer to the Filter instance
+ settings s;
+ FTNoIR_Filter* pFilter;
private slots:
void doOK();
void doCancel();
- void settingChanged() { settingsDirty = true; };
- void settingChanged( int ) { settingsDirty = true; };
};
//*******************************************************************************************************
@@ -100,8 +94,6 @@ private slots:
class FTNoIR_FilterDll : public Metadata
{
public:
- FTNoIR_FilterDll();
- ~FTNoIR_FilterDll();
void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("EWMA Filter Mk2"); }
void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("EWMA"); }
void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Exponentially Weighted Moving Average filter with dynamic smoothing parameter"); }
diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp
index eb259572..395d1058 100644
--- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp
+++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp
@@ -1,191 +1,73 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_filter_ewma2.h"
-#include "math.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-#include "ui_ftnoir_ewma_filtercontrols.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Filter Settings-dialog.
-//*******************************************************************************************************
-//
-// Constructor for server-settings-dialog
-//
-FilterControls::FilterControls() :
-QWidget()
-{
- ui.setupUi( this );
-
- QPoint offsetpos(100, 100);
- //if (parent) {
- // this->move(parent->pos() + offsetpos);
- //}
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
-
- // Connect sliders for reduction factor
- connect(ui.minSmooth, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.maxSmooth, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.powCurve, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int)));
-
- qDebug() << "FilterControls() says: started";
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-FilterControls::~FilterControls() {
- qDebug() << "~FilterControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void FilterControls::Initialize(QWidget *parent, IFilter* ptr) {
-
- //
- // The dialog can be opened, while the Tracker is running.
- // In that case, ptr will point to the active Filter-instance.
- // This can be used to update settings, while Tracking and may also be handy to display logging-data and such...
- //
- pFilter = ptr;
-
- //
- //
- //
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void FilterControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void FilterControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void FilterControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FilterControls::loadSettings() {
- qDebug() << "FilterControls::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FilterControls::loadSettings says: iniFile = " << currentFile;
-
- //
- // The EWMA2-filter-settings are in the Tracking group: this is because they used to be on the Main Form of FaceTrackNoIR
- //
- iniFile.beginGroup ( "Tracking" );
- ui.minSmooth->setValue (iniFile.value ( "minSmooth", 15 ).toInt());
- ui.maxSmooth->setValue (iniFile.value ( "maxSmooth", 50 ).toInt());
- ui.powCurve->setValue (iniFile.value ( "powCurve", 10 ).toInt());
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FilterControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "Tracking" );
- iniFile.setValue ( "minSmooth", ui.minSmooth->value() );
- iniFile.setValue ( "powCurve", ui.powCurve->value() );
- iniFile.setValue ( "maxSmooth", ui.maxSmooth->value() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Filter-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetFilterDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetFilterDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetFilterDialog=_GetFilterDialog@0")
-
-extern "C" FTNOIR_FILTER_BASE_EXPORT IFilterDialog* CALLING_CONVENTION GetDialog( )
-{
- return new FilterControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_filter_ewma2.h"
+#include "math.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+#include "ui_ftnoir_ewma_filtercontrols.h"
+
+FilterControls::FilterControls() :
+ QWidget(), pFilter(NULL)
+{
+ ui.setupUi( this );
+
+ connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+
+ tie_setting(s.kMaxSmoothing, ui.maxSmooth);
+ tie_setting(s.kMinSmoothing, ui.minSmooth);
+ tie_setting(s.kSmoothingScaleCurve, ui.powCurve);
+}
+
+void FilterControls::registerFilter(IFilter* flt)
+{
+ pFilter = (FTNoIR_Filter*) flt;
+}
+
+void FilterControls::unregisterFilter()
+{
+ pFilter = NULL;
+}
+
+void FilterControls::doOK() {
+ save();
+ this->close();
+}
+
+void FilterControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+void FilterControls::save() {
+ s.b->save();
+ if (pFilter)
+ pFilter->receiveSettings();
+}
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT IFilterDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new FilterControls;
+}
diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp
index a01b0661..6ef7768e 100644
--- a/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp
+++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp
@@ -1,57 +1,31 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The FilterDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_filter_ewma2.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_FilterDll::FTNoIR_FilterDll() {
-}
-
-FTNoIR_FilterDll::~FTNoIR_FilterDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Filter object.
-
-// Export both decorated and undecorated names.
-// GetFilterDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetFilterDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetFilterDll=_GetFilterDll@0")
-
-extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_FilterDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_filter_ewma2.h"
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_FilterDll;
+}
diff --git a/ftnoir_filter_kalman/ftnoir_filter_kalman.h b/ftnoir_filter_kalman/ftnoir_filter_kalman.h
new file mode 100644
index 00000000..f2a1b4ec
--- /dev/null
+++ b/ftnoir_filter_kalman/ftnoir_filter_kalman.h
@@ -0,0 +1,69 @@
+#pragma once
+/* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+#ifndef INCLUDED_FTN_FILTER_H
+#define INCLUDED_FTN_FILTER_H
+
+#undef FTNOIR_TRACKER_BASE_LIB
+#define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT
+
+#include "ftnoir_filter_base/ftnoir_filter_base.h"
+#include "ui_ftnoir_kalman_filtercontrols.h"
+#include "facetracknoir/global-settings.h"
+#include <opencv2/opencv.hpp>
+#include <vector>
+#include <QString>
+#include <QIcon>
+#include <QWidget>
+#include <QElapsedTimer>
+#include <QObject>
+#include "facetracknoir/options.h"
+using namespace options;
+
+class FTNOIR_FILTER_BASE_EXPORT FTNoIR_Filter : public IFilter
+{
+public:
+ FTNoIR_Filter();
+ void reset() virt_override;
+ void FilterHeadPoseData(const double *target_camera_position,
+ double *new_camera_position) virt_override;
+ cv::KalmanFilter kalman;
+ double prev_position[6];
+ double prev2_filter_pos[6];
+ double prev_filter_pos[6];
+ QElapsedTimer timer;
+ qint64 timedelta;
+};
+
+class FTNOIR_FILTER_BASE_EXPORT FTNoIR_FilterDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Kalman filter"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Kalman filter"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Kalman filter"); }
+ void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); }
+};
+
+class FTNOIR_FILTER_BASE_EXPORT FilterControls: public QWidget, public IFilterDialog
+{
+ Q_OBJECT
+public:
+ FilterControls() {
+ ui.setupUi(this);
+ connect(ui.btnOk, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+ show();
+ }
+ Ui::KalmanUICFilterControls ui;
+ virtual void registerFilter(IFilter*) virt_override {}
+ virtual void unregisterFilter() virt_override {}
+public slots:
+ void doOK();
+ void doCancel();
+};
+
+#endif
diff --git a/ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui b/ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui
new file mode 100644
index 00000000..e0c849c9
--- /dev/null
+++ b/ftnoir_filter_kalman/ftnoir_kalman_filtercontrols.ui
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KalmanUICFilterControls</class>
+ <widget class="QWidget" name="KalmanUICFilterControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>334</width>
+ <height>100</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Kalman settings</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../ftnoir_filter_ewma2/ewma-filter.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>
+ <widget class="QPushButton" name="btnOk">
+ <property name="geometry">
+ <rect>
+ <x>173</x>
+ <y>70</y>
+ <width>73</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="btnCancel">
+ <property name="geometry">
+ <rect>
+ <x>250</x>
+ <y>70</y>
+ <width>73</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </widget>
+ <resources>
+ <include location="../ftnoir_filter_ewma2/ewma-filter.qrc"/>
+ </resources>
+ <connections/>
+ <designerdata>
+ <property name="gridDeltaX">
+ <number>10</number>
+ </property>
+ <property name="gridDeltaY">
+ <number>10</number>
+ </property>
+ <property name="gridSnapX">
+ <bool>false</bool>
+ </property>
+ <property name="gridSnapY">
+ <bool>false</bool>
+ </property>
+ <property name="gridVisible">
+ <bool>true</bool>
+ </property>
+ </designerdata>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/ftnoir_filter_kalman/images/filter-16-ac.png b/ftnoir_filter_kalman/images/filter-16-ac.png
new file mode 100644
index 00000000..d263db2d
--- /dev/null
+++ b/ftnoir_filter_kalman/images/filter-16-ac.png
Binary files differ
diff --git a/ftnoir_protocol_ftn/ftn-protocol.qrc b/ftnoir_filter_kalman/kalman-filter.qrc
index 18ae0aae..9a7d75fa 100644
--- a/ftnoir_protocol_ftn/ftn-protocol.qrc
+++ b/ftnoir_filter_kalman/kalman-filter.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/">
- <file>images/facetracknoir.png</file>
+ <file>images/filter-16-ac.png</file>
</qresource>
</RCC>
diff --git a/ftnoir_filter_kalman/kalman.cpp b/ftnoir_filter_kalman/kalman.cpp
new file mode 100644
index 00000000..bef6ddad
--- /dev/null
+++ b/ftnoir_filter_kalman/kalman.cpp
@@ -0,0 +1,136 @@
+/* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+#include "ftnoir_filter_kalman.h"
+#include "facetracknoir/global-settings.h"
+#include <QDebug>
+#include <math.h>
+
+FTNoIR_Filter::FTNoIR_Filter() {
+ reset();
+}
+
+// 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() {
+ const double accel_variance = 1e-3;
+ const double noise_variance = 5e2;
+ kalman.init(12, 6, 0, CV_64F);
+ kalman.transitionMatrix = (cv::Mat_<double>(12, 12) <<
+ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+ double a = 0.25 * accel_variance;
+ double b = 0.5 * accel_variance;
+ double c = 1.0 * accel_variance;
+ kalman.processNoiseCov = (cv::Mat_<double>(12, 12) <<
+ a, 0, 0, 0, 0, 0, b, 0, 0, 0, 0, 0,
+ 0, a, 0, 0, 0, 0, 0, b, 0, 0, 0, 0,
+ 0, 0, a, 0, 0, 0, 0, 0, b, 0, 0, 0,
+ 0, 0, 0, a, 0, 0, 0, 0, 0, b, 0, 0,
+ 0, 0, 0, 0, a, 0, 0, 0, 0, 0, b, 0,
+ 0, 0, 0, 0, 0, a, 0, 0, 0, 0, 0, b,
+ b, 0, 0, 0, 0, 0, c, 0, 0, 0, 0, 0,
+ 0, b, 0, 0, 0, 0, 0, c, 0, 0, 0, 0,
+ 0, 0, b, 0, 0, 0, 0, 0, c, 0, 0, 0,
+ 0, 0, 0, b, 0, 0, 0, 0, 0, c, 0, 0,
+ 0, 0, 0, 0, b, 0, 0, 0, 0, 0, c, 0,
+ 0, 0, 0, 0, 0, b, 0, 0, 0, 0, 0, c);
+ cv::setIdentity(kalman.measurementMatrix);
+ 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;
+ prev2_filter_pos[i] = 0;
+ prev_filter_pos[i] = 0;
+ timedelta = 1;
+ timer.invalidate();
+ }
+}
+
+template<typename T>
+static inline T clamp(const T min, const T max, const T value)
+{
+ if (value < min)
+ return min;
+ if (value > max)
+ return max;
+ return value;
+}
+
+void FTNoIR_Filter::FilterHeadPoseData(const double* target_camera_position,
+ double *new_camera_position)
+{
+ bool new_target = false;
+
+ for (int i = 0; i < 6; i++)
+ if (prev_position[i] != target_camera_position[i])
+ {
+ new_target = true;
+ break;
+ }
+
+ if (new_target) {
+ cv::Mat output = kalman.predict();
+ cv::Mat measurement(6, 1, CV_64F);
+ for (int i = 0; i < 3; i++) {
+ measurement.at<double>(i) = target_camera_position[i+3];
+ measurement.at<double>(i+3) = target_camera_position[i];
+ }
+ kalman.correct(measurement);
+ for (int i = 0; i < 6; i++)
+ {
+ prev_position[i] = target_camera_position[i];
+ }
+ if (timer.isValid())
+ timedelta = timer.elapsed();
+ else
+ timedelta = 1;
+ for (int i = 0; i < 6; i++)
+ {
+ prev2_filter_pos[i] = prev_filter_pos[i];
+ prev_filter_pos[i] = new_camera_position[i] = output.at<double>((i + 3) % 6);
+ }
+ timer.start();
+ } else {
+ auto d = timer.isValid() ? timer.elapsed() : 1;
+ auto c = clamp(0.0, 1.0, d / (double) timedelta);
+ for (int i = 0; i < 6; i++)
+ new_camera_position[i] = prev2_filter_pos[i] + (prev_filter_pos[i] - prev2_filter_pos[i]) * c;
+ }
+}
+
+void FilterControls::doOK() {
+ close();
+}
+
+void FilterControls::doCancel() {
+ close();
+}
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_FilterDll;
+}
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT IFilter* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Filter;
+}
+
+extern "C" FTNOIR_FILTER_BASE_EXPORT IFilterDialog* CALLING_CONVENTION GetDialog() {
+ return new FilterControls;
+}
diff --git a/ftnoir_posewidget/glwidget.cpp b/ftnoir_posewidget/glwidget.cpp
index 671dd35d..26803385 100644
--- a/ftnoir_posewidget/glwidget.cpp
+++ b/ftnoir_posewidget/glwidget.cpp
@@ -1,230 +1,197 @@
-/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include <QtGui>
-#include "glwidget.h"
-#include <QWidget>
-#include <cmath>
-#include <algorithm>
-
-GLWidget::GLWidget(QWidget *parent) : QWidget(parent)
-{
- front = QImage(QString(":/images/side1.png"));
- back = QImage(QString(":/images/side6.png"));
- rotateBy(0, 0, 0);
-}
-
-GLWidget::~GLWidget()
-{
-}
-
-void GLWidget::paintEvent ( QPaintEvent * event ) {
- QWidget::paintEvent(event);
- QPainter p(this);
- project_quad_texture();
- p.drawPixmap(event->rect(), pixmap, event->rect());
-}
-
-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;
- update();
-}
-
-class Triangle {
-public:
- Triangle(const Vec2f& p1,
- const Vec2f& p2,
- const Vec2f& p3)
- {
- origin = p1;
- v0 = Vec2f(p3.x - p1.x, p3.y - p1.y);
- v1 = Vec2f(p2.x - p1.x, p2.y - p1.y);
- dot00 = dot(v0, v0);
- dot01 = dot(v0, v1);
- dot11 = dot(v1, v1);
- invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
- }
- bool barycentric_coords(const Vec2f& px, Vec2f& uv) const
- {
- Vec2f v2(px.x - origin.x, px.y - origin.y);
- double dot12 = dot(v1, v2);
- double dot02 = dot(v0, v2);
- double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
- double v = (dot00 * dot12 - dot01 * dot02) * invDenom;
- uv.x = u;
- uv.y = v;
- return (u >= 0) && (v >= 0) && (u + v <= 1);
- }
-
-private:
- double dot00, dot01, dot11, invDenom;
- Vec2f v0, v1, origin;
- double dot(const Vec2f& p1, const Vec2f& p2) const {
- return p1.x * p2.x + p1.y * p2.y;
- }
-};
-
-static __inline Vec3f cross(const Vec3f& p1, const Vec3f& p2)
-{
- return Vec3f(p1.y * p2.z - p2.y * p1.z,
- p2.x * p1.z - p1.x * p2.z,
- p1.x * p2.y - p1.y * p2.x);
-}
-
-static __inline Vec3f normal(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
-{
- Vec3f u(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
- Vec3f v(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
-
- Vec3f tmp = cross(u, v);
-
- double i = 1./sqrt(tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z);
-
- return Vec3f(i * tmp.x, i * tmp.y, i * tmp.z);
-}
-
-void GLWidget::project_quad_texture() {
- const int sx = width(), sy = height();
- Point pt[4];
- static Vec3f corners[] = {
- Vec3f(0, 0, 0),
- Vec3f(sx-1, 0, 0),
- Vec3f(0, sy-1, 0),
- Vec3f(sx-1, sy-1, 0)
- };
-
- for (int i = 0; i < 4; i++) {
- pt[i] = project(Vec3f(corners[i].x - sx/2, corners[i].y - sy/2, 0));
- pt[i].x += sx/2;
- pt[i].y += sy/2;
- }
-
- Vec3f normal1(0, 0, 1);
- Vec3f normal2;
- {
- Vec3f foo[3];
- for (int i = 0; i < 3; i++)
- foo[i] = project2(corners[i]);
- normal2 = normal(foo[0], foo[1], foo[2]);
- }
-
- double dir = normal1.x * normal2.x + normal1.y * normal2.y + normal1.z * normal2.z;
-
- QImage& tex = dir < 0 ? back : front;
-
- int ow = tex.width(), oh = tex.height();
-
- Vec2f p2[4];
-
- for (int i = 0; i < 4; i++)
- p2[i] = Vec2f(pt[i].x, pt[i].y);
-
- QImage texture(QSize(sx, sy), QImage::Format_RGB888);
- texture.fill(Qt::black);
-
- const Vec2f projected[2][3] = { { p2[0], p2[1], p2[2] }, { p2[3], p2[1], p2[2] } };
- const Vec2f origs[2][3] = {
- { Vec2f(0, 0), Vec2f(ow-1, 0), Vec2f(0, oh-1) },
- { Vec2f(ow-1, oh-1), Vec2f(ow-1, 0), Vec2f(0, oh-1) }
- };
- const Triangle triangles[2] = {
- Triangle(projected[0][0], projected[0][1], projected[0][2]),
- Triangle(projected[1][0], projected[1][1], projected[1][2])
- };
-
- int orig_pitch = tex.bytesPerLine();
- int dest_pitch = texture.bytesPerLine();
-
- const unsigned char* orig = tex.bits();
- unsigned char* dest = texture.bits();
-
- int orig_depth = tex.depth() / 8;
- int dest_depth = texture.depth() / 8;
-
- /* image breakage? */
- if (orig_depth < 3)
- return;
-
- for (int y = 0; y < sy; y++)
- for (int x = 0; x < sx; x++) {
- Vec2f pos;
- pos.x = x;
- pos.y = y;
- for (int i = 0; i < 2; i++) {
- Vec2f coords;
- if (triangles[i].barycentric_coords(pos, coords))
- {
- double qx = origs[i][0].x
- + coords.x * (origs[i][2].x - origs[i][0].x)
- + coords.y * (origs[i][1].x - origs[i][0].x);
- double qy = origs[i][0].y
- + coords.x * (origs[i][2].y - origs[i][0].y)
- + coords.y * (origs[i][1].y - origs[i][0].y);
- int qx1 = std::min<int>(ow - 1, std::max<int>(0, qx - 0.5));
- int qy1 = std::min<int>(oh - 1, std::max<int>(0, qy - 0.5));
- int qx2 = std::min<int>(ow - 1, std::max<int>(0, qx + 0.5));
- int qy2 = std::min<int>(oh - 1, std::max<int>(0, qy + 0.5));
-
- double dx1 = qx1 - qx;
- double dy1 = qy1 - qy;
- double dx2 = qx2 - qx;
- double dy2 = qy2 - qy;
-
- double d1 = 2 - (dx1 * dx1 + dy1 * dy1);
- double d2 = 2 - (dx2 * dx2 + dy2 * dy2);
- double d3 = 2 - (dx2 * dx2 + dy1 * dy1);
- double d4 = 2 - (dx1 * dx1 + dy2 * dy2);
-
- double inv_norm = 1. / (d1 + d2 + d3 + d4);
-
- d1 *= inv_norm;
- d2 *= inv_norm;
- d3 *= inv_norm;
- d4 *= inv_norm;
-
- double r = d1 * (double) orig[qy1 * orig_pitch + qx1 * orig_depth + 2]
- + d2 * (double) orig[qy2 * orig_pitch + qx2 * orig_depth + 2]
- + d3 * (double) orig[qy1 * orig_pitch + qx2 * orig_depth + 2]
- + d4 * (double) orig[qy2 * orig_pitch + qx1 * orig_depth + 2];
-
- double g = d1 * (double) orig[qy1 * orig_pitch + qx1 * orig_depth + 1]
- + d2 * (double) orig[qy2 * orig_pitch + qx2 * orig_depth + 1]
- + d3 * (double) orig[qy1 * orig_pitch + qx2 * orig_depth + 1]
- + d4 * (double) orig[qy2 * orig_pitch + qx1 * orig_depth + 1];
-
- double b = d1 * (double) orig[qy1 * orig_pitch + qx1 * orig_depth + 0]
- + d2 * (double) orig[qy2 * orig_pitch + qx2 * orig_depth + 0]
- + d3 * (double) orig[qy1 * orig_pitch + qx2 * orig_depth + 0]
- + d4 * (double) orig[qy2 * orig_pitch + qx1 * orig_depth + 0];
-
- dest[y * dest_pitch + x * dest_depth + 0] = std::max<int>(0, std::min<int>(255, r));
- dest[y * dest_pitch + x * dest_depth + 1] = std::max<int>(0, std::min<int>(255, g));
- dest[y * dest_pitch + x * dest_depth + 2] = std::max<int>(0, std::min<int>(255, b));
-
- break;
- }
- }
- }
- pixmap = QPixmap::fromImage(texture);
-} \ No newline at end of file
+/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include <QtGui>
+#include "glwidget.h"
+#include <QWidget>
+#include <cmath>
+#include <algorithm>
+
+GLWidget::GLWidget(QWidget *parent) : QWidget(parent)
+{
+ front = QImage(QString(":/images/side1.png"));
+ back = QImage(QString(":/images/side6.png"));
+ rotateBy(0, 0, 0);
+}
+
+GLWidget::~GLWidget()
+{
+}
+
+void GLWidget::paintEvent ( QPaintEvent * event ) {
+ QWidget::paintEvent(event);
+ QPainter p(this);
+ project_quad_texture();
+ p.drawImage(event->rect(), texture);
+}
+
+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;
+ update();
+}
+
+class Triangle {
+public:
+ Triangle(const Vec2f& p1,
+ const Vec2f& p2,
+ const Vec2f& p3)
+ {
+ origin = p1;
+ v0 = Vec2f(p3.x - p1.x, p3.y - p1.y);
+ v1 = Vec2f(p2.x - p1.x, p2.y - p1.y);
+ dot00 = dot(v0, v0);
+ dot01 = dot(v0, v1);
+ dot11 = dot(v1, v1);
+ invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ }
+ bool barycentric_coords(const Vec2f& px, Vec2f& uv) const
+ {
+ Vec2f v2(px.x - origin.x, px.y - origin.y);
+ double dot12 = dot(v1, v2);
+ double dot02 = dot(v0, v2);
+ double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+ double v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+ uv.x = u;
+ uv.y = v;
+ return (u >= 0) && (v >= 0) && (u + v <= 1);
+ }
+
+private:
+ double dot00, dot01, dot11, invDenom;
+ Vec2f v0, v1, origin;
+ double dot(const Vec2f& p1, const Vec2f& p2) const {
+ return p1.x * p2.x + p1.y * p2.y;
+ }
+};
+
+static __inline Vec3f cross(const Vec3f& p1, const Vec3f& p2)
+{
+ return Vec3f(p1.y * p2.z - p2.y * p1.z,
+ p2.x * p1.z - p1.x * p2.z,
+ p1.x * p2.y - p1.y * p2.x);
+}
+
+static __inline Vec3f normal(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
+{
+ Vec3f u(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
+ Vec3f v(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
+
+ Vec3f tmp = cross(u, v);
+
+ double i = 1./sqrt(tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z);
+
+ return Vec3f(i * tmp.x, i * tmp.y, i * tmp.z);
+}
+
+void GLWidget::project_quad_texture() {
+ const int sx = width(), sy = height();
+ Point pt[4];
+ static Vec3f corners[] = {
+ Vec3f(0, 0, 0),
+ Vec3f(sx-1, 0, 0),
+ Vec3f(0, sy-1, 0),
+ Vec3f(sx-1, sy-1, 0)
+ };
+
+ for (int i = 0; i < 4; i++) {
+ pt[i] = project(Vec3f(corners[i].x - sx/2, corners[i].y - sy/2, 0));
+ pt[i].x += sx/2;
+ pt[i].y += sy/2;
+ }
+
+ Vec3f normal1(0, 0, 1);
+ Vec3f normal2;
+ {
+ Vec3f foo[3];
+ for (int i = 0; i < 3; i++)
+ foo[i] = project2(corners[i]);
+ normal2 = normal(foo[0], foo[1], foo[2]);
+ }
+
+ double dir = normal1.x * normal2.x + normal1.y * normal2.y + normal1.z * normal2.z;
+
+ QImage& tex = dir < 0 ? back : front;
+
+ int ow = tex.width(), oh = tex.height();
+
+ Vec2f p2[4];
+
+ for (int i = 0; i < 4; i++)
+ p2[i] = Vec2f(pt[i].x, pt[i].y);
+ QImage texture(QSize(sx, sy), QImage::Format_RGB888);
+ QColor bgColor = palette().color(QPalette::Current, QPalette::Window);
+ texture.fill(bgColor);
+
+ const Vec2f projected[2][3] = { { p2[0], p2[1], p2[2] }, { p2[3], p2[1], p2[2] } };
+ const Vec2f origs[2][3] = {
+ { Vec2f(0, 0), Vec2f(ow-1, 0), Vec2f(0, oh-1) },
+ { Vec2f(ow-1, oh-1), Vec2f(ow-1, 0), Vec2f(0, oh-1) }
+ };
+ const Triangle triangles[2] = {
+ Triangle(projected[0][0], projected[0][1], projected[0][2]),
+ Triangle(projected[1][0], projected[1][1], projected[1][2])
+ };
+
+ int orig_pitch = tex.bytesPerLine();
+ int dest_pitch = texture.bytesPerLine();
+
+ const unsigned char* orig = tex.bits();
+ unsigned char* dest = texture.bits();
+
+ int orig_depth = tex.depth() / 8;
+ int dest_depth = texture.depth() / 8;
+
+ /* image breakage? */
+ if (orig_depth < 3)
+ return;
+
+ for (int y = 0; y < sy; y++)
+ for (int x = 0; x < sx; x++) {
+ Vec2f pos;
+ pos.x = x;
+ pos.y = y;
+ for (int i = 0; i < 2; i++) {
+ Vec2f coords;
+ if (triangles[i].barycentric_coords(pos, coords))
+ {
+ int px = origs[i][0].x
+ + coords.x * (origs[i][2].x - origs[i][0].x)
+ + coords.y * (origs[i][1].x - origs[i][0].x);
+ int py = origs[i][0].y
+ + coords.x * (origs[i][2].y - origs[i][0].y)
+ + coords.y * (origs[i][1].y - origs[i][0].y);
+ int r = orig[py * orig_pitch + px * orig_depth + 2];
+ int g = orig[py * orig_pitch + px * orig_depth + 1];
+ int b = orig[py * orig_pitch + px * orig_depth + 0];
+
+ dest[y * dest_pitch + x * dest_depth + 0] = r;
+ dest[y * dest_pitch + x * dest_depth + 1] = g;
+ dest[y * dest_pitch + x * dest_depth + 2] = b;
+
+ break;
+ }
+ }
+ }
+ this->texture = texture;
+}
diff --git a/ftnoir_posewidget/glwidget.h b/ftnoir_posewidget/glwidget.h
index 9525f7d4..c4b2e09d 100644
--- a/ftnoir_posewidget/glwidget.h
+++ b/ftnoir_posewidget/glwidget.h
@@ -1,116 +1,97 @@
-/********************************************************************************
-* 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. *
-* *
-* Adopted this widget from the 'textures' sample of the Nokia Qt toolkit. *
-* *
-* You should have received a copy of the GNU General Public License along *
-* with this program; if not, see <http://www.gnu.org/licenses/>. *
-*********************************************************************************/
-
-#ifndef GLWIDGET_H
-#define GLWIDGET_H
-
-#include <QtGui>
-#include <QPixmap>
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-
-struct Point {
- Point(int x, int y) :
- x(x), y(y)
- {
- }
- Point() :
- x(0), y(0)
- {
- }
- int x, y;
-};
-
-struct Vec3f {
- double x, y, z;
- Vec3f(double x, double y, double z) :
- x(x), y(y), z(z)
- {
- }
- Vec3f() :
- x(0), y(0), z(0)
- {
- }
-};
-
-struct Vec2f {
- double x, y;
- Vec2f(double x, double y) :
- x(x), y(y)
- {
- }
- Vec2f() :
- x(0), y(0)
- {
- }
-};
-
-class FTNOIR_TRACKER_BASE_EXPORT GLWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- GLWidget(QWidget *parent);
- ~GLWidget();
- void rotateBy(double xAngle, double yAngle, double zAngle);
-
-protected:
- void paintEvent ( QPaintEvent * event );
-
-private:
- Point project(const Vec3f& point) {
- Point rect;
-
- rect.x = point.x * matrix[0]
- + point.y * matrix[1]
- + point.z * matrix[2];
- rect.y = point.x * matrix[3]
- + point.y * matrix[4]
- + point.z * matrix[5];
-
- return rect;
- }
- Vec3f project2(const Vec3f& point) {
- Vec3f rect;
-
- rect.x = point.x * matrix[0]
- + point.y * matrix[1]
- + point.z * matrix[2];
- rect.y = point.x * matrix[3]
- + point.y * matrix[4]
- + point.z * matrix[5];
- rect.z = point.x * matrix[6]
- + point.y * matrix[7]
- + point.z * matrix[8];
- return rect;
- }
- void project_quad_texture();
- double matrix[9];
- QImage front;
- QImage back;
- QPixmap pixmap;
-};
-
-#endif
+/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl>
+ *
+ * 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 GLWIDGET_H
+#define GLWIDGET_H
+
+#include <QtGui>
+#include <QPixmap>
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+
+struct Point {
+ Point(int x, int y) :
+ x(x), y(y)
+ {
+ }
+ Point() :
+ x(0), y(0)
+ {
+ }
+ int x, y;
+};
+
+struct Vec3f {
+ double x, y, z;
+ Vec3f(double x, double y, double z) :
+ x(x), y(y), z(z)
+ {
+ }
+ Vec3f() :
+ x(0), y(0), z(0)
+ {
+ }
+};
+
+struct Vec2f {
+ double x, y;
+ Vec2f(double x, double y) :
+ x(x), y(y)
+ {
+ }
+ Vec2f() :
+ x(0), y(0)
+ {
+ }
+};
+
+class FTNOIR_TRACKER_BASE_EXPORT GLWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ GLWidget(QWidget *parent);
+ ~GLWidget();
+ void rotateBy(double xAngle, double yAngle, double zAngle);
+
+protected:
+ void paintEvent ( QPaintEvent * event );
+
+private:
+ Point project(const Vec3f& point) {
+ Point rect;
+
+ rect.x = point.x * matrix[0]
+ + point.y * matrix[1]
+ + point.z * matrix[2];
+ rect.y = point.x * matrix[3]
+ + point.y * matrix[4]
+ + point.z * matrix[5];
+
+ return rect;
+ }
+ Vec3f project2(const Vec3f& point) {
+ Vec3f rect;
+
+ rect.x = point.x * matrix[0]
+ + point.y * matrix[1]
+ + point.z * matrix[2];
+ rect.y = point.x * matrix[3]
+ + point.y * matrix[4]
+ + point.z * matrix[5];
+ rect.z = point.x * matrix[6]
+ + point.y * matrix[7]
+ + point.z * matrix[8];
+ return rect;
+ }
+ void project_quad_texture();
+ double matrix[9];
+ QImage front;
+ QImage back;
+ QImage texture;
+};
+
+#endif
diff --git a/ftnoir_posewidget/images/side1.png b/ftnoir_posewidget/images/side1.png
index e0315b77..d7467943 100644
--- a/ftnoir_posewidget/images/side1.png
+++ b/ftnoir_posewidget/images/side1.png
Binary files differ
diff --git a/ftnoir_posewidget/images/side6.png b/ftnoir_posewidget/images/side6.png
index f4160001..eaa80d7e 100644
--- a/ftnoir_posewidget/images/side6.png
+++ b/ftnoir_posewidget/images/side6.png
Binary files differ
diff --git a/ftnoir_protocol_base/ftnoir_protocol_base.h b/ftnoir_protocol_base/ftnoir_protocol_base.h
index d6e4cb58..d2f85ec0 100644
--- a/ftnoir_protocol_base/ftnoir_protocol_base.h
+++ b/ftnoir_protocol_base/ftnoir_protocol_base.h
@@ -1,91 +1,57 @@
-/********************************************************************************
-* 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/>. *
-* This class implements a tracker-base *
-*********************************************************************************/
-/*
- Modifications (last one on top):
-
- 20121115 - WVR: Added RegisterProtocol() and unRegisterProtocol() to Dialog Class
- 20110415 - WVR: Added overloaded operator - and -=
-*/
-
-#ifndef FTNOIR_PROTOCOL_BASE_H
-#define FTNOIR_PROTOCOL_BASE_H
-
-#include "ftnoir_protocol_base_global.h"
-#include "ftnoir_tracker_base/ftnoir_tracker_types.h"
-#include <QtGui/QWidget>
-#include <QtGui/QFrame>
-//#include "winbase.h"
-
-//#include "windows.h"
-//#include "winable.h"
-
-////////////////////////////////////////////////////////////////////////////////
-#ifdef __cplusplus
-# define EXTERN_C extern "C"
-#else
-# define EXTERN_C
-#endif // __cplusplus
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
-struct IProtocol
-{
- virtual ~IProtocol() {}
- virtual bool checkServerInstallationOK() = 0;
- virtual void sendHeadposeToGame( double *headpose, double *rawheadpose ) = 0;
- virtual QString getGameName() = 0;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
-struct IProtocolDll
-{
- virtual ~IProtocolDll() {}
-
- virtual void getFullName(QString *strToBeFilled) = 0;
- virtual void getShortName(QString *strToBeFilled) = 0;
- virtual void getDescription(QString *strToBeFilled) = 0;
- virtual void getIcon(QIcon *icon) = 0;
-};
-
-struct IProtocolDialog
-{
- virtual ~IProtocolDialog() {}
- virtual void Initialize(QWidget *parent) = 0;
- virtual void showEvent ( QShowEvent * event ) = 0;
-
- virtual void registerProtocol(IProtocol *protocol) = 0;
- virtual void unRegisterProtocol() = 0;
-};
-
-#endif // FTNOIR_PROTOCOL_BASE_H
+/********************************************************************************
+* 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/>. *
+* This class implements a tracker-base *
+*********************************************************************************/
+/*
+ Modifications (last one on top):
+
+ 20121115 - WVR: Added RegisterProtocol() and unRegisterProtocol() to Dialog Class
+ 20110415 - WVR: Added overloaded operator - and -=
+*/
+
+#ifndef FTNOIR_PROTOCOL_BASE_H
+#define FTNOIR_PROTOCOL_BASE_H
+
+#include "ftnoir_protocol_base_global.h"
+#include "ftnoir_tracker_base/ftnoir_tracker_types.h"
+#include <QWidget>
+#include <QFrame>
+
+struct IProtocol
+{
+ virtual ~IProtocol() = 0;
+ virtual bool checkServerInstallationOK() = 0;
+ virtual void sendHeadposeToGame( const double* headpose ) = 0;
+ virtual QString getGameName() = 0;
+};
+
+inline IProtocol::~IProtocol() { }
+
+struct IProtocolDialog
+{
+ virtual ~IProtocolDialog() {}
+ virtual void registerProtocol(IProtocol *protocol) = 0;
+ virtual void unRegisterProtocol() = 0;
+};
+
+#endif // FTNOIR_PROTOCOL_BASE_H
diff --git a/ftnoir_protocol_base/ftnoir_protocol_base_global.h b/ftnoir_protocol_base/ftnoir_protocol_base_global.h
index ca51e26d..06386c7f 100644
--- a/ftnoir_protocol_base/ftnoir_protocol_base_global.h
+++ b/ftnoir_protocol_base/ftnoir_protocol_base_global.h
@@ -1,12 +1,16 @@
-#ifndef FTNOIR_PROTOCOL_BASE_GLOBAL_H
-#define FTNOIR_PROTOCOL_BASE_GLOBAL_H
-
-#include <QtGlobal>
-
-#ifdef FTNOIR_PROTOCOL_BASE_LIB
-# define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_EXPORT
-#else
-# define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_IMPORT
-#endif
-
-#endif // FTNOIR_PROTOCOL_BASE_GLOBAL_H
+#ifndef FTNOIR_PROTOCOL_BASE_GLOBAL_H
+#define FTNOIR_PROTOCOL_BASE_GLOBAL_H
+
+#include <QtGlobal>
+
+#ifndef OPENTRACK_MAIN
+# if !defined(_MSC_VER)
+# define FTNOIR_PROTOCOL_BASE_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_EXPORT
+#endif
+#else
+# define FTNOIR_PROTOCOL_BASE_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // FTNOIR_PROTOCOL_BASE_GLOBAL_H
diff --git a/ftnoir_protocol_fg/fgtypes.h b/ftnoir_protocol_fg/fgtypes.h
index 68f85877..0f29be3d 100644
--- a/ftnoir_protocol_fg/fgtypes.h
+++ b/ftnoir_protocol_fg/fgtypes.h
@@ -1,27 +1,27 @@
-/********************************************************************************
-* FaceTrackNoIR This program is a private project of the some enthusiastic *
-* gamers from Holland, who don't like to pay much for *
-* head-tracking. *
-* *
-* Copyright (C) 2010 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* Homepage *
-* *
-* Type definitions for the FlightGear server. *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_FGTYPES_H
-#define INCLUDED_FGTYPES_H
-
-//
-// x,y,z position in metres, heading, pitch and roll in degrees...
-//
-#pragma pack(push, 2)
-struct TFlightGearData {
- double x, y, z, h, p, r;
- int status;
-};
-#pragma pack(pop)
-
-#endif//INCLUDED_FGTYPES_H
+/********************************************************************************
+* FaceTrackNoIR This program is a private project of the some enthusiastic *
+* gamers from Holland, who don't like to pay much for *
+* head-tracking. *
+* *
+* Copyright (C) 2010 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* *
+* Homepage *
+* *
+* Type definitions for the FlightGear server. *
+********************************************************************************/
+#pragma once
+#ifndef INCLUDED_FGTYPES_H
+#define INCLUDED_FGTYPES_H
+
+//
+// x,y,z position in metres, heading, pitch and roll in degrees...
+//
+#pragma pack(push, 2)
+struct TFlightGearData {
+ double x, y, z, h, p, r;
+ int status;
+};
+#pragma pack(pop)
+
+#endif//INCLUDED_FGTYPES_H
diff --git a/ftnoir_protocol_fg/ftnoir_fgcontrols.ui b/ftnoir_protocol_fg/ftnoir_fgcontrols.ui
index 116f830b..a4092c05 100644
--- a/ftnoir_protocol_fg/ftnoir_fgcontrols.ui
+++ b/ftnoir_protocol_fg/ftnoir_fgcontrols.ui
@@ -2,20 +2,23 @@
<ui version="4.0">
<class>UICFGControls</class>
<widget class="QWidget" name="UICFGControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>411</width>
- <height>194</height>
+ <width>415</width>
+ <height>112</height>
</rect>
</property>
<property name="windowTitle">
- <string>FlightGear settings FaceTrackNoIR</string>
+ <string>FlightGear protocol settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>images/FaceTrackNoIR.png</normaloff>images/FaceTrackNoIR.png</iconset>
+ <iconset resource="../ftnoir_filter_ewma2/ewma-filter.qrc">
+ <normaloff>:/images/filter-16.png</normaloff>:/images/filter-16.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -23,239 +26,101 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="4">
- <widget class="QSpinBox" name="spinIPFourthNibble">
- <property name="maximumSize">
- <size>
- <width>60</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="maximum">
- <number>255</number>
- </property>
- <property name="singleStep">
- <number>1</number>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QSpinBox" name="spinIPFirstNibble">
- <property name="maximumSize">
- <size>
- <width>60</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="maximum">
- <number>255</number>
- </property>
- <property name="singleStep">
- <number>1</number>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QSpinBox" name="spinIPSecondNibble">
- <property name="maximumSize">
- <size>
- <width>60</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="maximum">
- <number>255</number>
- </property>
- <property name="singleStep">
- <number>1</number>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QSpinBox" name="spinIPThirdNibble">
- <property name="maximumSize">
- <size>
- <width>60</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="maximum">
- <number>255</number>
- </property>
- <property name="singleStep">
- <number>1</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>IP-address remote PC</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="chkLocalPC">
- <property name="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="text">
- <string>Local PC only</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Port-number</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QSpinBox" name="spinPortNumber">
- <property name="minimum">
- <number>1000</number>
- </property>
- <property name="maximum">
- <number>10000</number>
- </property>
- </widget>
- </item>
- </layout>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>IP-address remote PC</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="spinIPFirstNibble">
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QSpinBox" name="spinIPSecondNibble">
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ </widget>
</item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <item row="0" column="3">
+ <widget class="QSpinBox" name="spinIPThirdNibble">
+ <property name="maximumSize">
+ <size>
+ <width>60</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="maximum">
+ <number>255</number>
</property>
- <property name="sizeHint" stdset="0">
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QSpinBox" name="spinIPFourthNibble">
+ <property name="maximumSize">
<size>
- <width>20</width>
- <height>40</height>
+ <width>60</width>
+ <height>16777215</height>
</size>
</property>
- </spacer>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Port-number</string>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>If FlightGear is on the same PC as FaceTrackNoIR, tick the 'Local PC only' box.</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Otherwise: enter IP-address and port-number for the remote PC.</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Remember: you may have to change firewall-settings too!</string>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="spinPortNumber">
+ <property name="minimum">
+ <number>1000</number>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <item row="2" column="2" colspan="3">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
</item>
</layout>
</widget>
@@ -265,11 +130,10 @@
<tabstop>spinIPThirdNibble</tabstop>
<tabstop>spinIPFourthNibble</tabstop>
<tabstop>spinPortNumber</tabstop>
- <tabstop>btnOK</tabstop>
- <tabstop>btnCancel</tabstop>
- <tabstop>chkLocalPC</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="../ftnoir_filter_ewma2/ewma-filter.qrc"/>
+ </resources>
<connections/>
<slots>
<slot>startEngineClicked()</slot>
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp
index 7b43e306..0ef6b50f 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp
@@ -1,228 +1,64 @@
-/********************************************************************************
-* 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/>. *
-* *
-* FGServer FGServer is the Class, that communicates headpose-data *
-* to FlightGear, using UDP. *
-* It is based on the (Linux) example made by Melchior FRANZ. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
-*/
-#include "ftnoir_protocol_fg.h"
-#include <QFile>
-#include "facetracknoir/global-settings.h"
-#include <ftnoir_tracker_base/ftnoir_tracker_types.h>
-
-// For Todd and Arda Kutlu
-//#define SEND_ASCII_DATA
-//#define LOG_OUTPUT
-
-/** constructor **/
-FTNoIR_Protocol::FTNoIR_Protocol()
-{
- blnConnectionActive = false;
- loadSettings();
-}
-
-/** destructor **/
-FTNoIR_Protocol::~FTNoIR_Protocol()
-{
- if (inSocket != 0) {
- inSocket->close();
- delete inSocket;
- }
-
- if (outSocket != 0) {
- outSocket->close();
- delete outSocket;
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Protocol::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FG" );
-
- bool blnLocalPC = iniFile.value ( "LocalPCOnly", 1 ).toBool();
- if (blnLocalPC) {
- destIP = QHostAddress::LocalHost;
- }
- else {
- QString destAddr = iniFile.value ( "IP-1", 192 ).toString() + "." + iniFile.value ( "IP-2", 168 ).toString() + "." + iniFile.value ( "IP-3", 2 ).toString() + "." + iniFile.value ( "IP-4", 1 ).toString();
- destIP = QHostAddress( destAddr );
- }
- destPort = iniFile.value ( "PortNumber", 5550 ).toInt();
-
- iniFile.endGroup ();
-
-}
-
-//
-// Update Headpose in Game.
-//
-void FTNoIR_Protocol::sendHeadposeToGame( double *headpose, double *rawheadpose ) {
-int no_bytes;
-QHostAddress sender;
-quint16 senderPort;
-
- //
- // Copy the Raw measurements directly to the client.
- //
- FlightData.x = headpose[TX];
- FlightData.y = headpose[Pitch];
- FlightData.z = headpose[TZ];
- FlightData.p = headpose[TY];
- FlightData.h = headpose[Yaw];
- FlightData.r = headpose[Roll];
- FlightData.status = fg_cmd;
-
- //
- // Try to send an UDP-message to the FlightGear
- //
-
-#ifdef SEND_ASCII_DATA
- sprintf_s(data, "%.2f %.2f %.2f %.2f %.2f %.2f\n\0", FlightData.x, FlightData.y, FlightData.z, FlightData.p, FlightData.h, FlightData.r);
-
- if (outSocket != 0) {
- no_bytes = outSocket->writeDatagram((const char *) &data, strlen( data ), destIP, destPort);
- if ( no_bytes > 0) {
- qDebug() << "FGServer::writePendingDatagrams says: bytes send =" << data;
- }
- else {
- qDebug() << "FGServer::writePendingDatagrams says: nothing sent!";
- }
- }
-
-#endif
-
- #ifdef LOG_OUTPUT
- // Use this for some debug-output to file...
- QFile datafile(QCoreApplication::applicationDirPath() + "\\FG_output.txt");
- if (datafile.open(QFile::WriteOnly | QFile::Append)) {
- QTextStream out(&datafile);
- out << "output:\t" << FlightData.x << "\t" << FlightData.y << "\t" << FlightData.z << "\t" << FlightData.p << "\t" << FlightData.h << "\t" << FlightData.r << '\n';
- }
- #endif
-
- #ifndef SEND_ASCII_DATA
- //! [1]
-// no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), QHostAddress::LocalHost, 5550);
- if (outSocket != 0) {
- no_bytes = outSocket->writeDatagram((const char *) &FlightData, sizeof( FlightData ), destIP, destPort);
- if ( no_bytes > 0) {
- // qDebug() << "FGServer::writePendingDatagrams says: bytes send =" << no_bytes << sizeof( double );
- }
- else {
- qDebug() << "FGServer::writePendingDatagrams says: nothing sent!";
- }
- }
- #endif
-
- //
- // FlightGear keeps sending data, so we must read that here.
- //
- if (inSocket != 0) {
- while (inSocket->hasPendingDatagrams()) {
-
- QByteArray datagram;
- datagram.resize(inSocket->pendingDatagramSize());
-
- inSocket->readDatagram( (char * ) &cmd, sizeof(cmd), &sender, &senderPort);
-
- fg_cmd = cmd; // Let's just accept that command for now...
- if ( cmd > 0 ) {
- qDebug() << "FGServer::sendHeadposeToGame hasPendingDatagrams, cmd = " << cmd;
-// headTracker->handleGameCommand ( cmd ); // Send it upstream, for the Tracker to handle
- }
-
- if (!blnConnectionActive) {
- blnConnectionActive = true;
- }
- }
- }
-}
-
-//
-// Check if the Client DLL exists and load it (to test it), if so.
-// Returns 'true' if all seems OK.
-//
-bool FTNoIR_Protocol::checkServerInstallationOK()
-{
- // Init. the data
- FlightData.x = 0.0f;
- FlightData.y = 0.0f;
- FlightData.z = 0.0f;
- FlightData.h = 0.0f;
- FlightData.p = 0.0f;
- FlightData.r = 0.0f;
- FlightData.status = 0;
- fg_cmd = 1;
-
- inSocket = 0;
- outSocket = 0;
-
- //
- // Create UDP-sockets.
- //
- if (inSocket == 0) {
- qDebug() << "FGServer::sendHeadposeToGame creating insocket";
- inSocket = new QUdpSocket();
-
- // Connect the inSocket to the port, to receive messages
- if (!inSocket->bind(QHostAddress::Any, destPort+1)) {
- QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to bind UDP-port",QMessageBox::Ok,QMessageBox::NoButton);
- delete inSocket;
- inSocket = 0;
- return false;
- }
- }
-
- if (outSocket == 0) {
- outSocket = new QUdpSocket();
- }
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocol - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocol@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Protocol;
-}
+/********************************************************************************
+* 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/>. *
+* *
+* FGServer FGServer is the Class, that communicates headpose-data *
+* to FlightGear, using UDP. *
+* It is based on the (Linux) example made by Melchior FRANZ. *
+********************************************************************************/
+#include "ftnoir_protocol_fg.h"
+#include "facetracknoir/global-settings.h"
+#include <ftnoir_tracker_base/ftnoir_tracker_types.h>
+
+// For Todd and Arda Kutlu
+
+void FTNoIR_Protocol::reloadSettings()
+{
+ s.b->reload();
+}
+
+void FTNoIR_Protocol::sendHeadposeToGame(const double* headpose) {
+ FlightData.x = headpose[TX] * 1e-2;
+ FlightData.y = headpose[TY] * 1e-2;
+ FlightData.z = headpose[TZ] * 1e-2;
+ FlightData.p = headpose[Pitch];
+ FlightData.h = headpose[Yaw];
+ FlightData.r = headpose[Roll];
+ FlightData.status = 1;
+ QHostAddress destIP(QString("%1.%2.%3.%4").arg(
+ QString::number(static_cast<int>(s.ip1)),
+ QString::number(static_cast<int>(s.ip2)),
+ QString::number(static_cast<int>(s.ip3)),
+ QString::number(static_cast<int>(s.ip4))));
+ int destPort = s.port;
+ (void) outSocket.writeDatagram(reinterpret_cast<const char*>(&FlightData), sizeof(FlightData), destIP, static_cast<quint16>(destPort));
+}
+
+bool FTNoIR_Protocol::checkServerInstallationOK()
+{
+ return outSocket.bind(QHostAddress::Any, 0, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.h b/ftnoir_protocol_fg/ftnoir_protocol_fg.h
index 1c4484b8..dca1f245 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg.h
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.h
@@ -1,121 +1,96 @@
-/********************************************************************************
-* 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) 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/>. *
-* *
-* FGServer FGServer is the Class, that communicates headpose-data *
-* to FlightGear, using UDP. *
-* It is based on the (Linux) example made by Melchior FRANZ. *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_FGSERVER_H
-#define INCLUDED_FGSERVER_H
-
-#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#include "ui_ftnoir_fgcontrols.h"
-#include "fgtypes.h"
-#include <QThread>
-#include <QUdpSocket>
-#include <QMessageBox>
-#include <QSettings>
-#include <math.h>
-#include "facetracknoir/global-settings.h"
-
-#define FT_PROGRAMID "FT_ProgramID"
-
-class FTNoIR_Protocol : public IProtocol
-{
-public:
- FTNoIR_Protocol();
- ~FTNoIR_Protocol();
- bool checkServerInstallationOK();
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
-private:
-
- bool blnConnectionActive;
-
- // Tracker *headTracker; // For upstream messages...
- TFlightGearData FlightData;
- QUdpSocket *inSocket; // Receive from FligthGear
- QUdpSocket *outSocket; // Send to FligthGear
- qint32 cmd;
- qint32 fg_cmd; // Command from FlightGear
- QHostAddress destIP; // Destination IP-address
- int destPort; // Destination port-number
- void loadSettings();
- QString getGameName() {
- return "FlightGear";
- }
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class FGControls: public QWidget, public IProtocolDialog
-{
- Q_OBJECT
-public:
-
- explicit FGControls();
- virtual ~FGControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerProtocol(IProtocol *protocol) {
- theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
- }
- void unRegisterProtocol() {
- theProtocol = NULL; // Reset the pointer
- }
-
-private:
- Ui::UICFGControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FTNoIR_Protocol *theProtocol;
-
-private slots:
- void doOK();
- void doCancel();
- void chkLocalPCOnlyChanged();
- void settingChanged() { settingsDirty = true; }
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
-//*******************************************************************************************************
-class FTNoIR_ProtocolDll : public Metadata
-{
-public:
- FTNoIR_ProtocolDll();
- ~FTNoIR_ProtocolDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear"); }
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear"); }
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear UDP protocol"); }
-
- void getIcon(QIcon *icon) { *icon = QIcon(":/images/flightgear.png"); }
-};
-
-
-#endif//INCLUDED_FGSERVER_H
-//END
+/********************************************************************************
+* 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) 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/>. *
+* *
+* FGServer FGServer is the Class, that communicates headpose-data *
+* to FlightGear, using UDP. *
+* It is based on the (Linux) example made by Melchior FRANZ. *
+********************************************************************************/
+#pragma once
+#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ui_ftnoir_fgcontrols.h"
+#include "fgtypes.h"
+#include <QThread>
+#include <QUdpSocket>
+#include <QMessageBox>
+#include "facetracknoir/global-settings.h"
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> ip1, ip2, ip3, ip4;
+ value<int> port;
+ settings() :
+ b(bundle("flightgear-proto")),
+ ip1(b, "ip1", 192),
+ ip2(b, "ip2", 168),
+ ip3(b, "ip3", 0),
+ ip4(b, "ip4", 2),
+ port(b, "port", 5542)
+ {}
+};
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ bool checkServerInstallationOK();
+ void sendHeadposeToGame(const double *headpose);
+ QString getGameName() {
+ return "FlightGear";
+ }
+ void reloadSettings();
+private:
+ settings s;
+ TFlightGearData FlightData;
+ QUdpSocket outSocket;
+};
+
+// Widget that has controls for FTNoIR protocol client-settings.
+class FGControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+ FGControls();
+ void registerProtocol(IProtocol *protocol) {
+ theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
+ }
+ void unRegisterProtocol() {
+ theProtocol = NULL; // Reset the pointer
+ }
+private:
+ Ui::UICFGControls ui;
+ FTNoIR_Protocol *theProtocol;
+ settings s;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FlightGear UDP protocol"); }
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/flightgear.png"); }
+};
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp
index c29f6d1a..1c3e5ef8 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp
@@ -1,221 +1,69 @@
-/********************************************************************************
-* 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/>. *
-* *
-* FGServer FGServer is the Class, that communicates headpose-data *
-* to FlightGear, using UDP. *
-* It is based on the (Linux) example made by Melchior FRANZ. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
-*/
-#include "ftnoir_protocol_fg.h"
-#include <QFile>
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-FGControls::FGControls() :
-QWidget()
-{
- ui.setupUi( this );
-
- QPoint offsetpos(100, 100);
- //if (parent) {
- // this->move(parent->pos() + offsetpos);
- //}
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.chkLocalPC, SIGNAL(stateChanged(int)), this, SLOT(chkLocalPCOnlyChanged()));
- connect(ui.spinIPFirstNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinIPSecondNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinIPThirdNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinIPFourthNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinPortNumber, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
-
- theProtocol = NULL;
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-FGControls::~FGControls() {
- qDebug() << "~FGControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void FGControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void FGControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void FGControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void FGControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FGControls::loadSettings() {
-// qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
-// qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "FG" );
- ui.chkLocalPC->setChecked (iniFile.value ( "LocalPCOnly", 1 ).toBool());
-
- ui.spinIPFirstNibble->setValue( iniFile.value ( "IP-1", 192 ).toInt() );
- ui.spinIPSecondNibble->setValue( iniFile.value ( "IP-2", 168 ).toInt() );
- ui.spinIPThirdNibble->setValue( iniFile.value ( "IP-3", 2 ).toInt() );
- ui.spinIPFourthNibble->setValue( iniFile.value ( "IP-4", 1 ).toInt() );
-
- ui.spinPortNumber->setValue( iniFile.value ( "PortNumber", 5550 ).toInt() );
- iniFile.endGroup ();
-
- chkLocalPCOnlyChanged();
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FGControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FG" );
- iniFile.setValue ( "LocalPCOnly", ui.chkLocalPC->isChecked() );
- iniFile.setValue ( "IP-1", ui.spinIPFirstNibble->value() );
- iniFile.setValue ( "IP-2", ui.spinIPSecondNibble->value() );
- iniFile.setValue ( "IP-3", ui.spinIPThirdNibble->value() );
- iniFile.setValue ( "IP-4", ui.spinIPFourthNibble->value() );
- iniFile.setValue ( "PortNumber", ui.spinPortNumber->value() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Handle change of the checkbox.
-//
-void FGControls::chkLocalPCOnlyChanged() {
-
- if ( ui.chkLocalPC->isChecked() ) {
- ui.spinIPFirstNibble->setValue( 127 );
- ui.spinIPFirstNibble->setEnabled ( false );
- ui.spinIPSecondNibble->setValue( 0 );
- ui.spinIPSecondNibble->setEnabled ( false );
- ui.spinIPThirdNibble->setValue( 0 );
- ui.spinIPThirdNibble->setEnabled ( false );
- ui.spinIPFourthNibble->setValue( 1 );
- ui.spinIPFourthNibble->setEnabled ( false );
- }
- else {
- ui.spinIPFirstNibble->setEnabled ( true );
- ui.spinIPSecondNibble->setEnabled ( true );
- ui.spinIPThirdNibble->setEnabled ( true );
- ui.spinIPFourthNibble->setEnabled ( true );
- }
-
- settingsDirty = true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
-{
- return new FGControls;
-}
+/********************************************************************************
+* 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/>. *
+* *
+* FGServer FGServer is the Class, that communicates headpose-data *
+* to FlightGear, using UDP. *
+* It is based on the (Linux) example made by Melchior FRANZ. *
+********************************************************************************/
+#include "ftnoir_protocol_fg.h"
+#include <QObject>
+#include <QFile>
+#include "facetracknoir/global-settings.h"
+
+//*******************************************************************************************************
+// FaceTrackNoIR Client Settings-dialog.
+//*******************************************************************************************************
+
+//
+// Constructor for server-settings-dialog
+//
+FGControls::FGControls() : theProtocol(nullptr)
+{
+ ui.setupUi( this );
+
+ tie_setting(s.ip1, ui.spinIPFirstNibble);
+ tie_setting(s.ip2, ui.spinIPSecondNibble);
+ tie_setting(s.ip3, ui.spinIPThirdNibble);
+ tie_setting(s.ip4, ui.spinIPFourthNibble);
+ tie_setting(s.port, ui.spinPortNumber);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+}
+
+void FGControls::doOK() {
+ s.b->save();
+ this->close();
+ if (theProtocol)
+ theProtocol->reloadSettings();
+}
+
+void FGControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new FGControls;
+}
diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp
index 45d6271c..3125f136 100644
--- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp
+++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp
@@ -1,57 +1,32 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_fg.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
-}
-
-FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_ProtocolDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_fg.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui b/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui
index d02297f3..6cb066bd 100644
--- a/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui
+++ b/ftnoir_protocol_fsuipc/ftnoir_fsuipccontrols.ui
@@ -2,12 +2,15 @@
<ui version="4.0">
<class>UICFSUIPCControls</class>
<widget class="QWidget" name="UICFSUIPCControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>541</width>
- <height>127</height>
+ <width>512</width>
+ <height>100</height>
</rect>
</property>
<property name="windowTitle">
@@ -23,198 +26,101 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
- <layout class="QHBoxLayout">
- <item>
- <widget class="QLabel" name="textLabel2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Location of FSUIPC.dll:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1">
+ <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>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="txtLocationOfDLL">
+ <property name="minimumSize">
+ <size>
+ <width>230</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Location of FSUIPC.dll</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="text">
+ <string>Location of FSUIPC.dll</string>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QLabel" name="txtLocationOfDLL">
- <property name="minimumSize">
- <size>
- <width>230</width>
- <height>0</height>
- </size>
- </property>
- <property name="toolTip">
- <string>Location of FSUIPC.dll</string>
- </property>
- <property name="frameShape">
- <enum>QFrame::Box</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Sunken</enum>
- </property>
- <property name="lineWidth">
- <number>1</number>
- </property>
- <property name="text">
- <string>Location of FSUIPC.dll</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnFindDLL">
- <property name="maximumSize">
- <size>
- <width>35</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="1" column="0" colspan="2">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>The DLL should be located in the Modules/ directory of MS FS 2004</string>
+ </property>
+ </widget>
</item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <item row="2" 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="sizeHint" stdset="0">
+ <property name="minimumSize">
<size>
- <width>20</width>
- <height>40</height>
+ <width>100</width>
+ <height>0</height>
</size>
</property>
- </spacer>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>The DLL should be placed in the Modules folder of MS Flight Simulator</string>
- </property>
- </widget>
- </item>
- </layout>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="btnFindDLL">
+ <property name="maximumSize">
+ <size>
+ <width>35</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
</item>
</layout>
</widget>
diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp
index e457d363..632d502a 100644
--- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp
+++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp
@@ -1,211 +1,168 @@
-/********************************************************************************
-* 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-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/>. *
-* *
-* FSUIPCServer FSUIPCServer is the Class, that communicates headpose-data *
-* to games, using the FSUIPC.dll. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
-*/
-#include "ftnoir_protocol_fsuipc.h"
-#include "facetracknoir/global-settings.h"
-
-/** constructor **/
-FTNoIR_Protocol::FTNoIR_Protocol()
-{
- loadSettings();
- ProgramName = "Microsoft FS2004";
-
- prevPosX = 0.0f;
- prevPosY = 0.0f;
- prevPosZ = 0.0f;
- prevRotX = 0.0f;
- prevRotY = 0.0f;
- prevRotZ = 0.0f;
-}
-
-/** destructor **/
-FTNoIR_Protocol::~FTNoIR_Protocol()
-{
- //
- // Free the DLL
- //
- FSUIPCLib.unload();
-}
-
-//
-// Scale the measured value to the Joystick values
-//
-int FTNoIR_Protocol::scale2AnalogLimits( float x, float min_x, float max_x ) {
-double y;
-double local_x;
-
- local_x = x;
- if (local_x > max_x) {
- local_x = max_x;
- }
- if (local_x < min_x) {
- local_x = min_x;
- }
- y = ( 16383 * local_x ) / max_x;
-
- return (int) y;
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Protocol::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FSUIPC" );
- LocationOfDLL = iniFile.value ( "LocationOfDLL", FSUIPC_FILENAME ).toString();
- qDebug() << "FSUIPCServer::loadSettings() says: Location of DLL = " << LocationOfDLL;
- iniFile.endGroup ();
-}
-
-//
-// Update Headpose in Game.
-//
-void FTNoIR_Protocol::sendHeadposeToGame(double *headpose, double *rawheadpose ) {
-DWORD result;
-TFSState pitch;
-TFSState yaw;
-TFSState roll;
-WORD FSZoom;
-
-float virtPosX;
-float virtPosY;
-float virtPosZ;
-
-float virtRotX;
-float virtRotY;
-float virtRotZ;
-
-// qDebug() << "FSUIPCServer::run() says: started!";
-
- virtRotX = -headpose[Pitch]; // degrees
- virtRotY = headpose[Yaw];
- virtRotZ = headpose[Roll];
-
- virtPosX = 0.0f; // cm, X and Y are not working for FS2002/2004!
- virtPosY = 0.0f;
- virtPosZ = headpose[TZ];
-
- //
- // Init. the FSUIPC offsets (derived from Free-track...)
- //
- pitch.Control = 66503;
- yaw.Control = 66504;
- roll.Control = 66505;
-
- //
- // Only do this when the data has changed. This way, the HAT-switch can be used when tracking is OFF.
- //
- if ((prevPosX != virtPosX) || (prevPosY != virtPosY) || (prevPosZ != virtPosZ) ||
- (prevRotX != virtRotX) || (prevRotY != virtRotY) || (prevRotZ != virtRotZ)) {
- //
- // Open the connection
- //
- FSUIPC_Open(SIM_ANY, &result);
-
- //
- // Check the FS-version
- //
- if (((result == FSUIPC_ERR_OK) || (result == FSUIPC_ERR_OPEN)) &&
- ((FSUIPC_FS_Version == SIM_FS2K2) || (FSUIPC_FS_Version == SIM_FS2K4))) {
-// qDebug() << "FSUIPCServer::run() says: FSUIPC opened succesfully";
- //
- // Write the 4! DOF-data to FS. Only rotations and zoom are possible.
- //
- pitch.Value = scale2AnalogLimits(virtRotX, -180, 180);
- FSUIPC_Write(0x3110, 8, &pitch, &result);
-
- yaw.Value = scale2AnalogLimits(virtRotY, -180, 180);
- FSUIPC_Write(0x3110, 8, &yaw, &result);
-
- roll.Value = scale2AnalogLimits(virtRotZ, -180, 180);
- FSUIPC_Write(0x3110, 8, &roll, &result);
-
- FSZoom = (WORD) (64/50) * virtPosZ + 64;
- FSUIPC_Write(0x832E, 2, &FSZoom, &result);
-
- //
- // Write the data, in one go!
- //
- FSUIPC_Process(&result);
- if (result == FSUIPC_ERR_SENDMSG) {
- FSUIPC_Close(); //timeout (1 second) so assume FS closed
- }
- }
- }
-
- prevPosX = virtPosX;
- prevPosY = virtPosY;
- prevPosZ = virtPosZ;
- prevRotX = virtRotX;
- prevRotY = virtRotY;
- prevRotZ = virtRotZ;
-}
-
-//
-// Returns 'true' if all seems OK.
-//
-bool FTNoIR_Protocol::checkServerInstallationOK()
-{
- qDebug() << "checkServerInstallationOK says: Starting Function";
-
- //
- // Load the DLL.
- //
- FSUIPCLib.setFileName( LocationOfDLL );
- if (FSUIPCLib.load() != true) {
- qDebug() << "checkServerInstallationOK says: Error loading FSUIPC DLL";
- return false;
- }
- else {
- qDebug() << "checkServerInstallationOK says: FSUIPC DLL loaded.";
- }
-
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocol - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocol@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT FTNoIR_Protocol* CALLING_CONVENTION GetConstructor(void)
-{
- return new FTNoIR_Protocol;
-}
+/********************************************************************************
+* 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-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/>. *
+* *
+* FSUIPCServer FSUIPCServer is the Class, that communicates headpose-data *
+* to games, using the FSUIPC.dll. *
+********************************************************************************/
+#include "ftnoir_protocol_fsuipc.h"
+#include "facetracknoir/global-settings.h"
+
+/** constructor **/
+FTNoIR_Protocol::FTNoIR_Protocol()
+{
+ prevPosX = 0.0f;
+ prevPosY = 0.0f;
+ prevPosZ = 0.0f;
+ prevRotX = 0.0f;
+ prevRotY = 0.0f;
+ prevRotZ = 0.0f;
+}
+
+FTNoIR_Protocol::~FTNoIR_Protocol()
+{
+ FSUIPCLib.unload();
+}
+
+//
+// Scale the measured value to the Joystick values
+//
+int FTNoIR_Protocol::scale2AnalogLimits( float x, float min_x, float max_x ) {
+double y;
+double local_x;
+
+ local_x = x;
+ if (local_x > max_x) {
+ local_x = max_x;
+ }
+ if (local_x < min_x) {
+ local_x = min_x;
+ }
+ y = ( 16383 * local_x ) / max_x;
+
+ return (int) y;
+}
+
+void FTNoIR_Protocol::sendHeadposeToGame(const double *headpose ) {
+ DWORD result;
+ TFSState pitch;
+ TFSState yaw;
+ TFSState roll;
+ WORD FSZoom;
+
+ float virtPosX;
+ float virtPosY;
+ float virtPosZ;
+
+ float virtRotX;
+ float virtRotY;
+ float virtRotZ;
+
+// qDebug() << "FSUIPCServer::run() says: started!";
+
+ virtRotX = -headpose[Pitch]; // degrees
+ virtRotY = headpose[Yaw];
+ virtRotZ = headpose[Roll];
+
+ virtPosX = 0.0f; // cm, X and Y are not working for FS2002/2004!
+ virtPosY = 0.0f;
+ virtPosZ = headpose[TZ];
+
+ //
+ // Init. the FSUIPC offsets (derived from Free-track...)
+ //
+ pitch.Control = 66503;
+ yaw.Control = 66504;
+ roll.Control = 66505;
+
+ //
+ // Only do this when the data has changed. This way, the HAT-switch can be used when tracking is OFF.
+ //
+ if ((prevPosX != virtPosX) || (prevPosY != virtPosY) || (prevPosZ != virtPosZ) ||
+ (prevRotX != virtRotX) || (prevRotY != virtRotY) || (prevRotZ != virtRotZ)) {
+ //
+ // Open the connection
+ //
+ FSUIPC_Open(SIM_ANY, &result);
+
+ //
+ // Check the FS-version
+ //
+ if (((result == FSUIPC_ERR_OK) || (result == FSUIPC_ERR_OPEN)) &&
+ ((FSUIPC_FS_Version == SIM_FS2K2) || (FSUIPC_FS_Version == SIM_FS2K4))) {
+// qDebug() << "FSUIPCServer::run() says: FSUIPC opened succesfully";
+ //
+ // Write the 4! DOF-data to FS. Only rotations and zoom are possible.
+ //
+ pitch.Value = scale2AnalogLimits(virtRotX, -180, 180);
+ FSUIPC_Write(0x3110, 8, &pitch, &result);
+
+ yaw.Value = scale2AnalogLimits(virtRotY, -180, 180);
+ FSUIPC_Write(0x3110, 8, &yaw, &result);
+
+ roll.Value = scale2AnalogLimits(virtRotZ, -180, 180);
+ FSUIPC_Write(0x3110, 8, &roll, &result);
+
+ FSZoom = (WORD) (64/50) * virtPosZ + 64;
+ FSUIPC_Write(0x832E, 2, &FSZoom, &result);
+
+ //
+ // Write the data, in one go!
+ //
+ FSUIPC_Process(&result);
+ if (result == FSUIPC_ERR_SENDMSG) {
+ FSUIPC_Close(); //timeout (1 second) so assume FS closed
+ }
+ }
+ }
+
+ prevPosX = virtPosX;
+ prevPosY = virtPosY;
+ prevPosZ = virtPosZ;
+ prevRotX = virtRotX;
+ prevRotY = virtRotY;
+ prevRotZ = virtRotZ;
+}
+
+bool FTNoIR_Protocol::checkServerInstallationOK()
+{
+ qDebug() << "checkServerInstallationOK says: Starting Function";
+
+ //
+ // Load the DLL.
+ //
+ FSUIPCLib.setFileName( s.LocationOfDLL );
+ if (FSUIPCLib.load() != true) {
+ qDebug() << "checkServerInstallationOK says: Error loading FSUIPC DLL";
+ return false;
+ }
+ else {
+ qDebug() << "checkServerInstallationOK says: FSUIPC DLL loaded.";
+ }
+
+ return true;
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT FTNoIR_Protocol* CALLING_CONVENTION GetConstructor(void)
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h
index 5da1d2ca..ff8d3b7f 100644
--- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h
+++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h
@@ -1,131 +1,110 @@
-/********************************************************************************
-* 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) 2010-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/>. *
-* *
-* FSUIPCServer FSUIPCServer is the Class, that communicates headpose-data *
-* to games, using the FSUIPC.dll. *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_FSUIPCSERVER_H
-#define INCLUDED_FSUIPCSERVER_H
-
-#include "Windows.h"
-#include <stdlib.h>
-#include "FSUIPC_User.h"
-#include "facetracknoir/global-settings.h"
-
-#include "..\ftnoir_protocol_base\ftnoir_protocol_base.h"
-#include "ui_FTNoIR_FSUIPCcontrols.h"
-#include <QMessageBox>
-#include <QSettings>
-#include <QLibrary>
-#include <QProcess>
-#include <QDebug>
-#include <QFile>
-#include <QFileDialog>
-
-#define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll"
-
-//
-// Define the structures necessary for the FSUIPC_Write calls
-//
-#pragma pack(push,1) // All fields in structure must be byte aligned.
-typedef struct
-{
- int Control; // Control identifier
- int Value; // Value of DOF
-} TFSState;
-#pragma pack(pop)
-
-class FTNoIR_Protocol : public IProtocol
-{
-public:
- FTNoIR_Protocol();
- ~FTNoIR_Protocol();
- bool checkServerInstallationOK();
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
- QString getGameName() {
- return "Microsoft Flight Simulator X";
- }
-private:
- // Private properties
- QString ProgramName;
- QLibrary FSUIPCLib;
- QString LocationOfDLL;
- float prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ;
-
- static int scale2AnalogLimits( float x, float min_x, float max_x );
- void loadSettings();
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class FSUIPCControls: public QWidget, public IProtocolDialog
-{
- Q_OBJECT
-public:
-
- explicit FSUIPCControls();
- virtual ~FSUIPCControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerProtocol(IProtocol *protocol) {
- theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
- }
- void unRegisterProtocol() {
- theProtocol = NULL; // Reset the pointer
- }
-
-private:
- Ui::UICFSUIPCControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FTNoIR_Protocol *theProtocol;
-
-private slots:
- void doOK();
- void doCancel();
- void settingChanged() { settingsDirty = true; };
- void getLocationOfDLL();
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
-//*******************************************************************************************************
-class FTNoIR_ProtocolDll : public Metadata
-{
-public:
- FTNoIR_ProtocolDll();
- ~FTNoIR_ProtocolDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FS2002/FS2004"); };
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FSUIPC"); };
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Microsoft FS2004 protocol"); };
-
- void getIcon(QIcon *icon) { *icon = QIcon(":/images/fs9.png"); };
-};
-
-
-#endif//INCLUDED_FSUIPCSERVER_H
-//END
+/********************************************************************************
+* 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) 2010-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/>. *
+* *
+* FSUIPCServer FSUIPCServer is the Class, that communicates headpose-data *
+* to games, using the FSUIPC.dll. *
+********************************************************************************/
+#pragma once
+#ifndef INCLUDED_FSUIPCSERVER_H
+#define INCLUDED_FSUIPCSERVER_H
+
+#include <windows.h>
+#include <stdlib.h>
+#include "FSUIPC_User.h"
+#include "facetracknoir/global-settings.h"
+#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ui_ftnoir_fsuipccontrols.h"
+#include <QMessageBox>
+#include <QSettings>
+#include <QLibrary>
+#include <QProcess>
+#include <QDebug>
+#include <QFile>
+#include <QFileDialog>
+#include "facetracknoir/options.h"
+using namespace options;
+
+#define FSUIPC_FILENAME "C:\\Program Files\\Microsoft Games\\Flight Simulator 9\\Modules\\FSUIPC.dll"
+
+struct settings {
+ pbundle b;
+ value<QString> LocationOfDLL;
+ settings() :
+ b(bundle("proto-fsuipc")),
+ LocationOfDLL(b, "dll-location", FSUIPC_FILENAME)
+ {}
+};
+
+#pragma pack(push,1) // All fields in structure must be byte aligned.
+typedef struct
+{
+ int Control; // Control identifier
+ int Value; // Value of DOF
+} TFSState;
+#pragma pack(pop)
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ FTNoIR_Protocol();
+ virtual ~FTNoIR_Protocol() virt_override;
+ bool checkServerInstallationOK();
+ void sendHeadposeToGame(const double* headpose);
+ QString getGameName() {
+ return "Microsoft Flight Simulator X";
+ }
+private:
+ QLibrary FSUIPCLib;
+ double prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ;
+ static int scale2AnalogLimits( float x, float min_x, float max_x );
+ settings s;
+};
+
+class FSUIPCControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+ FSUIPCControls();
+ void registerProtocol(IProtocol *) {}
+ void unRegisterProtocol() {}
+private:
+ Ui::UICFSUIPCControls ui;
+ settings s;
+private slots:
+ void doOK();
+ void doCancel();
+ void getLocationOfDLL();
+};
+
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FS2002/FS2004"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FSUIPC"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Microsoft FS2004 protocol"); }
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/fs9.png"); }
+};
+
+
+#endif//INCLUDED_FSUIPCSERVER_H
+//END
diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp
index 301bc0f4..d97cff99 100644
--- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp
+++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp
@@ -1,193 +1,62 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_fsuipc.h"
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-FSUIPCControls::FSUIPCControls() :
-QWidget()
-{
- ui.setupUi( this );
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.btnFindDLL, SIGNAL(clicked()), this, SLOT(getLocationOfDLL()));
-
- theProtocol = NULL;
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-FSUIPCControls::~FSUIPCControls() {
- qDebug() << "~FSUIPCControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void FSUIPCControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void FSUIPCControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void FSUIPCControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void FSUIPCControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FSUIPCControls::loadSettings() {
-
- qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "FSUIPC" );
- ui.txtLocationOfDLL->setText(iniFile.value ( "LocationOfDLL", FSUIPC_FILENAME ).toString() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FSUIPCControls::save() {
-
- qDebug() << "save() says: started";
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FSUIPC" );
- iniFile.setValue ( "LocationOfDLL", ui.txtLocationOfDLL->text() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Show the Dialog to set the DLL's location
-//
-void FSUIPCControls::getLocationOfDLL()
-{
- //
- // Get the new filename of the INI-file.
- //
- QString fileName = QFileDialog::getOpenFileName(this, tr("Locate file"),
- ui.txtLocationOfDLL->text(),
- tr("FSUIPC DLL file (FSUIPC*.dll);;All Files (*)"));
- if (!fileName.isEmpty()) {
- ui.txtLocationOfDLL->setText( fileName );
- settingsDirty = true;
- }
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog(void)
-{
- return new FSUIPCControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_fsuipc.h"
+#include "facetracknoir/global-settings.h"
+
+FSUIPCControls::FSUIPCControls() :
+ QWidget()
+{
+ ui.setupUi( this );
+ connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+ connect(ui.btnFindDLL, SIGNAL(clicked()), this, SLOT(getLocationOfDLL()));
+
+ tie_setting(s.LocationOfDLL, ui.txtLocationOfDLL);
+}
+
+void FSUIPCControls::doOK() {
+ s.b->save();
+ this->close();
+}
+
+void FSUIPCControls::doCancel() {
+ s.b->revert();
+ close();
+}
+
+void FSUIPCControls::getLocationOfDLL()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Locate file"),
+ ui.txtLocationOfDLL->text(),
+ tr("FSUIPC DLL file (FSUIPC*.dll);;All Files (*)"));
+ if (!fileName.isEmpty()) {
+ s.LocationOfDLL = fileName;
+ }
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog(void)
+{
+ return new FSUIPCControls;
+}
diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp
index 72d99fb9..57b174c5 100644
--- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp
+++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp
@@ -1,57 +1,31 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_fsuipc.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
-}
-
-FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata(void)
-{
- return new FTNoIR_ProtocolDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_fsuipc.h"
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata(void)
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_ft/ftnoir_ftcontrols.ui b/ftnoir_protocol_ft/ftnoir_ftcontrols.ui
index fc5abbcf..941aaff0 100644
--- a/ftnoir_protocol_ft/ftnoir_ftcontrols.ui
+++ b/ftnoir_protocol_ft/ftnoir_ftcontrols.ui
@@ -2,26 +2,38 @@
<ui version="4.0">
<class>UICFTControls</class>
<widget class="QWidget" name="UICFTControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>645</width>
- <height>416</height>
+ <width>489</width>
+ <height>402</height>
</rect>
</property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="minimumSize">
<size>
- <width>645</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
- <string>FreeTrack 2.0 settings FaceTrackNoIR</string>
+ <string>freetrack protocol settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>images/FaceTrackNoIR.ico</normaloff>images/FaceTrackNoIR.ico</iconset>
+ <iconset resource="ft-protocol.qrc">
+ <normaloff>:/images/freetrack.png</normaloff>:/images/freetrack.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -29,405 +41,179 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>70</height>
- </size>
- </property>
- <property name="title">
- <string>TIRViews</string>
- </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>TIRViews</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
<widget class="QCheckBox" name="chkTIRViews">
- <property name="geometry">
- <rect>
- <x>80</x>
- <y>30</y>
- <width>88</width>
- <height>17</height>
- </rect>
- </property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
- <string>Use TIRViews</string>
+ <string>Memory hacks</string>
</property>
</widget>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>10</y>
- <width>421</width>
- <height>16</height>
- </rect>
- </property>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_2">
<property name="text">
- <string>TIRViews is only required for some older games (like CFS3). For it to work, TIRViews.dll</string>
+ <string>Only for very old and buggy old games such as CFS3.</string>
</property>
- </widget>
- <widget class="QLabel" name="label_5">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>30</y>
- <width>421</width>
- <height>16</height>
- </rect>
+ <property name="scaledContents">
+ <bool>false</bool>
</property>
- <property name="text">
- <string>must be placed in the FaceTrackNoIR program folder. If the checkbox is disabled, the</string>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
- <widget class="QLabel" name="label_6">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>50</y>
- <width>411</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>the DLL was not found. You can get it from NaturalPoint.</string>
- </property>
- </widget>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>70</height>
- </size>
- </property>
- <property name="title">
- <string>TrackIR.exe</string>
- </property>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>TrackIR.exe</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout_3">
+ <item row="0" column="0">
<widget class="QCheckBox" name="chkStartDummy">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>30</y>
- <width>145</width>
- <height>17</height>
- </rect>
- </property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
- <string>Start dummy TrackIR.exe</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_3">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>10</y>
- <width>351</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Some programs check, to see if a process called TrackIR.exe is running,</string>
+ <string>Using EZCA</string>
</property>
</widget>
+ </item>
+ <item row="0" column="1">
<widget class="QLabel" name="label">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>30</y>
- <width>261</width>
- <height>16</height>
- </rect>
- </property>
<property name="text">
- <string>before enabling head-tracking (EZCA is one of them).</string>
+ <string>FSX-specific EZCA protocol hacks</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
- <widget class="QLabel" name="label_7">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>50</y>
- <width>231</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Check the checkbox, to overcome this problem.</string>
- </property>
- </widget>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_3">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>70</height>
- </size>
- </property>
- <property name="title">
- <string>Select interface</string>
- </property>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Select interface</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QComboBox" name="cbxSelectInterface"/>
+ </item>
+ <item row="0" column="1">
<widget class="QLabel" name="label_8">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>10</y>
- <width>351</width>
- <height>16</height>
- </rect>
- </property>
<property name="text">
- <string>Some games support both FreeTrack and TrackIR and may get confused,</string>
- </property>
- </widget>
- <widget class="QLabel" name="label_2">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>30</y>
- <width>261</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>when both interfaces are visible.</string>
+ <string>Disable one of the protocols if game is confused by presence of both at the same time.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
- <widget class="QLabel" name="label_9">
- <property name="geometry">
- <rect>
- <x>189</x>
- <y>50</y>
- <width>381</width>
- <height>16</height>
- </rect>
- </property>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Repair NPClient location</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignJustify|Qt::AlignTop</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QPushButton" name="bntLocateNPClient">
<property name="text">
- <string>Try to disable one interface, if you experience problems.</string>
- </property>
- </widget>
- <widget class="QComboBox" name="cbxSelectInterface">
- <property name="geometry">
- <rect>
- <x>6</x>
- <y>30</y>
- <width>168</width>
- <height>22</height>
- </rect>
+ <string>Locate DLL</string>
</property>
</widget>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_4">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>70</height>
- </size>
- </property>
- <property name="title">
- <string>Repair NPClient location</string>
- </property>
+ </item>
+ <item row="0" column="1">
<widget class="QLabel" name="label_10">
- <property name="geometry">
- <rect>
- <x>188</x>
- <y>10</y>
- <width>381</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>Users who use other software with an NPClient DLL (like TrackIR, FreeTrack or </string>
- </property>
- </widget>
- <widget class="QLabel" name="label_11">
- <property name="geometry">
- <rect>
- <x>184</x>
- <y>30</y>
- <width>411</width>
- <height>20</height>
- </rect>
- </property>
<property name="text">
- <string> GlovePIE) may need to repair the location of the DLL, after running FaceTrackNoIR.</string>
+ <string>Replace the registry entry if you want to use other software with the NPClient protocol and it doesn't work automatically.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
- <widget class="QLabel" name="label_12">
- <property name="geometry">
- <rect>
- <x>187</x>
- <y>50</y>
- <width>391</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>Use this button to locate the desired NPClient DLL.</string>
- </property>
- </widget>
- <widget class="QPushButton" name="bntLocateNPClient">
- <property name="geometry">
- <rect>
- <x>4</x>
- <y>30</y>
- <width>171</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>Locate DLL</string>
- </property>
- </widget>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ </item>
+ </layout>
+ </widget>
</item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <item row="4" column="0">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ </widget>
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="ft-protocol.qrc"/>
+ </resources>
<connections/>
<slots>
<slot>startEngineClicked()</slot>
diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp
index bb960696..281af6a0 100644
--- a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp
+++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp
@@ -1,297 +1,211 @@
-/********************************************************************************
-* 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. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20130209 - WVR: Some games support both interfaces and cause trouble. Added ComboBox to fix this (hide one interface
- by clearing the appropriate Registry-setting).
- 20130203 - WVR: Added Tirviews and dummy checkboxes to the Settings dialog. This is necessary for CFS3 etc.
- 20130125 - WVR: Upgraded to FT2.0: now the FreeTrack protocol supports all TIR-enabled games.
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
- 20100601 - WVR: Added Mutex-bit in run(). Thought it wasn't so important (still do...).
- 20100523 - WVR: Implemented the Freetrack-protocol just like Freetrack does. Earlier
- FaceTrackNoIR only worked with an adapted DLL, with a putdata function.
- Now it works direcly in shared memory!
-*/
-#include <algorithm>
-#include "ftnoir_protocol_ft.h"
-#include "ftnoir_csv/csv.h"
-
-/** constructor **/
-FTNoIR_Protocol::FTNoIR_Protocol() :
- shm(FT_MM_DATA, FREETRACK_MUTEX, sizeof(FTMemMap))
-{
- pMemData = (FTMemMap*) shm.mem;
- useTIRViews = false;
- useDummyExe = false;
- intUsedInterface = 0;
-
- loadSettings();
-
- ProgramName = "";
- intGameID = 0;
-
- viewsStart = 0;
- viewsStop = 0;
-}
-
-/** destructor **/
-FTNoIR_Protocol::~FTNoIR_Protocol()
-{
-
- qDebug()<< "~FTNoIR_Protocol: Destructor started.";
-
- //
- // Stop if started
- //
- if (viewsStop != NULL) {
- qDebug()<< "~FTNoIR_Protocol: Stopping TIRViews.";
- viewsStop();
- FTIRViewsLib.unload();
- }
-}
-
-//
-// Read the game-data from CSV
-//
-
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Protocol::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FT" );
- intUsedInterface = iniFile.value ( "UsedInterface", 0 ).toInt();
- iniFile.endGroup ();
-
- //
- // Use the settings-section from the deprecated fake-TIR protocol, as they are most likely to be found there.
- //
- iniFile.beginGroup ( "FTIR" );
- useTIRViews = iniFile.value ( "useTIRViews", 0 ).toBool();
- useDummyExe = iniFile.value ( "useDummyExe", 1 ).toBool();
- iniFile.endGroup ();
-}
-
-//
-// Update Headpose in Game.
-//
-void FTNoIR_Protocol::sendHeadposeToGame(double *headpose, double *rawheadpose ) {
-float virtPosX;
-float virtPosY;
-float virtPosZ;
-
-float virtRotX;
-float virtRotY;
-float virtRotZ;
-
-float headPosX;
-float headPosY;
-float headPosZ;
-
-float headRotX;
-float headRotY;
-float headRotZ;
-
- //
- // Scale the Raw measurements to the client measurements.
- //
- headRotX = getRadsFromDegrees(rawheadpose[Pitch]);
- headRotY = getRadsFromDegrees(rawheadpose[Yaw]);
- headRotZ = getRadsFromDegrees(rawheadpose[Roll]);
- headPosX = rawheadpose[TX] * 10;
- headPosY = rawheadpose[TY] * 10;
- headPosZ = rawheadpose[TZ] * 10;
-
- virtRotX = getRadsFromDegrees(headpose[Pitch]);
- virtRotY = getRadsFromDegrees(headpose[Yaw]);
- virtRotZ = getRadsFromDegrees(headpose[Roll]);
- virtPosX = headpose[TX] * 10;
- virtPosY = headpose[TY] * 10;
- virtPosZ = headpose[TZ] * 10;
-
- shm.lock();
-
- pMemData->data.RawX = headPosX;
- pMemData->data.RawY = headPosY;
- pMemData->data.RawZ = headPosZ;
- pMemData->data.RawPitch = headRotX;
- pMemData->data.RawYaw = headRotY;
- pMemData->data.RawRoll = headRotZ;
-
- //
- //
- pMemData->data.X = virtPosX;
- pMemData->data.Y = virtPosY;
- pMemData->data.Z = virtPosZ;
- pMemData->data.Pitch = virtRotX;
- pMemData->data.Yaw = virtRotY;
- pMemData->data.Roll = virtRotZ;
-
- //
- // Leave some values 0 yet...
- //
- pMemData->data.X1 = pMemData->data.DataID + 10;
- pMemData->data.X2 = 0;
- pMemData->data.X3 = 0;
- pMemData->data.X4 = 0;
- pMemData->data.Y1 = 0;
- pMemData->data.Y2 = 0;
- pMemData->data.Y3 = 0;
- pMemData->data.Y4 = 0;
-
- //
- // Check if the handle that was sent to the Game, was changed (on x64, this will be done by the ED-API)
- // If the "Report Program Name" command arrives (which is a '1', for now), raise the event from here!
- //
- //
- // The game-ID was changed?
- //
- if (intGameID != pMemData->GameID)
- {
- QString gamename;
- CSV::getGameData(pMemData->GameID, pMemData->table, gamename);
- pMemData->GameID2 = pMemData->GameID;
- intGameID = pMemData->GameID;
- QMutexLocker foo(&this->game_name_mutex);
- connected_game = gamename;
- }
-
- pMemData->data.DataID += 1;
-
- shm.unlock();
-}
-
-void FTNoIR_Protocol::start_tirviews() {
- QString aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll";
- if ( QFile::exists( aFileName )) {
- FTIRViewsLib.setFileName(aFileName);
- FTIRViewsLib.load();
-
- viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart");
- if (viewsStart == NULL) {
- qDebug() << "FTServer::run() says: TIRViewsStart function not found in DLL!";
- }
- else {
- qDebug() << "FTServer::run() says: TIRViewsStart executed!";
- viewsStart();
- }
-
- //
- // Load the Stop function from TIRViews.dll. Call it when terminating the thread.
- //
- viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop");
- if (viewsStop == NULL) {
- qDebug() << "FTServer::run() says: TIRViewsStop function not found in DLL!";
- }
- }
-}
-
-void FTNoIR_Protocol::start_dummy() {
- QString program = QCoreApplication::applicationDirPath() + "/TrackIR.exe";
- dummyTrackIR.startDetached("\"" + program + "\"");
-
- qDebug() << "FTServer::run() says: TrackIR.exe executed!" << program;
-}
-
-bool FTNoIR_Protocol::checkServerInstallationOK()
-{
- QSettings settings("Freetrack", "FreetrackClient"); // Registry settings (in HK_USER)
- QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER)
- QString aLocation; // Location of Client DLL
-
- qDebug() << "checkServerInstallationOK says: Starting Function";
-
- //
- // Write the path in the registry (for FreeTrack and FreeTrack20), for the game(s).
- //
- aLocation = QCoreApplication::applicationDirPath() + "/";
-
- qDebug() << "checkServerInstallationOK says: used interface = " << intUsedInterface;
- switch (intUsedInterface) {
- case 0: // Use both interfaces
- settings.setValue( "Path" , aLocation );
- settingsTIR.setValue( "Path" , aLocation );
- break;
- case 1: // Use FreeTrack, disable TrackIR
- settings.setValue( "Path" , aLocation );
- settingsTIR.setValue( "Path" , "" );
- break;
- case 2: // Use TrackIR, disable FreeTrack
- settings.setValue( "Path" , "" );
- settingsTIR.setValue( "Path" , aLocation );
- break;
- default:
- // should never be reached
- break;
- }
-
- //
- // TIRViews must be started first, or the NPClient DLL will never be loaded.
- //
- if (useTIRViews) {
- start_tirviews();
- }
-
- //
- // Check if TIRViews or dummy TrackIR.exe is required for this game
- //
- if (useDummyExe) {
- start_dummy();
- }
-
- if (shm.mem == (void*) 0 || shm.mem == (void*) -1)
- return false;
-
- pMemData->data.DataID = 1;
- pMemData->data.CamWidth = 100;
- pMemData->data.CamHeight = 250;
- pMemData->GameID2 = 0;
- memset(pMemData->table, 0, 8);
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocol - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocol@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Protocol;
-}
+/********************************************************************************
+* 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"
+
+FTNoIR_Protocol::FTNoIR_Protocol() :
+ shm(FT_MM_DATA, FREETRACK_MUTEX, sizeof(FTMemMap))
+{
+ pMemData = (FTMemMap*) shm.mem;
+ ProgramName = "";
+ intGameID = 0;
+ viewsStart = 0;
+ viewsStop = 0;
+}
+
+FTNoIR_Protocol::~FTNoIR_Protocol()
+{
+ if (viewsStop != NULL) {
+ viewsStop();
+ FTIRViewsLib.unload();
+ }
+ dummyTrackIR.terminate();
+ dummyTrackIR.kill();
+ dummyTrackIR.waitForFinished(50);
+}
+
+void FTNoIR_Protocol::sendHeadposeToGame(const double* headpose) {
+ float virtPosX;
+ float virtPosY;
+ float virtPosZ;
+
+ float virtRotX;
+ float virtRotY;
+ float virtRotZ;
+
+ float headPosX;
+ float headPosY;
+ float headPosZ;
+
+ float headRotX;
+ float headRotY;
+ float headRotZ;
+ headRotX = virtRotX = getRadsFromDegrees(headpose[Pitch]) * (s.useDummyExe ? 2.0 : 1.0);
+ headRotY = virtRotY = getRadsFromDegrees(headpose[Yaw]);
+ headRotZ = virtRotZ = getRadsFromDegrees(headpose[Roll]);
+ headPosX = virtPosX = headpose[TX] * 10;
+ headPosY = virtPosY = headpose[TY] * 10;
+ headPosZ = virtPosZ = headpose[TZ] * 10;
+
+ shm.lock();
+
+ pMemData->data.RawX = headPosX;
+ pMemData->data.RawY = headPosY;
+ pMemData->data.RawZ = headPosZ;
+ pMemData->data.RawPitch = headRotX;
+ pMemData->data.RawYaw = headRotY;
+ pMemData->data.RawRoll = headRotZ;
+
+ //
+ //
+ pMemData->data.X = virtPosX;
+ pMemData->data.Y = virtPosY;
+ pMemData->data.Z = virtPosZ;
+ pMemData->data.Pitch = virtRotX;
+ pMemData->data.Yaw = virtRotY;
+ pMemData->data.Roll = virtRotZ;
+
+ //
+ // Leave some values 0 yet...
+ //
+ pMemData->data.X1 = pMemData->data.DataID + 10;
+ pMemData->data.X2 = 0;
+ pMemData->data.X3 = 0;
+ pMemData->data.X4 = 0;
+ pMemData->data.Y1 = 0;
+ pMemData->data.Y2 = 0;
+ pMemData->data.Y3 = 0;
+ pMemData->data.Y4 = 0;
+
+ if (intGameID != pMemData->GameID)
+ {
+ QString gamename;
+ CSV::getGameData(pMemData->GameID, pMemData->table, gamename);
+ pMemData->GameID2 = pMemData->GameID;
+ intGameID = pMemData->GameID;
+ QMutexLocker foo(&this->game_name_mutex);
+ connected_game = gamename;
+ }
+
+ pMemData->data.DataID += 1;
+ shm.unlock();
+}
+
+void FTNoIR_Protocol::start_tirviews() {
+ QString aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll";
+ if ( QFile::exists( aFileName )) {
+ FTIRViewsLib.setFileName(aFileName);
+ FTIRViewsLib.load();
+
+ viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart");
+ if (viewsStart == NULL) {
+ qDebug() << "FTServer::run() says: TIRViewsStart function not found in DLL!";
+ }
+ else {
+ qDebug() << "FTServer::run() says: TIRViewsStart executed!";
+ viewsStart();
+ }
+
+ //
+ // Load the Stop function from TIRViews.dll. Call it when terminating the thread.
+ //
+ viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop");
+ if (viewsStop == NULL) {
+ qDebug() << "FTServer::run() says: TIRViewsStop function not found in DLL!";
+ }
+ }
+}
+
+void FTNoIR_Protocol::start_dummy() {
+
+
+ QString program = QCoreApplication::applicationDirPath() + "/TrackIR.exe";
+ dummyTrackIR.setProgram("\"" + program + "\"");
+ dummyTrackIR.start();
+
+ qDebug() << "FTServer::run() says: TrackIR.exe executed!" << program;
+}
+
+bool FTNoIR_Protocol::checkServerInstallationOK()
+{
+ QSettings settings("Freetrack", "FreetrackClient"); // Registry settings (in HK_USER)
+ QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER)
+ QString aLocation; // Location of Client DLL
+
+
+ if (!shm.success())
+ return false;
+
+ qDebug() << "checkServerInstallationOK says: Starting Function";
+
+ //
+ // Write the path in the registry (for FreeTrack and FreeTrack20), for the game(s).
+ //
+ aLocation = QCoreApplication::applicationDirPath() + "/";
+
+ qDebug() << "checkServerInstallationOK says: used interface = " << s.intUsedInterface;
+ switch (s.intUsedInterface) {
+ case 0: // Use both interfaces
+ settings.setValue( "Path" , aLocation );
+ settingsTIR.setValue( "Path" , aLocation );
+ break;
+ case 1: // Use FreeTrack, disable TrackIR
+ settings.setValue( "Path" , aLocation );
+ settingsTIR.setValue( "Path" , "" );
+ break;
+ case 2: // Use TrackIR, disable FreeTrack
+ settings.setValue( "Path" , "" );
+ settingsTIR.setValue( "Path" , aLocation );
+ break;
+ default:
+ // should never be reached
+ break;
+ }
+
+ //
+ // TIRViews must be started first, or the NPClient DLL will never be loaded.
+ //
+ if (s.useTIRViews) {
+ start_tirviews();
+ }
+
+ // more games need the dummy executable than previously thought
+ start_dummy();
+
+ pMemData->data.DataID = 1;
+ pMemData->data.CamWidth = 100;
+ pMemData->data.CamHeight = 250;
+ pMemData->GameID2 = 0;
+ memset(pMemData->table, 0, 8);
+
+ return true;
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.h b/ftnoir_protocol_ft/ftnoir_protocol_ft.h
index f87c7300..0af9ff07 100644
--- a/ftnoir_protocol_ft/ftnoir_protocol_ft.h
+++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.h
@@ -1,141 +1,120 @@
-/********************************************************************************
-* 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) 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/>. *
-* *
-* FTServer FTServer is the Class, that communicates headpose-data *
-* to games, using the FreeTrackClient.dll. *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_FTSERVER_H
-#define INCLUDED_FTSERVER_H
-
-#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#include "ui_ftnoir_ftcontrols.h"
-#include "facetracknoir/global-settings.h"
-#include "fttypes.h"
-#include <QMessageBox>
-#include <QSettings>
-#include <QLibrary>
-#include <QProcess>
-#include <QDebug>
-#include <QFile>
-#include <QString>
-#include <windows.h>
-#include <QMutex>
-#include <QMutexLocker>
-#include "compat/compat.h"
-//#include "math.h"
-
-//typedef char *(WINAPI *importProvider)(void);
-typedef void (WINAPI *importTIRViewsStart)(void);
-typedef void (WINAPI *importTIRViewsStop)(void);
-
-class FTNoIR_Protocol : public IProtocol
-{
-public:
- FTNoIR_Protocol();
- ~FTNoIR_Protocol();
- bool checkServerInstallationOK( );
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
- QString getGameName() {
- QMutexLocker foo(&game_name_mutex);
- return connected_game;
- }
-
-private:
- importTIRViewsStart viewsStart; // Functions inside TIRViews.dll
- importTIRViewsStop viewsStop;
-
- FTMemMap *pMemData;
- QString game_name;
- PortableLockedShm shm;
-
- // Private properties
- QString ProgramName;
- QLibrary FTIRViewsLib;
- QProcess dummyTrackIR;
- int intGameID;
- int intUsedInterface; // Determine which interface to use (or to hide from the game)
- bool useTIRViews; // Needs to be in the Settings dialog
- bool useDummyExe;
- float getRadsFromDegrees ( float degrees ) { return (degrees * 0.017453f); }
- void loadSettings();
- void start_tirviews();
- void start_dummy();
-
- QString connected_game;
- QMutex game_name_mutex;
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class FTControls: public QWidget, public IProtocolDialog
-{
- Q_OBJECT
-public:
-
- explicit FTControls();
- virtual ~FTControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerProtocol(IProtocol *protocol) {
- theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
- }
- void unRegisterProtocol() {
- theProtocol = NULL; // Reset the pointer
- }
-
-private:
- Ui::UICFTControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FTNoIR_Protocol *theProtocol;
-
-private slots:
- void selectDLL();
- void doOK();
- void doCancel();
- void settingChanged() { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
-//*******************************************************************************************************
-class FTNoIR_ProtocolDll : public Metadata
-{
-public:
- FTNoIR_ProtocolDll();
- ~FTNoIR_ProtocolDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack 2.0"); }
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack 2.0"); }
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Enhanced FreeTrack protocol"); }
-
- void getIcon(QIcon *icon) { *icon = QIcon(":/images/freetrack.png"); }
-};
-
-
-#endif//INCLUDED_FTSERVER_H
-//END
+/********************************************************************************
+* 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) 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/>. *
+* *
+* FTServer FTServer is the Class, that communicates headpose-data *
+* to games, using the FreeTrackClient.dll. *
+********************************************************************************/
+#pragma once
+#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ui_ftnoir_ftcontrols.h"
+#include "facetracknoir/global-settings.h"
+#include "fttypes.h"
+#include <QMessageBox>
+#include <QSettings>
+#include <QLibrary>
+#include <QProcess>
+#include <QDebug>
+#include <QFile>
+#include <QString>
+#include <windows.h>
+#include <QMutex>
+#include <QMutexLocker>
+#include "compat/compat.h"
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> intUsedInterface;
+ value<bool> useTIRViews, useDummyExe;
+ settings() :
+ b(bundle("proto-freetrack")),
+ intUsedInterface(b, "used-interfaces", 0),
+ useTIRViews(b, "use-memory-hacks", false),
+ useDummyExe(b, "ezca-mode", false)
+ {}
+};
+
+//typedef char *(WINAPI *importProvider)(void);
+typedef void (WINAPI *importTIRViewsStart)(void);
+typedef void (WINAPI *importTIRViewsStop)(void);
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ FTNoIR_Protocol();
+ virtual ~FTNoIR_Protocol();
+ bool checkServerInstallationOK( );
+ void sendHeadposeToGame( const double *headpose );
+ QString getGameName() {
+ QMutexLocker foo(&game_name_mutex);
+ return connected_game;
+ }
+private:
+ importTIRViewsStart viewsStart; // Functions inside TIRViews.dll
+ importTIRViewsStop viewsStop;
+
+ FTMemMap *pMemData;
+ QString game_name;
+ PortableLockedShm shm;
+
+ // Private properties
+ QString ProgramName;
+ QLibrary FTIRViewsLib;
+ QProcess dummyTrackIR;
+ static inline double getRadsFromDegrees ( double degrees )
+ {
+ return degrees * 0.017453;
+ }
+ int intGameID;
+ void start_tirviews();
+ void start_dummy();
+ QString connected_game;
+ QMutex game_name_mutex;
+ settings s;
+};
+
+class FTControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+ explicit FTControls();
+ void registerProtocol(IProtocol *) {}
+ void unRegisterProtocol() {}
+private:
+ Ui::UICFTControls ui;
+ settings s;
+private slots:
+ void selectDLL();
+ void doOK();
+ void doCancel();
+};
+
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack 2.0"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FreeTrack 2.0"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Enhanced FreeTrack protocol"); }
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/freetrack.png"); }
+};
diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp
index 8d4ef18f..5ce903b7 100644
--- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp
+++ b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp
@@ -1,233 +1,96 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_ft.h"
-#include <QDebug>
-#include <QFileDialog>
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-FTControls::FTControls() :
-QWidget()
-{
- QString aFileName; // File Path and Name
-
- ui.setupUi( this );
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.bntLocateNPClient, SIGNAL(clicked()), this, SLOT(selectDLL()));
- connect(ui.chkTIRViews, SIGNAL(stateChanged(int)), this, SLOT(settingChanged()));
- connect(ui.chkStartDummy, SIGNAL(stateChanged(int)), this, SLOT(settingChanged()));
- connect(ui.cbxSelectInterface, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged( int )));
-
- ui.cbxSelectInterface->addItem("Enable both");
- ui.cbxSelectInterface->addItem("Use FreeTrack, hide TrackIR");
- ui.cbxSelectInterface->addItem("Use TrackIR, hide FreeTrack");
-
- theProtocol = NULL;
-
- // Load the settings from the current .INI-file
- loadSettings();
-
-
- aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll";
- if ( !QFile::exists( aFileName ) ) {
- ui.chkTIRViews->setChecked( false );
- ui.chkTIRViews->setEnabled ( false );
-
- //
- // Best do this save() last, or it will continually reset the settings... :-(
- //
- save();
- }
- else {
- ui.chkTIRViews->setEnabled ( true );
- }
-
-
-}
-
-//
-// Destructor for server-dialog
-//
-FTControls::~FTControls() {
- qDebug() << "~FTControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void FTControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void FTControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void FTControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void FTControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTControls::loadSettings() {
- qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "FT" );
- ui.cbxSelectInterface->setCurrentIndex( iniFile.value ( "UsedInterface", 0 ).toInt() );
- iniFile.endGroup ();
-
- iniFile.beginGroup ( "FTIR" );
- ui.chkTIRViews->setChecked (iniFile.value ( "useTIRViews", 0 ).toBool());
- ui.chkStartDummy->setChecked (iniFile.value ( "useDummyExe", 1 ).toBool());
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FTControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FT" );
- iniFile.setValue ( "UsedInterface", ui.cbxSelectInterface->currentIndex());
- iniFile.endGroup ();
-
- iniFile.beginGroup ( "FTIR" );
- iniFile.setValue ( "useTIRViews", ui.chkTIRViews->isChecked() );
- iniFile.setValue ( "useDummyExe", ui.chkStartDummy->isChecked() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Select a NPClient.dll file, to repair the Location in the Registry.
-// Several program distribute their own version of this file.
-//
-void FTControls::selectDLL() {
- QFileDialog::Options options;
- QFileDialog::FileMode mode;
-
- options |= QFileDialog::DontUseNativeDialog;
- mode = QFileDialog::ExistingFile;
- QString selectedFilter;
- QString fileName = QFileDialog::getOpenFileName( this, tr("Select the desired NPClient DLL"), QCoreApplication::applicationDirPath() + "/NPClient.dll", tr("Dll file (*.dll);;All Files (*)"));
-
- //
- // Write the location of the file in the required Registry-key.
- //
- if (! fileName.isEmpty() ) {
- if (fileName.endsWith("NPClient.dll", Qt::CaseInsensitive) ) {
- QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER)
- QString aLocation = fileName.left(fileName.length() - 12); // Location of Client DLL
-
- settingsTIR.setValue( "Path" , aLocation );
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language.
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
-{
- return new FTControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_ft.h"
+#include <QDebug>
+#include <QFileDialog>
+
+//*******************************************************************************************************
+// FaceTrackNoIR Client Settings-dialog.
+//*******************************************************************************************************
+
+//
+// Constructor for server-settings-dialog
+//
+FTControls::FTControls() :
+ QWidget()
+{
+ QString aFileName; // File Path and Name
+
+ ui.setupUi( this );
+
+ // Connect Qt signals to member-functions
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+ connect(ui.bntLocateNPClient, SIGNAL(clicked()), this, SLOT(selectDLL()));
+
+ tie_setting(s.useDummyExe, ui.chkStartDummy);
+ tie_setting(s.useTIRViews, ui.chkTIRViews);
+
+ ui.cbxSelectInterface->addItem("Enable both");
+ ui.cbxSelectInterface->addItem("Use FreeTrack, hide TrackIR");
+ ui.cbxSelectInterface->addItem("Use TrackIR, hide FreeTrack");
+
+ tie_setting(s.intUsedInterface, ui.cbxSelectInterface);
+
+ aFileName = QCoreApplication::applicationDirPath() + "/TIRViews.dll";
+ if ( !QFile::exists( aFileName ) ) {
+ ui.chkTIRViews->setChecked( false );
+ ui.chkTIRViews->setEnabled ( false );
+ }
+ else {
+ ui.chkTIRViews->setEnabled ( true );
+ }
+}
+
+void FTControls::doOK() {
+ s.b->save();
+ this->close();
+}
+
+void FTControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+void FTControls::selectDLL() {
+ QString fileName = QFileDialog::getOpenFileName( this, tr("Select the desired NPClient DLL"), QCoreApplication::applicationDirPath() + "/NPClient.dll", tr("Dll file (*.dll);;All Files (*)"));
+
+ //
+ // Write the location of the file in the required Registry-key.
+ //
+ if (! fileName.isEmpty() ) {
+ if (fileName.endsWith("NPClient.dll", Qt::CaseInsensitive) ) {
+ QSettings settingsTIR("NaturalPoint", "NATURALPOINT\\NPClient Location"); // Registry settings (in HK_USER)
+ QString aLocation = fileName.left(fileName.length() - 12); // Location of Client DLL
+
+ settingsTIR.setValue( "Path" , aLocation );
+ }
+ }
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new FTControls;
+}
diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp
index 5f821f59..38f11211 100644
--- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp
+++ b/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp
@@ -1,54 +1,30 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_ft.h"
-#include <QDebug>
-
-FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
-}
-
-FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language.
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_ProtocolDll;
-} \ No newline at end of file
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_ft.h"
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_ft/fttypes.h b/ftnoir_protocol_ft/fttypes.h
index 0c65fc2f..ced844dc 100644
--- a/ftnoir_protocol_ft/fttypes.h
+++ b/ftnoir_protocol_ft/fttypes.h
@@ -1,34 +1,21 @@
-/********************************************************************************
-* FTTypes FTTypes contains th specific type definitions for the *
-* FreeTrack protocol. *
-* It was loosely translated from FTTypes.pas *
-* which was created by the FreeTrack-team. *
-* *
-* Copyright (C) 2013 Wim Vriend (Developing) *
-* Ron Hendriks (Testing and Research) *
-* *
-* Homepage <http://www.free-track.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/>. *
-* *
-* We would like to extend our grattitude to the creators of SweetSpotter, *
-* which has become the basis of this program: "Great work guys!" *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20130125 - WVR: Upgraded to FT2.0: now the FreeTrack protocol supports all TIR-enabled games. The memory-mapping was expanded for this purpose.
-*/
+/************************************************************************************
+ * * FTTypes FTTypes contains the specific type definitions for the *
+ * * FreeTrack protocol. *
+ * * It was loosely translated from FTTypes.pas *
+ * * which was created by the FreeTrack-team. *
+ * * *
+ * * Wim Vriend (Developing) *
+ * * Ron Hendriks (Testing and Research) *
+ * * *
+ * * Homepage <http://facetracknoir.sourceforge.net/home/default.htm> *
+ * * *
+ * * 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. *
+ * * *
+ * * The FTTypes sources were translated from the original Delphi sources *
+ * * created by the FreeTrack developers. *
+ */
#ifndef INCLUDED_FTTYPES_H
#define INCLUDED_FTTYPES_H
@@ -50,8 +37,8 @@ typedef __int32 my_32bit_int;
#define FREETRACK_MUTEX "FT_Mutext"
struct TFreeTrackData {
- int DataID;
- int CamWidth;
+ int DataID;
+ int CamWidth;
int CamHeight;
// virtual pose
float Yaw; // positive yaw to the left
@@ -80,7 +67,7 @@ struct TFreeTrackData {
typedef TFreeTrackData * PFreetrackData;
struct FTMemMap {
- TFreeTrackData data;
+ TFreeTrackData data;
my_32bit_int GameID;
unsigned char table[8];
my_32bit_int GameID2;
diff --git a/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui b/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui
index d8efec61..48679f3c 100644
--- a/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui
+++ b/ftnoir_protocol_ftn/ftnoir_ftncontrols.ui
@@ -2,20 +2,23 @@
<ui version="4.0">
<class>UICFTNControls</class>
<widget class="QWidget" name="UICFTNControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>411</width>
- <height>156</height>
+ <height>169</height>
</rect>
</property>
<property name="windowTitle">
- <string>FTNoIR protocol settings FaceTrackNoIR</string>
+ <string>UDP protocol settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>images/FaceTrackNoIR.png</normaloff>images/facetracknoir.png</iconset>
+ <iconset resource="../facetracknoir/main-facetracknoir.qrc">
+ <normaloff>:/images/facetracknoir.png</normaloff>:/images/facetracknoir.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -251,7 +254,9 @@
<tabstop>btnOK</tabstop>
<tabstop>btnCancel</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="../facetracknoir/main-facetracknoir.qrc"/>
+ </resources>
<connections/>
<slots>
<slot>startEngineClicked()</slot>
diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp
index bfe83853..e93a751e 100644
--- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp
+++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp
@@ -1,124 +1,55 @@
-/********************************************************************************
-* 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-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/>. *
-* *
-* FTNServer FTNServer is the Class, that communicates headpose-data *
-* to another FaceTrackNoIR program, using UDP. *
-* It is based on the (Linux) example made by Melchior FRANZ. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
-*/
-#include "ftnoir_protocol_ftn.h"
-#include <QFile>
-#include "facetracknoir/global-settings.h"
-
-/** constructor **/
-FTNoIR_Protocol::FTNoIR_Protocol()
-{
- loadSettings();
- outSocket = 0;
-}
-
-/** destructor **/
-FTNoIR_Protocol::~FTNoIR_Protocol()
-{
- if (outSocket != 0) {
- outSocket->close();
- delete outSocket;
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Protocol::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FTN" );
-
- QString destAddr = iniFile.value ( "IP-1", 192 ).toString() + "." + iniFile.value ( "IP-2", 168 ).toString() + "." + iniFile.value ( "IP-3", 2 ).toString() + "." + iniFile.value ( "IP-4", 1 ).toString();
- destIP = QHostAddress( destAddr );
- destPort = iniFile.value ( "PortNumber", 5550 ).toInt();
-
- iniFile.endGroup ();
-}
-
-//
-// Update Headpose in Game.
-//
-void FTNoIR_Protocol::sendHeadposeToGame(double *headpose, double *rawheadpose ) {
- int no_bytes;
- double test_data[6];
- //
- // Copy the Raw measurements directly to the client.
- //
- for (int i = 0; i < 6; i++)
- test_data[i] = headpose[i];
- //
- // Try to send an UDP-message to the receiver
- //
-
- //! [1]
- if (outSocket != 0) {
- no_bytes = outSocket->writeDatagram((const char *) test_data, sizeof( test_data ), destIP, destPort);
- if ( no_bytes > 0) {
-// qDebug() << "FTNServer::writePendingDatagrams says: bytes send =" << no_bytes << sizeof( double );
- }
- else {
- qDebug() << "FTNServer::writePendingDatagrams says: nothing sent!";
- }
- }
-}
-
-//
-// Check if the Client DLL exists and load it (to test it), if so.
-// Returns 'true' if all seems OK.
-//
-bool FTNoIR_Protocol::checkServerInstallationOK()
-{
- if (outSocket == 0) {
- outSocket = new QUdpSocket();
- }
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocol - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocol@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Protocol;
-}
+/********************************************************************************
+* 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-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/>. *
+* *
+* FTNServer FTNServer is the Class, that communicates headpose-data *
+* to another FaceTrackNoIR program, using UDP. *
+* It is based on the (Linux) example made by Melchior FRANZ. *
+********************************************************************************/
+#include "ftnoir_protocol_ftn.h"
+#include <QFile>
+#include "facetracknoir/global-settings.h"
+
+/** constructor **/
+FTNoIR_Protocol::FTNoIR_Protocol()
+{
+}
+
+void FTNoIR_Protocol::sendHeadposeToGame(const double *headpose) {
+ int destPort = s.port;
+ QHostAddress destIP(QString("%1.%2.%3.%4").arg(
+ QString::number(static_cast<int>(s.ip1)),
+ QString::number(static_cast<int>(s.ip2)),
+ QString::number(static_cast<int>(s.ip3)),
+ QString::number(static_cast<int>(s.ip4))));
+ outSocket.writeDatagram((const char *) headpose, sizeof( double[6] ), destIP, destPort);
+}
+
+bool FTNoIR_Protocol::checkServerInstallationOK()
+{
+ return outSocket.bind(QHostAddress::Any, 0, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h
index 1c4b493e..99e6c6a1 100644
--- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h
+++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h
@@ -1,104 +1,92 @@
-/********************************************************************************
-* 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) 2010-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/>. *
-* *
-* FTNServer FTNServer is the Class, that communicates headpose-data *
-* to FlightGear, using UDP. *
-* It is based on the (Linux) example made by Melchior FRANZ. *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_FTNSERVER_H
-#define INCLUDED_FTNSERVER_H
-
-#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "ui_ftnoir_ftncontrols.h"
-#include <QThread>
-#include <QUdpSocket>
-#include <QMessageBox>
-#include <QSettings>
-#include <math.h>
-#include "facetracknoir/global-settings.h"
-
-class FTNoIR_Protocol : public IProtocol
-{
-public:
- FTNoIR_Protocol();
- ~FTNoIR_Protocol();
- bool checkServerInstallationOK();
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
- QString getGameName() {
- return "UDP Tracker";
- }
-
-private:
- QUdpSocket *outSocket; // Send to FaceTrackNoIR
- QHostAddress destIP; // Destination IP-address
- int destPort; // Destination port-number
- void loadSettings();
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class FTNControls: public QWidget, public IProtocolDialog
-{
- Q_OBJECT
-public:
-
- explicit FTNControls();
- virtual ~FTNControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerProtocol(IProtocol *protocol) {}
- void unRegisterProtocol() {}
-
-private:
- Ui::UICFTNControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
-
-private slots:
- void doOK();
- void doCancel();
- void settingChanged() { settingsDirty = true; }
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
-//*******************************************************************************************************
-class FTNoIR_ProtocolDll : public Metadata
-{
-public:
- FTNoIR_ProtocolDll();
- ~FTNoIR_ProtocolDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FaceTrackNoIR"); }
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("FTN Client"); }
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("FaceTrackNoIR Client protocol"); }
-
- void getIcon(QIcon *icon) { *icon = QIcon(":/images/facetracknoir.png"); }
-};
-
-#endif//INCLUDED_FTNSERVER_H
-//END
+/********************************************************************************
+* 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) 2010-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/>. *
+* *
+* FTNServer FTNServer is the Class, that communicates headpose-data *
+* to FlightGear, using UDP. *
+* It is based on the (Linux) example made by Melchior FRANZ. *
+********************************************************************************/
+#pragma once
+
+#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "ui_ftnoir_ftncontrols.h"
+#include <QThread>
+#include <QUdpSocket>
+#include <QMessageBox>
+#include <math.h>
+#include "facetracknoir/global-settings.h"
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> ip1, ip2, ip3, ip4, port;
+ settings() :
+ b(bundle("udp-proto")),
+ ip1(b, "ip1", 192),
+ ip2(b, "ip2", 168),
+ ip3(b, "ip3", 0),
+ ip4(b, "ip4", 2),
+ port(b, "port", 4242)
+ {}
+};
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ FTNoIR_Protocol();
+ bool checkServerInstallationOK();
+ void sendHeadposeToGame(const double *headpose);
+ QString getGameName() {
+ return "UDP Tracker";
+ }
+private:
+ QUdpSocket outSocket;
+ settings s;
+};
+
+// Widget that has controls for FTNoIR protocol client-settings.
+class FTNControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+ FTNControls();
+ void registerProtocol(IProtocol *) {}
+ void unRegisterProtocol() {}
+private:
+ Ui::UICFTNControls ui;
+ settings s;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("UDP"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("UDP"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("opentrack UDP protocol"); }
+
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/facetracknoir.png"); }
+};
diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp
index a5265275..37db314f 100644
--- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp
+++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp
@@ -1,188 +1,62 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_ftn.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-FTNControls::FTNControls() :
-QWidget()
-{
- ui.setupUi( this );
-
- QPoint offsetpos(100, 100);
- //if (parent) {
- // this->move(parent->pos() + offsetpos);
- //}
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.spinIPFirstNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinIPSecondNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinIPThirdNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinIPFourthNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
- connect(ui.spinPortNumber, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-FTNControls::~FTNControls() {
- qDebug() << "~FTNControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void FTNControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void FTNControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void FTNControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void FTNControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNControls::loadSettings() {
-// qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
-// qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "FTN" );
- ui.spinIPFirstNibble->setValue( iniFile.value ( "IP-1", 192 ).toInt() );
- ui.spinIPSecondNibble->setValue( iniFile.value ( "IP-2", 168 ).toInt() );
- ui.spinIPThirdNibble->setValue( iniFile.value ( "IP-3", 2 ).toInt() );
- ui.spinIPFourthNibble->setValue( iniFile.value ( "IP-4", 1 ).toInt() );
-
- ui.spinPortNumber->setValue( iniFile.value ( "PortNumber", 5550 ).toInt() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void FTNControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FTN" );
- iniFile.setValue ( "IP-1", ui.spinIPFirstNibble->value() );
- iniFile.setValue ( "IP-2", ui.spinIPSecondNibble->value() );
- iniFile.setValue ( "IP-3", ui.spinIPThirdNibble->value() );
- iniFile.setValue ( "IP-4", ui.spinIPFourthNibble->value() );
- iniFile.setValue ( "PortNumber", ui.spinPortNumber->value() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
-{
- return new FTNControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_ftn.h"
+#include "facetracknoir/global-settings.h"
+
+FTNControls::FTNControls() :
+ QWidget()
+{
+ ui.setupUi( this );
+
+ tie_setting(s.ip1, ui.spinIPFirstNibble);
+ tie_setting(s.ip2, ui.spinIPSecondNibble);
+ tie_setting(s.ip3, ui.spinIPThirdNibble);
+ tie_setting(s.ip4, ui.spinIPFourthNibble);
+ tie_setting(s.port, ui.spinPortNumber);
+
+ connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+}
+
+//
+// OK clicked on server-dialog
+//
+void FTNControls::doOK() {
+ s.b->save();
+ this->close();
+}
+
+//
+// Cancel clicked on server-dialog
+//
+void FTNControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new FTNControls;
+}
diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp
index 61f06914..99689432 100644
--- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp
+++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp
@@ -1,57 +1,31 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_ftn.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
-}
-
-FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_ProtocolDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_ftn.h"
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_ftn/images/facetracknoir.png b/ftnoir_protocol_ftn/images/facetracknoir.png
deleted file mode 100644
index b69a13ef..00000000
--- a/ftnoir_protocol_ftn/images/facetracknoir.png
+++ /dev/null
Binary files differ
diff --git a/ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui b/ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui
new file mode 100644
index 00000000..d2b86445
--- /dev/null
+++ b/ftnoir_protocol_libevdev/ftnoir_libevdev_controls.ui
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UICLibevdevControls</class>
+ <widget class="QWidget" name="UICLibevdevControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>228</width>
+ <height>69</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>VJoy</string>
+ </property>
+ <property name="windowIcon">
+ <iconset>
+ <normaloff>:/images/vjoy.png</normaloff>:/images/vjoy.png</iconset>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <layout class="QVBoxLayout" name="_vertical_layout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Make sure rw for /dev/input/uinput!</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <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>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <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>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>btnOK</tabstop>
+ <tabstop>btnCancel</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp
new file mode 100644
index 00000000..70fde395
--- /dev/null
+++ b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.cpp
@@ -0,0 +1,101 @@
+#include "ftnoir_protocol_libevdev.h"
+#include "facetracknoir/global-settings.h"
+//#include "ftnoir_tracker_base/ftnoir_tracker_types.h"
+#include <cstdio>
+#include <algorithm>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define CHECK_LIBEVDEV(expr) if ((error = (expr)) != 0) goto error;
+
+static const int max_input = 65535;
+static const int mid_input = 32767;
+static const int min_input = 0;
+
+FTNoIR_Protocol::FTNoIR_Protocol() : dev(NULL), uidev(NULL)
+{
+ int error = 0;
+
+ dev = libevdev_new();
+
+ if (!dev)
+ goto error;
+
+ CHECK_LIBEVDEV(libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD));
+
+ libevdev_set_name(dev, "opentrack headpose");
+
+ struct input_absinfo absinfo;
+
+ absinfo.minimum = min_input;
+ absinfo.maximum = max_input;
+ absinfo.resolution = 1;
+ absinfo.value = mid_input;
+ absinfo.flat = 1;
+ absinfo.fuzz = 0;
+
+ CHECK_LIBEVDEV(libevdev_enable_event_type(dev, EV_ABS));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_X, &absinfo));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_Y, &absinfo));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_Z, &absinfo));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RX, &absinfo));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RY, &absinfo));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_ABS, ABS_RZ, &absinfo));
+
+ /* do not remove next 3 lines or udev scripts won't assign 0664 permissions -sh */
+ CHECK_LIBEVDEV(libevdev_enable_event_type(dev, EV_KEY));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_KEY, BTN_JOYSTICK, NULL));
+ CHECK_LIBEVDEV(libevdev_enable_event_code(dev, EV_KEY, BTN_TRIGGER, NULL));
+
+ CHECK_LIBEVDEV(libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uidev));
+
+ return;
+error:
+ if (uidev)
+ libevdev_uinput_destroy(uidev);
+ if (dev)
+ libevdev_free(dev);
+ if (error)
+ fprintf(stderr, "libevdev error: %d\n", error);
+ uidev = NULL;
+ dev = NULL;
+}
+
+FTNoIR_Protocol::~FTNoIR_Protocol()
+{
+ if (uidev)
+ libevdev_uinput_destroy(uidev);
+ if (dev)
+ libevdev_free(dev);
+}
+
+void FTNoIR_Protocol::sendHeadposeToGame(const double* headpose) {
+ static const int axes[] = {
+ /* translation goes first */
+ ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ
+ };
+
+ static const int max_value[] = {
+ 100,
+ 100,
+ 100,
+ 180,
+ 90,
+ 180
+ };
+
+ for (int i = 0; i < 6; i++)
+ {
+ int value = headpose[i] * mid_input / max_value[i] + mid_input;
+ int normalized = std::max(std::min(max_input, value), min_input);
+ (void) libevdev_uinput_write_event(uidev, EV_ABS, axes[i], normalized);
+ }
+
+ (void) libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h
new file mode 100644
index 00000000..f92bb7bb
--- /dev/null
+++ b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl>
+ *
+ * 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 "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ui_ftnoir_libevdev_controls.h"
+
+#include <QMessageBox>
+#include "facetracknoir/global-settings.h"
+
+extern "C" {
+# include <libevdev-1.0/libevdev/libevdev.h>
+# include <libevdev-1.0/libevdev/libevdev-uinput.h>
+}
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ FTNoIR_Protocol();
+ virtual ~FTNoIR_Protocol();
+ bool checkServerInstallationOK() {
+ return dev != NULL;
+ }
+ void sendHeadposeToGame(const double *headpose);
+ QString getGameName() {
+ return "Virtual joystick for Linux";
+ }
+private:
+ struct libevdev* dev;
+ struct libevdev_uinput* uidev;
+};
+
+// Widget that has controls for FTNoIR protocol client-settings.
+class LibevdevControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+
+ explicit LibevdevControls();
+ void registerProtocol(IProtocol *) {}
+ void unRegisterProtocol() {}
+
+private:
+ Ui::UICLibevdevControls ui;
+ void save();
+
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+//*******************************************************************************************************
+// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
+//*******************************************************************************************************
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ FTNoIR_ProtocolDll();
+ ~FTNoIR_ProtocolDll();
+
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("libevdev"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("libevdev"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("libevdev"); }
+
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/linux.png"); }
+};
diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp
new file mode 100644
index 00000000..bb54c354
--- /dev/null
+++ b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dialog.cpp
@@ -0,0 +1,26 @@
+#include "ftnoir_protocol_libevdev.h"
+#include "facetracknoir/global-settings.h"
+
+LibevdevControls::LibevdevControls() : QWidget()
+{
+ ui.setupUi( this );
+ connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+}
+
+void LibevdevControls::doOK() {
+ save();
+ this->close();
+}
+
+void LibevdevControls::doCancel() {
+ this->close();
+}
+
+void LibevdevControls::save() {
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new LibevdevControls;
+}
diff --git a/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dll.cpp b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dll.cpp
new file mode 100644
index 00000000..79a22d5e
--- /dev/null
+++ b/ftnoir_protocol_libevdev/ftnoir_protocol_libevdev_dll.cpp
@@ -0,0 +1,16 @@
+#include "ftnoir_protocol_libevdev.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+
+FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
+}
+
+FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
+{
+
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_libevdev/images/linux.png b/ftnoir_protocol_libevdev/images/linux.png
new file mode 100644
index 00000000..8836c0e2
--- /dev/null
+++ b/ftnoir_protocol_libevdev/images/linux.png
Binary files differ
diff --git a/ftnoir_tracker_sm/sm-tracker.qrc b/ftnoir_protocol_libevdev/libevdev-protocol.qrc
index d17d0899..70bb415f 100644
--- a/ftnoir_tracker_sm/sm-tracker.qrc
+++ b/ftnoir_protocol_libevdev/libevdev-protocol.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/">
- <file>images/sm.png</file>
+ <file>images/linux.png</file>
</qresource>
</RCC>
diff --git a/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui b/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui
index 8794e9cd..2705fff7 100644
--- a/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui
+++ b/ftnoir_protocol_mouse/ftnoir_mousecontrols.ui
@@ -2,20 +2,23 @@
<ui version="4.0">
<class>UICMOUSEControls</class>
<widget class="QWidget" name="UICMOUSEControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>250</width>
- <height>99</height>
+ <width>257</width>
+ <height>114</height>
</rect>
</property>
<property name="windowTitle">
- <string>MouseLook settings FaceTrackNoIR</string>
+ <string>Mouse protocol settings</string>
</property>
<property name="windowIcon">
- <iconset>
- <normaloff>:/images/Mouse.png</normaloff>:/images/Mouse.png</iconset>
+ <iconset resource="win32-mouse-protocol.qrc">
+ <normaloff>:/images/mouse.png</normaloff>:/images/mouse.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -190,7 +193,9 @@
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="win32-mouse-protocol.qrc"/>
+ </resources>
<connections/>
<slots>
<slot>startEngineClicked()</slot>
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp
index fc04c2f3..cc8aa11e 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp
@@ -1,107 +1,67 @@
-/********************************************************************************
-* 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-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/>. *
-* *
-* FTNoIR_Protocol_Mouse The Class, that communicates headpose-data by *
-* generating Mouse commands. *
-* Many games (like FPS's) support Mouse-look features, *
-* but no face-tracking. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
-*/
-#include "ftnoir_protocol_mouse.h"
-#include "facetracknoir/global-settings.h"
-
-/** constructor **/
-FTNoIR_Protocol::FTNoIR_Protocol()
-{
- loadSettings();
-}
-
-/** destructor **/
-FTNoIR_Protocol::~FTNoIR_Protocol()
-{
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Protocol::loadSettings() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "Mouse" );
- Mouse_X = (FTN_AngleName) (iniFile.value ( "Mouse_X", 0 ).toInt());
- Mouse_Y = (FTN_AngleName) (iniFile.value ( "Mouse_Y", 0 ).toInt());
- iniFile.endGroup ();
-}
-
-//
-// Update Headpose in Game.
-//
-void FTNoIR_Protocol::sendHeadposeToGame(double *headpose, double *rawheadpose ) {
- float fMouse_X = 0;
- float fMouse_Y = 0;
-
- 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);
- }
-}
-
-//
-// Returns 'true' if all seems OK.
-//
-bool FTNoIR_Protocol::checkServerInstallationOK()
-{
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocol - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocol@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Protocol;
-}
+/********************************************************************************
+* 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-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/>. *
+* *
+* FTNoIR_Protocol_Mouse The Class, that communicates headpose-data by *
+* generating Mouse commands. *
+* Many games (like FPS's) support Mouse-look features, *
+* but no face-tracking. *
+********************************************************************************/
+#include "ftnoir_protocol_mouse.h"
+#include "facetracknoir/global-settings.h"
+
+void FTNoIR_Protocol::sendHeadposeToGame(const double *headpose ) {
+ double fMouse_X = 0;
+ double fMouse_Y = 0;
+
+ 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);
+ }
+}
+
+void FTNoIR_Protocol::reload()
+{
+ s.b->reload();
+}
+
+bool FTNoIR_Protocol::checkServerInstallationOK()
+{
+ return true;
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h
index fd0058ea..01f283d3 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h
@@ -1,128 +1,109 @@
-/********************************************************************************
-* 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) 2010-2011 Wim Vriend (Developing) *
-* Ron Hendriks (Researching and Testing) *
-* *
-* http://facetracknoir.sourceforge.net/home/default.htm *
-* *
-* 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/>. *
-* *
-* FTNoIR_Protocol_Mouse The Class, that communicates headpose-data by *
-* generating Mouse commands. *
-* Many games (like FPS's) support Mouse-look features, *
-* but no face-tracking. *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_MOUSESERVER_H
-#define INCLUDED_MOUSESERVER_H
-
-#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
-#include "ui_ftnoir_mousecontrols.h"
-#include <QMessageBox>
-#include <QSettings>
-#include <QLibrary>
-#include <QProcess>
-#include <QDebug>
-#include <QFile>
-#include <windows.h>
-#include <winuser.h>
-#include "facetracknoir/global-settings.h"
-
-#define MOUSE_AXIS_MIN 0
-#define MOUSE_AXIS_MAX 65535
-
-enum FTN_AngleName {
- FTN_YAW = Yaw,
- FTN_PITCH = Pitch,
- FTN_ROLL = Roll,
- FTN_X = TX,
- FTN_Y = TY,
- FTN_Z = TZ
-};
-
-class FTNoIR_Protocol : public IProtocol
-{
-public:
- FTNoIR_Protocol();
- ~FTNoIR_Protocol();
- bool checkServerInstallationOK();
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
-
-private:
- HANDLE h;
- INPUT MouseStruct;
-
- FTN_AngleName Mouse_X; // Map one of the 6DOF's to this Mouse direction
- FTN_AngleName Mouse_Y;
- FTN_AngleName Mouse_Wheel;
- void loadSettings();
- QString getGameName() {
- return "Mouse tracker";
- }
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class MOUSEControls: public QWidget, public IProtocolDialog
-{
- Q_OBJECT
-public:
-
- explicit MOUSEControls();
- virtual ~MOUSEControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerProtocol(IProtocol *protocol) {
- theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
- }
- void unRegisterProtocol() {
- theProtocol = NULL; // Reset the pointer
- }
-
-private:
- Ui::UICMOUSEControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FTNoIR_Protocol *theProtocol;
-
-private slots:
- void doOK();
- void doCancel();
- void settingChanged( int setting ) { settingsDirty = true; }
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
-//*******************************************************************************************************
-class FTNoIR_ProtocolDll : public Metadata
-{
-public:
- FTNoIR_ProtocolDll();
- ~FTNoIR_ProtocolDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look"); }
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look"); }
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look protocol"); }
-
- void getIcon(QIcon *icon) { *icon = QIcon(":/images/mouse.png"); }
-};
-
-
-#endif//INCLUDED_MOUSESERVER_H
-//END
+/********************************************************************************
+* 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) 2010-2011 Wim Vriend (Developing) *
+* Ron Hendriks (Researching and Testing) *
+* *
+* http://facetracknoir.sourceforge.net/home/default.htm *
+* *
+* 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/>. *
+* *
+* FTNoIR_Protocol_Mouse The Class, that communicates headpose-data by *
+* generating Mouse commands. *
+* Many games (like FPS's) support Mouse-look features, *
+* but no face-tracking. *
+********************************************************************************/
+#pragma once
+#ifndef INCLUDED_MOUSESERVER_H
+#define INCLUDED_MOUSESERVER_H
+
+#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
+#include "ui_ftnoir_mousecontrols.h"
+#include <QMessageBox>
+#include <QSettings>
+#include <QLibrary>
+#include <QProcess>
+#include <QDebug>
+#include <QFile>
+#include <windows.h>
+#include <winuser.h>
+#include "facetracknoir/global-settings.h"
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> Mouse_X, Mouse_Y;
+ settings() :
+ b(bundle("mouse-proto")),
+ Mouse_X(b, "mouse-x", 0),
+ Mouse_Y(b, "mouse-y", 0)
+ {}
+};
+
+#define MOUSE_AXIS_MIN 0
+#define MOUSE_AXIS_MAX 65535
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ FTNoIR_Protocol() {}
+ bool checkServerInstallationOK();
+ void sendHeadposeToGame( const double *headpose);
+ QString getGameName() {
+ return "Mouse tracker";
+ }
+ void reload();
+private:
+ struct settings s;
+};
+
+// Widget that has controls for FTNoIR protocol client-settings.
+class MOUSEControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+ MOUSEControls();
+ void registerProtocol(IProtocol *protocol) {
+ _proto = (FTNoIR_Protocol *) protocol;
+ }
+ void unRegisterProtocol() {
+ _proto = NULL;
+ }
+private:
+ Ui::UICMOUSEControls ui;
+ settings s;
+ FTNoIR_Protocol* _proto;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+//*******************************************************************************************************
+// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
+//*******************************************************************************************************
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Mouse Look protocol"); }
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/mouse.png"); }
+};
+
+
+#endif//INCLUDED_MOUSESERVER_H
+//END
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp
index 2b737030..22b7024c 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp
@@ -1,189 +1,69 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_mouse.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-MOUSEControls::MOUSEControls() :
-QWidget()
-{
- ui.setupUi( this );
- ui.cbxSelectMouse_X->addItem("None");
- ui.cbxSelectMouse_X->addItem("X");
- ui.cbxSelectMouse_X->addItem("Y");
- ui.cbxSelectMouse_X->addItem("Z");
- ui.cbxSelectMouse_X->addItem("Yaw");
- ui.cbxSelectMouse_X->addItem("Pitch");
- ui.cbxSelectMouse_X->addItem("Roll");
-
- ui.cbxSelectMouse_Y->addItem("None");
- ui.cbxSelectMouse_Y->addItem("X");
- ui.cbxSelectMouse_Y->addItem("Y");
- ui.cbxSelectMouse_Y->addItem("Z");
- ui.cbxSelectMouse_Y->addItem("Yaw");
- ui.cbxSelectMouse_Y->addItem("Pitch");
- ui.cbxSelectMouse_Y->addItem("Roll");
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.cbxSelectMouse_X, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged( int )));
- connect(ui.cbxSelectMouse_Y, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged( int )));
- theProtocol = NULL;
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-MOUSEControls::~MOUSEControls() {
- qDebug() << "~MOUSEControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void MOUSEControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void MOUSEControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void MOUSEControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void MOUSEControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void MOUSEControls::loadSettings() {
- qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Mouse" );
- ui.cbxSelectMouse_X->setCurrentIndex(iniFile.value ( "Mouse_X", 0 ).toInt() );
- ui.cbxSelectMouse_Y->setCurrentIndex(iniFile.value ( "Mouse_Y", 0 ).toInt() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void MOUSEControls::save() {
- qDebug() << "save() says: started";
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "Mouse" );
- iniFile.setValue ( "Mouse_X", ui.cbxSelectMouse_X->currentIndex() );
- iniFile.setValue ( "Mouse_Y", ui.cbxSelectMouse_Y->currentIndex() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
-{
- return new MOUSEControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_mouse.h"
+#include "facetracknoir/global-settings.h"
+
+MOUSEControls::MOUSEControls() : _proto(nullptr)
+{
+ ui.setupUi( this );
+ ui.cbxSelectMouse_X->addItem("None");
+ ui.cbxSelectMouse_X->addItem("X");
+ ui.cbxSelectMouse_X->addItem("Y");
+ ui.cbxSelectMouse_X->addItem("Z");
+ ui.cbxSelectMouse_X->addItem("Yaw");
+ ui.cbxSelectMouse_X->addItem("Pitch");
+ ui.cbxSelectMouse_X->addItem("Roll");
+
+ ui.cbxSelectMouse_Y->addItem("None");
+ ui.cbxSelectMouse_Y->addItem("X");
+ ui.cbxSelectMouse_Y->addItem("Y");
+ ui.cbxSelectMouse_Y->addItem("Z");
+ ui.cbxSelectMouse_Y->addItem("Yaw");
+ ui.cbxSelectMouse_Y->addItem("Pitch");
+ ui.cbxSelectMouse_Y->addItem("Roll");
+
+ connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+
+ tie_setting(s.Mouse_X, ui.cbxSelectMouse_X);
+ tie_setting(s.Mouse_Y, ui.cbxSelectMouse_Y);
+}
+
+void MOUSEControls::doOK() {
+ s.b->save();
+ if (_proto)
+ _proto->reload();
+ this->close();
+}
+
+void MOUSEControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new MOUSEControls;
+}
diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp
index 219f62af..54f6b307 100644
--- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp
+++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp
@@ -1,57 +1,31 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_mouse.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
-}
-
-FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_ProtocolDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_mouse.h"
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_sc/ftnoir-protocol-sc.rc b/ftnoir_protocol_sc/ftnoir-protocol-sc.rc
index 3b43715e..80b6c12c 100644
--- a/ftnoir_protocol_sc/ftnoir-protocol-sc.rc
+++ b/ftnoir_protocol_sc/ftnoir-protocol-sc.rc
@@ -1,2 +1,4 @@
#include <winuser.h>
-142 RT_MANIFEST scserver.manifest \ No newline at end of file
+142 RT_MANIFEST scserver.manifest
+143 RT_MANIFEST scserver-sp2.manifest
+144 RT_MANIFEST scserver-acceleration.manifest \ No newline at end of file
diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp
index 3069a3bf..2714e980 100644
--- a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp
+++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp
@@ -1,362 +1,252 @@
-/********************************************************************************
-* 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-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/>. *
-* *
-* FTNoIR_Protocol: the Class, that communicates headpose-data *
-* to games, using the SimConnect.dll. *
-* SimConnect.dll is a so called 'side-by-side' assembly, so it *
-* must be treated as such... *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
-*/
-#include "ftnoir_protocol_sc.h"
-#include "facetracknoir/global-settings.h"
-
-importSimConnect_CameraSetRelative6DOF FTNoIR_Protocol::simconnect_set6DOF;
-HANDLE FTNoIR_Protocol::hSimConnect = 0; // Handle to SimConnect
-
-float FTNoIR_Protocol::virtSCPosX = 0.0f; // Headpose
-float FTNoIR_Protocol::virtSCPosY = 0.0f;
-float FTNoIR_Protocol::virtSCPosZ = 0.0f;
-
-float FTNoIR_Protocol::virtSCRotX = 0.0f;
-float FTNoIR_Protocol::virtSCRotY = 0.0f;
-float FTNoIR_Protocol::virtSCRotZ = 0.0f;
-
-float FTNoIR_Protocol::prevSCPosX = 0.0f; // previous Headpose
-float FTNoIR_Protocol::prevSCPosY = 0.0f;
-float FTNoIR_Protocol::prevSCPosZ = 0.0f;
-
-float FTNoIR_Protocol::prevSCRotX = 0.0f;
-float FTNoIR_Protocol::prevSCRotY = 0.0f;
-float FTNoIR_Protocol::prevSCRotZ = 0.0f;
-
-static QLibrary SCClientLib;
-
-/** constructor **/
-FTNoIR_Protocol::FTNoIR_Protocol()
-{
- ProgramName = "Microsoft FSX";
- blnSimConnectActive = false;
- hSimConnect = 0;
-}
-
-/** destructor **/
-FTNoIR_Protocol::~FTNoIR_Protocol()
-{
- qDebug() << "~FTNoIR_Protocol says: inside" << FTNoIR_Protocol::hSimConnect;
-
- if (hSimConnect != 0) {
- qDebug() << "~FTNoIR_Protocol says: before simconnect_close";
- if (SUCCEEDED( simconnect_close( FTNoIR_Protocol::hSimConnect ) ) ) {
- qDebug() << "~FTNoIR_Protocol says: close SUCCEEDED";
- }
- }
-// SCClientLib.unload(); Generates crash when tracker is ended...
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Protocol::loadSettings() {
-// None yet...
-}
-
-//
-// Update Headpose in Game.
-//
-void FTNoIR_Protocol::sendHeadposeToGame( double *headpose, double *rawheadpose ) {
-PDWORD_PTR MsgResult = 0;
-
-
- virtSCRotX = -headpose[Pitch]; // degrees
- virtSCRotY = -headpose[Yaw];
- virtSCRotZ = headpose[Roll];
-
- virtSCPosX = headpose[TX]/100.f; // cm to meters
- virtSCPosY = headpose[TY]/100.f;
- virtSCPosZ = -headpose[TZ]/100.f;
-
- //
- // It's only useful to send data, if the connection was made.
- //
- if (!blnSimConnectActive) {
- if (SUCCEEDED(simconnect_open(&hSimConnect, "FaceTrackNoIR", NULL, 0, 0, 0))) {
- qDebug() << "FTNoIR_Protocol::sendHeadposeToGame() says: SimConnect active!";
-
- //set up the events we want to listen for
- HRESULT hr;
-
- simconnect_subscribetosystemevent(hSimConnect, EVENT_PING, "Frame");
-
- hr = simconnect_mapclienteventtosimevent(hSimConnect, EVENT_INIT, "");
- hr = simconnect_addclienteventtonotificationgroup(hSimConnect, GROUP0, EVENT_INIT, false);
- hr = simconnect_setnotificationgrouppriority(hSimConnect, GROUP0, SIMCONNECT_GROUP_PRIORITY_HIGHEST);
- ////hr = SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT0, "VK_COMMA", EVENT_INIT);
- ////hr = SimConnect_SetInputGroupState(hSimConnect, INPUT0, SIMCONNECT_STATE_ON);
-
- blnSimConnectActive = true;
- }
- }
- else {
- //
- // Write the 6DOF-data to FSX
-// //
-// // Only do this when the data has changed. This way, the HAT-switch can be used when tracking is OFF.
-// //
-// if ((prevPosX != virtPosX) || (prevPosY != virtPosY) || (prevPosZ != virtPosZ) ||
-// (prevRotX != virtRotX) || (prevRotY != virtRotY) || (prevRotZ != virtRotZ)) {
-//// if (S_OK == simconnect_set6DOF(hSimConnect, virtPosX, virtPosY, virtPosZ, virtRotX, virtRotZ, virtRotY)) {
-//// qDebug() << "FTNoIR_Protocol::run() says: SimConnect data written!";
-//// }
-// }
-//
-// prevPosX = virtPosX;
-// prevPosY = virtPosY;
-// prevPosZ = virtPosZ;
-// prevRotX = virtRotX;
-// prevRotY = virtRotY;
-// prevRotZ = virtRotZ;
-
- if (SUCCEEDED(simconnect_calldispatch(hSimConnect, processNextSimconnectEvent, NULL))) {
- qDebug() << "FTNoIR_Protocol::sendHeadposeToGame() says: Dispatching";
- }
- else {
- qDebug() << "FTNoIR_Protocol::sendHeadposeToGame() says: Error Dispatching!";
- }
- }
-}
-
-class ActivationContext {
-public:
- ActivationContext(const int resid) {
- hactctx = INVALID_HANDLE_VALUE;
- actctx_cookie = NULL;
- ACTCTXA actx = {0};
- actx.cbSize = sizeof(ACTCTXA);
- actx.lpResourceName = MAKEINTRESOURCEA(resid);
- actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
- QString path = QCoreApplication::applicationDirPath() + "/opentrack-proto-simconnect.dll";
- QByteArray name = QFile::encodeName(path);
- actx.lpSource = name.constData();
- hactctx = CreateActCtxA(&actx);
- actctx_cookie = 0;
- if (hactctx != INVALID_HANDLE_VALUE) {
- if (!ActivateActCtx(hactctx, &actctx_cookie)) {
- qDebug() << "SC: can't set win32 activation context" << GetLastError();
- ReleaseActCtx(hactctx);
- hactctx = INVALID_HANDLE_VALUE;
- }
- } else {
- qDebug() << "SC: can't create win32 activation context";
- }
- }
- ~ActivationContext() {
- if (hactctx != INVALID_HANDLE_VALUE)
- {
- DeactivateActCtx(0, actctx_cookie);
- ReleaseActCtx(hactctx);
- }
- }
-private:
- ULONG_PTR actctx_cookie;
- HANDLE hactctx;
-};
-
-//
-// Returns 'true' if all seems OK.
-//
-bool FTNoIR_Protocol::checkServerInstallationOK()
-{
- if (!SCClientLib.isLoaded())
- {
- qDebug() << "SCCheckClientDLL says: Starting Function";
-
- SCClientLib.setFileName("SimConnect.DLL");
-
- ActivationContext ctx(142);
-
- if (!SCClientLib.load()) {
- qDebug() << "SC load" << SCClientLib.errorString();
- return false;
- }
- } else {
- qDebug() << "SimConnect already loaded";
- }
-
- //
- // Get the functions from the DLL.
- //
- simconnect_open = (importSimConnect_Open) SCClientLib.resolve("SimConnect_Open");
- if (simconnect_open == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_Open function not found in DLL!";
- return false;
- }
- simconnect_set6DOF = (importSimConnect_CameraSetRelative6DOF) SCClientLib.resolve("SimConnect_CameraSetRelative6DOF");
- if (simconnect_set6DOF == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_CameraSetRelative6DOF function not found in DLL!";
- return false;
- }
- simconnect_close = (importSimConnect_Close) SCClientLib.resolve("SimConnect_Close");
- if (simconnect_close == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_Close function not found in DLL!";
- return false;
- }
-
- //return true;
-
- simconnect_calldispatch = (importSimConnect_CallDispatch) SCClientLib.resolve("SimConnect_CallDispatch");
- if (simconnect_calldispatch == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_CallDispatch function not found in DLL!";
- return false;
- }
-
- simconnect_subscribetosystemevent = (importSimConnect_SubscribeToSystemEvent) SCClientLib.resolve("SimConnect_SubscribeToSystemEvent");
- if (simconnect_subscribetosystemevent == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_SubscribeToSystemEvent function not found in DLL!";
- return false;
- }
-
- simconnect_mapclienteventtosimevent = (importSimConnect_MapClientEventToSimEvent) SCClientLib.resolve("SimConnect_MapClientEventToSimEvent");
- if (simconnect_subscribetosystemevent == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_MapClientEventToSimEvent function not found in DLL!";
- return false;
- }
-
- simconnect_addclienteventtonotificationgroup = (importSimConnect_AddClientEventToNotificationGroup) SCClientLib.resolve("SimConnect_AddClientEventToNotificationGroup");
- if (simconnect_subscribetosystemevent == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_AddClientEventToNotificationGroup function not found in DLL!";
- return false;
- }
-
- simconnect_setnotificationgrouppriority = (importSimConnect_SetNotificationGroupPriority) SCClientLib.resolve("SimConnect_SetNotificationGroupPriority");
- if (simconnect_subscribetosystemevent == NULL) {
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_SetNotificationGroupPriority function not found in DLL!";
- return false;
- }
-
- qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect functions resolved in DLL!";
-
- return true;
-}
-
-void CALLBACK FTNoIR_Protocol::processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
-{
-// HRESULT hr;
-
- switch(pData->dwID)
- {
- case SIMCONNECT_RECV_ID_EVENT:
- {
- SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;
-
- qDebug() << "FTNoIR_Protocol::processNextSimconnectEvent() says: SimConnect active!";
- //switch(evt->uEventID)
- //{
- // //case EVENT_CAMERA_RIGHT:
-
- // // cameraBank = normalize180( cameraBank + 5.0f);
-
- // // hr = SimConnect_CameraSetRelative6DOF(hSimConnect, 0.0f, 0.0f, 0.0f,
- // // SIMCONNECT_CAMERA_IGNORE_FIELD,SIMCONNECT_CAMERA_IGNORE_FIELD, cameraBank);
-
- // // printf("\nCamera Bank = %f", cameraBank);
- // // break;
-
- // //case EVENT_CAMERA_LEFT:
- // //
- // // cameraBank = normalize180( cameraBank - 5.0f);
-
- // // hr = SimConnect_CameraSetRelative6DOF(hSimConnect, 0.0f, 0.0f, 0.0f,
- // // SIMCONNECT_CAMERA_IGNORE_FIELD,SIMCONNECT_CAMERA_IGNORE_FIELD, cameraBank);
- // //
- // // printf("\nCamera Bank = %f", cameraBank);
- // // break;
-
- // //default:
- // // break;
- //}
- //break;
- }
- case SIMCONNECT_RECV_ID_EVENT_FRAME:
- {
-// qDebug() << "FTNoIR_Protocol::processNextSimconnectEvent() says: Frame event!";
- if ((prevSCPosX != virtSCPosX) || (prevSCPosY != virtSCPosY) || (prevSCPosZ != virtSCPosZ) ||
- (prevSCRotX != virtSCRotX) || (prevSCRotY != virtSCRotY) || (prevSCRotZ != virtSCRotZ)) {
- if (S_OK == simconnect_set6DOF(hSimConnect, virtSCPosX, virtSCPosY, virtSCPosZ, virtSCRotX, virtSCRotZ, virtSCRotY)) {
- // qDebug() << "FTNoIR_Protocol::run() says: SimConnect data written!";
- }
- }
- prevSCPosX = virtSCPosX;
- prevSCPosY = virtSCPosY;
- prevSCPosZ = virtSCPosZ;
- prevSCRotX = virtSCRotX;
- prevSCRotY = virtSCRotY;
- prevSCRotZ = virtSCRotZ;
- }
-
- case SIMCONNECT_RECV_ID_EXCEPTION:
- {
- SIMCONNECT_RECV_EXCEPTION *except = (SIMCONNECT_RECV_EXCEPTION*)pData;
-
- switch (except->dwException)
- {
- case SIMCONNECT_EXCEPTION_ERROR:
- printf("\nCamera error");
- break;
-
- default:
- printf("\nException");
- break;
- }
- break;
- }
-
- case SIMCONNECT_RECV_ID_QUIT:
- {
- qDebug() << "FTNoIR_Protocol::processNextSimconnectEvent() says: Quit event!";
-// quit = 1;
- break;
- }
-
- default:
- break;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocol - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocol@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocol=_GetProtocol@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Protocol;
-}
+/********************************************************************************
+* 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-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/>. *
+* *
+* FTNoIR_Protocol: the Class, that communicates headpose-data *
+* to games, using the SimConnect.dll. *
+* SimConnect.dll is a so called 'side-by-side' assembly, so it *
+* must be treated as such... *
+********************************************************************************/
+#include "ftnoir_protocol_sc.h"
+#include "facetracknoir/global-settings.h"
+
+importSimConnect_CameraSetRelative6DOF FTNoIR_Protocol::simconnect_set6DOF;
+HANDLE FTNoIR_Protocol::hSimConnect = 0; // Handle to SimConnect
+
+float FTNoIR_Protocol::virtSCPosX = 0.0f; // Headpose
+float FTNoIR_Protocol::virtSCPosY = 0.0f;
+float FTNoIR_Protocol::virtSCPosZ = 0.0f;
+
+float FTNoIR_Protocol::virtSCRotX = 0.0f;
+float FTNoIR_Protocol::virtSCRotY = 0.0f;
+float FTNoIR_Protocol::virtSCRotZ = 0.0f;
+
+float FTNoIR_Protocol::prevSCPosX = 0.0f; // previous Headpose
+float FTNoIR_Protocol::prevSCPosY = 0.0f;
+float FTNoIR_Protocol::prevSCPosZ = 0.0f;
+
+float FTNoIR_Protocol::prevSCRotX = 0.0f;
+float FTNoIR_Protocol::prevSCRotY = 0.0f;
+float FTNoIR_Protocol::prevSCRotZ = 0.0f;
+
+static QLibrary SCClientLib;
+
+FTNoIR_Protocol::FTNoIR_Protocol()
+{
+ blnSimConnectActive = false;
+ hSimConnect = 0;
+}
+
+FTNoIR_Protocol::~FTNoIR_Protocol()
+{
+ qDebug() << "~FTNoIR_Protocol says: inside" << FTNoIR_Protocol::hSimConnect;
+
+ if (hSimConnect != 0) {
+ qDebug() << "~FTNoIR_Protocol says: before simconnect_close";
+ if (SUCCEEDED( simconnect_close( FTNoIR_Protocol::hSimConnect ) ) ) {
+ qDebug() << "~FTNoIR_Protocol says: close SUCCEEDED";
+ }
+ }
+}
+
+void FTNoIR_Protocol::sendHeadposeToGame( const double *headpose ) {
+ virtSCRotX = -headpose[Pitch]; // degrees
+ virtSCRotY = -headpose[Yaw];
+ virtSCRotZ = headpose[Roll];
+
+ virtSCPosX = headpose[TX]/100.f; // cm to meters
+ virtSCPosY = headpose[TY]/100.f;
+ virtSCPosZ = -headpose[TZ]/100.f;
+
+ if (!blnSimConnectActive) {
+ if (SUCCEEDED(simconnect_open(&hSimConnect, "FaceTrackNoIR", NULL, 0, 0, 0))) {
+ HRESULT hr;
+
+ simconnect_subscribetosystemevent(hSimConnect, EVENT_PING, "Frame");
+
+ hr = simconnect_mapclienteventtosimevent(hSimConnect, EVENT_INIT, "");
+ hr = simconnect_addclienteventtonotificationgroup(hSimConnect, GROUP0, EVENT_INIT, false);
+ hr = simconnect_setnotificationgrouppriority(hSimConnect, GROUP0, SIMCONNECT_GROUP_PRIORITY_HIGHEST);
+ blnSimConnectActive = true;
+ }
+ }
+ else
+ (void) (simconnect_calldispatch(hSimConnect, processNextSimconnectEvent, NULL));
+}
+
+class ActivationContext {
+public:
+ ActivationContext(const int resid) {
+ hactctx = INVALID_HANDLE_VALUE;
+ actctx_cookie = 0;
+ ACTCTXA actx = {0};
+ actx.cbSize = sizeof(ACTCTXA);
+ actx.lpResourceName = MAKEINTRESOURCEA(resid);
+ actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
+#ifdef _MSC_VER
+# define PREFIX ""
+#else
+# define PREFIX "lib"
+#endif
+ QString path = QCoreApplication::applicationDirPath() + "/" PREFIX "opentrack-proto-simconnect.dll";
+ QByteArray name = QFile::encodeName(path);
+ actx.lpSource = name.constData();
+ hactctx = CreateActCtxA(&actx);
+ actctx_cookie = 0;
+ if (hactctx != INVALID_HANDLE_VALUE) {
+ if (!ActivateActCtx(hactctx, &actctx_cookie)) {
+ qDebug() << "SC: can't set win32 activation context" << GetLastError();
+ ReleaseActCtx(hactctx);
+ hactctx = INVALID_HANDLE_VALUE;
+ }
+ } else {
+ qDebug() << "SC: can't create win32 activation context";
+ }
+ }
+ ~ActivationContext() {
+ if (hactctx != INVALID_HANDLE_VALUE)
+ {
+ DeactivateActCtx(0, actctx_cookie);
+ ReleaseActCtx(hactctx);
+ }
+ }
+private:
+ ULONG_PTR actctx_cookie;
+ HANDLE hactctx;
+};
+
+bool FTNoIR_Protocol::checkServerInstallationOK()
+{
+ if (!SCClientLib.isLoaded())
+ {
+ ActivationContext ctx(142 + static_cast<int>(s.sxs_manifest));
+
+ SCClientLib.setFileName("SimConnect.dll");
+ if (!SCClientLib.load()) {
+ qDebug() << "SC load" << SCClientLib.errorString();
+ return false;
+ }
+ }
+
+ //
+ // Get the functions from the DLL.
+ //
+ simconnect_open = (importSimConnect_Open) SCClientLib.resolve("SimConnect_Open");
+ if (simconnect_open == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_Open function not found in DLL!";
+ return false;
+ }
+ simconnect_set6DOF = (importSimConnect_CameraSetRelative6DOF) SCClientLib.resolve("SimConnect_CameraSetRelative6DOF");
+ if (simconnect_set6DOF == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_CameraSetRelative6DOF function not found in DLL!";
+ return false;
+ }
+ simconnect_close = (importSimConnect_Close) SCClientLib.resolve("SimConnect_Close");
+ if (simconnect_close == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_Close function not found in DLL!";
+ return false;
+ }
+
+ //return true;
+
+ simconnect_calldispatch = (importSimConnect_CallDispatch) SCClientLib.resolve("SimConnect_CallDispatch");
+ if (simconnect_calldispatch == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_CallDispatch function not found in DLL!";
+ return false;
+ }
+
+ simconnect_subscribetosystemevent = (importSimConnect_SubscribeToSystemEvent) SCClientLib.resolve("SimConnect_SubscribeToSystemEvent");
+ if (simconnect_subscribetosystemevent == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_SubscribeToSystemEvent function not found in DLL!";
+ return false;
+ }
+
+ simconnect_mapclienteventtosimevent = (importSimConnect_MapClientEventToSimEvent) SCClientLib.resolve("SimConnect_MapClientEventToSimEvent");
+ if (simconnect_subscribetosystemevent == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_MapClientEventToSimEvent function not found in DLL!";
+ return false;
+ }
+
+ simconnect_addclienteventtonotificationgroup = (importSimConnect_AddClientEventToNotificationGroup) SCClientLib.resolve("SimConnect_AddClientEventToNotificationGroup");
+ if (simconnect_subscribetosystemevent == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_AddClientEventToNotificationGroup function not found in DLL!";
+ return false;
+ }
+
+ simconnect_setnotificationgrouppriority = (importSimConnect_SetNotificationGroupPriority) SCClientLib.resolve("SimConnect_SetNotificationGroupPriority");
+ if (simconnect_subscribetosystemevent == NULL) {
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect_SetNotificationGroupPriority function not found in DLL!";
+ return false;
+ }
+
+ qDebug() << "FTNoIR_Protocol::checkServerInstallationOK() says: SimConnect functions resolved in DLL!";
+
+ return true;
+}
+
+void CALLBACK FTNoIR_Protocol::processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
+{
+ switch(pData->dwID)
+ {
+ default:
+ break;
+ case SIMCONNECT_RECV_ID_EVENT_FRAME:
+ {
+ if ((prevSCPosX != virtSCPosX) || (prevSCPosY != virtSCPosY) || (prevSCPosZ != virtSCPosZ) ||
+ (prevSCRotX != virtSCRotX) || (prevSCRotY != virtSCRotY) || (prevSCRotZ != virtSCRotZ)) {
+ (void) simconnect_set6DOF(hSimConnect, virtSCPosX, virtSCPosY, virtSCPosZ, virtSCRotX, virtSCRotZ, virtSCRotY);
+ }
+ prevSCPosX = virtSCPosX;
+ prevSCPosY = virtSCPosY;
+ prevSCPosZ = virtSCPosZ;
+ prevSCRotX = virtSCRotX;
+ prevSCRotY = virtSCRotY;
+ prevSCRotZ = virtSCRotZ;
+ }
+ case SIMCONNECT_RECV_ID_EXCEPTION:
+ {
+ SIMCONNECT_RECV_EXCEPTION *except = (SIMCONNECT_RECV_EXCEPTION*)pData;
+
+ switch (except->dwException)
+ {
+ case SIMCONNECT_EXCEPTION_ERROR:
+ qDebug() << "Camera error";
+ break;
+
+ default:
+ qDebug() << "Exception";
+ break;
+ }
+ break;
+ }
+
+ case SIMCONNECT_RECV_ID_QUIT:
+ {
+ break;
+ }
+ }
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocol* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Protocol;
+}
diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.h b/ftnoir_protocol_sc/ftnoir_protocol_sc.h
index c22c36c7..a13c0097 100644
--- a/ftnoir_protocol_sc/ftnoir_protocol_sc.h
+++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.h
@@ -1,176 +1,157 @@
-/********************************************************************************
-* 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) 2010-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/>. *
-* *
-* SCServer SCServer is the Class, that communicates headpose-data *
-* to games, using the SimConnect.dll. *
-* SimConnect.dll is a so called 'side-by-side' assembly, so it *
-* must be treated as such... *
-********************************************************************************/
-#pragma once
-#ifndef INCLUDED_SCSERVER_H
-#define INCLUDED_SCSERVER_H
-#include "facetracknoir/global-settings.h"
-//
-// Prevent the SimConnect manifest from being merged in the application-manifest
-// This is necessary to run FaceTrackNoIR on a PC without FSX
-//
-#define SIMCONNECT_H_NOMANIFEST
-#define _WIN32_WINNT 0x0502
-
-#include <Windows.h>
-#include <SimConnect.h>
-
-#include <..\ftnoir_protocol_base\ftnoir_protocol_base.h>
-#include <ui_FTNoIR_SCcontrols.h>
-#include <QMessageBox>
-#include <QSettings>
-#include <QLibrary>
-#include <QProcess>
-#include <QDebug>
-#include <QFile>
-//#include "math.h"
-
-typedef HRESULT (WINAPI *importSimConnect_Open)(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex);
-typedef HRESULT (WINAPI *importSimConnect_Close)(HANDLE hSimConnect);
-typedef HRESULT (WINAPI *importSimConnect_CameraSetRelative6DOF)(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg);
-typedef HRESULT (WINAPI *importSimConnect_CallDispatch)(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext);
-typedef HRESULT (WINAPI *importSimConnect_SubscribeToSystemEvent)(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName);
-typedef HRESULT (WINAPI *importSimConnect_MapClientEventToSimEvent)(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName);
-typedef HRESULT (WINAPI *importSimConnect_AddClientEventToNotificationGroup)(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable);
-typedef HRESULT (WINAPI *importSimConnect_SetNotificationGroupPriority)(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority);
-
-#define SC_CLIENT_FILENAME "SimConnect.dll"
-
-enum GROUP_ID
-{
- GROUP0=0,
-};
-
-enum EVENT_ID
-{
- EVENT_PING=0,
- EVENT_INIT,
-};
-
-enum INPUT_ID
-{
- INPUT0=0,
-};
-
-class FTNoIR_Protocol : public IProtocol
-{
-public:
- FTNoIR_Protocol();
- ~FTNoIR_Protocol();
- bool checkServerInstallationOK();
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
- QString getGameName() {
- return "FS2004/FSX";
- }
-
-private:
- // Private properties
- QString ProgramName;
-
- static float virtSCPosX;
- static float virtSCPosY;
- static float virtSCPosZ;
-
- static float virtSCRotX;
- static float virtSCRotY;
- static float virtSCRotZ;
-
- static float prevSCPosX;
- static float prevSCPosY;
- static float prevSCPosZ;
-
- static float prevSCRotX;
- static float prevSCRotY;
- static float prevSCRotZ;
-
- bool blnSimConnectActive;
-
- importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL
- importSimConnect_Close simconnect_close;
- static importSimConnect_CameraSetRelative6DOF simconnect_set6DOF;
- importSimConnect_CallDispatch simconnect_calldispatch;
- importSimConnect_SubscribeToSystemEvent simconnect_subscribetosystemevent;
- importSimConnect_MapClientEventToSimEvent simconnect_mapclienteventtosimevent;
- importSimConnect_AddClientEventToNotificationGroup simconnect_addclienteventtonotificationgroup;
- importSimConnect_SetNotificationGroupPriority simconnect_setnotificationgrouppriority;
-
- static HANDLE hSimConnect; // Handle to SimConnect
- static void CALLBACK processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext);
- void loadSettings();
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class SCControls: public QWidget, public IProtocolDialog
-{
- Q_OBJECT
-public:
-
- explicit SCControls();
- virtual ~SCControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerProtocol(IProtocol *protocol) {
- theProtocol = (FTNoIR_Protocol *) protocol; // Accept the pointer to the Protocol
- }
- void unRegisterProtocol() {
- theProtocol = NULL; // Reset the pointer
- }
-
-private:
- Ui::UICSCControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
- FTNoIR_Protocol *theProtocol;
-
-private slots:
- void doOK();
- void doCancel();
- void settingChanged() { settingsDirty = true; };
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
-//*******************************************************************************************************
-class FTNoIR_ProtocolDll : public Metadata
-{
-public:
- FTNoIR_ProtocolDll();
- ~FTNoIR_ProtocolDll();
-
- void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FSX SimConnect"); };
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("SimConnect"); };
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Microsoft SimConnect protocol"); };
-
- void getIcon(QIcon *icon) { *icon = QIcon(":/images/fsx.png"); };
-};
-
-#endif//INCLUDED_SCSERVER_H
-//END
+/********************************************************************************
+* 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) 2010-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/>. *
+* *
+* SCServer SCServer is the Class, that communicates headpose-data *
+* to games, using the SimConnect.dll. *
+* SimConnect.dll is a so called 'side-by-side' assembly, so it *
+* must be treated as such... *
+********************************************************************************/
+#pragma once
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0502
+#include "facetracknoir/global-settings.h"
+//
+// Prevent the SimConnect manifest from being merged in the application-manifest
+// This is necessary to run FaceTrackNoIR on a PC without FSX
+//
+#define SIMCONNECT_H_NOMANIFEST
+#include <windows.h>
+#include <SimConnect.h>
+
+#include <ftnoir_protocol_base/ftnoir_protocol_base.h>
+#include <ui_ftnoir_sccontrols.h>
+#include <QMessageBox>
+#include <QSettings>
+#include <QLibrary>
+#include <QProcess>
+#include <QDebug>
+#include <QFile>
+#include "facetracknoir/options.h"
+using namespace options;
+
+typedef HRESULT (WINAPI *importSimConnect_Open)(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex);
+typedef HRESULT (WINAPI *importSimConnect_Close)(HANDLE hSimConnect);
+typedef HRESULT (WINAPI *importSimConnect_CameraSetRelative6DOF)(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg);
+typedef HRESULT (WINAPI *importSimConnect_CallDispatch)(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext);
+typedef HRESULT (WINAPI *importSimConnect_SubscribeToSystemEvent)(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName);
+typedef HRESULT (WINAPI *importSimConnect_MapClientEventToSimEvent)(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName);
+typedef HRESULT (WINAPI *importSimConnect_AddClientEventToNotificationGroup)(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable);
+typedef HRESULT (WINAPI *importSimConnect_SetNotificationGroupPriority)(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority);
+
+#define SC_CLIENT_FILENAME "SimConnect.dll"
+
+enum GROUP_ID
+{
+ GROUP0=0,
+};
+
+enum EVENT_ID
+{
+ EVENT_PING=0,
+ EVENT_INIT,
+};
+
+enum INPUT_ID
+{
+ INPUT0=0,
+};
+
+struct settings {
+ pbundle b;
+ value<int> sxs_manifest;
+ settings() :
+ b(bundle("proto-simconnect")),
+ sxs_manifest(b, "sxs-manifest-version", 0)
+ {}
+};
+
+class FTNoIR_Protocol : public IProtocol
+{
+public:
+ FTNoIR_Protocol();
+ virtual ~FTNoIR_Protocol();
+ bool checkServerInstallationOK();
+ void sendHeadposeToGame(const double* headpose);
+ QString getGameName() {
+ return "FS2004/FSX";
+ }
+private:
+ static float virtSCPosX;
+ static float virtSCPosY;
+ static float virtSCPosZ;
+
+ static float virtSCRotX;
+ static float virtSCRotY;
+ static float virtSCRotZ;
+
+ static float prevSCPosX;
+ static float prevSCPosY;
+ static float prevSCPosZ;
+
+ static float prevSCRotX;
+ static float prevSCRotY;
+ static float prevSCRotZ;
+
+ bool blnSimConnectActive;
+
+ importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL
+ importSimConnect_Close simconnect_close;
+ static importSimConnect_CameraSetRelative6DOF simconnect_set6DOF;
+ importSimConnect_CallDispatch simconnect_calldispatch;
+ importSimConnect_SubscribeToSystemEvent simconnect_subscribetosystemevent;
+ importSimConnect_MapClientEventToSimEvent simconnect_mapclienteventtosimevent;
+ importSimConnect_AddClientEventToNotificationGroup simconnect_addclienteventtonotificationgroup;
+ importSimConnect_SetNotificationGroupPriority simconnect_setnotificationgrouppriority;
+
+ static HANDLE hSimConnect; // Handle to SimConnect
+ static void CALLBACK processNextSimconnectEvent(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext);
+ settings s;
+};
+
+// Widget that has controls for FTNoIR protocol client-settings.
+class SCControls: public QWidget, public IProtocolDialog
+{
+ Q_OBJECT
+public:
+ SCControls();
+ void registerProtocol(IProtocol *protocol) {}
+ void unRegisterProtocol() {}
+private:
+ Ui::UICSCControls ui;
+ settings s;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+//*******************************************************************************************************
+// FaceTrackNoIR Protocol DLL. Functions used to get general info on the Protocol
+//*******************************************************************************************************
+class FTNoIR_ProtocolDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled) { *strToBeFilled = QString("FSX SimConnect"); }
+ void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("SimConnect"); }
+ void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Microsoft SimConnect protocol"); }
+ void getIcon(QIcon *icon) { *icon = QIcon(":/images/fsx.png"); }
+};
diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp
index bbc56e54..c7428d77 100644
--- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp
+++ b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp
@@ -1,153 +1,54 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_sc.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-SCControls::SCControls() :
-QWidget()
-{
- ui.setupUi( this );
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- //connect(ui.cbxSelectPPJoyNumber, SIGNAL(currentIndexChanged(int)), this, SLOT(virtualJoystickSelected( int )));
-
- theProtocol = NULL;
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-SCControls::~SCControls() {
- qDebug() << "~SCControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void SCControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void SCControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void SCControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// Cancel clicked on server-dialog
-//
-void SCControls::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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void SCControls::loadSettings() {
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void SCControls::save() {
-
- settingsDirty = false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol-settings dialog object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDialog - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDialog@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDialog=_GetProtocolDialog@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
-{
- return new SCControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_sc.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+
+SCControls::SCControls() :
+QWidget()
+{
+ ui.setupUi( this );
+
+ // Connect Qt signals to member-functions
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ tie_setting(s.sxs_manifest, ui.comboBox);
+}
+
+void SCControls::doOK() {
+ s.b->save();
+ this->close();
+}
+
+void SCControls::doCancel() {
+ s.b->revert();
+ close();
+}
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT IProtocolDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new SCControls;
+}
diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp
index 72d63c5e..0a52fa96 100644
--- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp
+++ b/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp
@@ -1,57 +1,32 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_protocol_SC.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_ProtocolDll::FTNoIR_ProtocolDll() {
-}
-
-FTNoIR_ProtocolDll::~FTNoIR_ProtocolDll()
-{
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Factory function that creates instances if the Protocol object.
-
-// Export both decorated and undecorated names.
-// GetProtocolDll - Undecorated name, which can be easily used with GetProcAddress
-// Win32 API function.
-// _GetProtocolDll@0 - Common name decoration for __stdcall functions in C language.
-//#pragma comment(linker, "/export:GetProtocolDll=_GetProtocolDll@0")
-
-extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_ProtocolDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_protocol_sc.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+
+extern "C" FTNOIR_PROTOCOL_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_ProtocolDll;
+}
diff --git a/ftnoir_protocol_sc/ftnoir_sccontrols.ui b/ftnoir_protocol_sc/ftnoir_sccontrols.ui
index a0cbf393..87dc8d86 100644
--- a/ftnoir_protocol_sc/ftnoir_sccontrols.ui
+++ b/ftnoir_protocol_sc/ftnoir_sccontrols.ui
@@ -2,12 +2,15 @@
<ui version="4.0">
<class>UICSCControls</class>
<widget class="QWidget" name="UICSCControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>346</width>
- <height>104</height>
+ <width>290</width>
+ <height>79</height>
</rect>
</property>
<property name="windowTitle">
@@ -23,132 +26,39 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
- <layout class="QHBoxLayout">
- <item>
- <widget class="QLabel" name="textLabel2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>There are no setting necessary for SimConnect</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>FSX version</string>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <item row="0" column="1">
+ <widget class="QComboBox" name="comboBox">
<item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
+ <property name="text">
+ <string>SP1</string>
+ </property>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
+ <property name="text">
+ <string>SP2</string>
+ </property>
</item>
<item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
+ <property name="text">
+ <string>Acceleration</string>
+ </property>
</item>
- </layout>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
</item>
</layout>
</widget>
diff --git a/ftnoir_protocol_sc/scserver-acceleration.manifest b/ftnoir_protocol_sc/scserver-acceleration.manifest
new file mode 100644
index 00000000..06459587
--- /dev/null
+++ b/ftnoir_protocol_sc/scserver-acceleration.manifest
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type='win32' name='Microsoft.FlightSimulator.SimConnect ' version='10.0.61242.0' processorArchitecture='x86' publicKeyToken='67c7c14424d61b5b' />
+ </dependentAssembly>
+ </dependency>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/ftnoir_protocol_sc/scserver-sp2.manifest b/ftnoir_protocol_sc/scserver-sp2.manifest
new file mode 100644
index 00000000..19b123ba
--- /dev/null
+++ b/ftnoir_protocol_sc/scserver-sp2.manifest
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type='win32' name='Microsoft.FlightSimulator.SimConnect ' version='10.0.60905.0' processorArchitecture='x86' publicKeyToken='67c7c14424d61b5b' />
+ </dependentAssembly>
+ </dependency>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/ftnoir_protocol_sc/scserver.manifest b/ftnoir_protocol_sc/scserver.manifest
index 6d6a8edb..60311d6e 100644
--- a/ftnoir_protocol_sc/scserver.manifest
+++ b/ftnoir_protocol_sc/scserver.manifest
@@ -2,7 +2,12 @@
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
<dependentAssembly>
- <assemblyIdentity type='win32' name='Microsoft.FlightSimulator.SimConnect ' version='10.0.60905.0' processorArchitecture='x86' publicKeyToken='67c7c14424d61b5b' />
+ <assemblyIdentity type='win32' name='Microsoft.FlightSimulator.SimConnect' version='10.0.61259.0' processorArchitecture='x86' publicKeyToken='67c7c14424d61b5b' />
+ </dependentAssembly>
+ </dependency>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
</assembly>
diff --git a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp
index 50a7bf97..a3a5cb5f 100644
--- a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp
+++ b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.cpp
@@ -14,8 +14,10 @@ FTNoIR_Protocol::~FTNoIR_Protocol()
VJoy_Shutdown();
}
-void FTNoIR_Protocol::sendHeadposeToGame( double *headpose, double *rawheadpose ) {
+void FTNoIR_Protocol::sendHeadposeToGame( const double *headpose ) {
JOYSTICK_STATE state[2] = { 0 };
+
+ state[0].POV = (4 << 12) | (4 << 8) | (4 << 4) | 4;
state[0].XAxis = std::min<int>(VJOY_AXIS_MAX, std::max<int>(VJOY_AXIS_MIN, headpose[Yaw] * VJOY_AXIS_MAX / 180.0));
state[0].YAxis = std::min<int>(VJOY_AXIS_MAX, std::max<int>(VJOY_AXIS_MIN, headpose[Pitch] * VJOY_AXIS_MAX / 180.0));
diff --git a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h
index 5c260d2e..873b4e3c 100644
--- a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h
+++ b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy.h
@@ -28,14 +28,13 @@
#pragma once
#include "ftnoir_protocol_base/ftnoir_protocol_base.h"
#include "ui_ftnoir_vjoy_controls.h"
-#include <Windows.h>
-#include <VJoy.h>
#include <QThread>
#include <QUdpSocket>
#include <QMessageBox>
#include <QSettings>
#include <math.h>
#include "facetracknoir/global-settings.h"
+#include <windows.h>
#define FT_PROGRAMID "FT_ProgramID"
@@ -43,15 +42,15 @@ class FTNoIR_Protocol : public IProtocol
{
public:
FTNoIR_Protocol();
- ~FTNoIR_Protocol();
+ virtual ~FTNoIR_Protocol();
bool checkServerInstallationOK() {
return true;
}
- void sendHeadposeToGame( double *headpose, double *rawheadpose );
-private:
+ void sendHeadposeToGame( const double *headpose );
QString getGameName() {
return "Virtual joystick";
}
+private:
};
// Widget that has controls for FTNoIR protocol client-settings.
@@ -61,10 +60,6 @@ class VJoyControls: public QWidget, public IProtocolDialog
public:
explicit VJoyControls();
- virtual ~VJoyControls();
- void showEvent ( QShowEvent *) {}
-
- void Initialize(QWidget *);
void registerProtocol(IProtocol *l) {}
void unRegisterProtocol() {}
@@ -92,3 +87,39 @@ public:
void getIcon(QIcon *icon) { *icon = QIcon(":/images/vjoy.png"); }
};
+
+#define VJOY_AXIS_MIN -32768
+#define VJOY_AXIS_NIL 0
+#define VJOY_AXIS_MAX 32767
+
+#include <pshpack1.h>
+
+typedef struct _JOYSTICK_STATE
+{
+ UCHAR ReportId; // Report Id
+ SHORT XAxis; // X Axis
+ SHORT YAxis; // Y Axis
+ SHORT ZAxis; // Z Axis
+ SHORT XRotation; // X Rotation
+ SHORT YRotation; // Y Rotation
+ SHORT ZRotation; // Z Rotation
+ SHORT Slider; // Slider
+ SHORT Dial; // Dial
+ USHORT POV; // POV
+ UINT32 Buttons; // 32 Buttons
+} JOYSTICK_STATE, * PJOYSTICK_STATE;
+
+#include <poppack.h>
+
+#undef EXTERN_C
+#if _MSC_VER
+# define EXTERN_C
+#else
+# define EXTERN_C extern "C"
+#endif
+#if _MSC_VER
+# pragma comment(linker, "/implib:vjoy.def")
+#endif
+EXTERN_C BOOL __stdcall VJoy_Initialize(PCHAR name, PCHAR serial);
+EXTERN_C VOID __stdcall VJoy_Shutdown();
+EXTERN_C BOOL __stdcall VJoy_UpdateJoyState(int id, PJOYSTICK_STATE pJoyState);
diff --git a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp
index 0009553b..febb7b18 100644
--- a/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp
+++ b/ftnoir_protocol_vjoy/ftnoir_protocol_vjoy_dialog.cpp
@@ -8,21 +8,6 @@ VJoyControls::VJoyControls() : QWidget()
connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
}
-VJoyControls::~VJoyControls() {
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void VJoyControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
void VJoyControls::doOK() {
save();
this->close();
diff --git a/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui b/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui
index 1a244410..2214b887 100644
--- a/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui
+++ b/ftnoir_protocol_vjoy/ftnoir_vjoy_controls.ui
@@ -2,12 +2,15 @@
<ui version="4.0">
<class>UICVJoyControls</class>
<widget class="QWidget" name="UICVJoyControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>228</width>
- <height>64</height>
+ <height>69</height>
</rect>
</property>
<property name="windowTitle">
diff --git a/ftnoir_protocol_vjoy/vjoy.def b/ftnoir_protocol_vjoy/vjoy.def
new file mode 100644
index 00000000..aea590a4
--- /dev/null
+++ b/ftnoir_protocol_vjoy/vjoy.def
@@ -0,0 +1,5 @@
+LIBRARY vjoy.dll
+IMPORTS
+VJoy_Initialize = _VJoy_Initialize
+VJoy_Shutdown = _VJoy_Shutdown
+VJoy_UpdateJoyState = _VJoy_UpdateJoyState
diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp b/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp
index bb877cc6..58ffe974 100644
--- a/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp
+++ b/ftnoir_protocol_wine/ftnoir_protocol_wine.cpp
@@ -1,39 +1,3 @@
-/********************************************************************************
-* 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/>. *
-* *
-* FTServer FTServer is the Class, that communicates headpose-data *
-* to games, using the FreeTrackClient.dll. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20110401 - WVR: Moved protocol to a DLL, convenient for installation etc.
- 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
- is called from run() of Tracker.cpp
- 20100601 - WVR: Added Mutex-bit in run(). Thought it wasn't so important (still do...).
- 20100523 - WVR: Implemented the Freetrack-protocol just like Freetrack does. Earlier
- FaceTrackNoIR only worked with an adapted DLL, with a putdata function.
- Now it works direcly in shared memory!
-*/
#include "ftnoir_protocol_wine.h"
#include <string.h>
#include <sys/mman.h>
@@ -43,7 +7,7 @@
/** constructor **/
FTNoIR_Protocol::FTNoIR_Protocol() : lck_shm(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)), shm(NULL), gameid(0)
{
- if (lck_shm.mem != (void*) -1) {
+ if (lck_shm.success()) {
shm = (WineSHM*) lck_shm.mem;
memset(shm, 0, sizeof(*shm));
}
@@ -55,13 +19,18 @@ FTNoIR_Protocol::~FTNoIR_Protocol()
{
if (shm) {
shm->stop = true;
- wrapper.waitForFinished(2000);
+ wrapper.waitForFinished(100);
}
- wrapper.kill();
- shm_unlink("/" WINE_SHM_NAME);
+ wrapper.terminate();
+ if (!wrapper.waitForFinished(100))
+ {
+ wrapper.kill();
+ wrapper.waitForFinished(42);
+ }
+ //shm_unlink("/" WINE_SHM_NAME);
}
-void FTNoIR_Protocol::sendHeadposeToGame( double *headpose, double *rawheadpose ) {
+void FTNoIR_Protocol::sendHeadposeToGame( const double *headpose ) {
if (shm)
{
lck_shm.lock();
@@ -89,7 +58,7 @@ void FTNoIR_Protocol::sendHeadposeToGame( double *headpose, double *rawheadpose
//
bool FTNoIR_Protocol::checkServerInstallationOK()
{
- return lck_shm.mem != (void*)-1;
+ return lck_shm.success();
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine.h b/ftnoir_protocol_wine/ftnoir_protocol_wine.h
index c4837992..50d2bc0c 100644
--- a/ftnoir_protocol_wine/ftnoir_protocol_wine.h
+++ b/ftnoir_protocol_wine/ftnoir_protocol_wine.h
@@ -33,7 +33,6 @@
#include "ftnoir_csv/csv.h"
#include "ui_ftnoir_winecontrols.h"
#include <QMessageBox>
-#include <QSettings>
#include <QLibrary>
#include <QProcess>
#include <QDebug>
@@ -48,11 +47,14 @@ class FTNoIR_Protocol : public IProtocol
{
public:
FTNoIR_Protocol();
- ~FTNoIR_Protocol();
+ virtual ~FTNoIR_Protocol();
bool checkServerInstallationOK();
- void sendHeadposeToGame(double* headpose, double* rawheadpose );
-
+ void sendHeadposeToGame(const double* headpose);
+ QString getGameName() {
+ QMutexLocker foo(&game_name_mutex);
+ return connected_game;
+ }
private:
PortableLockedShm lck_shm;
WineSHM* shm;
@@ -60,10 +62,6 @@ private:
int gameid;
QString connected_game;
QMutex game_name_mutex;
- QString getGameName() {
- QMutexLocker((QMutex*)&game_name_mutex);
- return connected_game;
- }
};
// Widget that has controls for FTNoIR protocol client-settings.
@@ -71,11 +69,8 @@ class FTControls: public QWidget, public IProtocolDialog
{
Q_OBJECT
public:
-
FTControls();
- void showEvent ( QShowEvent * event ) {show();}
- void Initialize(QWidget *parent) {show();}
- void registerProtocol(IProtocol *protocol) {}
+ void registerProtocol(IProtocol *) {}
void unRegisterProtocol() {}
private:
diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp b/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp
index 4021a8e5..ecbc2137 100644
--- a/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp
+++ b/ftnoir_protocol_wine/ftnoir_protocol_wine_dialog.cpp
@@ -1,35 +1,3 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
#include "ftnoir_protocol_wine.h"
#include <QDebug>
#include "facetracknoir/global-settings.h"
diff --git a/ftnoir_protocol_wine/ftnoir_protocol_wine_dll.cpp b/ftnoir_protocol_wine/ftnoir_protocol_wine_dll.cpp
index 1e9298b0..dd7f17a6 100644
--- a/ftnoir_protocol_wine/ftnoir_protocol_wine_dll.cpp
+++ b/ftnoir_protocol_wine/ftnoir_protocol_wine_dll.cpp
@@ -1,35 +1,3 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The ProtocolDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
#include "ftnoir_protocol_wine.h"
#include <QDebug>
#include "facetracknoir/global-settings.h"
diff --git a/ftnoir_protocol_wine/ftnoir_winecontrols.ui b/ftnoir_protocol_wine/ftnoir_winecontrols.ui
index 71e99d88..9356c448 100644
--- a/ftnoir_protocol_wine/ftnoir_winecontrols.ui
+++ b/ftnoir_protocol_wine/ftnoir_winecontrols.ui
@@ -2,12 +2,15 @@
<ui version="4.0">
<class>UICFTControls</class>
<widget class="QWidget" name="UICFTControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>411</width>
- <height>112</height>
+ <width>409</width>
+ <height>110</height>
</rect>
</property>
<property name="windowTitle">
diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx
index a81bccae..6e512b6e 100644
--- a/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx
+++ b/ftnoir_protocol_wine/opentrack-wrapper-wine-main.cxx
@@ -12,6 +12,7 @@ public:
~ShmPosix();
void lock();
void unlock();
+ bool success();
void* mem;
private:
int fd, size;
@@ -23,6 +24,7 @@ public:
~ShmWine();
void lock();
void unlock();
+ bool success();
void* mem;
private:
void *hMutex, *hMapFile;
@@ -33,11 +35,11 @@ int main(void)
{
ShmPosix lck_posix(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM));
ShmWine lck_wine("FT_SharedMem", "FT_Mutext", sizeof(FTMemMap));
- if(lck_posix.mem == (void*)-1) {
+ if(!lck_posix.success()) {
printf("Can't open posix map: %d\n", errno);
return 1;
}
- if(lck_wine.mem == NULL) {
+ if(!lck_wine.success()) {
printf("Can't open Wine map\n");
return 1;
}
diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx
index c88dd332..010c4440 100644
--- a/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx
+++ b/ftnoir_protocol_wine/opentrack-wrapper-wine-posix.cxx
@@ -1,9 +1,8 @@
+#define OPENTRACK_COMPAT_BUNDLED
#ifdef _WIN32
-#undef _WIN32
-#endif
-#ifdef __WIN32
-#undef __WIN32
+# undef _WIN32
#endif
+
#define PortableLockedShm ShmPosix
#include "compat/compat.h"
#include "compat/compat.cpp"
diff --git a/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx b/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx
index 6d5484a9..e7102600 100644
--- a/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx
+++ b/ftnoir_protocol_wine/opentrack-wrapper-wine-windows.cxx
@@ -1,7 +1,11 @@
+#define OPENTRACK_COMPAT_BUNDLED
+
#ifndef __WIN32
#define __WIN32
#endif
+
#define PortableLockedShm ShmWine
+
#include "ftnoir_protocol_ft/fttypes.h"
#include "compat/compat.h"
#include "compat/compat.cpp"
diff --git a/ftnoir_tracker_aruco/ar_video_widget.cpp b/ftnoir_tracker_aruco/ar_video_widget.cpp
new file mode 100644
index 00000000..9a089213
--- /dev/null
+++ b/ftnoir_tracker_aruco/ar_video_widget.cpp
@@ -0,0 +1,42 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "ar_video_widget.h"
+
+#include <QDebug>
+
+using namespace std;
+
+void ArucoVideoWidget::update_image(const cv::Mat& frame)
+{
+ QMutexLocker foo(&mtx);
+ _frame = frame.clone();
+}
+
+void ArucoVideoWidget::update_and_repaint()
+{
+ QMutexLocker foo(&mtx);
+ if (_frame.cols*_frame.rows <= 0)
+ return;
+ QImage qframe = QImage(_frame.cols, _frame.rows, QImage::Format_RGB888);
+ uchar* data = qframe.bits();
+ const int pitch = qframe.bytesPerLine();
+ for (int y = 0; y < _frame.rows; y++)
+ {
+ for (int x = 0; x < _frame.cols; x++)
+ {
+ const auto& elt = _frame.at<cv::Vec3b>(y, x);
+ const cv::Scalar elt2 = static_cast<cv::Scalar>(elt);
+ data[y * pitch + x * 3 + 0] = elt2.val[2];
+ data[y * pitch + x * 3 + 1] = elt2.val[1];
+ data[y * pitch + x * 3 + 2] = elt2.val[0];
+ }
+ }
+ auto qframe2 = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
+ texture = qframe2;
+ update();
+}
diff --git a/ftnoir_tracker_pt/video_widget.h b/ftnoir_tracker_aruco/ar_video_widget.h
index 66959fde..e2cf4d9f 100644
--- a/ftnoir_tracker_pt/video_widget.h
+++ b/ftnoir_tracker_aruco/ar_video_widget.h
@@ -1,42 +1,47 @@
-/* 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 VIDEOWIDGET_H
-#define VIDEOWIDGET_H
-
-#include <QTime>
-#include <opencv2/opencv.hpp>
-#include <memory>
-#include <QWidget>
-#include <QMutex>
-#include <QMutexLocker>
-#include <QLabel>
-#include <QPainter>
-#include <QPaintEvent>
-
-// ----------------------------------------------------------------------------
-class VideoWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- VideoWidget(QWidget *parent) : QWidget(parent), mtx() {
- }
- void update_image(cv::Mat frame, std::auto_ptr< std::vector<cv::Vec2f> >);
-protected slots:
- void paintEvent( QPaintEvent* e ) {
- QMutexLocker foo(&mtx);
- QPainter painter(this);
- painter.drawPixmap(e->rect(), pixmap, e->rect());
- }
-
-private:
- QMutex mtx;
- QPixmap pixmap;
-};
-
-#endif // VIDEOWIDGET_H
+/* 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 VIDEOWIDGET_H
+#define VIDEOWIDGET_H
+
+#include <QTimer>
+#include <QWidget>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QLabel>
+#include <QPainter>
+#include <QPaintEvent>
+#include <QTimer>
+#include <opencv/cv.hpp>
+
+// ----------------------------------------------------------------------------
+class ArucoVideoWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ArucoVideoWidget(QWidget *parent) : QWidget(parent) {
+ connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint()));
+ timer.start(60);
+ }
+ void update_image(const cv::Mat& frame);
+protected slots:
+ void paintEvent( QPaintEvent* e ) {
+ QMutexLocker foo(&mtx);
+ QPainter painter(this);
+ painter.drawImage(e->rect(), texture);
+ }
+ void update_and_repaint();
+
+private:
+ QMutex mtx;
+ QImage texture;
+ QTimer timer;
+ cv::Mat _frame;
+};
+
+#endif // VIDEOWIDGET_H
diff --git a/ftnoir_tracker_aruco/aruco-trackercontrols.ui b/ftnoir_tracker_aruco/aruco-trackercontrols.ui
index 3ad9fa40..1d5a4241 100644
--- a/ftnoir_tracker_aruco/aruco-trackercontrols.ui
+++ b/ftnoir_tracker_aruco/aruco-trackercontrols.ui
@@ -9,475 +9,365 @@
<rect>
<x>0</x>
<y>0</y>
- <width>593</width>
- <height>280</height>
+ <width>615</width>
+ <height>326</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
- <width>750</width>
- <height>280</height>
+ <width>6666</width>
+ <height>6666</height>
</size>
</property>
<property name="windowTitle">
<string>HT tracker settings</string>
</property>
- <widget class="QLabel" name="label">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>141</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Horizontal FOV</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="cameraFOV">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>10</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <property name="locale">
- <locale language="English" country="UnitedStates"/>
- </property>
- <property name="minimum">
- <double>35.000000000000000</double>
- </property>
- <property name="maximum">
- <double>180.000000000000000</double>
- </property>
- <property name="value">
- <double>52.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_2">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>137</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Frames per second</string>
- </property>
- </widget>
- <widget class="QComboBox" name="cameraFPS">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>40</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string notr="true">Default</string>
- </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="spacing">
+ <number>7</number>
+ </property>
+ <item row="9" column="1" rowspan="3">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Head position</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="cx">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <double>-10000.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QDoubleSpinBox" name="cz">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <double>-10000.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDoubleSpinBox" name="cy">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <double>-10000.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>10000.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>30</string>
- </property>
+ <item row="0" column="3" rowspan="3" colspan="2">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Enable axes</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="horizontalSpacing">
+ <number>7</number>
+ </property>
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="rx">
+ <property name="text">
+ <string>RX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="tx">
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="ry">
+ <property name="text">
+ <string>RY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="ty">
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="rz">
+ <property name="text">
+ <string>RZ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="tz">
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>60</string>
- </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Frames per second</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>120</string>
- </property>
+ <item row="2" column="1" colspan="2">
+ <widget class="QComboBox" name="cameraName"/>
</item>
- </widget>
- <widget class="QLabel" name="label_3">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>70</y>
- <width>133</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Camera name</string>
- </property>
- </widget>
- <widget class="QPushButton" name="buttonOK">
- <property name="geometry">
- <rect>
- <x>430</x>
- <y>250</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QPushButton" name="buttonCancel">
- <property name="geometry">
- <rect>
- <x>510</x>
- <y>250</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- <widget class="QGroupBox" name="groupBox">
- <property name="geometry">
- <rect>
- <x>390</x>
- <y>10</y>
- <width>101</width>
- <height>81</height>
- </rect>
- </property>
- <property name="title">
- <string>Enable axes</string>
- </property>
- <widget class="QCheckBox" name="rx">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RX</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="ry">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RY</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="rz">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>60</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RZ</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="tx">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>20</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="ty">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>40</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="tz">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>60</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </widget>
- <widget class="QComboBox" name="cameraName">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>70</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- </widget>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>100</y>
- <width>128</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Resolution</string>
- </property>
- </widget>
- <widget class="QComboBox" name="resolution">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>100</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string>640x480</string>
- </property>
+ <item row="1" column="1" colspan="2">
+ <widget class="QComboBox" name="cameraFPS">
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>30</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>60</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>120</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>180</string>
+ </property>
+ </item>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>320x240</string>
- </property>
+ <item row="7" column="1">
+ <widget class="QCheckBox" name="red_only">
+ <property name="text">
+ <string>Recommended!</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>320x200</string>
- </property>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Camera name</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>Default (not recommended!)</string>
- </property>
+ <item row="0" column="1" colspan="2">
+ <widget class="QDoubleSpinBox" name="cameraFOV">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <property name="minimum">
+ <double>35.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>52.000000000000000</double>
+ </property>
+ </widget>
</item>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>130</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_5">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>130</y>
- <width>111</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Distortion coefficients</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_2">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>160</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_3">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>190</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_4">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>220</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_5">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>250</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_6">
- <property name="geometry">
- <rect>
- <x>325</x>
- <y>133</y>
- <width>253</width>
- <height>60</height>
- </rect>
- </property>
- <property name="text">
- <string>The ARUCO Library has been developed by
-the Ava group of the Univeristy of Cordoba(Spain)
-Contact to
-Rafael Muñoz Salinas &lt;rmsalinas@uco.es&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- <widget class="QLineEdit" name="lineEdit">
- <property name="geometry">
- <rect>
- <x>370</x>
- <y>200</y>
- <width>181</width>
- <height>20</height>
- </rect>
- </property>
- <property name="text">
- <string>https://github.com/rmsalinas/aruco</string>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
+ <item row="6" column="2" rowspan="5" colspan="3">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The ARUCO Library has been developed by the Ava group of the Univeristy of Cordoba, Spain&lt;/p&gt;&lt;p&gt;Rafael Muñoz Salinas &amp;lt;&lt;a href=&quot;mailto:rmsalinas@uco.es&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;rmsalinas@uco.es&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;&lt;a href=&quot;https://github.com/rmsalinas/aruco&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;https://github.com/rmsalinas/aruco&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="margin">
+ <number>4</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="0">
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Red channel only</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="resolution">
+ <item>
+ <property name="text">
+ <string>640x480</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>320x240</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>320x200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Default (not recommended!)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Horizontal FOV</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="4">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QDoubleSpinBox" name="marker_pitch">
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Resolution</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Marker pitch</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
+ <tabstops>
+ <tabstop>cameraFOV</tabstop>
+ <tabstop>cameraFPS</tabstop>
+ <tabstop>cameraName</tabstop>
+ <tabstop>resolution</tabstop>
+ <tabstop>red_only</tabstop>
+ <tabstop>marker_pitch</tabstop>
+ <tabstop>cx</tabstop>
+ <tabstop>cy</tabstop>
+ <tabstop>cz</tabstop>
+ <tabstop>rx</tabstop>
+ <tabstop>ry</tabstop>
+ <tabstop>rz</tabstop>
+ <tabstop>tx</tabstop>
+ <tabstop>ty</tabstop>
+ <tabstop>tz</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
<resources/>
<connections/>
<designerdata>
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
index 152c1e32..ae7ca0b5 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.cpp
@@ -15,17 +15,21 @@
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
#include <vector>
+#include <cstdio>
-#if defined(_WIN32) || defined(__WIN32)
-#include <dshow.h>
+#if defined(_WIN32)
+# undef NOMINMAX
+# define NOMINMAX
+# define NO_DSHOW_STRSAFE
+# include <dshow.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
// delicious copypasta
static QList<QString> get_camera_names(void) {
QList<QString> ret;
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
@@ -78,7 +82,7 @@ static QList<QString> get_camera_names(void) {
if (access(buf, R_OK | W_OK) == 0) {
ret.append(buf);
} else {
- break;
+ continue;
}
}
#endif
@@ -97,55 +101,27 @@ static resolution_tuple resolution_choices[] = {
{ 0, 0 }
};
-void Tracker::load_settings()
+Tracker::Tracker() : stop(false), layout(nullptr), videoWidget(nullptr)
{
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
-
- iniFile.beginGroup( "aruco-Tracker" );
- fov = iniFile.value("fov", 56).toFloat();
- force_fps = iniFile.value("fps", 0).toInt();
- camera_index = iniFile.value("camera-index", -1).toInt();
- int res = iniFile.value("resolution", 0).toInt();
- if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
- res = 0;
- resolution_tuple r = resolution_choices[res];
- force_width = r.width;
- force_height = r.height;
- enableRX = iniFile.value("enable-rx", true).toBool();
- enableRY = iniFile.value("enable-ry", true).toBool();
- enableRZ = iniFile.value("enable-rz", true).toBool();
- enableTX = iniFile.value("enable-tx", true).toBool();
- enableTY = iniFile.value("enable-ty", true).toBool();
- enableTZ = iniFile.value("enable-tz", true).toBool();
- for (int i = 0; i < 5; i++)
- dc[i] = iniFile.value(QString("dc%1").arg(i), 0).toFloat();
- iniFile.endGroup();
-}
-
-Tracker::Tracker()
-{
- fresh = false;
- stop = false;
- videoWidget = NULL;
- layout = NULL;
- enableRX = enableRY = enableRZ = enableTX = enableTY = enableTZ = true;
- load_settings();
}
Tracker::~Tracker()
{
- if (layout)
- delete layout;
+ stop = true;
+ wait();
if (videoWidget)
delete videoWidget;
+ if(layout)
+ delete layout;
+ qDebug() << "releasing camera, brace for impact";
+ camera.release();
+ qDebug() << "all done!";
}
void Tracker::StartTracker(QFrame* videoframe)
{
videoframe->show();
- videoWidget = new VideoWidget(videoframe);
+ videoWidget = new ArucoVideoWidget(videoframe);
QHBoxLayout* layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(videoWidget);
@@ -153,143 +129,263 @@ void Tracker::StartTracker(QFrame* videoframe)
delete videoframe->layout();
videoframe->setLayout(layout);
videoWidget->show();
- this->layout = layout;
- load_settings();
- connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()));
- timer.start(50);
start();
for (int i = 0; i < 6; i++)
pose[i] = 0;
-}
-
-void Tracker::paint_widget() {
- if (fresh) {
- fresh = false;
- videoWidget->update();
- }
+ this->layout = layout;
}
#define HT_PI 3.1415926535
void Tracker::run()
{
- cv::VideoCapture camera(camera_index);
-
- if (force_width)
- camera.set(CV_CAP_PROP_FRAME_WIDTH, force_width);
- if (force_height)
- camera.set(CV_CAP_PROP_FRAME_HEIGHT, force_height);
- if (force_fps)
- camera.set(CV_CAP_PROP_FPS, force_fps);
+ int res = s.resolution;
+ if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
+ res = 0;
+ resolution_tuple r = resolution_choices[res];
+ int fps;
+ switch (static_cast<int>(s.force_fps))
+ {
+ default:
+ case 0:
+ fps = 0;
+ break;
+ case 1:
+ fps = 30;
+ break;
+ case 2:
+ fps = 60;
+ break;
+ case 3:
+ fps = 120;
+ break;
+ case 4:
+ fps = 180;
+ break;
+ }
+ camera = cv::VideoCapture(s.camera_index);
+ if (r.width)
+ {
+ camera.set(CV_CAP_PROP_FRAME_WIDTH, r.width);
+ camera.set(CV_CAP_PROP_FRAME_HEIGHT, r.height);
+ }
+ if (fps)
+ camera.set(CV_CAP_PROP_FPS, fps);
aruco::MarkerDetector detector;
detector.setDesiredSpeed(3);
- detector.setThresholdParams(11, 5);
- cv::Mat color, grayscale, rvec, tvec;
-
+
+ cv::Rect last_roi(65535, 65535, 0, 0);
+
+ cv::Mat color, color_, grayscale, rvec, tvec;
+
+ const double stateful_coeff = 0.88;
+
+ if (!camera.isOpened())
+ {
+ fprintf(stderr, "aruco tracker: can't open camera\n");
+ return;
+ }
+
+ auto freq = cv::getTickFrequency();
+ auto last_time = cv::getTickCount();
+ int cur_fps = 0;
+ int last_fps = 0;
+ cv::Point2f last_centroid;
+ bool first = true;
+
while (!stop)
{
- if (!camera.read(color))
- break;
- cv::cvtColor(color, grayscale, cv::COLOR_BGR2GRAY);
- const float focal_length_w = 0.5 * grayscale.cols / tan(0.5 * fov * HT_PI / 180);
- const float focal_length_h = 0.5 * grayscale.rows / tan(0.5 * fov * grayscale.rows / grayscale.cols * HT_PI / 180.0);
+ if (!camera.read(color_))
+ continue;
+ auto tm = cv::getTickCount();
+ color_.copyTo(color);
+ if (s.red_only)
+ {
+ cv::Mat channel[3];
+ cv::split(color, channel);
+ grayscale = channel[2];
+ } else
+ cv::cvtColor(color, grayscale, cv::COLOR_BGR2GRAY);
+
+ const int scale = frame.cols > 480 ? 2 : 1;
+ detector.setThresholdParams(scale > 1 ? 11 : 7, 4);
+
+ 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);
cv::Mat intrinsics = cv::Mat::eye(3, 3, CV_32FC1);
intrinsics.at<float> (0, 0) = focal_length_w;
intrinsics.at<float> (1, 1) = focal_length_h;
intrinsics.at<float> (0, 2) = grayscale.cols/2;
intrinsics.at<float> (1, 2) = grayscale.rows/2;
-
+
cv::Mat dist_coeffs = cv::Mat::zeros(5, 1, CV_32FC1);
-
- for (int i = 0; i < 5; i++)
- dist_coeffs.at<float>(i) = dc[i];
-
+
std::vector< aruco::Marker > markers;
-
- detector.detect(grayscale, markers, cv::Mat(), cv::Mat(), -1, false);
-
+
+ const double size_min = 0.04;
+ const double size_max = 0.38;
+
+ if (last_roi.width > 0 &&
+ (detector.detect(grayscale(last_roi), markers, cv::Mat(), cv::Mat(), -1, false),
+ markers.size() == 1 && markers[0].size() == 4))
+ {
+ detector.setMinMaxSize(std::max(0.01, size_min * grayscale.cols / last_roi.width),
+ std::min(1.0, size_max * grayscale.cols / last_roi.width));
+ auto& m = markers.at(0);
+ for (int i = 0; i < 4; i++)
+ {
+ auto& p = m.at(i);
+ p.x += last_roi.x;
+ p.y += last_roi.y;
+ }
+ }
+ else
+ {
+ 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 aruco::Marker& m = markers.at(0);
+ const auto& m = markers.at(0);
for (int i = 0; i < 4; i++)
- cv::line(color, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), 4);
+ cv::line(color, m[i], m[(i+1)%4], cv::Scalar(0, 0, 255), scale, 8);
}
-
- frame = color;
-
- if (frame.rows > 0 && !fresh)
+
+ auto time = cv::getTickCount();
+
+ if ((long) (time / freq) != (long) (last_time / freq))
{
- videoWidget->update_image(frame.data, frame.cols, frame.rows);
- fresh = true;
+ last_fps = cur_fps;
+ cur_fps = 0;
+ last_time = time;
}
+
+ cur_fps++;
+
+ char buf[128];
+
+ 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), scale);
+ ::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), scale);
if (markers.size() == 1 && markers[0].size() == 4) {
- const aruco::Marker& m = markers.at(0);
- const float size = 7;
+ const auto& m = markers.at(0);
+ const float size = 40;
+ const double p = s.marker_pitch;
+ const double sq = sin(p * HT_PI / 180);
+ const double cq = cos(p * HT_PI / 180);
+
cv::Mat obj_points(4,3,CV_32FC1);
- obj_points.at<float>(1,0)=-size;
- obj_points.at<float>(1,1)=-size;
- obj_points.at<float>(1,2)=0;
- obj_points.at<float>(2,0)=size;
- obj_points.at<float>(2,1)=-size;
- obj_points.at<float>(2,2)=0;
- obj_points.at<float>(3,0)=size;
- obj_points.at<float>(3,1)=size;
- obj_points.at<float>(3,2)=0;
- obj_points.at<float>(0,0)=-size;
- obj_points.at<float>(0,1)=size;
- obj_points.at<float>(0,2)=0;
-
- cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec, tvec, false, cv::ITERATIVE);
-
+ obj_points.at<float>(1,0)=-size + s.headpos_x;
+ obj_points.at<float>(1,1)=-size * cq + s.headpos_y;
+ obj_points.at<float>(1,2)=-size * sq + s.headpos_z;
+ obj_points.at<float>(2,0)=size + s.headpos_x;
+ obj_points.at<float>(2,1)=-size * cq + s.headpos_y;
+ obj_points.at<float>(2,2)=-size * sq + s.headpos_z;
+ obj_points.at<float>(3,0)=size + s.headpos_x;
+ obj_points.at<float>(3,1)=size * cq + s.headpos_y;
+ obj_points.at<float>(3,2)=size * sq + s.headpos_z;
+ obj_points.at<float>(0,0)=-size + s.headpos_x;
+ obj_points.at<float>(0,1)=size * cq + s.headpos_y;
+ obj_points.at<float>(0,2)=size * sq + s.headpos_z;
+
+ last_roi = cv::Rect(65535, 65535, 0, 0);
+
+ for (int i = 0; i < 4; i++)
+ {
+ auto foo = m.at(i);
+ last_roi.x = std::min<int>(foo.x, last_roi.x);
+ last_roi.y = std::min<int>(foo.y, last_roi.y);
+ last_roi.width = std::max<int>(foo.x, last_roi.width);
+ last_roi.height = std::max<int>(foo.y, last_roi.height);
+ }
+ {
+ last_roi.width -= last_roi.x;
+ last_roi.height -= last_roi.y;
+ last_roi.x -= last_roi.width * stateful_coeff;
+ last_roi.y -= last_roi.height * stateful_coeff;
+ last_roi.width *= stateful_coeff * 3;
+ last_roi.height *= stateful_coeff * 3;
+ last_roi.x = std::max<int>(0, last_roi.x);
+ last_roi.y = std::max<int>(0, last_roi.y);
+ last_roi.width = std::min<int>(grayscale.cols - last_roi.x, last_roi.width);
+ last_roi.height = std::min<int>(grayscale.rows - last_roi.y, last_roi.height);
+ }
+
+ cv::solvePnP(obj_points, m, intrinsics, dist_coeffs, rvec, tvec, !first, cv::ITERATIVE);
+ first = false;
cv::Mat rotation_matrix = cv::Mat::zeros(3, 3, CV_64FC1);
-
cv::Mat junk1(3, 3, CV_64FC1), junk2(3, 3, CV_64FC1);
-
cv::Rodrigues(rvec, rotation_matrix);
-
- cv::Vec3d foo = cv::RQDecomp3x3(rotation_matrix, junk1, junk2);
-
- QMutexLocker lck(&mtx);
-
- for (int i = 0; i < 3; i++)
- pose[i] = tvec.at<double>(i);
-
- pose[Yaw] = foo[1];
- pose[Pitch] = -foo[0];
- pose[Roll] = foo[2];
-
- pose[Yaw] -= atan(pose[TX] / pose[TZ]) * 180 / HT_PI;
- pose[Pitch] -= atan(pose[TY] / pose[TZ]) * 180 / HT_PI;
+
+ {
+ cv::Vec3d euler = cv::RQDecomp3x3(rotation_matrix, junk1, junk2);
+
+ if (fabs(euler[0]) + fabs(s.marker_pitch) > 60)
+ {
+ first = true;
+ qDebug() << "reset levmarq due to pitch breakage";
+ }
+
+ QMutexLocker lck(&mtx);
+
+ for (int i = 0; i < 3; i++)
+ pose[i] = tvec.at<double>(i);
+
+ pose[Yaw] = euler[1];
+ pose[Pitch] = -euler[0];
+ pose[Roll] = euler[2];
+ }
+
+ 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);
+ }
+
+ last_centroid = repr2[0];
+ }
+ else
+ {
+ last_roi = cv::Rect(65535, 65535, 0, 0);
+ first = true;
}
+
+ if (frame.rows > 0)
+ videoWidget->update_image(frame);
}
}
-bool Tracker::GiveHeadPoseData(double *data)
+void Tracker::GetHeadPoseData(double *data)
{
QMutexLocker lck(&mtx);
- if (enableRX)
+ if (s.eyaw)
data[Yaw] = pose[Yaw];
- if (enableRY)
+ if (s.epitch)
data[Pitch] = pose[Pitch];
- if (enableRZ)
+ if (s.eroll)
data[Roll] = pose[Roll];
- if (enableTX)
- data[TX] = pose[TX];
- if (enableTY)
- data[TY] = pose[TY];
- if (enableTZ)
- data[TZ] = pose[TZ];
-
- return true;
+ if (s.ex)
+ data[TX] = pose[TX] * .1;
+ if (s.ey)
+ data[TY] = pose[TY] * .1;
+ if (s.ez)
+ data[TZ] = pose[TZ] * .1;
}
class TrackerDll : public Metadata
{
// ITrackerDll interface
- void Initialize() {}
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
void getDescription(QString *strToBeFilled);
@@ -349,163 +445,39 @@ extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDial
TrackerControls::TrackerControls()
{
+ tracker = nullptr;
ui.setupUi(this);
setAttribute(Qt::WA_NativeWindow, true);
- connect(ui.cameraName, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.cameraFPS, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.cameraFOV, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(double)));
- connect(ui.rx, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.ry, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.rz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.tx, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.ty, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.tz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.buttonOK, SIGNAL(clicked()), this, SLOT(doOK()));
- //connect(ui.buttonSettings, SIGNAL(clicked()), this, SLOT(cameraSettings()));
- loadSettings();
- settingsDirty = false;
-}
-
-TrackerControls::~TrackerControls()
-{
-}
-
-void TrackerControls::showEvent(QShowEvent *event)
-{
-}
-
-void TrackerControls::Initialize(QWidget* parent)
-{
- loadSettings();
- show();
-}
-
-void TrackerControls::loadSettings()
-{
- ui.cameraName->clear();
- QList<QString> names = get_camera_names();
- names.prepend("Any available");
- ui.cameraName->addItems(names);
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
- iniFile.beginGroup( "aruco-Tracker" );
- ui.cameraName->setCurrentIndex(iniFile.value("camera-index", -1).toInt() + 1);
- ui.cameraFOV->setValue(iniFile.value("fov", 56).toFloat());
- int fps;
- switch (iniFile.value("fps", 0).toInt())
- {
- default:
- case 0:
- fps = 0;
- break;
- case 30:
- fps = 1;
- break;
- case 60:
- fps = 2;
- break;
- case 120:
- fps = 3;
- break;
- }
- ui.cameraFPS->setCurrentIndex(fps);
- ui.rx->setCheckState(iniFile.value("enable-rx", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.ry->setCheckState(iniFile.value("enable-ry", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.rz->setCheckState(iniFile.value("enable-rz", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.tx->setCheckState(iniFile.value("enable-tx", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.ty->setCheckState(iniFile.value("enable-ty", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.tz->setCheckState(iniFile.value("enable-tz", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.resolution->setCurrentIndex(iniFile.value("resolution", 0).toInt());
-
- ui.doubleSpinBox->setValue(iniFile.value("dc0").toDouble());
- ui.doubleSpinBox_2->setValue(iniFile.value("dc1").toDouble());
- ui.doubleSpinBox_3->setValue(iniFile.value("dc2").toDouble());
- ui.doubleSpinBox_4->setValue(iniFile.value("dc3").toDouble());
- ui.doubleSpinBox_5->setValue(iniFile.value("dc4").toDouble());
-
- iniFile.endGroup();
- settingsDirty = false;
-}
-
-void TrackerControls::save()
-{
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
-
- iniFile.beginGroup( "aruco-Tracker" );
- iniFile.setValue("fov", ui.cameraFOV->value());
- int fps;
- switch (ui.cameraFPS->currentIndex())
- {
- case 0:
- default:
- fps = 0;
- break;
- case 1:
- fps = 30;
- break;
- case 2:
- fps = 60;
- break;
- case 3:
- fps = 120;
- break;
- }
- iniFile.setValue("fps", fps);
- iniFile.setValue("camera-index", ui.cameraName->currentIndex() - 1);
- iniFile.setValue("enable-rx", ui.rx->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-ry", ui.ry->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-rz", ui.rz->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-tx", ui.tx->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-ty", ui.ty->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-tz", ui.tz->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("resolution", ui.resolution->currentIndex());
-
- iniFile.setValue("dc0", ui.doubleSpinBox->value());
- iniFile.setValue("dc1", ui.doubleSpinBox_2->value());
- iniFile.setValue("dc2", ui.doubleSpinBox_3->value());
- iniFile.setValue("dc3", ui.doubleSpinBox_4->value());
- iniFile.setValue("dc4", ui.doubleSpinBox_5->value());
-
- iniFile.endGroup();
- settingsDirty = false;
+ tie_setting(s.camera_index, ui.cameraName);
+ tie_setting(s.resolution, ui.resolution);
+ tie_setting(s.force_fps, ui.cameraFPS);
+ tie_setting(s.fov, ui.cameraFOV);
+ tie_setting(s.eyaw, ui.rx);
+ tie_setting(s.epitch, ui.ry);
+ tie_setting(s.eroll, ui.rz);
+ tie_setting(s.ex, ui.tx);
+ tie_setting(s.ey, ui.ty);
+ tie_setting(s.ez, ui.tz);
+ tie_setting(s.headpos_x, ui.cx);
+ tie_setting(s.headpos_y, ui.cy);
+ tie_setting(s.headpos_z, ui.cz);
+ tie_setting(s.red_only, ui.red_only);
+ tie_setting(s.marker_pitch, ui.marker_pitch);
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+ ui.cameraName->addItems(get_camera_names());
}
void TrackerControls::doOK()
{
- save();
+ s.b->save();
+ if (tracker)
+ tracker->reload();
this->close();
}
void TrackerControls::doCancel()
{
- 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:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
+ s.b->revert();
+ this->close();
}
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
index 7f21f020..4cab84b5 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco.h
@@ -10,46 +10,63 @@
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "ui_aruco-trackercontrols.h"
-#include "video_widget.h"
+#include "ar_video_widget.h"
#include <QObject>
-#include <QTimer>
#include <QThread>
#include <QMutex>
#include <QHBoxLayout>
+#include <QDialog>
#include <opencv2/opencv.hpp>
+#include <opencv/highgui.h>
+#include "facetracknoir/options.h"
+using namespace options;
-class Tracker : public QThread, public ITracker
+struct settings {
+ pbundle b;
+ value<double> fov, headpos_x, headpos_y, headpos_z;
+ value<int> camera_index, force_fps, resolution;
+ value<bool> red_only;
+ value<bool> eyaw, epitch, eroll, ex, ey, ez;
+ value<double> marker_pitch;
+ settings() :
+ b(bundle("aruco-tracker")),
+ fov(b, "field-of-view", 56),
+ headpos_x(b, "headpos-x", 0),
+ headpos_y(b, "headpos-y", 0),
+ headpos_z(b, "headpos-z", 0),
+ camera_index(b, "camera-index", 0),
+ force_fps(b, "force-fps", 0),
+ resolution(b, "force-resolution", 0),
+ red_only(b, "red-only", false),
+ eyaw(b, "enable-y", true),
+ epitch(b, "enable-p", true),
+ eroll(b, "enable-r", true),
+ ex(b, "enable-x", true),
+ ey(b, "enable-y", true),
+ ez(b, "enable-z", true),
+ marker_pitch(b, "marker-pitch", 0)
+ {}
+};
+
+class Tracker : protected QThread, public ITracker
{
Q_OBJECT
public:
Tracker();
- ~Tracker();
+ virtual ~Tracker();
void StartTracker(QFrame* frame);
- bool GiveHeadPoseData(double *data);
- bool enableTX, enableTY, enableTZ, enableRX, enableRY, enableRZ;
- bool NeedsTimeToFinish() {
- return true;
- }
- void WaitForExit() {
- stop = true;
- wait();
- }
+ void GetHeadPoseData(double *data);
void run();
+ void reload() { s.b->reload(); }
private:
QMutex mtx;
- QTimer timer;
- VideoWidget* videoWidget;
- QHBoxLayout* layout;
- volatile bool fresh, stop;
- float fov;
- int camera_index;
- float dc[5];
- int force_fps, force_width, force_height;
- void load_settings();
+ volatile bool stop;
+ QHBoxLayout* layout;
+ ArucoVideoWidget* videoWidget;
+ settings s;
double pose[6];
cv::Mat frame;
-private slots:
- void paint_widget();
+ cv::VideoCapture camera;
};
// Widget that has controls for FTNoIR protocol client-settings.
@@ -57,27 +74,20 @@ class TrackerControls : public QWidget, public ITrackerDialog
{
Q_OBJECT
public:
-
- explicit TrackerControls();
- virtual ~TrackerControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {}
- void unRegisterTracker() {}
-
+ TrackerControls();
+ void registerTracker(ITracker * x) {
+ tracker = dynamic_cast<Tracker*>(x);
+ }
+ void unRegisterTracker() {
+ tracker = nullptr;
+ }
private:
Ui::Form ui;
- void loadSettings();
- void save();
- bool settingsDirty;
-
+ Tracker* tracker;
+ settings s;
private slots:
void doOK();
void doCancel();
- void settingChanged() { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
- void settingChanged(double) { settingsDirty = true; }
};
#endif
diff --git a/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h b/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h
index 1e53f802..ffdc5262 100644
--- a/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h
+++ b/ftnoir_tracker_aruco/ftnoir_tracker_aruco_dll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 Stanis³aw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -12,7 +12,6 @@
class TrackerDll : public Metadata
{
// ITrackerDll interface
- void Initialize() {}
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
void getDescription(QString *strToBeFilled);
diff --git a/ftnoir_tracker_aruco/include/boarddetector.h b/ftnoir_tracker_aruco/include/boarddetector.h
index a0ee2361..4770b5c9 100644
--- a/ftnoir_tracker_aruco/include/boarddetector.h
+++ b/ftnoir_tracker_aruco/include/boarddetector.h
@@ -134,6 +134,6 @@ private:
};
-};
+}
#endif
diff --git a/ftnoir_tracker_aruco/include/cvdrawingutils.h b/ftnoir_tracker_aruco/include/cvdrawingutils.h
index ff67242f..38e9986e 100644
--- a/ftnoir_tracker_aruco/include/cvdrawingutils.h
+++ b/ftnoir_tracker_aruco/include/cvdrawingutils.h
@@ -46,7 +46,7 @@ namespace aruco
static void draw3dCube(cv::Mat &Image,Board &m,const CameraParameters &CP);
};
-};
+}
#endif
diff --git a/ftnoir_tracker_aruco/include/markerdetector.h b/ftnoir_tracker_aruco/include/markerdetector.h
index 35369cea..4d6e7b90 100644
--- a/ftnoir_tracker_aruco/include/markerdetector.h
+++ b/ftnoir_tracker_aruco/include/markerdetector.h
@@ -52,10 +52,13 @@ class ARUCO_EXPORTS MarkerDetector
contour=M.contour;
idx=M.idx;
}
- MarkerCandidate & operator=(const MarkerCandidate &M){
+ MarkerCandidate operator=(const MarkerCandidate &M){
+ if (this == &M)
+ return *this;
(*(Marker*)this)=(*(Marker*)&M);
contour=M.contour;
idx=M.idx;
+ return M;
}
vector<cv::Point> contour;//all the points of its contour
@@ -350,9 +353,5 @@ private:
void draw(cv::Mat out,const std::vector<Marker> &markers );
};
-
-
-
-
-};
+}
#endif
diff --git a/ftnoir_tracker_aruco/video_widget.cpp b/ftnoir_tracker_aruco/video_widget.cpp
deleted file mode 100644
index 84cba6a3..00000000
--- a/ftnoir_tracker_aruco/video_widget.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "video_widget.h"
-
-#include <QDebug>
-
-using namespace std;
-
-void VideoWidget::update_image(unsigned char *frame, int width, int height)
-{
- QMutexLocker foo(&mtx);
- QImage qframe = QImage(width, height, QImage::Format_RGB888);
- uchar* data = qframe.bits();
- const int pitch = qframe.bytesPerLine();
- for (int y = 0; y < height; y++)
- for (int x = 0; x < width; x++)
- {
- const int pos = 3 * (y*width + x);
- data[y * pitch + x * 3 + 0] = frame[pos + 2];
- data[y * pitch + x * 3 + 1] = frame[pos + 1];
- data[y * pitch + x * 3 + 2] = frame[pos + 0];
- }
- qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
- pixmap = QPixmap::fromImage(qframe);
-}
diff --git a/ftnoir_tracker_aruco/video_widget.h b/ftnoir_tracker_aruco/video_widget.h
deleted file mode 100644
index 87b6278a..00000000
--- a/ftnoir_tracker_aruco/video_widget.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef VIDEOWIDGET_H
-#define VIDEOWIDGET_H
-
-#include <QTime>
-#include <QWidget>
-#include <QMutex>
-#include <QMutexLocker>
-#include <QLabel>
-#include <QPainter>
-#include <QPaintEvent>
-
-// ----------------------------------------------------------------------------
-class VideoWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- VideoWidget(QWidget *parent) : QWidget(parent), mtx() {
- }
- void update_image(unsigned char* frame, int width, int height);
-protected slots:
- void paintEvent( QPaintEvent* e ) {
- QMutexLocker foo(&mtx);
- QPainter painter(this);
- painter.drawPixmap(e->rect(), pixmap, e->rect());
- }
-private:
- QMutex mtx;
- QPixmap pixmap;
-};
-
-#endif // VIDEOWIDGET_H
diff --git a/ftnoir_tracker_base/ftnoir_tracker_base.h b/ftnoir_tracker_base/ftnoir_tracker_base.h
index 182a364c..09723d84 100644
--- a/ftnoir_tracker_base/ftnoir_tracker_base.h
+++ b/ftnoir_tracker_base/ftnoir_tracker_base.h
@@ -1,101 +1,65 @@
-/********************************************************************************
-* 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/>. *
-* This class implements a tracker-base *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20122109 - C14: Replaced Release with virtual destructor
- 20120009 - WVR: Removed AutoClosePtr (seemed like it didn't work OK)
- 20110415 - WVR: Added overloaded operator - and -=
-*/
-#ifndef FTNOIR_TRACKER_BASE_H
-#define FTNOIR_TRACKER_BASE_H
-
-#include "ftnoir_tracker_base_global.h"
-#include "ftnoir_tracker_types.h"
-#include <QtGui/QWidget>
-#include <QtGui/QFrame>
-#include <QWaitCondition>
-#include <QMutex>
-#include <QFrame>
-
-////////////////////////////////////////////////////////////////////////////////
-#ifdef __cplusplus
-# define EXTERN_C extern "C"
-#else
-# define EXTERN_C
-#endif // __cplusplus
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
-struct ITracker
-{
- virtual ~ITracker() {}
- virtual void StartTracker( QFrame* frame ) = 0;
- virtual bool GiveHeadPoseData(double *data) = 0;
-
- virtual void WaitForExit() = 0;
-
- virtual void NotifyCenter() {}
-};
-
-typedef ITracker* ITrackerPtr;
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
-struct ITrackerDialog
-{
- virtual ~ITrackerDialog() {}
- virtual void Initialize(QWidget *parent) = 0;
- virtual void registerTracker(ITracker *tracker) = 0;
- virtual void unRegisterTracker() = 0;
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-// COM-Like abstract interface.
-// This interface doesn't require __declspec(dllexport/dllimport) specifier.
-// Method calls are dispatched via virtual table.
-// Any C++ compiler can use it.
-// Instances are obtained via factory function.
-struct ITrackerDll
-{
- virtual ~ITrackerDll() {}
- virtual void Initialize() = 0;
-
- virtual void getFullName(QString *strToBeFilled) = 0;
- virtual void getShortName(QString *strToBeFilled) = 0;
- virtual void getDescription(QString *strToBeFilled) = 0;
- virtual void getIcon(QIcon *icon) = 0;
-};
-
-
-#endif // FTNOIR_TRACKER_BASE_H
+/********************************************************************************
+* 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/>. *
+* This class implements a tracker-base *
+*********************************************************************************/
+#ifndef FTNOIR_TRACKER_BASE_H
+#define FTNOIR_TRACKER_BASE_H
+
+#include "ftnoir_tracker_base_global.h"
+#include "ftnoir_tracker_types.h"
+#include <QWidget>
+#include <QFrame>
+#include <QWaitCondition>
+#include <QMutex>
+#include <QFrame>
+
+////////////////////////////////////////////////////////////////////////////////
+// COM-Like abstract interface.
+// This interface doesn't require __declspec(dllexport/dllimport) specifier.
+// Method calls are dispatched via virtual table.
+// Any C++ compiler can use it.
+// Instances are obtained via factory function.
+struct ITracker
+{
+ virtual ~ITracker() = 0;
+ virtual void StartTracker( QFrame* frame ) = 0;
+ virtual void GetHeadPoseData(double *data) = 0;
+ virtual int preferredHz() { return 200; }
+};
+
+inline ITracker::~ITracker() { }
+
+////////////////////////////////////////////////////////////////////////////////
+// COM-Like abstract interface.
+// This interface doesn't require __declspec(dllexport/dllimport) specifier.
+// Method calls are dispatched via virtual table.
+// Any C++ compiler can use it.
+// Instances are obtained via factory function.
+struct ITrackerDialog
+{
+ virtual ~ITrackerDialog() {}
+ virtual void registerTracker(ITracker *tracker) = 0;
+ virtual void unRegisterTracker() = 0;
+};
+
+#endif // FTNOIR_TRACKER_BASE_H
diff --git a/ftnoir_tracker_base/ftnoir_tracker_base_global.h b/ftnoir_tracker_base/ftnoir_tracker_base_global.h
index a449c282..e717d845 100644
--- a/ftnoir_tracker_base/ftnoir_tracker_base_global.h
+++ b/ftnoir_tracker_base/ftnoir_tracker_base_global.h
@@ -1,12 +1,18 @@
-#ifndef FTNOIR_TRACKER_BASE_GLOBAL_H
-#define FTNOIR_TRACKER_BASE_GLOBAL_H
-
-#include <QtGlobal>
-
-#ifdef FTNOIR_TRACKER_BASE_LIB
-# define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_EXPORT
-#else
-# define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT
-#endif
-
-#endif // FTNOIR_TRACKER_BASE_GLOBAL_H
+#ifndef FTNOIR_TRACKER_BASE_GLOBAL_H
+#define FTNOIR_TRACKER_BASE_GLOBAL_H
+
+#include <QtGlobal>
+
+#ifndef FTNOIR_TRACKER_BASE_EXPORT
+# ifndef OPENTRACK_MAIN
+# if !defined(_MSC_VER)
+# define FTNOIR_TRACKER_BASE_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_EXPORT
+# endif
+# else
+# define FTNOIR_TRACKER_BASE_EXPORT Q_DECL_IMPORT
+# endif
+#endif
+
+#endif // FTNOIR_TRACKER_BASE_GLOBAL_H
diff --git a/ftnoir_tracker_base/ftnoir_tracker_ma_types.h b/ftnoir_tracker_base/ftnoir_tracker_ma_types.h
deleted file mode 100644
index b3101ad3..00000000
--- a/ftnoir_tracker_base/ftnoir_tracker_ma_types.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Definitions for the Shared Memory to send the data to FaceTrackNoIR
-//
-#define MA_MM_DATA "MA_SharedMem"
-#define MA_FACEAPI "MA_FaceAPI"
-#define MA_MUTEX "MA_Mutex"
-
-struct TFaceData {
- int DataID;
-// smEngineHeadPoseData new_pose;
-};
-typedef TFaceData * PFaceData;
-
-struct SMMemMap {
- int command; // Command from FaceTrackNoIR
- int status; // Status from faceAPI
- TFaceData data;
- HANDLE handle;
- int state;
- int par_val_int; // Value of parameter, indicated by 'command'
- int par_val_float;
- int initial_filter_level; // Internal faceAPI Filter level
- int handshake;
-};
-typedef SMMemMap * PSMMemMap;
-
-enum FTNoIR_Tracker_Command {
- FT_MA_START = 10,
- FT_MA_STOP = 20,
- FT_MA_SHOW_CAM = 30,
- FT_MA_SET_PAR_FILTER = 50,
- FT_MA_EXIT = 100
-};
diff --git a/ftnoir_tracker_base/ftnoir_tracker_sm_types.h b/ftnoir_tracker_base/ftnoir_tracker_sm_types.h
deleted file mode 100644
index 1faf893f..00000000
--- a/ftnoir_tracker_base/ftnoir_tracker_sm_types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Definitions for the Shared Memory to send the data to FaceTrackNoIR
-//
-#define SM_MM_DATA "SM_SharedMem"
-#define SM_FACEAPI "SM_FaceAPI"
-#define SM_MUTEX "SM_Mutex"
-
-#include "faceapi/stdafx.h"
-#include <sm_api.h>
-
-struct TFaceData {
- int DataID;
- smEngineHeadPoseData new_pose;
-};
-typedef TFaceData * PFaceData;
-
-struct SMMemMap {
- int command; // Command from FaceTrackNoIR
- int status; // Status from faceAPI
- TFaceData data;
- HANDLE handle;
- int state;
- int par_val_int; // Value of parameter, indicated by 'command'
- int par_val_float;
- int initial_filter_level; // Internal faceAPI Filter level
- int handshake;
-};
-typedef SMMemMap * PSMMemMap;
-
-enum FTNoIR_Tracker_Command {
- FT_SM_START = 10,
- FT_SM_STOP = 20,
- FT_SM_SHOW_CAM = 30,
- FT_SM_SET_PAR_FILTER = 50,
- FT_SM_EXIT = 100
-};
diff --git a/ftnoir_tracker_base/ftnoir_tracker_types.h b/ftnoir_tracker_base/ftnoir_tracker_types.h
index 8bf12990..d38baee4 100644
--- a/ftnoir_tracker_base/ftnoir_tracker_types.h
+++ b/ftnoir_tracker_base/ftnoir_tracker_types.h
@@ -1,37 +1,4 @@
-/********************************************************************************
-* 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/>. *
-* This class implements a tracker-base *
-*********************************************************************************/
-/*
- Modifications (last one on top):
- 20120924 - C14: Moved T6DOF to separate file (not pulic interface)
- 20110415 - WVR: Added overloaded operator - and -=
-*/
-#ifndef FTNOIR_TRACKER_TYPES_H
-#define FTNOIR_TRACKER_TYPES_H
-
-
-enum Axis {
- TX = 0, TY, TZ, Yaw, Pitch, Roll};
-
-#endif // FTNOIR_TRACKER_TYPES_H
+#pragma once
+enum Axis {
+ TX = 0, TY, TZ, Yaw, Pitch, Roll
+};
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
index b755010c..76a6ba71 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.cpp
@@ -7,7 +7,7 @@
#include "facetracknoir/global-settings.h"
#include <cmath>
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
#include <dshow.h>
#else
#include <unistd.h>
@@ -16,7 +16,7 @@
// delicious copypasta
static QList<QString> get_camera_names(void) {
QList<QString> ret;
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
@@ -62,14 +62,14 @@ static QList<QString> get_camera_names(void) {
pEnumCat->Release();
}
pSysDevEnum->Release();
-#else
+#elif !defined(__APPLE__)
for (int i = 0; i < 16; i++) {
char buf[128];
sprintf(buf, "/dev/video%d", i);
if (access(buf, R_OK | W_OK) == 0) {
ret.append(buf);
} else {
- break;
+ continue;
}
}
#endif
@@ -88,67 +88,71 @@ static resolution_tuple resolution_choices[] = {
{ 0, 0 }
};
-static void load_settings(ht_config_t* config, Tracker* tracker)
+void Tracker::load_settings(ht_config_t* config)
{
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
+ int nframes = 0;
+ switch (static_cast<int>(s.fps))
+ {
+ default:
+ case 0:
+ nframes = 0;
+ break;
+ case 1:
+ nframes = 30;
+ break;
+ case 2:
+ nframes = 60;
+ break;
+ case 3:
+ nframes = 120;
+ break;
+ case 4:
+ nframes = 180;
+ break;
+ }
- iniFile.beginGroup( "HT-Tracker" );
config->classification_delay = 500;
- config->field_of_view = iniFile.value("fov", 52).toFloat();
- config->pyrlk_pyramids = 3;
+ config->field_of_view = s.fov;
+ config->pyrlk_pyramids = 0;
config->pyrlk_win_size_w = config->pyrlk_win_size_h = 21;
- config->max_keypoints = 200;
- config->keypoint_distance = 4.5;
- //config->force_width = 640;
- //config->force_height = 480;
- config->force_fps = iniFile.value("fps", 0).toInt();
- config->camera_index = iniFile.value("camera-index", -1).toInt();
+ config->max_keypoints = 150;
+ config->keypoint_distance = 6;
+ config->force_fps = nframes;
+ config->camera_index = s.camera_idx - 1;
config->ransac_num_iters = 100;
- config->ransac_max_reprojection_error = 6.5;
- config->ransac_max_inlier_error = 6.5;
- config->ransac_abs_max_mean_error = 15;
- config->ransac_max_mean_error = 4.5;
+ config->ransac_max_reprojection_error = 10;
+ config->ransac_max_inlier_error = 10;
+ config->ransac_abs_max_mean_error = 14;
+ config->ransac_max_mean_error = 8;
config->debug = 0;
- config->ransac_min_features = 0.8;
- int res = iniFile.value("resolution", 0).toInt();
+ config->ransac_min_features = 0.86;
+ int res = s.resolution;
if (res < 0 || res >= (int)(sizeof(resolution_choices) / sizeof(resolution_tuple)))
res = 0;
resolution_tuple r = resolution_choices[res];
config->force_width = r.width;
config->force_height = r.height;
- config->flandmark_delay = 200;
- qDebug() << "width" << r.width << "height" << r.height;
- if (tracker)
- {
- tracker->enableRX = iniFile.value("enable-rx", true).toBool();
- tracker->enableRY = iniFile.value("enable-ry", true).toBool();
- tracker->enableRZ = iniFile.value("enable-rz", true).toBool();
- tracker->enableTX = iniFile.value("enable-tx", true).toBool();
- tracker->enableTY = iniFile.value("enable-ty", true).toBool();
- tracker->enableTZ = iniFile.value("enable-tz", true).toBool();
- }
-
+ config->flandmark_delay = 500;
for (int i = 0; i < 5; i++)
- config->dist_coeffs[i] = iniFile.value(QString("dc%1").arg(i), 0).toDouble();
-
- iniFile.endGroup();
+ config->dist_coeffs[i] = 0;
}
-Tracker::Tracker() : lck_shm(HT_SHM_NAME, HT_MUTEX_NAME, sizeof(ht_shm_t)), fresh(false)
+Tracker::Tracker() :
+ lck_shm(HT_SHM_NAME, HT_MUTEX_NAME, sizeof(ht_shm_t)),
+ shm(reinterpret_cast<ht_shm_t*>(lck_shm.mem)),
+ videoWidget(nullptr),
+ layout(nullptr)
{
- videoWidget = NULL;
- layout = NULL;
- enableRX = enableRY = enableRZ = enableTX = enableTY = enableTZ = true;
- shm = (ht_shm_t*) lck_shm.mem;
shm->terminate = 0;
- load_settings(&shm->config, this);
shm->result.filled = false;
}
Tracker::~Tracker()
{
+ if (shm) {
+ shm->terminate = true;
+ subprocess.waitForFinished(5000);
+ }
subprocess.kill();
if (shm)
shm->terminate = true;
@@ -161,7 +165,7 @@ Tracker::~Tracker()
void Tracker::StartTracker(QFrame* videoframe)
{
videoframe->show();
- videoWidget = new VideoWidget(videoframe);
+ videoWidget = new HTVideoWidget(videoframe);
QHBoxLayout* layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(videoWidget);
@@ -170,60 +174,51 @@ void Tracker::StartTracker(QFrame* videoframe)
videoframe->setLayout(layout);
videoWidget->show();
this->layout = layout;
- load_settings(&shm->config, this);
+ load_settings(&shm->config);
shm->frame.channels = shm->frame.width = shm->frame.height = 0;
shm->pause = shm->terminate = shm->running = false;
shm->timer = 0;
subprocess.setWorkingDirectory(QCoreApplication::applicationDirPath() + "/tracker-ht");
-#if defined(_WIN32) || defined(__WIN32)
+#if defined(_WIN32)
subprocess.start("\"" + QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir" + "\"");
#else
subprocess.start(QCoreApplication::applicationDirPath() + "/tracker-ht/headtracker-ftnoir");
#endif
- connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()));
- timer.start(40);
}
-void Tracker::paint_widget() {
- if (fresh) {
- fresh = false;
- videoWidget->update();
- }
-}
-
-bool Tracker::GiveHeadPoseData(double *data)
+void Tracker::GetHeadPoseData(double *data)
{
- bool ret = false;
-
lck_shm.lock();
shm->timer = 0;
if (shm->frame.width > 0)
{
videoWidget->update_image(shm->frame.frame, shm->frame.width, shm->frame.height);
//memcpy(foo, shm->frame.frame, shm->frame.width * shm->frame.height * 3);
- fresh = true;
shm->frame.width = 0;
}
if (shm->result.filled) {
- if (enableRX)
+ if (s.enableRX)
data[Yaw] = shm->result.rotx;
- if (enableRY) {
+ if (s.enableRY) {
data[Pitch] = shm->result.roty;
}
- if (enableRZ) {
+ if (s.enableRZ) {
data[Roll] = shm->result.rotz;
}
- if (enableTX)
+ if (s.enableTX)
data[TX] = shm->result.tx;
- if (enableTY)
+ if (s.enableTY)
data[TY] = shm->result.ty;
- if (enableTZ)
+ if (s.enableTZ)
data[TZ] = shm->result.tz;
- ret = true;
+ if (fabs(data[Yaw]) > 60 || fabs(data[Pitch]) > 50 || fabs(data[Roll]) > 40)
+ {
+ shm->pause = true;
+ }
+ } else {
+ shm->pause = false;
}
lck_shm.unlock();
-
- return ret;
}
//-----------------------------------------------------------------------------
@@ -247,31 +242,16 @@ void TrackerDll::getIcon(QIcon *icon)
*icon = QIcon(":/images/ht.png");
}
-
-//-----------------------------------------------------------------------------
-//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
{
return new TrackerDll;
}
-//#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
{
return new Tracker;
}
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
{
return new TrackerControls;
@@ -280,162 +260,32 @@ extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDial
TrackerControls::TrackerControls()
{
ui.setupUi(this);
- setAttribute(Qt::WA_NativeWindow, true);
- connect(ui.cameraName, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.cameraFPS, SIGNAL(currentIndexChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.cameraFOV, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(double)));
- connect(ui.rx, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.ry, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.rz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.tx, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.ty, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.tz, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.buttonOK, SIGNAL(clicked()), this, SLOT(doOK()));
- //connect(ui.buttonSettings, SIGNAL(clicked()), this, SLOT(cameraSettings()));
- loadSettings();
- settingsDirty = false;
-}
-
-TrackerControls::~TrackerControls()
-{
-}
-
-void TrackerControls::showEvent(QShowEvent *event)
-{
-}
-
-void TrackerControls::Initialize(QWidget* parent)
-{
- loadSettings();
- show();
-}
-
-void TrackerControls::loadSettings()
-{
- ui.cameraName->clear();
- QList<QString> names = get_camera_names();
- names.prepend("Any available");
- ui.cameraName->addItems(names);
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
- iniFile.beginGroup( "HT-Tracker" );
- ui.cameraName->setCurrentIndex(iniFile.value("camera-index", -1).toInt() + 1);
- ui.cameraFOV->setValue(iniFile.value("fov", 52).toFloat());
- int fps;
- switch (iniFile.value("fps", 0).toInt())
- {
- default:
- case 0:
- fps = 0;
- break;
- case 30:
- fps = 1;
- break;
- case 60:
- fps = 2;
- break;
- case 120:
- fps = 3;
- break;
- }
- ui.cameraFPS->setCurrentIndex(fps);
- ui.rx->setCheckState(iniFile.value("enable-rx", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.ry->setCheckState(iniFile.value("enable-ry", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.rz->setCheckState(iniFile.value("enable-rz", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.tx->setCheckState(iniFile.value("enable-tx", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.ty->setCheckState(iniFile.value("enable-ty", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.tz->setCheckState(iniFile.value("enable-tz", true).toBool() ? Qt::Checked : Qt::Unchecked);
- ui.resolution->setCurrentIndex(iniFile.value("resolution", 0).toInt());
-
- ui.doubleSpinBox->setValue(iniFile.value("dc0").toDouble());
- ui.doubleSpinBox_2->setValue(iniFile.value("dc1").toDouble());
- ui.doubleSpinBox_3->setValue(iniFile.value("dc2").toDouble());
- ui.doubleSpinBox_4->setValue(iniFile.value("dc3").toDouble());
- ui.doubleSpinBox_5->setValue(iniFile.value("dc4").toDouble());
-
- iniFile.endGroup();
- settingsDirty = false;
-}
-
-void TrackerControls::save()
-{
- QSettings settings("opentrack");
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
-
- iniFile.beginGroup( "HT-Tracker" );
- iniFile.setValue("fov", ui.cameraFOV->value());
- int fps;
- switch (ui.cameraFPS->currentIndex())
- {
- case 0:
- default:
- fps = 0;
- break;
- case 1:
- fps = 30;
- break;
- case 2:
- fps = 60;
- break;
- case 3:
- fps = 120;
- break;
- }
- iniFile.setValue("fps", fps);
- iniFile.setValue("camera-index", ui.cameraName->currentIndex() - 1);
- iniFile.setValue("enable-rx", ui.rx->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-ry", ui.ry->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-rz", ui.rz->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-tx", ui.tx->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-ty", ui.ty->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("enable-tz", ui.tz->checkState() != Qt::Unchecked ? true : false);
- iniFile.setValue("resolution", ui.resolution->currentIndex());
-
- iniFile.setValue("dc0", ui.doubleSpinBox->value());
- iniFile.setValue("dc1", ui.doubleSpinBox_2->value());
- iniFile.setValue("dc2", ui.doubleSpinBox_3->value());
- iniFile.setValue("dc3", ui.doubleSpinBox_4->value());
- iniFile.setValue("dc4", ui.doubleSpinBox_5->value());
-
- iniFile.endGroup();
- settingsDirty = false;
+ ui.cameraName->clear();
+ QList<QString> names = get_camera_names();
+ names.prepend("Any available");
+ ui.cameraName->addItems(names);
+ tie_setting(s.camera_idx, ui.cameraName);
+ tie_setting(s.fps, ui.cameraFPS);
+ tie_setting(s.fov, ui.cameraFOV);
+ tie_setting(s.enableTX, ui.tx);
+ tie_setting(s.enableTY, ui.ty);
+ tie_setting(s.enableTZ, ui.tz);
+ tie_setting(s.enableRX, ui.rx);
+ tie_setting(s.enableRY, ui.ry);
+ tie_setting(s.enableRZ, ui.rz);
+ tie_setting(s.resolution, ui.resolution);
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
}
void TrackerControls::doOK()
{
- save();
+ s.b->save();
this->close();
}
void TrackerControls::doCancel()
{
- 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:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
+ s.b->revert();
+ this->close();
}
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht.h b/ftnoir_tracker_ht/ftnoir_tracker_ht.h
index fcdea140..583249dc 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht.h
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht.h
@@ -12,40 +12,48 @@
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "headtracker-ftnoir.h"
#include "ui_ht-trackercontrols.h"
-#include "video_widget.h"
+#include "ht_video_widget.h"
#include "compat/compat.h"
#include <QObject>
-#include <QTimer>
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<bool> enableTX, enableTY, enableTZ, enableRX, enableRY, enableRZ;
+ value<double> fov;
+ value<int> fps, camera_idx, resolution;
+ settings() :
+ b(bundle("HT-Tracker")),
+ enableTX(b, "enable-tx", true),
+ enableTY(b, "enable-ty", true),
+ enableTZ(b, "enable-tz", true),
+ enableRX(b, "enable-rx", true),
+ enableRY(b, "enable-ry", true),
+ enableRZ(b, "enable-rz", true),
+ fov(b, "fov", 56),
+ fps(b, "fps", 0),
+ camera_idx(b, "camera-index", 0),
+ resolution(b, "resolution", 0)
+ {}
+};
class Tracker : public QObject, public ITracker
{
Q_OBJECT
public:
Tracker();
- ~Tracker();
+ virtual ~Tracker();
void StartTracker(QFrame* frame);
- bool GiveHeadPoseData(double *data);
- bool enableTX, enableTY, enableTZ, enableRX, enableRY, enableRZ;
- ht_shm_t* shm;
- bool NeedsTimeToFinish() {
- return true;
- }
- void WaitForExit() {
- if (shm) {
- shm->terminate = true;
- subprocess.waitForFinished(5000);
- }
- subprocess.kill();
- }
+ void GetHeadPoseData(double *data);
+ void load_settings(ht_config_t* config);
private:
- QTimer timer;
+ settings s;
PortableLockedShm lck_shm;
+ ht_shm_t* shm;
QProcess subprocess;
- VideoWidget* videoWidget;
+ HTVideoWidget* videoWidget;
QHBoxLayout* layout;
- volatile bool fresh;
-private slots:
- void paint_widget();
};
// Widget that has controls for FTNoIR protocol client-settings.
@@ -53,27 +61,17 @@ class TrackerControls : public QWidget, public ITrackerDialog
{
Q_OBJECT
public:
-
explicit TrackerControls();
- virtual ~TrackerControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {}
+ void registerTracker(ITracker *) {}
void unRegisterTracker() {}
private:
Ui::Form ui;
- void loadSettings();
- void save();
- bool settingsDirty;
+ settings s;
private slots:
void doOK();
void doCancel();
- void settingChanged() { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
- void settingChanged(double) { settingsDirty = true; }
};
#endif
diff --git a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h
index 1e53f802..ffdc5262 100644
--- a/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h
+++ b/ftnoir_tracker_ht/ftnoir_tracker_ht_dll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 Stanis³aw Halik <sthalik@misaki.pl>
+/* Copyright (c) 2013 Stanisław Halik <sthalik@misaki.pl>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -12,7 +12,6 @@
class TrackerDll : public Metadata
{
// ITrackerDll interface
- void Initialize() {}
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
void getDescription(QString *strToBeFilled);
diff --git a/ftnoir_tracker_ht/ht-api.h b/ftnoir_tracker_ht/ht-api.h
index e6960206..2ab2e840 100644
--- a/ftnoir_tracker_ht/ht-api.h
+++ b/ftnoir_tracker_ht/ht-api.h
@@ -1,38 +1,33 @@
#pragma once
#ifndef HT_API
-#ifndef __cplusplus
-# define HT_EXTERN
-#else
-# define HT_EXTERN extern "C"
-#endif
# if defined(_WIN32) && !defined(MINGW)
-# define HT_API(t) HT_EXTERN __declspec(dllexport) t __stdcall
+# define HT_API(t) __declspec(dllexport) t __stdcall
# else
-# define HT_API(t) HT_EXTERN t
+# define HT_API(t) t
# endif
#endif
#if !defined(_WIN32) && !defined(_isnan)
# define _isnan isnan
#endif
-#include <stdio.h>
+#include <opencv2/core/core.hpp>
struct ht_context;
typedef struct ht_context headtracker_t;
typedef struct ht_config {
- float field_of_view;
- float classification_delay;
- int pyrlk_pyramids;
- int pyrlk_win_size_w;
- int pyrlk_win_size_h;
+ float field_of_view;
+ float classification_delay;
+ int pyrlk_pyramids;
+ int pyrlk_win_size_w;
+ int pyrlk_win_size_h;
float ransac_max_inlier_error;
float ransac_max_reprojection_error;
- int max_keypoints;
- float keypoint_distance;
+ int max_keypoints;
+ float keypoint_distance;
int force_width;
- int force_height;
- int force_fps;
- int camera_index;
- bool debug;
+ int force_height;
+ int force_fps;
+ int camera_index;
+ bool debug;
int ransac_num_iters;
float ransac_min_features;
float ransac_max_mean_error;
@@ -44,42 +39,11 @@ typedef struct ht_config {
typedef struct {
double rotx, roty, rotz;
double tx, ty, tz;
- bool filled;
+ bool filled;
} ht_result_t;
-typedef enum {
- cfg_type_float = 0,
- cfg_type_int = 1,
- cfg_type_bool = 2,
- cfg_type_double = 3
-} ht_cfg_type_t;
-
-typedef union
-{
- double d;
- float f;
- int i;
-} ht_cfg_value_t;
-
-typedef struct {
- const char* name;
- int offset;
- ht_cfg_type_t type;
- ht_cfg_value_t default_value;
- ht_cfg_value_t min;
- ht_cfg_value_t max;
- const char* docstring;
-} ht_reflection_t;
-
-typedef struct {
- int rows, cols, channels;
- unsigned char* data;
-} ht_frame_t;
-
HT_API(headtracker_t*) ht_make_context(const ht_config_t* config, const char* filename);
-HT_API(void) ht_load_config(FILE* stream, ht_config_t* cfg);
HT_API(void) ht_free_context(headtracker_t* ctx);
-HT_API(void) ht_get_bgr_frame(headtracker_t* ctx, ht_frame_t* ret);
-HT_API(void) ht_make_config(ht_config_t* cfg);
+HT_API(const cv::Mat) ht_get_bgr_frame(headtracker_t* ctx);
HT_API(bool) ht_cycle(headtracker_t* ctx, ht_result_t* euler);
HT_API(void) ht_reset(headtracker_t* ctx);
diff --git a/ftnoir_tracker_ht/ht-trackercontrols.ui b/ftnoir_tracker_ht/ht-trackercontrols.ui
index fbe7a41a..f57022c8 100644
--- a/ftnoir_tracker_ht/ht-trackercontrols.ui
+++ b/ftnoir_tracker_ht/ht-trackercontrols.ui
@@ -9,8 +9,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>593</width>
- <height>280</height>
+ <width>531</width>
+ <height>166</height>
</rect>
</property>
<property name="sizePolicy">
@@ -28,420 +28,200 @@
<property name="windowTitle">
<string>HT tracker settings</string>
</property>
- <widget class="QLabel" name="label">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>141</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Horizontal FOV</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="cameraFOV">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>10</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <property name="locale">
- <locale language="English" country="UnitedStates"/>
- </property>
- <property name="minimum">
- <double>35.000000000000000</double>
- </property>
- <property name="maximum">
- <double>180.000000000000000</double>
- </property>
- <property name="value">
- <double>52.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_2">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>137</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Frames per second</string>
- </property>
- </widget>
- <widget class="QComboBox" name="cameraFPS">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>40</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string notr="true">Default</string>
- </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QDoubleSpinBox" name="cameraFOV">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <property name="minimum">
+ <double>35.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>52.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Horizontal FOV</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" rowspan="3">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Enable axes</string>
+ </property>
+ <widget class="QCheckBox" name="rx">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>70</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>RX</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="ry">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>70</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>RY</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="rz">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>60</y>
+ <width>70</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>RZ</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="tx">
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>20</y>
+ <width>70</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>TX</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="ty">
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>40</y>
+ <width>70</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>TY</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" name="tz">
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>60</y>
+ <width>70</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>TZ</string>
+ </property>
+ </widget>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>30</string>
- </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Frames per second</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>60</string>
- </property>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="cameraFPS">
+ <item>
+ <property name="text">
+ <string notr="true">Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>30</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>60</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>120</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>180</string>
+ </property>
+ </item>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>120</string>
- </property>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Camera name</string>
+ </property>
+ </widget>
</item>
- </widget>
- <widget class="QLabel" name="label_3">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>70</y>
- <width>133</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Camera name</string>
- </property>
- </widget>
- <widget class="QPushButton" name="buttonOK">
- <property name="geometry">
- <rect>
- <x>430</x>
- <y>250</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QPushButton" name="buttonCancel">
- <property name="geometry">
- <rect>
- <x>510</x>
- <y>250</y>
- <width>75</width>
- <height>23</height>
- </rect>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- <widget class="QGroupBox" name="groupBox">
- <property name="geometry">
- <rect>
- <x>390</x>
- <y>10</y>
- <width>101</width>
- <height>81</height>
- </rect>
- </property>
- <property name="title">
- <string>Enable axes</string>
- </property>
- <widget class="QCheckBox" name="rx">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RX</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="ry">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>40</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RY</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="rz">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>60</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>RZ</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="tx">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>20</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TX</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="ty">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>40</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TY</string>
- </property>
- </widget>
- <widget class="QCheckBox" name="tz">
- <property name="geometry">
- <rect>
- <x>60</x>
- <y>60</y>
- <width>70</width>
- <height>17</height>
- </rect>
- </property>
- <property name="text">
- <string>TZ</string>
- </property>
- </widget>
- </widget>
- <widget class="QComboBox" name="cameraName">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>70</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- </widget>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>100</y>
- <width>128</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Resolution</string>
- </property>
- </widget>
- <widget class="QComboBox" name="resolution">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>100</y>
- <width>251</width>
- <height>22</height>
- </rect>
- </property>
- <item>
- <property name="text">
- <string>640x480</string>
- </property>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="cameraName"/>
</item>
- <item>
- <property name="text">
- <string>320x240</string>
- </property>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Resolution</string>
+ </property>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>320x200</string>
- </property>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="resolution">
+ <item>
+ <property name="text">
+ <string>640x480</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>320x240</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>320x200</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Default (not recommended!)</string>
+ </property>
+ </item>
+ </widget>
</item>
- <item>
- <property name="text">
- <string>Default (not recommended!)</string>
- </property>
+ <item row="4" column="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
</item>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>130</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QLabel" name="label_5">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>130</y>
- <width>111</width>
- <height>16</height>
- </rect>
- </property>
- <property name="text">
- <string>Distortion coefficients</string>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_2">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>160</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_3">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>190</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_4">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>220</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
- <widget class="QDoubleSpinBox" name="doubleSpinBox_5">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>250</y>
- <width>171</width>
- <height>22</height>
- </rect>
- </property>
- <property name="frame">
- <bool>true</bool>
- </property>
- <property name="buttonSymbols">
- <enum>QAbstractSpinBox::NoButtons</enum>
- </property>
- <property name="decimals">
- <number>24</number>
- </property>
- <property name="minimum">
- <double>-1000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.000000000000000</double>
- </property>
- </widget>
+ </layout>
</widget>
<resources/>
<connections/>
diff --git a/ftnoir_tracker_ht/ht_video_widget.cpp b/ftnoir_tracker_ht/ht_video_widget.cpp
new file mode 100644
index 00000000..c6d59b34
--- /dev/null
+++ b/ftnoir_tracker_ht/ht_video_widget.cpp
@@ -0,0 +1,44 @@
+/* Copyright (c) 2012 Patrick Ruoff
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#include "ht_video_widget.h"
+
+#include <QDebug>
+
+using namespace std;
+
+void HTVideoWidget::update_image(unsigned char *frame, int width, int height)
+{
+ QMutexLocker foo(&mtx);
+ memcpy(fb, frame, width * height * 3);
+ this->width = width;
+ this->height = height;
+}
+
+void HTVideoWidget::update_and_repaint()
+{
+ QMutexLocker foo(&mtx);
+ if (width*height <= 0)
+ return;
+ QImage qframe = QImage(width, height, QImage::Format_RGB888);
+ uchar* data = qframe.bits();
+ const int pitch = qframe.bytesPerLine();
+ for (int y = 0; y < height; y++)
+ {
+ const int part = y*width;
+ for (int x = 0; x < width; x++)
+ {
+ const int pos = 3 * (part + x);
+ data[y * pitch + x * 3 + 0] = fb[pos + 2];
+ data[y * pitch + x * 3 + 1] = fb[pos + 1];
+ data[y * pitch + x * 3 + 2] = fb[pos + 0];
+ }
+ }
+ auto qframe2 = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
+ texture = qframe2;
+ update();
+}
diff --git a/ftnoir_tracker_ht/video_widget.h b/ftnoir_tracker_ht/ht_video_widget.h
index 87b6278a..cbfe6ddc 100644
--- a/ftnoir_tracker_ht/video_widget.h
+++ b/ftnoir_tracker_ht/ht_video_widget.h
@@ -15,25 +15,33 @@
#include <QLabel>
#include <QPainter>
#include <QPaintEvent>
+#include <QTimer>
// ----------------------------------------------------------------------------
-class VideoWidget : public QWidget
+class HTVideoWidget : public QWidget
{
- Q_OBJECT
+ Q_OBJECT
public:
- VideoWidget(QWidget *parent) : QWidget(parent), mtx() {
- }
+ HTVideoWidget(QWidget *parent) : QWidget(parent), fb(), width(0), height(0) {
+ connect(&timer, SIGNAL(timeout()), this, SLOT(update_and_repaint()));
+ timer.start(60);
+ }
void update_image(unsigned char* frame, int width, int height);
protected slots:
void paintEvent( QPaintEvent* e ) {
QMutexLocker foo(&mtx);
QPainter painter(this);
- painter.drawPixmap(e->rect(), pixmap, e->rect());
+ painter.drawImage(e->rect(), texture);
}
+ void update_and_repaint();
+
private:
QMutex mtx;
- QPixmap pixmap;
+ QImage texture;
+ QTimer timer;
+ char fb[2048*2048*3];
+ int width,height;
};
#endif // VIDEOWIDGET_H
diff --git a/ftnoir_tracker_ht/stdafx.h b/ftnoir_tracker_ht/stdafx.h
index 0e532c9f..6f1539b7 100644
--- a/ftnoir_tracker_ht/stdafx.h
+++ b/ftnoir_tracker_ht/stdafx.h
@@ -4,7 +4,6 @@
#include <QImage>
#include <QLabel>
#include <QCoreApplication>
-#include <QSettings>
#include <QIcon>
#include <QHBoxLayout>
#include <QTimer>
diff --git a/ftnoir_tracker_ht/video_widget.cpp b/ftnoir_tracker_ht/video_widget.cpp
deleted file mode 100644
index 84cba6a3..00000000
--- a/ftnoir_tracker_ht/video_widget.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "video_widget.h"
-
-#include <QDebug>
-
-using namespace std;
-
-void VideoWidget::update_image(unsigned char *frame, int width, int height)
-{
- QMutexLocker foo(&mtx);
- QImage qframe = QImage(width, height, QImage::Format_RGB888);
- uchar* data = qframe.bits();
- const int pitch = qframe.bytesPerLine();
- for (int y = 0; y < height; y++)
- for (int x = 0; x < width; x++)
- {
- const int pos = 3 * (y*width + x);
- data[y * pitch + x * 3 + 0] = frame[pos + 2];
- data[y * pitch + x * 3 + 1] = frame[pos + 1];
- data[y * pitch + x * 3 + 2] = frame[pos + 0];
- }
- qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
- pixmap = QPixmap::fromImage(qframe);
-}
diff --git a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui
index 0cee05f0..e5e41bec 100644
--- a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui
+++ b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui
@@ -2,12 +2,15 @@
<ui version="4.0">
<class>UIHydraControls</class>
<widget class="QWidget" name="UIHydraControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>411</width>
- <height>142</height>
+ <width>172</width>
+ <height>145</height>
</rect>
</property>
<property name="windowTitle">
@@ -23,7 +26,7 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="minimumSize">
@@ -35,333 +38,163 @@
<property name="title">
<string>Enable Axis</string>
</property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>143</width>
- <height>60</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
-
-
-
-
-
-
-
-
- <item row="0" column="0">
- <widget class="QLabel" name="label_61">
- <property name="text">
- <string>Pitch:</string>
- </property>
- </widget>
- </item>
-
- <item row="0" column="1">
- <widget class="QCheckBox" name="chkEnablePitch">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </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="0">
- <widget class="QLabel" name="label_91">
- <property name="text">
- <string>Yaw:</string>
- </property>
- </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="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
-
-
-
- <item row="2" column="0">
- <widget class="QLabel" name="label_111">
- <property name="text">
- <string>Roll:</string>
- </property>
- </widget>
- </item>
-
- <item row="2" column="1">
- <widget class="QCheckBox" name="chkEnableRoll">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <item row="0" column="2">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>X:</string>
- </property>
- </widget>
- </item>
-
- <item row="0" column="3">
- <widget class="QCheckBox" name="chkEnableX">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </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="QLabel" name="label_9">
- <property name="text">
- <string>Y:</string>
- </property>
- </widget>
- </item>
-
-
- <item row="1" column="3">
- <widget class="QCheckBox" name="chkEnableY">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
-
-
-
- <item row="2" column="2">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Z:</string>
- </property>
- </widget>
- </item>
-
- <item row="2" column="3">
- <widget class="QCheckBox" name="chkEnableZ">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- </layout>
- </widget>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_61">
+ <property name="text">
+ <string>Pitch:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="chkEnablePitch">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </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="0" column="2">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>X:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QCheckBox" name="chkEnableX">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </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="0">
+ <widget class="QLabel" name="label_91">
+ <property name="text">
+ <string>Yaw:</string>
+ </property>
+ </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="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Y:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QCheckBox" name="chkEnableY">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </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_111">
+ <property name="text">
+ <string>Roll:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="chkEnableRoll">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>Z:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QCheckBox" name="chkEnableZ">
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
<item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ </widget>
</item>
</layout>
</widget>
- <tabstops>
- <tabstop>btnOK</tabstop>
- <tabstop>btnCancel</tabstop>
- </tabstops>
<resources/>
<connections/>
<slots>
diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp
index 3789c7bf..70af2893 100644
--- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp
+++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp
@@ -3,27 +3,15 @@
#include "facetracknoir/global-settings.h"
#include "facetracknoir/rotation.h"
#include <cstdio>
-#define SIXENSE_STATIC_LIB
-#define SIXENSE_UTILS_STATIC_LIB
+#ifdef _WIN32
+# define SIXENSE_STATIC_LIB
+# define SIXENSE_UTILS_STATIC_LIB
+#endif
#include <sixense.h>
#include <sixense_math.hpp>
-#ifdef WIN32
-#include <sixense_utils/mouse_pointer.hpp>
-#endif
-#include <sixense_utils/derivatives.hpp>
-#include <sixense_utils/button_states.hpp>
-#include <sixense_utils/event_triggers.hpp>
-#include <sixense_utils/controller_manager/controller_manager.hpp>
-Hydra_Tracker::Hydra_Tracker()
+Hydra_Tracker::Hydra_Tracker() : should_quit(false)
{
- bEnableRoll = true;
- bEnablePitch = true;
- bEnableYaw = true;
- bEnableX = true;
- bEnableY = true;
- bEnableZ = true;
- should_quit = false;
for (int i = 0; i < 6; i++)
newHeadPose[i] = 0;
}
@@ -34,52 +22,19 @@ Hydra_Tracker::~Hydra_Tracker()
sixenseExit();
}
-/*
-void controller_manager_setup_callback( sixenseUtils::ControllerManager::setup_step step ) {
-
- QMessageBox::warning(0,"OpenTrack Info", "controller manager callback",QMessageBox::Ok,QMessageBox::NoButton);
- if( sixenseUtils::getTheControllerManager()->isMenuVisible() ) {
- // Ask the controller manager what the next instruction string should be.
- std::string controller_manager_text_string = sixenseUtils::getTheControllerManager()->getStepString();
- QMessageBox::warning(0,"OpenTrack Info", controller_manager_text_string.c_str(),QMessageBox::Ok,QMessageBox::NoButton);
- // We could also load the supplied controllermanager textures using the filename: sixenseUtils::getTheControllerManager()->getTextureFileName();
-
- }
-}*/
-
-void Hydra_Tracker::StartTracker(QFrame* videoFrame)
+void Hydra_Tracker::StartTracker(QFrame*)
{
- //QMessageBox::warning(0,"FaceTrackNoIR Notification", "Tracking loading settings...",QMessageBox::Ok,QMessageBox::NoButton);
- loadSettings();
-
- // Init sixense
- //QMessageBox::warning(0,"OpenTrack Info", "sixense init",QMessageBox::Ok,QMessageBox::NoButton);
sixenseInit();
- //QMessageBox::warning(0,"OpenTrack Info", "sixense init complete, setting controller manager",QMessageBox::Ok,QMessageBox::NoButton);
- // Init the controller manager. This makes sure the controllers are present, assigned to left and right hands, and that
- // the hemisphere calibration is complete.
- //sixenseUtils::getTheControllerManager()->setGameType( sixenseUtils::ControllerManager::ONE_PLAYER_TWO_CONTROLLER );
- //sixenseUtils::getTheControllerManager()->registerSetupCallback( controller_manager_setup_callback );
- //QMessageBox::warning(0,"OpenTrack Info", "controller manager callback registered",QMessageBox::Ok,QMessageBox::NoButton);
- return;
}
-
-bool Hydra_Tracker::GiveHeadPoseData(double *data)
+void Hydra_Tracker::GetHeadPoseData(double *data)
{
sixenseSetActiveBase(0);
sixenseAllControllerData acd;
sixenseGetAllNewestData( &acd );
- //sixenseUtils::getTheControllerManager()->update( &acd );
-
- //sixenseControllerData cd;
- //Rotation quat = Rotation(acd.controllers[0].rot_quat[1],acd.controllers[0].rot_quat[2],acd.controllers[0].rot_quat[3],acd.controllers[0].rot_quat[0]);
- sixenseMath::Matrix4 mat = sixenseMath::Matrix4(acd.controllers[0].rot_mat);// sixenseMath::Quat(acd.controllers[0].rot_quat[1],acd.controllers[0].rot_quat[2],acd.controllers[0].rot_quat[3],acd.controllers[0].rot_quat[0]);
+ sixenseMath::Matrix4 mat = sixenseMath::Matrix4(acd.controllers[0].rot_mat);
- double yaw = 0.0f;
- double pitch = 0.0f;
- double roll = 0.0f;
float ypr[3];
mat.getEulerAngles().fill(ypr);
@@ -92,64 +47,26 @@ bool Hydra_Tracker::GiveHeadPoseData(double *data)
newHeadPose[TY] = acd.controllers[0].pos[1]/50.0f;
newHeadPose[TZ] = acd.controllers[0].pos[2]/50.0f;
- if (bEnableX) {
+ if (s.bEnableX) {
data[TX] = newHeadPose[TX];
}
- if (bEnableY) {
+ if (s.bEnableY) {
data[TY] = newHeadPose[TY];
}
- if (bEnableY) {
+ if (s.bEnableY) {
data[TZ] = newHeadPose[TZ];
}
-
- if (bEnableYaw) {
+ if (s.bEnableYaw) {
data[Yaw] = newHeadPose[Yaw] * 57.295781f;
}
- if (bEnablePitch) {
+ if (s.bEnablePitch) {
data[Pitch] = newHeadPose[Pitch] * 57.295781f;
}
- if (bEnableRoll) {
+ if (s.bEnableRoll) {
data[Roll] = newHeadPose[Roll] * 57.295781f;
}
-
- return true;
}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void Hydra_Tracker::loadSettings() {
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Hydra" );
- bEnableRoll = iniFile.value ( "EnableRoll", 1 ).toBool();
- bEnablePitch = iniFile.value ( "EnablePitch", 1 ).toBool();
- bEnableYaw = iniFile.value ( "EnableYaw", 1 ).toBool();
- bEnableX = iniFile.value ( "EnableX", 1 ).toBool();
- bEnableY = iniFile.value ( "EnableY", 1 ).toBool();
- bEnableZ = iniFile.value ( "EnableZ", 1 ).toBool();
-
- iniFile.endGroup ();
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
{
return new Hydra_Tracker;
diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h
index 3f7bf0a8..05a8b076 100644
--- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h
+++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h
@@ -1,89 +1,65 @@
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "ui_ftnoir_hydra_clientcontrols.h"
#include <QMessageBox>
-#include <QSettings>
#include <QWaitCondition>
#include <math.h>
#include "facetracknoir/global-settings.h"
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<bool> bEnableRoll, bEnablePitch, bEnableYaw, bEnableX, bEnableY, bEnableZ;
+ settings() :
+ b(bundle("tracker-hydra")),
+ bEnableRoll(b, "enable-rz", true),
+ bEnablePitch(b, "enable-ry", true),
+ bEnableYaw(b, "enable-rx", true),
+ bEnableX(b, "enable-tx", true),
+ bEnableY(b, "enable-ty", true),
+ bEnableZ(b, "enable-tz", true)
+ {}
+};
+
class Hydra_Tracker : public ITracker
{
public:
Hydra_Tracker();
- ~Hydra_Tracker();
-
- void StartTracker( QFrame *videoframe );
- bool GiveHeadPoseData(double *data);
- void loadSettings();
+ ~Hydra_Tracker();
+ void StartTracker(QFrame *) virt_override;
+ void GetHeadPoseData(double *data) virt_override;
volatile bool should_quit;
- void WaitForExit() {
- return;
- }
protected:
void run(); // qthread override run method
-
private:
+ settings s;
bool isCalibrated;
-
double newHeadPose[6]; // Structure with new headpose
- bool bEnableRoll;
- bool bEnablePitch;
- bool bEnableYaw;
-
- bool bEnableX;
- bool bEnableY;
- bool bEnableZ;
-
QMutex mutex;
+ virtual int preferredHz() virt_override { return 250; }
};
-// Widget that has controls for FTNoIR protocol client-settings.
class TrackerControls: public QWidget, public ITrackerDialog
{
Q_OBJECT
public:
-
explicit TrackerControls();
- ~TrackerControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {};
- void unRegisterTracker() {};
-
+ void registerTracker(ITracker *) {}
+ void unRegisterTracker() {}
private:
+ settings s;
Ui::UIHydraControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
-
private slots:
void doOK();
void doCancel();
- void settingChanged() { settingsDirty = true; };
- void settingChanged(int) { settingsDirty = true; };
};
-//*******************************************************************************************************
-// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker
-//*******************************************************************************************************
class FTNoIR_TrackerDll : public Metadata
{
public:
- FTNoIR_TrackerDll();
- ~FTNoIR_TrackerDll();
-
- void Initialize();
-
void getFullName(QString *strToBeFilled);
void getShortName(QString *strToBeFilled);
void getDescription(QString *strToBeFilled);
void getIcon(QIcon *icon);
-
-private:
- QString trackerFullName; // Trackers' name and description
- QString trackerShortName;
- QString trackerDescription;
};
diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp
index 77d4963b..14be2c37 100644
--- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp
+++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp
@@ -1,179 +1,33 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_hydra.h"
#include "facetracknoir/global-settings.h"
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
TrackerControls::TrackerControls() :
QWidget()
{
ui.setupUi( this );
// Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
-
- connect(ui.chkEnableRoll, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnablePitch, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableYaw, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
-#if 0
- connect(ui.chkEnableX, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableY, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableZ, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
-#endif
- // Load the settings from the current .INI-file
- loadSettings();
-}
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
-//
-// Destructor for server-dialog
-//
-TrackerControls::~TrackerControls() {
- qDebug() << "~TrackerControls() says: started";
+ tie_setting(s.bEnableYaw, ui.chkEnableYaw);
+ tie_setting(s.bEnablePitch, ui.chkEnablePitch);
+ tie_setting(s.bEnableRoll, ui.chkEnableRoll);
+ tie_setting(s.bEnableX, ui.chkEnableX);
+ tie_setting(s.bEnableY, ui.chkEnableY);
+ tie_setting(s.bEnableZ, ui.chkEnableZ);
}
-//
-// Initialize tracker-client-dialog
-//
-void TrackerControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
void TrackerControls::doOK() {
- save();
+ s.b->save();
this->close();
}
-// override show event
-void TrackerControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// 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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
+ s.b->revert();
+ close();
}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void TrackerControls::loadSettings() {
-
-// qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
-// qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Hydra" );
- ui.chkEnableRoll->setChecked(iniFile.value ( "EnableRoll", 1 ).toBool());
- ui.chkEnablePitch->setChecked(iniFile.value ( "EnablePitch", 1 ).toBool());
- ui.chkEnableYaw->setChecked(iniFile.value ( "EnableYaw", 1 ).toBool());
- ui.chkEnableX->setChecked(iniFile.value ( "EnableX", 1 ).toBool());
- ui.chkEnableY->setChecked(iniFile.value ( "EnableY", 1 ).toBool());
- ui.chkEnableZ->setChecked(iniFile.value ( "EnableZ", 1 ).toBool());
-
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void TrackerControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "Hydra" );
- iniFile.setValue ( "EnableRoll", ui.chkEnableRoll->isChecked() );
- iniFile.setValue ( "EnablePitch", ui.chkEnablePitch->isChecked() );
- iniFile.setValue ( "EnableYaw", ui.chkEnableYaw->isChecked() );
- iniFile.setValue ( "EnableX", ui.chkEnableX->isChecked() );
- iniFile.setValue ( "EnableY", ui.chkEnableY->isChecked() );
- iniFile.setValue ( "EnableZ", ui.chkEnableZ->isChecked() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
{
return new TrackerControls;
diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp
index 4f5d8b10..a2cc7c01 100644
--- a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp
+++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp
@@ -3,42 +3,25 @@
#include <QDebug>
#include "facetracknoir/global-settings.h"
-FTNoIR_TrackerDll::FTNoIR_TrackerDll() {
- //populate the description strings
- trackerFullName = "Hydra";
- trackerShortName = "Hydra";
- trackerDescription = "Hydra";
-}
-
-FTNoIR_TrackerDll::~FTNoIR_TrackerDll()
-{
-
-}
-
-void FTNoIR_TrackerDll::Initialize()
-{
- return;
-}
-
void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled)
{
- *strToBeFilled = trackerFullName;
-};
+ *strToBeFilled = "Hydra";
+}
void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled)
{
- *strToBeFilled = trackerShortName;
-};
+ *strToBeFilled = "Hydra";
+}
void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled)
{
- *strToBeFilled = trackerDescription;
-};
+ *strToBeFilled = "Hydra";
+}
void FTNoIR_TrackerDll::getIcon(QIcon *icon)
{
*icon = QIcon(":/images/facetracknoir.png");
-};
+}
////////////////////////////////////////////////////////////////////////////////
// Factory function that creates instances if the Tracker object.
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp
new file mode 100644
index 00000000..f9789dce
--- /dev/null
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.cpp
@@ -0,0 +1,230 @@
+#include "ftnoir_tracker_joystick.h"
+#include "facetracknoir/global-settings.h"
+#undef NDEBUG
+#include <QMutexLocker>
+
+FTNoIR_Tracker::FTNoIR_Tracker() :
+ g_pDI(nullptr),
+ g_pJoystick(nullptr),
+ iter(-1),
+ mtx(QMutex::Recursive)
+{
+ for (int i = 0; i < 6; i++)
+ min_[i] = max_[i] = 0;
+ GUID bar = {0};
+}
+
+void FTNoIR_Tracker::reload()
+{
+ s.b->reload();
+ QMutexLocker foo(&mtx);
+ if (g_pJoystick)
+ {
+ g_pJoystick->Unacquire();
+ g_pJoystick->Release();
+ }
+ if (g_pDI)
+ g_pDI->Release();
+
+ g_pJoystick = nullptr;
+ g_pDI = nullptr;
+
+ StartTracker(frame);
+}
+
+FTNoIR_Tracker::~FTNoIR_Tracker()
+{
+ if (g_pJoystick)
+ {
+ g_pJoystick->Unacquire();
+ g_pJoystick->Release();
+ }
+ if (g_pDI)
+ {
+ g_pDI->Release();
+ }
+}
+
+static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
+ VOID* pContext )
+{
+ auto self = (FTNoIR_Tracker*) pContext;
+
+ // For axes that are returned, set the DIPROP_RANGE property for the
+ // enumerated axis in order to scale min/max values.
+ if( pdidoi->dwType & DIDFT_AXIS )
+ {
+ DIPROPRANGE diprg = {0};
+ diprg.diph.dwSize = sizeof( DIPROPRANGE );
+ diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER );
+ diprg.diph.dwHow = DIPH_BYID;
+ diprg.diph.dwObj = pdidoi->dwType;
+
+ // Set the range for the axis
+
+ if( FAILED( self->g_pJoystick->GetProperty( DIPROP_RANGE, &diprg.diph ) ) )
+ return DIENUM_STOP;
+
+ self->min_[self->iter] = diprg.lMin;
+ self->max_[self->iter] = diprg.lMax;
+ qDebug() << "axis" << self->iter << diprg.lMin << diprg.lMax;
+ self->iter++;
+ }
+
+ return self->iter == 8 ? DIENUM_STOP : DIENUM_CONTINUE;
+}
+
+static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext )
+{
+ 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);
+ }
+
+ return stop ? DIENUM_STOP : DIENUM_CONTINUE;
+}
+
+void FTNoIR_Tracker::StartTracker(QFrame* frame)
+{
+ QMutexLocker foo(&mtx);
+ this->frame = frame;
+ iter = 0;
+ auto hr = CoInitialize( nullptr );
+
+ if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION,
+ IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) )
+ {
+ qDebug() << "create";
+ goto fail;
+ }
+
+ if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
+ EnumJoysticksCallback,
+ this,
+ DIEDFL_ATTACHEDONLY)))
+ {
+ qDebug() << "enum2";
+ goto fail;
+ }
+
+ if (!g_pJoystick)
+ {
+ qDebug() << "ENODEV";
+ goto fail;
+ }
+
+ if (FAILED(g_pJoystick->SetDataFormat(&c_dfDIJoystick)))
+ {
+ qDebug() << "format";
+ goto fail;
+ }
+
+ if (FAILED(g_pJoystick->SetCooperativeLevel((HWND) frame->window()->winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)))
+ {
+ qDebug() << "coop";
+ goto fail;
+ }
+
+ iter = 0;
+
+ if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback,
+ ( VOID* )this, DIDFT_ALL )))
+ {
+ qDebug() << "enum axes";
+ goto fail;
+ }
+
+ qDebug() << "joy init success";
+
+ return;
+
+fail:
+ if (g_pJoystick)
+ g_pJoystick->Release();
+ if (g_pDI)
+ g_pDI->Release();
+ g_pJoystick = nullptr;
+ g_pDI = nullptr;
+
+ qDebug() << "joy init failure";
+}
+
+void FTNoIR_Tracker::GetHeadPoseData(double *data)
+{
+ QMutexLocker foo(&mtx);
+ DIJOYSTATE js = {0};
+
+ if( !g_pDI || !g_pJoystick)
+ return;
+
+ auto hr = g_pJoystick->Poll();
+ if( FAILED( hr ))
+ {
+ hr = g_pJoystick->Acquire();
+ for (int i = 0; hr == DIERR_INPUTLOST && i < 200; i++)
+ hr = g_pJoystick->Acquire();
+ if (hr != DI_OK)
+ {
+ qDebug() << "joy read failure" << hr;
+ return;
+ }
+ }
+
+ 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.rglSlider[0],
+ js.rglSlider[1]
+ };
+
+ const double limits[] = {
+ 100,
+ 100,
+ 100,
+ 180,
+ 90,
+ 180
+ };
+
+ int axes[] = {
+ s.axis_0,
+ s.axis_1,
+ s.axis_2,
+ s.axis_3,
+ s.axis_4,
+ s.axis_5
+ };
+
+ for (int i = 0; i < 6; i++)
+ {
+ auto idx = axes[i] - 1;
+ if (idx < 0 || idx > 7)
+ {
+ data[i] = 0;
+ }
+ else {
+ auto mid = (min_[idx] + max_[idx]) / 2;
+ auto val = values[idx] - mid;
+
+ auto max = (max_[idx] - min_[idx]) / 2;
+ auto min = (min_[idx] - max_[idx]) / -2;
+ data[i] = val * limits[i] / (double) (val >= 0 ? max : min);
+ }
+ }
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Tracker;
+}
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h
new file mode 100644
index 00000000..06d06186
--- /dev/null
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick.h
@@ -0,0 +1,104 @@
+/* Copyright (c) 2013 Stanislaw Halik <sthalik@misaki.pl>
+ *
+ * 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 "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "ui_ftnoir_tracker_joystick_controls.h"
+#include <QComboBox>
+#include <QCheckBox>
+#include <QSpinBox>
+#include <QMessageBox>
+#include <QSettings>
+#include <QList>
+#include <QMutex>
+#include <QFrame>
+#include <cmath>
+#include "facetracknoir/global-settings.h"
+#ifndef DIRECTINPUT_VERSION
+# define DIRECTINPUT_VERSION 0x800
+#endif
+#include <windows.h>
+#include <commctrl.h>
+#include <basetsd.h>
+#include <dinput.h>
+#include <oleauto.h>
+#include <shellapi.h>
+
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> axis_0;
+ value<int> axis_1;
+ value<int> axis_2;
+ value<int> axis_3;
+ value<int> axis_4;
+ value<int> axis_5;
+ value<QString> joyid;
+ settings() :
+ b(bundle("tracker-joystick")),
+ axis_0(b, "axis-0", 0),
+ axis_1(b, "axis-1", 0),
+ axis_2(b, "axis-2", 0),
+ axis_3(b, "axis-3", 0),
+ axis_4(b, "axis-4", 0),
+ axis_5(b, "axis-5", 0),
+ joyid(b, "joy-id", "")
+ {}
+};
+
+class FTNoIR_Tracker : public ITracker
+{
+public:
+ FTNoIR_Tracker();
+ ~FTNoIR_Tracker();
+ void StartTracker(QFrame *frame);
+ void GetHeadPoseData(double *data);
+ void reload();
+ LPDIRECTINPUT8 g_pDI;
+ LPDIRECTINPUTDEVICE8 g_pJoystick;
+ int min_[8], max_[8];
+ QMutex mtx;
+ QFrame* frame;
+ DIDEVICEINSTANCE def;
+ int iter; // XXX bad style
+ settings s;
+};
+
+class TrackerControls: public QWidget, public ITrackerDialog
+{
+ Q_OBJECT
+public:
+ TrackerControls();
+ void registerTracker(ITracker *foo) {
+ tracker = dynamic_cast<FTNoIR_Tracker*>(foo);
+ }
+ void unRegisterTracker() {
+ tracker = NULL;
+ }
+ QList<GUID> guids;
+ Ui::UIJoystickControls ui;
+ FTNoIR_Tracker* tracker;
+ settings s;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+class FTNoIR_TrackerDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled);
+ void getShortName(QString *strToBeFilled);
+ void getDescription(QString *strToBeFilled);
+ void getIcon(QIcon *icon);
+private:
+ QString trackerFullName; // Trackers' name and description
+ QString trackerShortName;
+ QString trackerDescription;
+};
+
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui
new file mode 100644
index 00000000..5d349169
--- /dev/null
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_controls.ui
@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UIJoystickControls</class>
+ <widget class="QWidget" name="UIJoystickControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>216</width>
+ <height>259</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Joystick protocol 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="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>85</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Axis enablement</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>X</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>Roll</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="comboBox_5">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QComboBox" name="comboBox_6">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="comboBox_4">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="comboBox_2">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="comboBox">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>Yaw</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="comboBox_3">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#7</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>#8</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Z</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="text">
+ <string>Pitch</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Joy Id</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <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>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>joylist</tabstop>
+ <tabstop>comboBox</tabstop>
+ <tabstop>comboBox_2</tabstop>
+ <tabstop>comboBox_3</tabstop>
+ <tabstop>comboBox_4</tabstop>
+ <tabstop>comboBox_5</tabstop>
+ <tabstop>comboBox_6</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+ <slots>
+ <slot>startEngineClicked()</slot>
+ <slot>stopEngineClicked()</slot>
+ <slot>cameraSettingsClicked()</slot>
+ </slots>
+</ui>
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp
new file mode 100644
index 00000000..b0766634
--- /dev/null
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dialog.cpp
@@ -0,0 +1,66 @@
+#include "ftnoir_tracker_joystick.h"
+#include "facetracknoir/global-settings.h"
+
+static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext )
+{
+ auto self = ( TrackerControls* )pContext;
+
+ self->guids.push_back(pdidInstance->guidInstance);
+ self->ui.joylist->addItem(QString(pdidInstance->tszInstanceName));
+
+ return DIENUM_CONTINUE;
+}
+
+TrackerControls::TrackerControls() : tracker(nullptr)
+{
+ ui.setupUi( this );
+
+ // Connect Qt signals to member-functions
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
+
+ tie_setting(s.axis_0, ui.comboBox);
+ tie_setting(s.axis_1, ui.comboBox_2);
+ tie_setting(s.axis_2, ui.comboBox_3);
+ tie_setting(s.axis_3, ui.comboBox_4);
+ tie_setting(s.axis_4, ui.comboBox_5);
+ tie_setting(s.axis_5, ui.comboBox_6);
+
+ {
+ auto hr = CoInitialize( nullptr );
+ LPDIRECTINPUT8 g_pDI = nullptr;
+
+ if( FAILED( hr = DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION,
+ IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) ) )
+ goto fin;
+
+ if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
+ EnumJoysticksCallback,
+ this,
+ DIEDFL_ATTACHEDONLY )))
+ goto fin;
+
+fin:
+ if (g_pDI)
+ g_pDI->Release();
+ }
+
+ tie_setting(s.joyid, ui.joylist);
+}
+
+void TrackerControls::doOK() {
+ s.b->save();
+ if (tracker)
+ tracker->reload();
+ this->close();
+}
+
+void TrackerControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new TrackerControls;
+}
diff --git a/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp
new file mode 100644
index 00000000..325d24a4
--- /dev/null
+++ b/ftnoir_tracker_joystick/ftnoir_tracker_joystick_dll.cpp
@@ -0,0 +1,28 @@
+#include "ftnoir_tracker_joystick.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+
+void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled)
+{
+ *strToBeFilled = "Joystick";
+}
+
+void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled)
+{
+ *strToBeFilled = "Joystick";
+}
+
+void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled)
+{
+ *strToBeFilled = "Joystick";
+}
+
+void FTNoIR_TrackerDll::getIcon(QIcon *icon)
+{
+ *icon = QIcon(":/images/facetracknoir.png");
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_TrackerDll;
+}
diff --git a/ftnoir_tracker_pt/camera.cpp b/ftnoir_tracker_pt/camera.cpp
deleted file mode 100644
index fe39b436..00000000
--- a/ftnoir_tracker_pt/camera.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "camera.h"
-#include <QDebug>
-
-using namespace cv;
-
-// ----------------------------------------------------------------------------
-void Camera::set_index(int index)
-{
- if (desired_index != index)
- {
- desired_index = index;
- _set_index();
-
- // reset fps
- dt_valid = 0;
- dt_mean = 0;
- active_index = index;
- }
-}
-
-void Camera::set_f(float f)
-{
- if (cam_desired.f != f)
- {
- cam_desired.f = f;
- _set_f();
- }
-}
-void Camera::set_fps(int fps)
-{
- if (cam_desired.fps != fps)
- {
- cam_desired.fps = fps;
- _set_fps();
- }
-}
-
-void Camera::set_res(int x_res, int y_res)
-{
- if (cam_desired.res_x != x_res || cam_desired.res_y != y_res)
- {
- cam_desired.res_x = x_res;
- cam_desired.res_y = y_res;
- _set_res();
- }
-}
-
-bool Camera::get_frame(float dt, cv::Mat* frame)
-{
- bool new_frame = _get_frame(frame);
- // measure fps of valid frames
- const float dt_smoothing_const = 0.9;
- dt_valid += dt;
- if (new_frame)
- {
- dt_mean = dt_smoothing_const * dt_mean + (1.0 - dt_smoothing_const) * dt_valid;
- cam_info.fps = 1.0 / dt_mean;
- dt_valid = 0;
- }
- return new_frame;
-}
-
-// ----------------------------------------------------------------------------
-void CVCamera::start()
-{
- cap = new VideoCapture(desired_index);
-// extract camera info
- 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);
-}
-
-void CVCamera::stop()
-{
- if (cap) {
- cap->release();
- delete cap;
- cap = NULL;
- }
- active = false;
-}
-
-bool CVCamera::_get_frame(Mat* frame)
-{
- bool ret = cap->read(*frame);
- //if (ret)
- // flip(tmp, *frame, 0);
- return ret;
-}
-
-void CVCamera::_set_index()
-{
- if (active) restart();
-}
-
-void CVCamera::_set_f()
-{
- cam_info.f = cam_desired.f;
-}
-
-void CVCamera::_set_fps()
-{
- if (cap) cap->set(CV_CAP_PROP_FPS, cam_desired.fps);
-}
-
-void CVCamera::_set_res()
-{
- if (cap)
- {
- cap->set(CV_CAP_PROP_FRAME_WIDTH, cam_desired.res_x);
- cap->set(CV_CAP_PROP_FRAME_HEIGHT, cam_desired.res_y);
- cam_info.res_x = cap->get(CV_CAP_PROP_FRAME_WIDTH);
- cam_info.res_y = cap->get(CV_CAP_PROP_FRAME_HEIGHT);
- }
-}
-
-#if 0
-// ----------------------------------------------------------------------------
-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_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
diff --git a/ftnoir_tracker_pt/camera.h b/ftnoir_tracker_pt/camera.h
deleted file mode 100644
index 6fec12da..00000000
--- a/ftnoir_tracker_pt/camera.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef CAMERA_H
-#define CAMERA_H
-
-#include <opencv2/opencv.hpp>
-#include <opencv/highgui.h>
-//#include "videoInput/videoInput.h"
-
-// ----------------------------------------------------------------------------
-struct CamInfo
-{
- CamInfo() : res_x(0), res_y(0), fps(0), f(1) {}
-
- int res_x;
- int res_y;
- int fps;
- float f; // (focal length) / (sensor width)
-};
-
-// ----------------------------------------------------------------------------
-// base class for cameras
-class Camera
-{
-public:
- Camera() : desired_index(0), active_index(-1), active(false), dt_valid(0), dt_mean(0) {}
- virtual ~Camera() {}
-
- // start/stop capturing
- virtual void start() = 0;
- virtual void stop() = 0;
- void restart() { stop(); start(); }
-
- void set_index(int index);
- void set_f(float f);
- void set_fps(int fps);
- void set_res(int x_res, int y_res);
-
- // gets a frame from the camera, dt: time since last call in seconds
- bool get_frame(float dt, cv::Mat* frame);
-
- // WARNING: returned references are valid as long as object
- const CamInfo& get_info() const { return cam_info; }
- const CamInfo& get_desired() const { return cam_desired; }
-
-protected:
- // get a frame from the camera
- virtual bool _get_frame(cv::Mat* frame) = 0;
-
- // update the camera
- virtual void _set_index() = 0;
- virtual void _set_f() = 0;
- virtual void _set_fps() = 0;
- virtual void _set_res() = 0;
-
- int desired_index;
- int active_index;
- bool active;
- float dt_valid;
- float dt_mean;
- CamInfo cam_info;
- CamInfo cam_desired;
-};
-
-
-// ----------------------------------------------------------------------------
-// OpenCV camera
-
-class CVCamera : public Camera
-{
-public:
- CVCamera() : cap(NULL) {}
- ~CVCamera() { stop(); }
-
- void start();
- void stop();
-
-protected:
- bool _get_frame(cv::Mat* frame);
- void _set_index();
- void _set_f();
- void _set_fps();
- void _set_res();
-
- cv::VideoCapture* cap;
-};
-
-
-// ----------------------------------------------------------------------------
-// videoInput camera
-#if 0
-class VICamera : public Camera
-{
-public:
- VICamera();
- ~VICamera() { stop(); }
-
- void start();
- void stop();
-
-protected:
- bool _get_frame(cv::Mat* frame);
- void _set_index();
- void _set_f();
- void _set_fps();
- void _set_res();
-
- videoInput VI;
- cv::Mat new_frame;
- unsigned char* frame_buffer;
-};
-#endif
-
-#endif //CAMERA_H
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp
deleted file mode 100644
index 99b2f680..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "ftnoir_tracker_pt.h"
-#include <QHBoxLayout>
-#include <cmath>
-#include <QDebug>
-#include <QFile>
-#include <QCoreApplication>
-#include "facetracknoir/global-settings.h"
-
-using namespace std;
-using namespace cv;
-
-//#define PT_PERF_LOG //log performance
-
-//-----------------------------------------------------------------------------
-Tracker::Tracker()
- : tracking_valid(false), frame_count(0), commands(0), video_widget(NULL), fresh(false)
-{
- should_quit = false;
- qDebug()<<"Tracker::Tracker";
- TrackerSettings settings;
- settings.load_ini();
- apply(settings);
-}
-
-Tracker::~Tracker()
-{
- qDebug()<<"Tracker::~Tracker";
- set_command(ABORT);
- wait();
- if (video_widget) delete video_widget;
-}
-
-void Tracker::set_command(Command command)
-{
- //QMutexLocker lock(&mutex);
- commands |= command;
-}
-
-void Tracker::reset_command(Command command)
-{
- //QMutexLocker lock(&mutex);
- commands &= ~command;
-}
-
-void Tracker::run()
-{
- qDebug()<<"Tracker:: Thread started";
-
-#ifdef PT_PERF_LOG
- QFile log_file(QCoreApplication::applicationDirPath() + "/PointTrackerPerformance.txt");
- if (!log_file.open(QIODevice::WriteOnly | QIODevice::Text)) return;
- QTextStream log_stream(&log_file);
-#endif
-
- time.start();
- float dt;
- bool new_frame;
- forever
- {
- {
- QMutexLocker lock(&mutex);
- if (should_quit)
- break;
-
- if (commands & ABORT) break;
- if (commands & PAUSE) continue;
- commands = 0;
-
- dt = time.elapsed() / 1000.0;
- time.restart();
-
- new_frame = camera.get_frame(dt, &frame);
- if (new_frame && !frame.empty())
- {
- const std::vector<cv::Vec2f>& points = point_extractor.extract_points(frame, dt, draw_frame);
- tracking_valid = point_tracker.track(points, camera.get_info().f, dt);
- frame_count++;
- fresh = true;
- }
-#ifdef PT_PERF_LOG
- log_stream<<"dt: "<<dt;
- if (!frame.empty()) log_stream<<" fps: "<<camera.get_info().fps;
- log_stream<<"\n";
-#endif
- refreshVideo();
- }
- msleep(sleep_time);
- }
-
- qDebug()<<"Tracker:: Thread stopping";
-}
-
-void Tracker::apply(const TrackerSettings& settings)
-{
- qDebug()<<"Tracker:: Applying settings";
- QMutexLocker lock(&mutex);
- camera.set_index(settings.cam_index);
- camera.set_res(settings.cam_res_x, settings.cam_res_y);
- camera.set_fps(settings.cam_fps);
- camera.set_f(settings.cam_f);
- point_extractor.threshold_val = settings.threshold;
- point_extractor.min_size = settings.min_point_size;
- point_extractor.max_size = settings.max_point_size;
- point_tracker.point_model = std::auto_ptr<PointModel>(new PointModel(settings.M01, settings.M02));
- point_tracker.dynamic_pose_resolution = settings.dyn_pose_res;
- sleep_time = settings.sleep_time;
- point_tracker.dt_reset = settings.reset_time / 1000.0;
- draw_frame = settings.video_widget;
- cam_pitch = settings.cam_pitch;
-
- bEnableRoll = settings.bEnableRoll;
- bEnablePitch = settings.bEnablePitch;
- bEnableYaw = settings.bEnableYaw;
- bEnableX = settings.bEnableX;
- bEnableY = settings.bEnableY;
- bEnableZ = settings.bEnableZ;
-
- t_MH = settings.t_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.get_pose();
- FrameTrafo X_MH(Matx33f::eye(), t_MH);
- X_CH_0 = X_CM_0 * X_MH;
-}
-
-void Tracker::refreshVideo()
-{
- if (video_widget && fresh)
- {
- Mat frame_copy;
- std::auto_ptr< vector<Vec2f> > points;
- {
- //QMutexLocker lock(&mutex);
- if (!draw_frame || frame.empty()) return;
-
- // copy the frame and points from the tracker thread
- frame_copy = frame.clone();
- points = std::auto_ptr< vector<Vec2f> >(new vector<Vec2f>(point_extractor.get_points()));
- }
- //QMutexLocker lck(&mutex);
- video_widget->update_image(frame_copy, points);
- }
-}
-
-void Tracker::StartTracker(QFrame* videoframe)
-{
- const int VIDEO_FRAME_WIDTH = videoframe->width();
- const int VIDEO_FRAME_HEIGHT = videoframe->height();
- TrackerSettings settings;
- settings.load_ini();
- apply(settings);
- qDebug("Tracker::Initialize");
- // setup video frame
- video_widget = new VideoWidget(videoframe);
- QHBoxLayout* layout = new QHBoxLayout();
- layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(video_widget);
- if (videoframe->layout()) delete videoframe->layout();
- videoframe->setLayout(layout);
- video_widget->resize(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT);
- videoframe->show();
- connect(&timer, SIGNAL(timeout()), this, SLOT(paint_widget()));
- timer.start(40);
- camera.start();
- start();
- reset_command(PAUSE);
-}
-
-void Tracker::paint_widget() {
- if (fresh) {
- fresh = false;
- video_widget->update();
- }
-}
-
-bool Tracker::GiveHeadPoseData(double *data)
-{
- const double rad2deg = 180.0/3.14159265;
- const double deg2rad = 1.0/rad2deg;
- {
- QMutexLocker lock(&mutex);
-
- if (!tracking_valid) return false;
-
- FrameTrafo X_CM = point_tracker.get_pose();
- FrameTrafo X_MH(Matx33f::eye(), t_MH);
- FrameTrafo X_CH = X_CM * X_MH;
-
- Matx33f R = X_CH.R * X_CH_0.R.t();
- Vec3f t = X_CH.t - X_CH_0.t;
-
- // correct for camera pitch
- Matx33f R_CP( 1, 0, 0,
- 0, cos(deg2rad*cam_pitch), sin(deg2rad*cam_pitch),
- 0, -sin(deg2rad*cam_pitch), cos(deg2rad*cam_pitch));
- R = R_CP * R * R_CP.t();
- t = R_CP * t;
-
- // get translation(s)
- if (bEnableX) {
- data[TX] = t[0] / 10.0; // convert to cm
- }
- if (bEnableY) {
- data[TY] = t[1] / 10.0;
- }
- if (bEnableZ) {
- data[TZ] = t[2] / 10.0;
- }
-
- // translate rotation matrix from opengl (G) to roll-pitch-yaw (R) frame
- // -z -> x, y -> z, x -> -y
- Matx33f R_RG( 0, 0,-1,
- -1, 0, 0,
- 0, 1, 0);
- R = R_RG * R * R_RG.t();
-
- // extract rotation angles
- double alpha, beta, gamma;
- //beta = atan2( -R(2,0), sqrt(R(0,0)*R(0,0) + R(1,0)*R(1,0)) );
- 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));
-
- if (bEnableYaw) {
- data[Yaw] = rad2deg * alpha;
- }
- if (bEnablePitch) {
- data[Pitch] = rad2deg * beta;
- }
- if (bEnableRoll) {
- data[Roll] = rad2deg * gamma;
- }
- }
- return true;
-}
-
-//-----------------------------------------------------------------------------
-//#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
-{
- return new Tracker;
-}
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.h b/ftnoir_tracker_pt/ftnoir_tracker_pt.h
deleted file mode 100644
index 0c45c6b6..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef FTNOIR_TRACKER_PT_H
-#define FTNOIR_TRACKER_PT_H
-
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "ftnoir_tracker_pt_settings.h"
-#include "camera.h"
-#include "point_extractor.h"
-#include "point_tracker.h"
-#include "video_widget.h"
-#include "timer.h"
-
-#include <QThread>
-#include <QMutex>
-#include <QTime>
-#include <opencv2/opencv.hpp>
-#include <QFrame>
-#include <QTimer>
-
-//-----------------------------------------------------------------------------
-class Tracker : public QThread, public ITracker
-{
- Q_OBJECT
-public:
- Tracker();
- ~Tracker();
-
- // ITracker interface
- void StartTracker(QFrame* videoFrame);
- bool GiveHeadPoseData(double *data);
-
- void refreshVideo();
-
- void apply(const TrackerSettings& settings);
- void center();
- void reset(); // reset the trackers internal state variables
- void run();
- void WaitForExit() {
- should_quit = true;
- wait();
- }
-
- void get_pose(FrameTrafo* X_CM) { QMutexLocker lock(&mutex); *X_CM = point_tracker.get_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(); }
-
-protected:
- FrameTrafo X_CH_0; // for centering
- cv::Mat frame; // the output frame for display
-
- enum Command {
- ABORT = 1<<0,
- PAUSE = 1<<1
- };
- void set_command(Command command);
- void reset_command(Command command);
-
- CVCamera camera;
- PointExtractor point_extractor;
- PointTracker point_tracker;
- bool tracking_valid;
-
- cv::Vec3f t_MH;
- int cam_pitch;
-
- bool draw_frame;
- int sleep_time;
-
- bool bEnableRoll;
- bool bEnablePitch;
- bool bEnableYaw;
- bool bEnableX;
- bool bEnableY;
- bool bEnableZ;
-
- long frame_count;
- volatile int commands;
-
- VideoWidget* video_widget;
- Timer time;
- QMutex mutex;
- volatile bool should_quit;
- volatile bool fresh;
- QTimer timer;
-
-protected slots:
- void paint_widget();
-};
-
-#endif // FTNOIR_TRACKER_PT_H
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc b/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc
deleted file mode 100644
index 5734917f..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt.qrc
+++ /dev/null
@@ -1,10 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>resources/icon.png</file>
- <file>resources/cap_front.png</file>
- <file>resources/cap_side.png</file>
- <file>resources/clip_front.png</file>
- <file>resources/clip_side.png</file>
- <file>resources/logo_ir.png</file>
- </qresource>
-</RCC>
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt.rc b/ftnoir_tracker_pt/ftnoir_tracker_pt.rc
deleted file mode 100644
index 11c5d52f..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt.rc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE 9, 1
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp
deleted file mode 100644
index 4837f4a9..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "ftnoir_tracker_pt_dialog.h"
-
-#include <QMessageBox>
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-//-----------------------------------------------------------------------------
-TrackerDialog::TrackerDialog()
- : settings_dirty(false), tracker(NULL), trans_calib_running(false), timer(this)
-{
- qDebug()<<"TrackerDialog::TrackerDialog";
- setAttribute(Qt::WA_DeleteOnClose, false);
-
- ui.setupUi( this );
-
- settings.load_ini();
- dialog_settings.load_ini();
-
- // initialize ui values
- ui.videowidget_check->setChecked(settings.video_widget);
- ui.dynpose_check->setChecked(settings.dyn_pose_res);
- ui.sleep_spin->setValue(settings.sleep_time);
- ui.reset_spin->setValue(settings.reset_time);
- ui.camindex_spin->setValue(settings.cam_index);
- ui.f_dspin->setValue(settings.cam_f);
- ui.res_x_spin->setValue(settings.cam_res_x);
- ui.res_y_spin->setValue(settings.cam_res_y);
- ui.fps_spin->setValue(settings.cam_fps);
- ui.campitch_spin->setValue(settings.cam_pitch);
- ui.threshold_slider->setValue(settings.threshold);
-
- ui.chkEnableRoll->setChecked(settings.bEnableRoll);
- ui.chkEnablePitch->setChecked(settings.bEnablePitch);
- ui.chkEnableYaw->setChecked(settings.bEnableYaw);
- ui.chkEnableX->setChecked(settings.bEnableX);
- ui.chkEnableY->setChecked(settings.bEnableY);
- ui.chkEnableZ->setChecked(settings.bEnableZ);
-
- ui.mindiam_spin->setValue(settings.min_point_size);
- ui.maxdiam_spin->setValue(settings.max_point_size);
- ui.model_tabs->setCurrentIndex(dialog_settings.active_model_panel);
- ui.clip_bheight_spin->setValue(dialog_settings.clip_by);
- ui.clip_blength_spin->setValue(dialog_settings.clip_bz);
- ui.clip_theight_spin->setValue(dialog_settings.clip_ty);
- ui.clip_tlength_spin->setValue(dialog_settings.clip_tz);
- ui.cap_width_spin->setValue(dialog_settings.cap_x);
- ui.cap_height_spin->setValue(dialog_settings.cap_y);
- ui.cap_length_spin->setValue(dialog_settings.cap_z);
- ui.m1x_spin->setValue(dialog_settings.M01x);
- ui.m1y_spin->setValue(dialog_settings.M01y);
- ui.m1z_spin->setValue(dialog_settings.M01z);
- ui.m2x_spin->setValue(dialog_settings.M02x);
- ui.m2y_spin->setValue(dialog_settings.M02y);
- ui.m2z_spin->setValue(dialog_settings.M02z);
- ui.tx_spin->setValue(settings.t_MH[0]);
- ui.ty_spin->setValue(settings.t_MH[1]);
- ui.tz_spin->setValue(settings.t_MH[2]);
-
- // connect Qt signals and slots
- connect( ui.videowidget_check,SIGNAL(toggled(bool)), this,SLOT(set_video_widget(bool)) );
- connect( ui.dynpose_check,SIGNAL(toggled(bool)), this,SLOT(set_dyn_pose_res(bool)) );
- connect( ui.sleep_spin,SIGNAL(valueChanged(int)), this,SLOT(set_sleep_time(int)) );
- connect( ui.reset_spin,SIGNAL(valueChanged(int)), this,SLOT(set_reset_time(int)) );
- connect( ui.camindex_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_index(int)) );
- connect( ui.f_dspin,SIGNAL(valueChanged(double)), this,SLOT(set_cam_f(double)) );
- connect( ui.res_x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_res_x(int)) );
- connect( ui.res_y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_res_y(int)) );
- connect( ui.fps_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_fps(int)) );
- connect( ui.campitch_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cam_pitch(int)) );
- connect( ui.threshold_slider,SIGNAL(sliderMoved(int)), this,SLOT(set_threshold(int)) );
-
- 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.mindiam_spin,SIGNAL(valueChanged(int)), this,SLOT(set_min_point_size(int)) );
- connect( ui.maxdiam_spin,SIGNAL(valueChanged(int)), this,SLOT(set_max_point_size(int)) );
- connect( ui.model_tabs,SIGNAL(currentChanged(int)), this,SLOT(set_model(int)) );
- connect( ui.clip_theight_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_t_height(int)) );
- connect( ui.clip_tlength_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_t_length(int)) );
- connect( ui.clip_bheight_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_b_height(int)) );
- connect( ui.clip_blength_spin,SIGNAL(valueChanged(int)), this,SLOT(set_clip_b_length(int)) );
- connect( ui.cap_width_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_width(int)) );
- connect( ui.cap_height_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_height(int)) );
- connect( ui.cap_length_spin,SIGNAL(valueChanged(int)), this,SLOT(set_cap_length(int)) );
- connect( ui.m1x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1x(int)) );
- connect( ui.m1y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1y(int)) );
- connect( ui.m1z_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m1z(int)) );
- connect( ui.m2x_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2x(int)) );
- connect( ui.m2y_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2y(int)) );
- connect( ui.m2z_spin,SIGNAL(valueChanged(int)), this,SLOT(set_m2z(int)) );
- connect( ui.tx_spin,SIGNAL(valueChanged(int)), this,SLOT(set_tx(int)) );
- connect( ui.ty_spin,SIGNAL(valueChanged(int)), this,SLOT(set_ty(int)) );
- connect( ui.tz_spin,SIGNAL(valueChanged(int)), this,SLOT(set_tz(int)) );
-
- connect( ui.tcalib_button,SIGNAL(toggled(bool)), this,SLOT(startstop_trans_calib(bool)) );
-
- connect(ui.reset_button, SIGNAL(clicked()), this, SLOT(doReset()));
- //connect(ui.center_button, SIGNAL(clicked()), this, SLOT(doCenter()));
-
- connect(ui.ok_button, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.cancel_button, SIGNAL(clicked()), this, SLOT(doCancel()));
-
- connect(&timer,SIGNAL(timeout()), this,SLOT(poll_tracker_info()));
- timer.start(100);
-}
-
-TrackerDialog::~TrackerDialog()
-{
- qDebug()<<"TrackerDialog::~TrackerDialog";
-}
-
-void TrackerDialog::set_clip()
-{
- settings.M01[0] = 0;
- settings.M01[1] = dialog_settings.clip_ty;
- settings.M01[2] = -dialog_settings.clip_tz;
- settings.M02[0] = 0;
- settings.M02[1] = -dialog_settings.clip_by;
- settings.M02[2] = -dialog_settings.clip_bz;
-
- settings_changed();
-}
-
-void TrackerDialog::set_cap()
-{
- settings.M01[0] = -dialog_settings.cap_x;
- settings.M01[1] = -dialog_settings.cap_y;
- settings.M01[2] = -dialog_settings.cap_z;
- settings.M02[0] = dialog_settings.cap_x;
- settings.M02[1] = -dialog_settings.cap_y;
- settings.M02[2] = -dialog_settings.cap_z;
-
- settings_changed();
-}
-
-void TrackerDialog::set_custom()
-{
- settings.M01[0] = dialog_settings.M01x;
- settings.M01[1] = dialog_settings.M01y;
- settings.M01[2] = dialog_settings.M01z;
- settings.M02[0] = dialog_settings.M02x;
- settings.M02[1] = dialog_settings.M02y;
- settings.M02[2] = dialog_settings.M02z;
-
- settings_changed();
-}
-
-void TrackerDialog::set_model(int val)
-{
- dialog_settings.active_model_panel = val;
-
- switch (val) {
-
- case TrackerDialogSettings::MODEL_CLIP:
- set_clip();
- break;
-
- case TrackerDialogSettings::MODEL_CAP:
- set_cap();
- break;
-
- case TrackerDialogSettings::MODEL_CUSTOM:
- set_custom();
- break;
-
- default:
- break;
- }
-}
-
-void TrackerDialog::startstop_trans_calib(bool start)
-{
- if (start)
- {
- qDebug()<<"TrackerDialog:: Starting translation calibration";
- trans_calib.reset();
- trans_calib_running = true;
- }
- else
- {
- qDebug()<<"TrackerDialog:: Stoppping translation calibration";
- trans_calib_running = false;
- settings.t_MH = trans_calib.get_estimate();
- settings_changed();
- }
-}
-
-void TrackerDialog::trans_calib_step()
-{
- if (tracker)
- {
- FrameTrafo X_CM;
- tracker->get_pose(&X_CM);
- trans_calib.update(X_CM.R, X_CM.t);
- cv::Vec3f t_MH = trans_calib.get_estimate();
- //qDebug()<<"TrackerDialog:: Current translation estimate: "<<t_MH[0]<<t_MH[1]<<t_MH[2];
- ui.tx_spin->setValue(t_MH[0]);
- ui.ty_spin->setValue(t_MH[1]);
- ui.tz_spin->setValue(t_MH[2]);
- }
-}
-
-void TrackerDialog::settings_changed()
-{
- settings_dirty = true;
- if (tracker) tracker->apply(settings);
-}
-
-void TrackerDialog::doCenter()
-{
- if (tracker) tracker->center();
-}
-
-void TrackerDialog::doReset()
-{
- if (tracker) tracker->reset();
-}
-
-void TrackerDialog::doOK()
-{
- settings.save_ini();
- dialog_settings.save_ini();
- close();
-}
-
-void TrackerDialog::doCancel()
-{
- if (settings_dirty) {
- 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();
- dialog_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();
- }
-}
-
-void TrackerDialog::poll_tracker_info()
-{
- if (tracker)
- {
- QString to_print;
-
- // display caminfo
- CamInfo info;
- tracker->get_cam_info(&info);
- to_print = QString::number(info.res_x)+"x"+QString::number(info.res_y)+" @ "+QString::number(info.fps)+" FPS";
- ui.caminfo_label->setText(to_print);
- ui.caminfo_label_2->setText(to_print);
-
- // display pointinfo
- int n_points = tracker->get_n_points();
- to_print = QString::number(n_points);
- if (n_points == 3)
- to_print += " OK!";
- else
- to_print += " BAD!";
- ui.pointinfo_label->setText(to_print);
- ui.pointinfo_label_2->setText(to_print);
-
- // update calibration
- if (trans_calib_running) trans_calib_step();
- }
- else
- {
- QString to_print = "Tracker offline";
- ui.caminfo_label->setText(to_print);
- ui.caminfo_label_2->setText(to_print);
- ui.pointinfo_label->setText(to_print);
- ui.pointinfo_label_2->setText(to_print);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// ITrackerDialog interface
-void TrackerDialog::Initialize(QWidget *parent)
-{
- QPoint offsetpos(200, 200);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-void TrackerDialog::registerTracker(ITracker *t)
-{
- qDebug()<<"TrackerDialog:: Tracker registered";
- tracker = static_cast<Tracker*>(t);
- if (isVisible() && settings_dirty) tracker->apply(settings);
- ui.tcalib_button->setEnabled(true);
- //ui.center_button->setEnabled(true);
- ui.reset_button->setEnabled(true);
-}
-
-void TrackerDialog::unRegisterTracker()
-{
- qDebug()<<"TrackerDialog:: Tracker un-registered";
- tracker = NULL;
- ui.tcalib_button->setEnabled(false);
- //ui.center_button->setEnabled(false);
- ui.reset_button->setEnabled(false);
-}
-
-//-----------------------------------------------------------------------------
-//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
-{
- return new TrackerDialog;
-}
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h
deleted file mode 100644
index ada331e5..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef FTNOIR_TRACKER_PT_DIALOG_H
-#define FTNOIR_TRACKER_PT_DIALOG_H
-
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "ftnoir_tracker_pt_settings.h"
-#include "ftnoir_tracker_pt.h"
-#include "ui_ftnoir_pt_controls.h"
-#include "trans_calib.h"
-
-#include <QTimer>
-
-//-----------------------------------------------------------------------------
-class TrackerDialog : public QWidget, public ITrackerDialog
-{
- Q_OBJECT
-public:
- TrackerDialog();
- ~TrackerDialog();
-
- // ITrackerDialog interface
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker);
- void unRegisterTracker();
-
- void trans_calib_step();
-
-protected slots:
- // ugly qt stuff
- void set_video_widget(bool val) { settings.video_widget = val; settings_changed(); }
- void set_dyn_pose_res(bool val) { settings.dyn_pose_res = val; settings_changed(); }
- void set_sleep_time(int val) { settings.sleep_time = val; settings_changed(); }
- void set_reset_time(int val) { settings.reset_time = val; settings_changed(); }
- void set_cam_index(int val) { settings.cam_index = val; settings_changed(); }
- void set_cam_f(double val) { settings.cam_f = val; settings_changed(); }
- void set_cam_res_x(int val) { settings.cam_res_x = val; settings_changed(); }
- void set_cam_res_y(int val) { settings.cam_res_y = val; settings_changed(); }
- void set_cam_fps(int val) { settings.cam_fps = val; settings_changed(); }
- void set_cam_pitch(int val) { settings.cam_pitch = val; settings_changed(); }
- void set_min_point_size(int val) { settings.min_point_size = val; settings_changed(); }
- void set_max_point_size(int val) { settings.max_point_size = val; settings_changed(); }
- void set_threshold(int val) { settings.threshold = val; settings_changed(); }
- void set_ena_roll(bool val) { settings.bEnableRoll = val; settings_changed(); }
- void set_ena_pitch(bool val) { settings.bEnablePitch = val; settings_changed(); }
- void set_ena_yaw(bool val) { settings.bEnableYaw = val; settings_changed(); }
- void set_ena_x(bool val) { settings.bEnableX = val; settings_changed(); }
- void set_ena_y(bool val) { settings.bEnableY = val; settings_changed(); }
- void set_ena_z(bool val) { settings.bEnableZ = val; settings_changed(); }
-
- void set_clip_t_height(int val) { dialog_settings.clip_ty = val; set_clip(); }
- void set_clip_t_length(int val) { dialog_settings.clip_tz = val; set_clip(); }
- void set_clip_b_height(int val) { dialog_settings.clip_by = val; set_clip(); }
- void set_clip_b_length(int val) { dialog_settings.clip_bz = val; set_clip(); }
- void set_cap_width(int val) { dialog_settings.cap_x = val; set_cap(); }
- void set_cap_height(int val) { dialog_settings.cap_y = val; set_cap(); }
- void set_cap_length(int val) { dialog_settings.cap_z = val; set_cap(); }
- void set_m1x(int val) { dialog_settings.M01x = val; set_custom(); }
- void set_m1y(int val) { dialog_settings.M01y = val; set_custom(); }
- void set_m1z(int val) { dialog_settings.M01z = val; set_custom(); }
- void set_m2x(int val) { dialog_settings.M02x = val; set_custom(); }
- void set_m2y(int val) { dialog_settings.M02y = val; set_custom(); }
- void set_m2z(int val) { dialog_settings.M02z = val; set_custom(); }
- void set_tx(int val) { settings.t_MH[0] = val; settings_changed(); }
- void set_ty(int val) { settings.t_MH[1] = val; settings_changed(); }
- void set_tz(int val) { settings.t_MH[2] = val; settings_changed(); }
- void set_model(int model_id);
-
- void doCenter();
- void doReset();
-
- void doOK();
- void doCancel();
-
- void startstop_trans_calib(bool start);
-
- void poll_tracker_info();
-
-protected:
- void set_clip();
- void set_cap();
- void set_custom();
-
- void settings_changed();
-
- TrackerSettings settings;
- TrackerDialogSettings dialog_settings;
- bool settings_dirty;
-
- Tracker* tracker;
- TranslationCalibrator trans_calib;
- bool trans_calib_running;
- QTimer timer;
- Ui::UICPTClientControls ui;
-};
-
-#endif //FTNOIR_TRACKER_PT_DIALOG_H
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp
deleted file mode 100644
index 3164b291..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "ftnoir_tracker_pt.h"
-#include <QCoreApplication>
-#include <QSettings>
-
-//-----------------------------------------------------------------------------
-void TrackerSettings::load_ini()
-{
- qDebug("TrackerSettings::load_ini()");
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup( "PointTracker" );
-
- cam_index = iniFile.value("CameraId", 0).toInt();
- cam_f = iniFile.value("CameraF", 1).toFloat();
- cam_res_x = iniFile.value("CameraResX", 640).toInt();
- cam_res_y = iniFile.value("CameraResY", 480).toInt();
- cam_fps = iniFile.value("CameraFPS", 30).toInt();
- cam_pitch = iniFile.value("CameraPitch", 0).toInt();
- threshold = iniFile.value("PointExtractThreshold", 128).toInt();
- min_point_size = iniFile.value("PointExtractMinSize", 2).toInt();
- max_point_size = iniFile.value("PointExtractMaxSize", 50).toInt();
- M01[0] = iniFile.value("PointModelM01x", 0).toFloat();
- M01[1] = iniFile.value("PointModelM01y", 40).toFloat();
- M01[2] = iniFile.value("PointModelM01z", -30).toFloat();
- M02[0] = iniFile.value("PointModelM02x", 0).toFloat();
- M02[1] = iniFile.value("PointModelM02y", -70).toFloat();
- M02[2] = iniFile.value("PointModelM02z", -80).toFloat();
- t_MH[0] = iniFile.value("tMHx", 0).toFloat();
- t_MH[1] = iniFile.value("tMHy", 0).toFloat();
- t_MH[2] = iniFile.value("tMHz", 0).toFloat();
- dyn_pose_res = iniFile.value("DynamicPoseResolution", true).toBool();
- video_widget = iniFile.value("VideoWidget", true).toBool();
- sleep_time = iniFile.value("SleepTime", 10).toInt();
- reset_time = iniFile.value("ResetTime", 1000).toInt();
-
- bEnableRoll = iniFile.value( "EnableRoll", 1 ).toBool();
- bEnablePitch = iniFile.value( "EnablePitch", 1 ).toBool();
- bEnableYaw = iniFile.value( "EnableYaw", 1 ).toBool();
- bEnableX = iniFile.value( "EnableX", 1 ).toBool();
- bEnableY = iniFile.value( "EnableY", 1 ).toBool();
- bEnableZ = iniFile.value( "EnableZ", 1 ).toBool();
-
- iniFile.endGroup();
-}
-
-void TrackerSettings::save_ini() const
-{
- qDebug("TrackerSettings::save_ini()");
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "PointTracker" );
-
- iniFile.setValue("CameraId", cam_index);
- iniFile.setValue("CameraF", cam_f);
- iniFile.setValue("CameraResX", cam_res_x);
- iniFile.setValue("CameraResY", cam_res_y);
- iniFile.setValue("CameraFPS", cam_fps);
- iniFile.setValue("CameraPitch", cam_pitch);
- iniFile.setValue("PointExtractThreshold", threshold);
- iniFile.setValue("PointExtractMinSize", min_point_size);
- iniFile.setValue("PointExtractMaxSize", max_point_size);
- iniFile.setValue("PointModelM01x", M01[0]);
- iniFile.setValue("PointModelM01y", M01[1]);
- iniFile.setValue("PointModelM01z", M01[2]);
- iniFile.setValue("PointModelM02x", M02[0]);
- iniFile.setValue("PointModelM02y", M02[1]);
- iniFile.setValue("PointModelM02z", M02[2]);
- iniFile.setValue("tMHx", t_MH[0]);
- iniFile.setValue("tMHy", t_MH[1]);
- iniFile.setValue("tMHz", t_MH[2]);
- iniFile.setValue("DynamicPoseResolution", dyn_pose_res);
- iniFile.setValue("VideoWidget", video_widget);
- iniFile.setValue("SleepTime", sleep_time);
- iniFile.setValue("ResetTime", reset_time);
-
- iniFile.setValue( "EnableRoll", bEnableRoll );
- iniFile.setValue( "EnablePitch", bEnablePitch );
- iniFile.setValue( "EnableYaw", bEnableYaw );
- iniFile.setValue( "EnableX", bEnableX );
- iniFile.setValue( "EnableY", bEnableY );
- iniFile.setValue( "EnableZ", bEnableZ );
-
- iniFile.endGroup();
-}
-
-//-----------------------------------------------------------------------------
-void TrackerDialogSettings::load_ini()
-{
- qDebug("TrackerDialogSettings::load_ini()");
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup( "PointTrackerDialog" );
-
- active_model_panel = iniFile.value("ActiveModelPanel", MODEL_CLIP).toInt();
- M01x = iniFile.value("CustomM01x", 0).toInt();
- M01y = iniFile.value("CustomM01y", 40).toInt();
- M01z = iniFile.value("CustomM01z", -30).toInt();
- M02x = iniFile.value("CustomM02x", 0).toInt();
- M02y = iniFile.value("CustomM02y", -70).toInt();
- M02z = iniFile.value("CustomM02z", -80).toInt();
- clip_ty = iniFile.value("ClipTopHeight", 40).toInt();
- clip_tz = iniFile.value("ClipTopLength", 30).toInt();
- clip_by = iniFile.value("ClipBottomHeight", 70).toInt();
- clip_bz = iniFile.value("ClipBottomLength", 80).toInt();
- cap_x = iniFile.value("CapHalfWidth", 40).toInt();
- cap_y = iniFile.value("CapHeight", 60).toInt();
- cap_z = iniFile.value("CapLength", 100).toInt();
-}
-
-void TrackerDialogSettings::save_ini() const
-{
- qDebug("TrackerDialogSettings::save_ini()");
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "PointTrackerDialog" );
-
- iniFile.setValue("ActiveModelPanel", active_model_panel);
- iniFile.setValue("CustomM01x", M01x);
- iniFile.setValue("CustomM01y", M01y);
- iniFile.setValue("CustomM01z", M01z);
- iniFile.setValue("CustomM02x", M02x);
- iniFile.setValue("CustomM02y", M02y);
- iniFile.setValue("CustomM02z", M02z);
- iniFile.setValue("ClipTopHeight", clip_ty);
- iniFile.setValue("ClipTopLength", clip_tz);
- iniFile.setValue("ClipBottomHeight", clip_by);
- iniFile.setValue("ClipBottomLength", clip_bz);
- iniFile.setValue("CapHalfWidth", cap_x);
- iniFile.setValue("CapHeight", cap_y);
- iniFile.setValue("CapLength", cap_z);
-} \ No newline at end of file
diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h
deleted file mode 100644
index 88162c86..00000000
--- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef FTNOIR_TRACKER_PT_SETTINGS_H
-#define FTNOIR_TRACKER_PT_SETTINGS_H
-
-#include <opencv2/opencv.hpp>
-#include "point_tracker.h"
-
-
-//-----------------------------------------------------------------------------
-struct TrackerSettings
-{
- // camera
- int cam_index;
- float cam_f;
- int cam_res_x;
- int cam_res_y;
- int cam_fps;
- int cam_pitch;
-
- // point extraction
- int threshold;
- int min_point_size;
- int max_point_size;
-
- // point tracking
- cv::Vec3f M01;
- cv::Vec3f M02;
- bool dyn_pose_res;
-
- // head to model translation
- cv::Vec3f t_MH;
-
- int sleep_time; // in ms
- int reset_time; // in ms
- bool video_widget;
-
- bool bEnableRoll;
- bool bEnablePitch;
- bool bEnableYaw;
- bool bEnableX;
- bool bEnableY;
- bool bEnableZ;
-
- void load_ini();
- void save_ini() const;
-};
-
-
-//-----------------------------------------------------------------------------
-struct TrackerDialogSettings
-{
- enum
- {
- MODEL_CLIP,
- MODEL_CAP,
- MODEL_CUSTOM
- };
- int active_model_panel;
-
- int M01x;
- int M01y;
- int M01z;
- int M02x;
- int M02y;
- int M02z;
- int clip_ty;
- int clip_tz;
- int clip_by;
- int clip_bz;
- int cap_x;
- int cap_y;
- int cap_z;
-
- void load_ini();
- void save_ini() const;
-};
-
-#endif //FTNOIR_TRACKER_PT_SETTINGS_H \ No newline at end of file
diff --git a/ftnoir_tracker_pt/point_extractor.cpp b/ftnoir_tracker_pt/point_extractor.cpp
deleted file mode 100644
index 61e86bec..00000000
--- a/ftnoir_tracker_pt/point_extractor.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "point_extractor.h"
-#include <QDebug>
-
-using namespace cv;
-using namespace std;
-
-// ----------------------------------------------------------------------------
-const vector<Vec2f>& PointExtractor::extract_points(Mat frame, float dt, bool draw_output)
-{
- const int W = frame.cols;
- const int H = frame.rows;
-
- // clear old points
- points.clear();
-
- // convert to grayscale
- Mat frame_grey;
- cvtColor(frame, frame_grey, COLOR_BGR2GRAY);
-
- // convert to binary
- Mat frame_bin;
- threshold(frame_grey, frame_bin, threshold_val, 255, THRESH_BINARY);
-
- unsigned int region_size_min = 3.14*min_size*min_size;
- unsigned int region_size_max = 3.14*max_size*max_size;
-
- int blob_index = 1;
- for (int y=0; y<H; y++)
- {
- for (int x=0; x<W; x++)
- {
- // find connected components with floodfill
- if (frame_bin.at<unsigned char>(y,x) != 255) continue;
- Rect rect;
- floodFill(frame_bin, Point(x,y), Scalar(blob_index), &rect, Scalar(0), Scalar(0), FLOODFILL_FIXED_RANGE);
- blob_index++;
-
- // calculate the size of the connected component
- unsigned int region_size = 0;
- for (int i=rect.y; i < (rect.y+rect.height); i++)
- {
- for (int j=rect.x; j < (rect.x+rect.width); j++)
- {
- if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue;
- region_size++;
- }
- }
-
- if (region_size < region_size_min || region_size > region_size_max) continue;
-
- // calculate the center of mass:
- // mx = (sum_ij j*f(frame_grey_ij)) / (sum_ij f(frame_grey_ij))
- // my = ...
- // f maps from [threshold,256] -> [0, 1], lower values are mapped to 0
- float m = 0;
- float mx = 0;
- float my = 0;
- for (int i=rect.y; i < (rect.y+rect.height); i++)
- {
- for (int j=rect.x; j < (rect.x+rect.width); j++)
- {
- if (frame_bin.at<unsigned char>(i,j) != blob_index-1) continue;
- float val = frame_grey.at<unsigned char>(i,j);
- val = float(val - threshold_val)/(256 - threshold_val);
- val = val*val; // makes it more stable (less emphasis on low values, more on the peak)
- m += val;
- mx += j * val;
- my += i * val;
- }
- }
-
- // convert to centered camera coordinate system with y axis upwards
- Vec2f c;
- c[0] = (mx/m - W/2)/W;
- c[1] = -(my/m - H/2)/W;
- points.push_back(c);
-
- if (blob_index >= 255) break;
- }
- if (blob_index >= 255) break;
- }
-
- // draw output image
- if (draw_output) {
- frame.setTo(Scalar(255,0,0), frame_bin);
- }
-
- return points;
-}
diff --git a/ftnoir_tracker_pt/resource.h b/ftnoir_tracker_pt/resource.h
deleted file mode 100644
index c14e94ad..00000000
--- a/ftnoir_tracker_pt/resource.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by FTNoIR_Tracker_PT.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/ftnoir_tracker_pt/resources/icon.png b/ftnoir_tracker_pt/resources/icon.png
deleted file mode 100644
index 49af20e4..00000000
--- a/ftnoir_tracker_pt/resources/icon.png
+++ /dev/null
Binary files differ
diff --git a/ftnoir_tracker_pt/timer.cpp b/ftnoir_tracker_pt/timer.cpp
deleted file mode 100644
index 9e6ca8b8..00000000
--- a/ftnoir_tracker_pt/timer.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "timer.h"
-
-#include <stdlib.h>
-
-// ----------------------------------------------------------------------------
-Timer::Timer()
-: startTime(0), endTime(0), running(false)
-{
-#ifdef WIN32
- QueryPerformanceFrequency(&frequency);
- startCount.QuadPart = 0;
- endCount.QuadPart = 0;
-#else
- startCount.tv_sec = startCount.tv_usec = 0;
- endCount.tv_sec = endCount.tv_usec = 0;
-#endif
-}
-
-
-void Timer::start()
-{
-#ifdef WIN32
- QueryPerformanceCounter(&startCount);
-#else
- gettimeofday(&startCount, NULL);
-#endif
- running = true;
-}
-
-
-void Timer::stop()
-{
-#ifdef WIN32
- QueryPerformanceCounter(&endCount);
-#else
- gettimeofday(&endCount, NULL);
-#endif
- running = false;
-}
-
-
-double Timer::elapsed()
-{
-#ifdef WIN32
- if (running)
- QueryPerformanceCounter(&endCount);
-
- startTime = startCount.QuadPart * (1e3 / frequency.QuadPart);
- endTime = endCount.QuadPart * (1e3 / frequency.QuadPart);
-#else
- (void) gettimeofday(&endCount, NULL);
-
- startTime = (startCount.tv_sec * 1e3) + startCount.tv_usec;
- endTime = (endCount.tv_sec * 1e3) + endCount.tv_usec;
-#endif
-
- return endTime - startTime;
-} \ No newline at end of file
diff --git a/ftnoir_tracker_pt/timer.h b/ftnoir_tracker_pt/timer.h
deleted file mode 100644
index 2aaf725a..00000000
--- a/ftnoir_tracker_pt/timer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef PT_TIMER_H
-#define PT_TIMER_H
-
-#ifdef WIN32 // Windows system specific
-#include <windows.h>
-#else // Unix based system specific
-#include <sys/time.h>
-#endif
-
-// ----------------------------------------------------------------------------
-// high resolution timer based on http://www.songho.ca/misc/timer/timer.html
-class Timer
-{
-public:
- Timer();
-
- void start();
- void stop();
- void restart() { start(); } // for Qt compatibility
- double elapsed(); // get elapsed time in ms
-
-protected:
- double startTime; // starting time in ms
- double endTime; // ending time in ms
- bool running;
-
-#ifdef WIN32
- LARGE_INTEGER frequency; // ticks per second
- LARGE_INTEGER startCount;
- LARGE_INTEGER endCount;
-#else
- timeval startCount;
- timeval endCount;
-#endif
-};
-
-#endif //PT_TIMER_H \ No newline at end of file
diff --git a/ftnoir_tracker_pt/video_widget.cpp b/ftnoir_tracker_pt/video_widget.cpp
deleted file mode 100644
index a13542ba..00000000
--- a/ftnoir_tracker_pt/video_widget.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "video_widget.h"
-
-#include <QDebug>
-
-using namespace cv;
-using namespace std;
-
-void VideoWidget::update_image(Mat frame, std::auto_ptr< vector<Vec2f> >)
-{
- QMutexLocker foo(&mtx);
-
- if (frame.channels() != 3 && frame.channels() != 1)
- return;
-
- int width = frame.cols, height = frame.rows;
- unsigned char* src = frame.data;
-
- QImage qframe(width, height, QImage::Format_RGB888);
- if (frame.channels() == 3)
- {
- uchar* data = qframe.bits();
- const int pitch = qframe.bytesPerLine();
- for (int y = 0; y < height; y++)
- for (int x = 0; x < width; x++)
- {
- const int pos = 3 * (y*width + x);
- data[y * pitch + x * 3 + 0] = src[pos + 2];
- data[y * pitch + x * 3 + 1] = src[pos + 1];
- data[y * pitch + x * 3 + 2] = src[pos + 0];
- }
- } else {
- uchar* data = qframe.bits();
- const int pitch = qframe.bytesPerLine();
- for (int y = 0; y < height; y++)
- for (int x = 0; x < width; x++)
- {
- const int pos = (y*width + x);
- data[y * pitch + x * 3 + 0] = src[pos];
- data[y * pitch + x * 3 + 1] = src[pos];
- data[y * pitch + x * 3 + 2] = src[pos];
- }
- }
- qframe = qframe.scaled(size(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
- pixmap = QPixmap::fromImage(qframe);
-}
diff --git a/ftnoir_tracker_pt/videoinput/videoinput.h b/ftnoir_tracker_pt/videoinput/videoinput.h
deleted file mode 100644
index 02841418..00000000
--- a/ftnoir_tracker_pt/videoinput/videoinput.h
+++ /dev/null
@@ -1,385 +0,0 @@
-#ifndef _VIDEOINPUT
-#define _VIDEOINPUT
-
-//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-//THE SOFTWARE.
-
-//////////////////////////////////////////////////////////
-//Written by Theodore Watson - theo.watson@gmail.com //
-//Do whatever you want with this code but if you find //
-//a bug or make an improvement I would love to know! //
-// //
-//Warning This code is experimental //
-//use at your own risk :) //
-//////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/* Shoutouts
-
-Thanks to:
-
- Dillip Kumar Kara for crossbar code.
- Zachary Lieberman for getting me into this stuff
- and for being so generous with time and code.
- The guys at Potion Design for helping me with VC++
- Josh Fisher for being a serious C++ nerd :)
- Golan Levin for helping me debug the strangest
- and slowest bug in the world!
-
- And all the people using this library who send in
- bugs, suggestions and improvements who keep me working on
- the next version - yeah thanks a lot ;)
-
-*/
-/////////////////////////////////////////////////////////
-
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <wchar.h>
-
-//this is for TryEnterCriticalSection
-#ifndef _WIN32_WINNT
- # define _WIN32_WINNT 0x400
-#endif
-#include <windows.h>
-
-
-//Example Usage
-/*
- //create a videoInput object
- videoInput VI;
-
- //Prints out a list of available devices and returns num of devices found
- int numDevices = VI.listDevices();
-
- int device1 = 0; //this could be any deviceID that shows up in listDevices
- int device2 = 1; //this could be any deviceID that shows up in listDevices
-
- //if you want to capture at a different frame rate (default is 30)
- //specify it here, you are not guaranteed to get this fps though.
- //VI.setIdealFramerate(dev, 60);
-
- //setup the first device - there are a number of options:
-
- VI.setupDevice(device1); //setup the first device with the default settings
- //VI.setupDevice(device1, VI_COMPOSITE); //or setup device with specific connection type
- //VI.setupDevice(device1, 320, 240); //or setup device with specified video size
- //VI.setupDevice(device1, 320, 240, VI_COMPOSITE); //or setup device with video size and connection type
-
- //VI.setFormat(device1, VI_NTSC_M); //if your card doesn't remember what format it should be
- //call this with the appropriate format listed above
- //NOTE: must be called after setupDevice!
-
- //optionally setup a second (or third, fourth ...) device - same options as above
- VI.setupDevice(device2);
-
- //As requested width and height can not always be accomodated
- //make sure to check the size once the device is setup
-
- int width = VI.getWidth(device1);
- int height = VI.getHeight(device1);
- int size = VI.getSize(device1);
-
- unsigned char * yourBuffer1 = new unsigned char[size];
- unsigned char * yourBuffer2 = new unsigned char[size];
-
- //to get the data from the device first check if the data is new
- if(VI.isFrameNew(device1)){
- VI.getPixels(device1, yourBuffer1, false, false); //fills pixels as a BGR (for openCV) unsigned char array - no flipping
- VI.getPixels(device1, yourBuffer2, true, true); //fills pixels as a RGB (for openGL) unsigned char array - flipping!
- }
-
- //same applies to device2 etc
-
- //to get a settings dialog for the device
- VI.showSettingsWindow(device1);
-
-
- //Shut down devices properly
- VI.stopDevice(device1);
- VI.stopDevice(device2);
-*/
-
-
-////////////////////////////////////// VARS AND DEFS //////////////////////////////////
-
-
-//STUFF YOU CAN CHANGE
-
-//change for verbose debug info
-static bool verbose = true;
-
-//if you need VI to use multi threaded com
-//#define VI_COM_MULTI_THREADED
-
-//STUFF YOU DON'T CHANGE
-
-//videoInput defines
-#define VI_VERSION 0.1995
-#define VI_MAX_CAMERAS 20
-#define VI_NUM_TYPES 18 //DON'T TOUCH
-#define VI_NUM_FORMATS 18 //DON'T TOUCH
-
-//defines for setPhyCon - tuner is not as well supported as composite and s-video
-#define VI_COMPOSITE 0
-#define VI_S_VIDEO 1
-#define VI_TUNER 2
-#define VI_USB 3
-#define VI_1394 4
-
-//defines for formats
-#define VI_NTSC_M 0
-#define VI_PAL_B 1
-#define VI_PAL_D 2
-#define VI_PAL_G 3
-#define VI_PAL_H 4
-#define VI_PAL_I 5
-#define VI_PAL_M 6
-#define VI_PAL_N 7
-#define VI_PAL_NC 8
-#define VI_SECAM_B 9
-#define VI_SECAM_D 10
-#define VI_SECAM_G 11
-#define VI_SECAM_H 12
-#define VI_SECAM_K 13
-#define VI_SECAM_K1 14
-#define VI_SECAM_L 15
-#define VI_NTSC_M_J 16
-#define VI_NTSC_433 17
-
-
-//allows us to directShow classes here with the includes in the cpp
-struct ICaptureGraphBuilder2;
-struct IGraphBuilder;
-struct IBaseFilter;
-struct IAMCrossbar;
-struct IMediaControl;
-struct ISampleGrabber;
-struct IMediaEventEx;
-struct IAMStreamConfig;
-struct _AMMediaType;
-class SampleGrabberCallback;
-typedef _AMMediaType AM_MEDIA_TYPE;
-
-//keeps track of how many instances of VI are being used
-//don't touch
-static int comInitCount = 0;
-
-
-//////////////////////////////////////// VIDEO DEVICE ///////////////////////////////////
-
-class videoDevice{
-
-
- public:
-
- videoDevice();
- void setSize(int w, int h);
- void NukeDownstream(IBaseFilter *pBF);
- void destroyGraph();
- ~videoDevice();
-
- int videoSize;
- int width;
- int height;
- int tryWidth;
- int tryHeight;
-
- ICaptureGraphBuilder2 *pCaptureGraph; // Capture graph builder object
- IGraphBuilder *pGraph; // Graph builder object
- IMediaControl *pControl; // Media control object
- IBaseFilter *pVideoInputFilter; // Video Capture filter
- IBaseFilter *pGrabberF;
- IBaseFilter * pDestFilter;
- IAMStreamConfig *streamConf;
- ISampleGrabber * pGrabber; // Grabs frame
- AM_MEDIA_TYPE * pAmMediaType;
-
- IMediaEventEx * pMediaEvent;
-
- GUID videoType;
- long formatType;
-
- SampleGrabberCallback * sgCallback;
-
- bool tryDiffSize;
- bool useCrossbar;
- bool readyToCapture;
- bool sizeSet;
- bool setupStarted;
- bool specificFormat;
- bool autoReconnect;
- int nFramesForReconnect;
- unsigned long nFramesRunning;
- int connection;
- int storeConn;
- int myID;
- long requestedFrameTime; //ie fps
-
- char nDeviceName[255];
- WCHAR wDeviceName[255];
-
- unsigned char * pixels;
- char * pBuffer;
-
-};
-
-
-
-
-////////////////////////////////////// VIDEO INPUT /////////////////////////////////////
-
-
-
-class videoInput{
-
- public:
- videoInput();
- ~videoInput();
-
- //turns off console messages - default is to print messages
- static void setVerbose(bool _verbose);
-
- //Functions in rough order they should be used.
- static int listDevices(bool silent = false);
-
- //needs to be called after listDevices - otherwise returns NULL
- static char * getDeviceName(int deviceID);
-
- //choose to use callback based capture - or single threaded
- void setUseCallback(bool useCallback);
-
- //call before setupDevice
- //directshow will try and get the closest possible framerate to what is requested
- void setIdealFramerate(int deviceID, int idealFramerate);
-
- //some devices will stop delivering frames after a while - this method gives you the option to try and reconnect
- //to a device if videoInput detects that a device has stopped delivering frames.
- //you MUST CALL isFrameNew every app loop for this to have any effect
- void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect);
-
- //Choose one of these four to setup your device
- bool setupDevice(int deviceID);
- bool setupDevice(int deviceID, int w, int h);
-
- //These two are only for capture cards
- //USB and Firewire cameras souldn't specify connection
- bool setupDevice(int deviceID, int connection);
- bool setupDevice(int deviceID, int w, int h, int connection);
-
- //If you need to you can set your NTSC/PAL/SECAM
- //preference here. if it is available it will be used.
- //see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B
- //should be called after setupDevice
- //can be called multiple times
- bool setFormat(int deviceNumber, int format);
-
- //Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true
- bool isFrameNew(int deviceID);
-
- bool isDeviceSetup(int deviceID);
-
- //Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too
- unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false);
-
- //Or pass in a buffer for getPixels to fill returns true if successful.
- bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false);
-
- //Launches a pop up settings window
- //For some reason in GLUT you have to call it twice each time.
- void showSettingsWindow(int deviceID);
-
- //Manual control over settings thanks.....
- //These are experimental for now.
- bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
- bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = NULL);
- bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long &currentValue, long &flags, long &defaultValue);
-
- bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
- bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = NULL);
- bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long &currentValue, long &flags, long &defaultValue);
-
- //bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
-
- //get width, height and number of pixels
- int getWidth(int deviceID);
- int getHeight(int deviceID);
- int getSize(int deviceID);
-
- //completely stops and frees a device
- void stopDevice(int deviceID);
-
- //as above but then sets it up with same settings
- bool restartDevice(int deviceID);
-
- //number of devices available
- int devicesFound;
-
- long propBrightness;
- long propContrast;
- long propHue;
- long propSaturation;
- long propSharpness;
- long propGamma;
- long propColorEnable;
- long propWhiteBalance;
- long propBacklightCompensation;
- long propGain;
-
- long propPan;
- long propTilt;
- long propRoll;
- long propZoom;
- long propExposure;
- long propIris;
- long propFocus;
-
-
- private:
- void setPhyCon(int deviceID, int conn);
- void setAttemptCaptureSize(int deviceID, int w, int h);
- bool setup(int deviceID);
- void processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip);
- int start(int deviceID, videoDevice * VD);
- int getDeviceCount();
- void getMediaSubtypeAsString(GUID type, char * typeAsString);
-
- HRESULT getDevice(IBaseFilter **pSrcFilter, int deviceID, WCHAR * wDeviceName, char * nDeviceName);
- static HRESULT ShowFilterPropertyPages(IBaseFilter *pFilter);
- HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath);
- HRESULT routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode);
-
- //don't touch
- static bool comInit();
- static bool comUnInit();
-
- int connection;
- int callbackSetCount;
- bool bCallback;
-
- GUID CAPTURE_MODE;
-
- //Extra video subtypes
- GUID MEDIASUBTYPE_Y800;
- GUID MEDIASUBTYPE_Y8;
- GUID MEDIASUBTYPE_GREY;
-
- videoDevice * VDList[VI_MAX_CAMERAS];
- GUID mediaSubtypes[VI_NUM_TYPES];
- long formatTypes[VI_NUM_FORMATS];
-
- static void __cdecl basicThread(void * objPtr);
-
- static char deviceNames[VI_MAX_CAMERAS][255];
-
-};
-
- #endif
diff --git a/ftnoir_tracker_pt/videoinput/videoinput_vc8.lib b/ftnoir_tracker_pt/videoinput/videoinput_vc8.lib
deleted file mode 100644
index 15ca9cf3..00000000
--- a/ftnoir_tracker_pt/videoinput/videoinput_vc8.lib
+++ /dev/null
Binary files differ
diff --git a/ftnoir_tracker_pt/videoinput/videoinput_vc9.lib b/ftnoir_tracker_pt/videoinput/videoinput_vc9.lib
deleted file mode 100644
index 32637cc9..00000000
--- a/ftnoir_tracker_pt/videoinput/videoinput_vc9.lib
+++ /dev/null
Binary files differ
diff --git a/ftnoir_tracker_rift/ftnoir_rift.qrc b/ftnoir_tracker_rift/ftnoir_rift.qrc
new file mode 100644
index 00000000..cd174fc4
--- /dev/null
+++ b/ftnoir_tracker_rift/ftnoir_rift.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/rift_medium.png</file>
+ <file>images/rift_small.png</file>
+ <file>images/rift_tiny.png</file>
+ </qresource>
+</RCC>
diff --git a/ftnoir_tracker_rift/ftnoir_rift_clientcontrols.ui b/ftnoir_tracker_rift/ftnoir_rift_clientcontrols.ui
index eaf5b9d6..a9168239 100644
--- a/ftnoir_tracker_rift/ftnoir_rift_clientcontrols.ui
+++ b/ftnoir_tracker_rift/ftnoir_rift_clientcontrols.ui
@@ -1,15 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UIRiftControls</class>
- <widget class="QWidget" name="UIHydraControls">
+ <widget class="QWidget" name="UIRiftControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>411</width>
- <height>142</height>
+ <width>209</width>
+ <height>288</height>
</rect>
</property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="windowTitle">
<string>Oculus Rift tracker settings FaceTrackNoIR</string>
</property>
@@ -23,232 +32,260 @@
<property name="autoFillBackground">
<bool>false</bool>
</property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
<widget class="QGroupBox" name="groupBox_3">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>85</height>
- </size>
- </property>
<property name="title">
<string>Enable Axis</string>
</property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>143</width>
- <height>60</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
-
-
-
- <item row="0" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>Pitch:</string>
- </property>
- </widget>
- </item>
-
- <item row="0" column="1">
- <widget class="QCheckBox" name="chkEnablePitch">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </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="0">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Yaw:</string>
- </property>
- </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="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
-
-
-
- <item row="2" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Roll:</string>
- </property>
- </widget>
- </item>
-
- <item row="2" column="1">
- <widget class="QCheckBox" name="chkEnableRoll">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
-
-
-
-
-
-
-
-
- </layout>
- </widget>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pitch:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="chkEnablePitch">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </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="0">
+ <widget class="QLabel" name="label_9">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Yaw:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="chkEnableYaw">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </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_11">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Roll:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="chkEnableRoll">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>20</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Yaw spring</string>
</property>
- </spacer>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="yawSpring">
+ <property name="text">
+ <string>Enable</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Persistence</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="persistence">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>0.900000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.001000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Constant drift</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDoubleSpinBox" name="constantDrift">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="minimum">
+ <double>0.000100000000000</double>
+ </property>
+ <property name="maximum">
+ <double>0.100000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.001000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Deadzone</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QDoubleSpinBox" name="deadzone">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="decimals">
+ <number>5</number>
+ </property>
+ <property name="maximum">
+ <double>0.100000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <item row="2" column="0">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
</item>
</layout>
</widget>
- <tabstops>
- <tabstop>btnOK</tabstop>
- <tabstop>btnCancel</tabstop>
- </tabstops>
<resources/>
<connections/>
<slots>
diff --git a/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp b/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp
index eb05d5f9..b548db71 100644
--- a/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp
+++ b/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp
@@ -8,167 +8,84 @@ using namespace OVR;
Rift_Tracker::Rift_Tracker()
{
- pSensor.Clear();
- pHMD.Clear();
- pManager.Clear();
- bEnableRoll = true;
- bEnablePitch = true;
- bEnableYaw = true;
-#if 0
- bEnableX = true;
- bEnableY = true;
- bEnableZ = true;
-#endif
- isCalibrated = false;
- should_quit = false;
- for (int i = 0; i < 6; i++)
- newHeadPose[i] = 0;
+ should_quit = false;
+ pManager = NULL;
+ pSensor = NULL;
+ pSFusion = NULL;
+ old_yaw = 0;
}
Rift_Tracker::~Rift_Tracker()
{
- pSensor.Clear();
- pHMD.Clear();
- pManager.Clear();
- System::Destroy();
+ if (pSensor)
+ pSensor->Release();
+ if (pSFusion)
+ delete pSFusion;
+ if (pManager)
+ pManager->Release();
+ System::Destroy();
}
-/*
-void controller_manager_setup_callback( sixenseUtils::ControllerManager::setup_step step ) {
-
- QMessageBox::warning(0,"OpenTrack Info", "controller manager callback",QMessageBox::Ok,QMessageBox::NoButton);
- if( sixenseUtils::getTheControllerManager()->isMenuVisible() ) {
- // Ask the controller manager what the next instruction string should be.
- std::string controller_manager_text_string = sixenseUtils::getTheControllerManager()->getStepString();
- QMessageBox::warning(0,"OpenTrack Info", controller_manager_text_string.c_str(),QMessageBox::Ok,QMessageBox::NoButton);
- // We could also load the supplied controllermanager textures using the filename: sixenseUtils::getTheControllerManager()->getTextureFileName();
-
- }
-}*/
-
-void Rift_Tracker::StartTracker(QFrame* videoFrame)
+void Rift_Tracker::StartTracker(QFrame*)
{
- //QMessageBox::warning(0,"FaceTrackNoIR Notification", "Tracking loading settings...",QMessageBox::Ok,QMessageBox::NoButton);
- loadSettings();
- //
- // Startup the Oculus SDK device handling, use the first Rift sensor we find.
- //
System::Init(Log::ConfigureDefaultLog(LogMask_All));
- pManager = *DeviceManager::Create();
- DeviceEnumerator<HMDDevice>& enumerator = pManager->EnumerateDevices<HMDDevice>();
- if (enumerator.IsAvailable())
+ pManager = DeviceManager::Create();
+ if (pManager != NULL)
{
- pHMD = *enumerator.CreateDevice();
-
- pSensor = *pHMD->GetSensor();
-
- if (pSensor){
- SFusion.AttachToSensor(pSensor);
+ DeviceEnumerator<OVR::SensorDevice> enumerator = pManager->EnumerateDevices<OVR::SensorDevice>();
+ if (enumerator.IsAvailable())
+ {
+ pSensor = enumerator.CreateDevice();
+
+ if (pSensor){
+ pSFusion = new OVR::SensorFusion();
+ pSFusion->Reset();
+ pSFusion->AttachToSensor(pSensor);
+ }else{
+ QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to create Rift sensor",QMessageBox::Ok,QMessageBox::NoButton);
+ }
+
}else{
- QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to find Rift tracker",QMessageBox::Ok,QMessageBox::NoButton);
+ QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to enumerate Rift tracker",QMessageBox::Ok,QMessageBox::NoButton);
}
- isCalibrated = false;
- MagCal.BeginAutoCalibration(SFusion);
-
- }
+ }else{
+ QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to start Rift tracker",QMessageBox::Ok,QMessageBox::NoButton);
+ }
}
-bool Rift_Tracker::GiveHeadPoseData(double *data)
+void Rift_Tracker::GetHeadPoseData(double *data)
{
- if (pHMD.GetPtr() != NULL) {
-
- if (MagCal.IsAutoCalibrating())
- {
- MagCal.UpdateAutoCalibration(SFusion);
- if (MagCal.IsCalibrated())
- {
- if(isCalibrated == false){
- //QMessageBox::warning(0,"OpenTrack Info", "Calibrated magnetic sensor",QMessageBox::Ok,QMessageBox::NoButton);
- //fprintf(stderr,"magnetic calibration complete\n");
- isCalibrated = true;
- }
- //Vector3f mc = MagCal.GetMagCenter();
- //SetAdjustMessage("Magnetometer Calibration Complete\nCenter: %f %f %f",mc.x,mc.y,mc.z);
- }
- //SetAdjustMessage("Mag has been successfully calibrated");
- }
-
- Quatf hmdOrient = SFusion.GetOrientation();
-
+ if (pSFusion != NULL && pSensor != NULL) {
+ Quatf hmdOrient = pSFusion->GetOrientation();
+ double newHeadPose[6];
+
float yaw = 0.0f;
float pitch = 0.0f;
float roll = 0.0f;
hmdOrient.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&yaw, &pitch , &roll);
- newHeadPose[Yaw] = yaw;
- newHeadPose[Pitch] =pitch;
+ newHeadPose[Pitch] = pitch;
newHeadPose[Roll] = roll;
-
-#if 0
-
- newHeadPose[TX] = acd.controllers[0].pos[0]/50.0f;
- newHeadPose[TY] = acd.controllers[0].pos[1]/50.0f;
- newHeadPose[TZ] = acd.controllers[0].pos[2]/50.0f;
-
- //if (bEnableX) {
- data[TX] = newHeadPose[TX];
- //}
- //if (bEnableY) {
- data[TY] = newHeadPose[TY];
- //}
- //if (bEnableY) {
- data[TZ] = newHeadPose[TZ];
- //}
-#endif
- if (bEnableYaw) {
+ newHeadPose[Yaw] = yaw;
+ if (s.useYawSpring)
+ {
+ newHeadPose[Yaw] = old_yaw*s.persistence + (yaw-old_yaw);
+ if(newHeadPose[Yaw]>s.deadzone)newHeadPose[Yaw]-= s.constant_drift;
+ if(newHeadPose[Yaw]<-s.deadzone)newHeadPose[Yaw]+= s.constant_drift;
+ old_yaw=yaw;
+ }
+ if (s.bEnableYaw) {
data[Yaw] = newHeadPose[Yaw] * 57.295781f;
}
- if (bEnablePitch) {
+ if (s.bEnablePitch) {
data[Pitch] = newHeadPose[Pitch] * 57.295781f;
}
- if (bEnableRoll) {
+ if (s.bEnableRoll) {
data[Roll] = newHeadPose[Roll] * 57.295781f;
}
}
- return pHMD.GetPtr() != NULL;
}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void Rift_Tracker::loadSettings() {
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Rift" );
- bEnableRoll = iniFile.value ( "EnableRoll", 1 ).toBool();
- bEnablePitch = iniFile.value ( "EnablePitch", 1 ).toBool();
- bEnableYaw = iniFile.value ( "EnableYaw", 1 ).toBool();
-#if 0
- bEnableX = iniFile.value ( "EnableX", 1 ).toBool();
- bEnableY = iniFile.value ( "EnableY", 1 ).toBool();
- bEnableZ = iniFile.value ( "EnableZ", 1 ).toBool();
-#endif
- iniFile.endGroup ();
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
{
return new Rift_Tracker;
diff --git a/ftnoir_tracker_rift/ftnoir_tracker_rift.h b/ftnoir_tracker_rift/ftnoir_tracker_rift.h
index 7bacb91c..7162b7ca 100644
--- a/ftnoir_tracker_rift/ftnoir_tracker_rift.h
+++ b/ftnoir_tracker_rift/ftnoir_tracker_rift.h
@@ -1,80 +1,70 @@
+#pragma once
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
#include "ui_ftnoir_rift_clientcontrols.h"
#include <QMessageBox>
-#include <QSettings>
#include <QWaitCondition>
-#include <math.h>
+#include <cmath>
#include "facetracknoir/global-settings.h"
#include "OVR.h"
-#include "Util/Util_MagCalibration.h"
+#include <memory>
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<bool> bEnableYaw, bEnablePitch, bEnableRoll, useYawSpring;
+ value<double> constant_drift, persistence, deadzone;
+ settings() :
+ b(bundle("Rift")),
+ bEnableYaw(b, "EnableYaw", true),
+ bEnablePitch(b, "EnablePitch", true),
+ bEnableRoll(b, "EnableRoll", true),
+ useYawSpring(b, "yaw-spring", false),
+ constant_drift(b, "constant-drift", 0.000005),
+ persistence(b, "persistence", 0.99999),
+ deadzone(b, "deadzone", 0.02)
+ {}
+};
+
class Rift_Tracker : public ITracker
{
public:
Rift_Tracker();
- ~Rift_Tracker();
+ virtual ~Rift_Tracker() virt_override;
- void StartTracker( QFrame *videoframe );
- bool GiveHeadPoseData(double *data);
- void loadSettings();
+ void StartTracker(QFrame *) virt_override;
+ void GetHeadPoseData(double *data) virt_override;
+ virtual int preferredHz() virt_override { return 250; }
volatile bool should_quit;
- void WaitForExit() {}
protected:
void run(); // qthread override run method
private:
static bool isInitialised;
- OVR::Ptr<OVR::DeviceManager> pManager;
- OVR::Ptr<OVR::HMDDevice> pHMD;
- OVR::Ptr<OVR::SensorDevice> pSensor;
- OVR::SensorFusion SFusion;
- // Magnetometer calibration and yaw correction
- OVR::Util::MagCalibration MagCal;
- bool isCalibrated;
-
- double newHeadPose[6]; // Structure with new headpose
- bool bEnableRoll;
- bool bEnablePitch;
- bool bEnableYaw;
-#if 0
- bool bEnableX;
- bool bEnableY;
- bool bEnableZ;
-#endif
- QMutex mutex;
+ OVR::DeviceManager* pManager;
+ OVR::SensorDevice* pSensor;
+ OVR::SensorFusion* pSFusion;
+ settings s;
+ double old_yaw;
};
-// Widget that has controls for FTNoIR protocol client-settings.
class TrackerControls: public QWidget, public ITrackerDialog
{
Q_OBJECT
public:
-
explicit TrackerControls();
- ~TrackerControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {}
+ void registerTracker(ITracker *) {}
void unRegisterTracker() {}
private:
Ui::UIRiftControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
-
+ settings s;
private slots:
void doOK();
void doCancel();
- void settingChanged() { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
};
-//*******************************************************************************************************
-// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker
-//*******************************************************************************************************
class FTNoIR_TrackerDll : public Metadata
{
public:
diff --git a/ftnoir_tracker_rift/ftnoir_tracker_rift_dialog.cpp b/ftnoir_tracker_rift/ftnoir_tracker_rift_dialog.cpp
index 0b644723..ad532100 100644
--- a/ftnoir_tracker_rift/ftnoir_tracker_rift_dialog.cpp
+++ b/ftnoir_tracker_rift/ftnoir_tracker_rift_dialog.cpp
@@ -1,182 +1,35 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_rift.h"
#include "facetracknoir/global-settings.h"
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
TrackerControls::TrackerControls() :
QWidget()
{
ui.setupUi( this );
// Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
-
- connect(ui.chkEnableRoll, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnablePitch, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableYaw, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
-#if 0
- connect(ui.chkEnableX, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableY, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableZ, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
-#endif
- // Load the settings from the current .INI-file
- loadSettings();
-}
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel()));
-//
-// Destructor for server-dialog
-//
-TrackerControls::~TrackerControls() {
- qDebug() << "~TrackerControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void TrackerControls::Initialize(QWidget *parent) {
+ tie_setting(s.bEnableYaw, ui.chkEnableYaw);
+ tie_setting(s.bEnablePitch, ui.chkEnablePitch);
+ tie_setting(s.bEnableRoll, ui.chkEnableRoll);
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
+ tie_setting(s.constant_drift, ui.constantDrift);
+ tie_setting(s.deadzone, ui.deadzone);
+ tie_setting(s.persistence, ui.persistence);
+ tie_setting(s.useYawSpring, ui.yawSpring);
}
-//
-// OK clicked on server-dialog
-//
void TrackerControls::doOK() {
- save();
+ s.b->save();
this->close();
}
-// override show event
-void TrackerControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// 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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
+ s.b->revert();
+ close();
}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void TrackerControls::loadSettings() {
-
-// qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
-// qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "Rift" );
- ui.chkEnableRoll->setChecked(iniFile.value ( "EnableRoll", 1 ).toBool());
- ui.chkEnablePitch->setChecked(iniFile.value ( "EnablePitch", 1 ).toBool());
- ui.chkEnableYaw->setChecked(iniFile.value ( "EnableYaw", 1 ).toBool());
-#if 0
- ui.chkEnableX->setChecked(iniFile.value ( "EnableX", 1 ).toBool());
- ui.chkEnableY->setChecked(iniFile.value ( "EnableY", 1 ).toBool());
- ui.chkEnableZ->setChecked(iniFile.value ( "EnableZ", 1 ).toBool());
-#endif
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void TrackerControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "Rift" );
- iniFile.setValue ( "EnableRoll", ui.chkEnableRoll->isChecked() );
- iniFile.setValue ( "EnablePitch", ui.chkEnablePitch->isChecked() );
- iniFile.setValue ( "EnableYaw", ui.chkEnableYaw->isChecked() );
-#if 0
- iniFile.setValue ( "EnableX", ui.chkEnableX->isChecked() );
- iniFile.setValue ( "EnableY", ui.chkEnableY->isChecked() );
- iniFile.setValue ( "EnableZ", ui.chkEnableZ->isChecked() );
-#endif
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
-
extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
{
return new TrackerControls;
diff --git a/ftnoir_tracker_rift/ftnoir_tracker_rift_dll.cpp b/ftnoir_tracker_rift/ftnoir_tracker_rift_dll.cpp
index 775eedfc..2b24411c 100644
--- a/ftnoir_tracker_rift/ftnoir_tracker_rift_dll.cpp
+++ b/ftnoir_tracker_rift/ftnoir_tracker_rift_dll.cpp
@@ -18,31 +18,22 @@ FTNoIR_TrackerDll::~FTNoIR_TrackerDll()
void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled)
{
*strToBeFilled = trackerFullName;
-};
+}
void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled)
{
*strToBeFilled = trackerShortName;
-};
+}
void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled)
{
*strToBeFilled = trackerDescription;
-};
+}
void FTNoIR_TrackerDll::getIcon(QIcon *icon)
{
- *icon = QIcon(":/images/facetracknoir.png");
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
+ *icon = QIcon(":/images/rift_tiny.png");
+}
extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
{
diff --git a/ftnoir_tracker_rift/images/medium.png b/ftnoir_tracker_rift/images/medium.png
new file mode 100644
index 00000000..a5ba49e7
--- /dev/null
+++ b/ftnoir_tracker_rift/images/medium.png
Binary files differ
diff --git a/ftnoir_tracker_rift/images/rift_medium.png b/ftnoir_tracker_rift/images/rift_medium.png
new file mode 100644
index 00000000..a5ba49e7
--- /dev/null
+++ b/ftnoir_tracker_rift/images/rift_medium.png
Binary files differ
diff --git a/ftnoir_tracker_rift/images/rift_small.png b/ftnoir_tracker_rift/images/rift_small.png
new file mode 100644
index 00000000..3f18080c
--- /dev/null
+++ b/ftnoir_tracker_rift/images/rift_small.png
Binary files differ
diff --git a/ftnoir_tracker_rift/images/rift_tiny.png b/ftnoir_tracker_rift/images/rift_tiny.png
new file mode 100644
index 00000000..76fe0f58
--- /dev/null
+++ b/ftnoir_tracker_rift/images/rift_tiny.png
Binary files differ
diff --git a/ftnoir_tracker_rift/images/small.png b/ftnoir_tracker_rift/images/small.png
new file mode 100644
index 00000000..3f18080c
--- /dev/null
+++ b/ftnoir_tracker_rift/images/small.png
Binary files differ
diff --git a/ftnoir_tracker_rift/images/tiny.png b/ftnoir_tracker_rift/images/tiny.png
new file mode 100644
index 00000000..76fe0f58
--- /dev/null
+++ b/ftnoir_tracker_rift/images/tiny.png
Binary files differ
diff --git a/ftnoir_tracker_sm/ftnoir_sm_controls.ui b/ftnoir_tracker_sm/ftnoir_sm_controls.ui
deleted file mode 100644
index 06ebc9ca..00000000
--- a/ftnoir_tracker_sm/ftnoir_sm_controls.ui
+++ /dev/null
@@ -1,405 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>UICSMClientControls</class>
- <widget class="QWidget" name="UICSMClientControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>388</width>
- <height>313</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>faceAPI tracker settings FaceTrackNoIR</string>
- </property>
- <property name="windowIcon">
- <iconset>
- <normaloff>images/sm.png</normaloff>images/sm.png</iconset>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <layout class="QVBoxLayout" name="_vertical_layout">
- <item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="1">
- <widget class="QLabel" name="_engine_state_label">
- <property name="minimumSize">
- <size>
- <width>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string>wait...</string>
- </property>
- </widget>
- </item>
- <item row="1" column="4">
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="3" column="1">
- <widget class="QPushButton" name="btnCameraSettings">
- <property name="text">
- <string>Camera</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="btnEngineStart">
- <property name="text">
- <string>Start</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QPushButton" name="btnEngineStop">
- <property name="text">
- <string>Stop</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Engine state:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Internal filtering:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QComboBox" name="cbxFilterSetting"/>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>140</height>
- </size>
- </property>
- <property name="title">
- <string>Enable Axis</string>
- </property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>20</y>
- <width>55</width>
- <height>110</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>Roll:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Pitch:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>Yaw:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QCheckBox" name="chkEnableRoll">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </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="3" column="0">
- <widget class="QLabel" name="label_12">
- <property name="text">
- <string>X:</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_13">
- <property name="text">
- <string>Y:</string>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_14">
- <property name="text">
- <string>Z:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="chkEnablePitch">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QCheckBox" name="chkEnableYaw">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QCheckBox" name="chkEnableX">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </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="chkEnableY">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QCheckBox" name="chkEnableZ">
- <property name="maximumSize">
- <size>
- <width>20</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout"/>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnSave">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>70</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <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>70</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- </item>
- <item>
- <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>70</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>100</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>10</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>btnOK</tabstop>
- <tabstop>btnCancel</tabstop>
- </tabstops>
- <resources/>
- <connections/>
- <slots>
- <slot>startEngineClicked()</slot>
- <slot>stopEngineClicked()</slot>
- <slot>cameraSettingsClicked()</slot>
- </slots>
-</ui>
diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp
deleted file mode 100644
index 74e1d3d2..00000000
--- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_sm.h"
-#include <QtGui>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_Tracker::FTNoIR_Tracker() : lck_shm(SM_MM_DATA, SM_MUTEX, sizeof(SMMemMap))
-{
- pMemData = (SMMemMap*) lck_shm.mem;
-}
-
-FTNoIR_Tracker::~FTNoIR_Tracker()
-{
- qDebug() << "~FTNoIR_Tracker says: cleaning up";
-
- bEnableRoll = true;
- bEnablePitch = true;
- bEnableYaw = true;
- bEnableX = true;
- bEnableY = true;
- bEnableZ = true;
-}
-
-void FTNoIR_Tracker::StartTracker(QFrame *videoframe )
-{
- qDebug() << "FTNoIR_Tracker::Initialize says: Starting ";
-
- loadSettings();
-
- if ( pMemData != NULL ) {
- pMemData->command = 0; // Reset any and all commands
- if (videoframe != NULL) {
- pMemData->handle = videoframe->winId(); // Handle of Videoframe widget
- }
- else {
- pMemData->handle = NULL; // reset Handle of Videoframe widget
- }
- }
-
- //
- // Start FTNoIR_FaceAPI_EXE.exe. The exe contains all faceAPI-stuff and is non-Qt...
- //
- // XXX TODO isolate it into separate directory
- faceAPI = new QProcess();
- faceAPI->setWorkingDirectory(QCoreApplication::applicationDirPath() + "/faceapi");
- faceAPI->start("\"" + QCoreApplication::applicationDirPath() + "/faceapi/opentrack-faceapi-wrapper" + "\"");
- // Show the video widget
- qDebug() << "FTNoIR_Tracker::Initialize says: videoframe = " << videoframe;
-
- if (videoframe != NULL) {
- videoframe->show();
- }
- if ( pMemData != NULL ) {
- pMemData->command = FT_SM_START; // Start command
- }
-}
-
-void FTNoIR_Tracker::WaitForExit()
-{
-
- qDebug() << "FTNoIR_Tracker::StopTracker says: Starting ";
- // stops the faceapi engine
- if ( pMemData != NULL ) {
-// if (exit == true) {
- pMemData->command = FT_SM_EXIT;
- //}
- //else {
- // pMemData->command = FT_SM_STOP; // Issue 'stop' command
- //}
- }
-}
-
-bool FTNoIR_Tracker::GiveHeadPoseData(double *data)
-{
- //
- // Check if the pointer is OK and wait for the Mutex.
- //
- lck_shm.lock();
-
- //
- // Copy the measurements to FaceTrackNoIR.
- //
- if (bEnableX) {
- data[TX] = pMemData->data.new_pose.head_pos.x * 100.0f; // From meters to centimeters
- }
- if (bEnableY) {
- data[TY] = pMemData->data.new_pose.head_pos.y * 100.0f;
- }
- if (bEnableZ) {
- data[TZ] = pMemData->data.new_pose.head_pos.z * 100.0f;
- }
- if (bEnableYaw) {
- data[Yaw] = pMemData->data.new_pose.head_rot.y_rads * 57.295781f; // From rads to degrees
- }
- if (bEnablePitch) {
- data[Pitch] = pMemData->data.new_pose.head_rot.x_rads * 57.295781f;
- }
- if (bEnableRoll) {
- data[Roll] = pMemData->data.new_pose.head_rot.z_rads * 57.295781f;
- }
-
- //
- // Reset the handshake, to let faceAPI know we're still here!
- //
- pMemData->handshake = 0;
- lck_shm.unlock();
-
- return ( pMemData->data.new_pose.confidence > 0 );
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Tracker::loadSettings() {
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "SMTracker" );
- if (pMemData) {
- pMemData->initial_filter_level = iniFile.value ( "FilterLevel", 1 ).toInt();
- }
-
- bEnableRoll = iniFile.value ( "EnableRoll", 1 ).toBool();
- bEnablePitch = iniFile.value ( "EnablePitch", 1 ).toBool();
- bEnableYaw = iniFile.value ( "EnableYaw", 1 ).toBool();
- bEnableX = iniFile.value ( "EnableX", 1 ).toBool();
- bEnableY = iniFile.value ( "EnableY", 1 ).toBool();
- bEnableZ = iniFile.value ( "EnableZ", 1 ).toBool();
-
- iniFile.endGroup ();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Tracker;
-}
diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp
deleted file mode 100644
index f515dedc..00000000
--- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_sm.h"
-#include <QtGui>
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// faceAPI Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-TrackerControls::TrackerControls() :
- QWidget(),
- shm(SM_MM_DATA, SM_MUTEX, sizeof(TFaceData))
-{
- pMemData = (SMMemMap*) shm.mem;
-
- ui.setupUi( this );
-
- theTracker = NULL;
- prev_state = -1;
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.btnEngineStart, SIGNAL(clicked()), this, SLOT(doStartEngine()));
- connect(ui.btnEngineStop, SIGNAL(clicked()), this, SLOT(doStopEngine()));
- connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save()));
-
- ui.cbxFilterSetting->addItem("None");
- ui.cbxFilterSetting->addItem("Normal");
- ui.cbxFilterSetting->addItem("High");
- connect(ui.cbxFilterSetting, SIGNAL(currentIndexChanged(int)), this, SLOT(doSetFilter( int )));
- connect(ui.btnCameraSettings, SIGNAL(clicked()), this, SLOT(doShowCam()));
-
- //Setup the timer for showing the headpose.
- timUpdateSettings = new QTimer(this);
- connect(timUpdateSettings, SIGNAL(timeout()), this, SLOT(doTimUpdate()));
- timUpdateSettings->start(100);
- connect(this, SIGNAL(stateChanged( int )), this, SLOT(showSettings( int )));
-
- connect(ui.chkEnableRoll, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnablePitch, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableYaw, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableX, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableY, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableZ, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
-}
-
-//
-// Destructor for server-dialog
-//
-TrackerControls::~TrackerControls() {
- qDebug() << "~TrackerControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void TrackerControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(200, 200);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
-
- // Load the settings from the current .INI-file
- loadSettings();
-
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void TrackerControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void TrackerControls::showEvent ( QShowEvent * event ) {
- prev_state = -1;
- loadSettings();
-}
-
-//
-// 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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void TrackerControls::loadSettings() {
-
-// qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
-// qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "SMTracker" );
- ui.cbxFilterSetting->setCurrentIndex(iniFile.value ( "FilterLevel", 1 ).toInt());
-
- ui.chkEnableRoll->setChecked(iniFile.value ( "EnableRoll", 1 ).toBool());
- ui.chkEnablePitch->setChecked(iniFile.value ( "EnablePitch", 1 ).toBool());
- ui.chkEnableYaw->setChecked(iniFile.value ( "EnableYaw", 1 ).toBool());
- ui.chkEnableX->setChecked(iniFile.value ( "EnableX", 1 ).toBool());
- ui.chkEnableY->setChecked(iniFile.value ( "EnableY", 1 ).toBool());
- ui.chkEnableZ->setChecked(iniFile.value ( "EnableZ", 1 ).toBool());
-
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void TrackerControls::save() {
-
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "SMTracker" );
- iniFile.setValue ( "FilterLevel", ui.cbxFilterSetting->currentIndex() );
-
- iniFile.setValue ( "EnableRoll", ui.chkEnableRoll->isChecked() );
- iniFile.setValue ( "EnablePitch", ui.chkEnablePitch->isChecked() );
- iniFile.setValue ( "EnableYaw", ui.chkEnableYaw->isChecked() );
- iniFile.setValue ( "EnableX", ui.chkEnableX->isChecked() );
- iniFile.setValue ( "EnableY", ui.chkEnableY->isChecked() );
- iniFile.setValue ( "EnableZ", ui.chkEnableZ->isChecked() );
-
- iniFile.endGroup ();
-
- //
- // If the Tracker is active, let it load the new Settings.
- //
- if (theTracker) {
- theTracker->loadSettings();
- }
-
- settingsDirty = false;
-}
-
-// Show the current engine-settings etc.
-//
-void TrackerControls::doTimUpdate()
-{
- int state = pMemData->state;
- if ( state != prev_state) {
- emit stateChanged(state);
- prev_state = state;
- }
-}
-
-//
-// Show the current engine-settings etc.
-//
-void TrackerControls::showSettings( int newState )
-{
- qDebug() << "TrackerControls::showSettings says: Starting Function";
- switch (newState)
- {
- case SM_API_ENGINE_STATE_TERMINATED:
- ui._engine_state_label->setText("TERMINATED");
- break;
- case SM_API_ENGINE_STATE_INVALID:
- ui._engine_state_label->setText("INVALID");
- break;
- case SM_API_ENGINE_STATE_IDLE:
- ui._engine_state_label->setText("IDLE");
- break;
- case SM_API_ENGINE_STATE_HT_INITIALIZING:
- ui._engine_state_label->setText("INITIALIZING");
- break;
- case SM_API_ENGINE_STATE_HT_TRACKING:
- ui._engine_state_label->setText("TRACKING");
- break;
- case SM_API_ENGINE_STATE_HT_SEARCHING:
- ui._engine_state_label->setText("SEARCHING");
- break;
- default:
- ui._engine_state_label->setText("Unknown State!");
- break;
- }
-
- ui.cbxFilterSetting->setEnabled( (newState == SM_API_ENGINE_STATE_IDLE) );
-}
-
-//
-// Send a command without parameter-value to the tracking Engine.
-//
-void TrackerControls::doCommand(int command)
-{
- shm.lock();
- pMemData->command = command;
- shm.unlock();
-}
-
-//
-// Send a command with integer parameter-value to the tracking Engine.
-//
-void TrackerControls::doCommand(int command, int value)
-{
- shm.lock();
- pMemData->command = command; // Send command
- pMemData->par_val_int = value;
- shm.unlock();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog()
-{
- return new TrackerControls;
-}
diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp
deleted file mode 100644
index c824a217..00000000
--- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The TrackerDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_tracker_sm.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_TrackerDll::FTNoIR_TrackerDll() {
- //populate the description strings
- trackerFullName = "faceAPI V3.2.6";
- trackerShortName = "faceAPI";
- trackerDescription = "SeeingMachines faceAPI V3.2.6";
-}
-
-FTNoIR_TrackerDll::~FTNoIR_TrackerDll()
-{
-
-}
-void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled)
-{
- *strToBeFilled = trackerFullName;
-};
-
-void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled)
-{
- *strToBeFilled = trackerShortName;
-};
-
-void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled)
-{
- *strToBeFilled = trackerDescription;
-};
-
-void FTNoIR_TrackerDll::getIcon(QIcon *icon)
-{
- *icon = QIcon(":/images/sm.png");
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_TrackerDll;
-}
diff --git a/ftnoir_tracker_sm/ftnoir_tracker_sm.h b/ftnoir_tracker_sm/ftnoir_tracker_sm.h
deleted file mode 100644
index 33cfb9ef..00000000
--- a/ftnoir_tracker_sm/ftnoir_tracker_sm.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_base\ftnoir_tracker_base.h"
-#include "..\ftnoir_tracker_base\ftnoir_tracker_sm_types.h"
-#include "ui_FTNoIR_SM_controls.h"
-
-#include <QMessageBox>
-#include <QSettings>
-#include <QProcess>
-#include "Windows.h"
-#include "math.h"
-#include "facetracknoir/global-settings.h"
-#include "compat/compat.h"
-#include <QFrame>
-
-using namespace std;
-
-class FTNoIR_Tracker : public ITracker
-{
-public:
- FTNoIR_Tracker();
- ~FTNoIR_Tracker();
-
- void StartTracker( QFrame* parent_window );
- void StopTracker( bool exit );
- bool GiveHeadPoseData(double *data); // Returns true if confidence is good
- void WaitForExit();
-
- void loadSettings();
-
-private:
- //
- // global variables
- //
- PortableLockedShm lck_shm;
- SMMemMap *pMemData;
- QProcess *faceAPI;
-
- bool bEnableRoll;
- bool bEnablePitch;
- bool bEnableYaw;
- bool bEnableX;
- bool bEnableY;
- bool bEnableZ;
-};
-
-// Widget that has controls for SMoIR protocol client-settings.
-class TrackerControls: public QWidget, public ITrackerDialog
-{
- Q_OBJECT
-public:
-
- explicit TrackerControls();
- virtual ~TrackerControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {
- theTracker = (FTNoIR_Tracker *) tracker; // Accept the pointer to the Tracker
- }
- void unRegisterTracker() {
- theTracker = NULL; // Reset the pointer
- }
-
-private:
- Ui::UICSMClientControls ui;
- void loadSettings();
- void doCommand( int command );
- void doCommand( int command, int value );
-
- /** helper **/
- bool settingsDirty;
- int prev_state; // Previous engine state
-
- //
- // global variables
- //
- SMMemMap *pMemData;
-
- smEngineHandle *engine_handle;
- QTimer *timUpdateSettings; // Timer to display current settings
-
- FTNoIR_Tracker *theTracker;
- PortableLockedShm shm;
-
-private slots:
- void doOK();
- void doCancel();
- void save();
- void settingChanged() { settingsDirty = true; }
- void doTimUpdate();
- void showSettings( int newState );
- void doStartEngine(){
- doCommand(FT_SM_START);
- }
- void doStopEngine(){
- doCommand(FT_SM_STOP);
- }
- void doShowCam(){
- doCommand(FT_SM_SHOW_CAM);
- }
- void doSetFilter(int value){
- doCommand(FT_SM_SET_PAR_FILTER, value);
- }
- void settingChanged(int dummy) {
- settingsDirty = true;
- }
-
-signals:
- void stateChanged(int newState);
-
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker
-//*******************************************************************************************************
-class FTNoIR_TrackerDll : public Metadata
-{
-public:
- FTNoIR_TrackerDll();
- ~FTNoIR_TrackerDll();
-
- void Initialize();
-
- void getFullName(QString *strToBeFilled);
- void getShortName(QString *strToBeFilled);
- void getDescription(QString *strToBeFilled);
- void getIcon(QIcon *icon);
-
-private:
- QString trackerFullName; // Trackers' name and description
- QString trackerShortName;
- QString trackerDescription;
-};
diff --git a/ftnoir_tracker_sm/images/sm.png b/ftnoir_tracker_sm/images/sm.png
deleted file mode 100644
index 4910d1f0..00000000
--- a/ftnoir_tracker_sm/images/sm.png
+++ /dev/null
Binary files differ
diff --git a/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui b/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui
index 5883e317..5c602792 100644
--- a/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui
+++ b/ftnoir_tracker_udp/ftnoir_ftnclientcontrols.ui
@@ -2,20 +2,23 @@
<ui version="4.0">
<class>UICFTNClientControls</class>
<widget class="QWidget" name="UICFTNClientControls">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>411</width>
- <height>210</height>
+ <height>232</height>
</rect>
</property>
<property name="windowTitle">
- <string>FTNoIR tracker settings FaceTrackNoIR</string>
+ <string>UDP tracker settings</string>
</property>
<property name="windowIcon">
<iconset>
- <normaloff>images/FaceTrackNoIR.png</normaloff>images/FaceTrackNoIR.png</iconset>
+ <normaloff>../facetracknoir/images/facetracknoir.png</normaloff>../facetracknoir/images/facetracknoir.png</iconset>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
@@ -74,8 +77,8 @@
<rect>
<x>10</x>
<y>20</y>
- <width>143</width>
- <height>60</height>
+ <width>147</width>
+ <height>68</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp
index 83f518fa..02ae21f0 100644
--- a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp
+++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp
@@ -1,173 +1,83 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_udp.h"
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_Tracker::FTNoIR_Tracker()
-{
- inSocket = 0;
- outSocket = 0;
-
- bEnableRoll = true;
- bEnablePitch = true;
- bEnableYaw = true;
- bEnableX = true;
- bEnableY = true;
- bEnableZ = true;
- portAddress = 5551;
- should_quit = false;
-
- for (int i = 0; i < 6; i++)
- newHeadPose[i] = 0;
-}
-
-FTNoIR_Tracker::~FTNoIR_Tracker()
-{
- if (inSocket) {
- inSocket->close();
- delete inSocket;
- }
-
- if (outSocket) {
- outSocket->close();
- delete outSocket;
- }
-}
-
-/** QThread run @override **/
-void FTNoIR_Tracker::run() {
-
-QHostAddress sender;
-quint16 senderPort;
-
- //
- // Read the data that was received.
- //
- forever {
- if (should_quit)
- break;
- if (inSocket != 0) {
- while (inSocket->hasPendingDatagrams()) {
-
- QByteArray datagram;
- datagram.resize(inSocket->pendingDatagramSize());
- mutex.lock();
- inSocket->readDatagram( (char * ) &newHeadPose, sizeof(newHeadPose), &sender, &senderPort);
- mutex.unlock();
- }
- }
- else {
- break;
- }
-
- usleep(10000);
- }
-}
-
-void FTNoIR_Tracker::StartTracker(QFrame* videoFrame)
-{
- loadSettings();
- //
- // Create UDP-sockets if they don't exist already.
- // They must be created here, because they must be in the new thread (FTNoIR_Tracker::run())
- //
- if (inSocket == 0) {
- qDebug() << "FTNoIR_Tracker::Initialize() creating insocket";
- inSocket = new QUdpSocket();
- // Connect the inSocket to the port, to receive messages
-
- if (!inSocket->bind(QHostAddress::Any, (int) portAddress, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) {
- QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to bind UDP-port",QMessageBox::Ok,QMessageBox::NoButton);
- delete inSocket;
- inSocket = 0;
- }
- }
- start();
- return;
-}
-
-bool FTNoIR_Tracker::GiveHeadPoseData(double *data)
-{
- mutex.lock();
- if (bEnableX) {
- data[TX] = newHeadPose[TX];
- }
- if (bEnableX) {
- data[TY] = newHeadPose[TY];
- }
- if (bEnableX) {
- data[TZ] = newHeadPose[TZ];
- }
- if (bEnableYaw) {
- data[Yaw] = newHeadPose[Yaw];
- }
- if (bEnablePitch) {
- data[Pitch] = newHeadPose[Pitch];
- }
- if (bEnableRoll) {
- data[Roll] = newHeadPose[Roll];
- }
- mutex.unlock();
- return true;
-}
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void FTNoIR_Tracker::loadSettings() {
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- qDebug() << "FTNoIR_Tracker::loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "FTNClient" );
- bEnableRoll = iniFile.value ( "EnableRoll", 1 ).toBool();
- bEnablePitch = iniFile.value ( "EnablePitch", 1 ).toBool();
- bEnableYaw = iniFile.value ( "EnableYaw", 1 ).toBool();
- bEnableX = iniFile.value ( "EnableX", 1 ).toBool();
- bEnableY = iniFile.value ( "EnableY", 1 ).toBool();
- bEnableZ = iniFile.value ( "EnableZ", 1 ).toBool();
- portAddress = (float) iniFile.value ( "PortNumber", 5550 ).toInt();
- iniFile.endGroup ();
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTracker=_GetTracker@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Tracker;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_udp.h"
+#include "facetracknoir/global-settings.h"
+
+FTNoIR_Tracker::FTNoIR_Tracker() : should_quit(false)
+{
+ should_quit = false;
+
+ for (int i = 0; i < 6; i++)
+ newHeadPose[i] = 0;
+}
+
+FTNoIR_Tracker::~FTNoIR_Tracker()
+{
+ should_quit = true;
+ wait();
+}
+
+/** QThread run @override **/
+void FTNoIR_Tracker::run() {
+ forever {
+ if (should_quit)
+ break;
+ while (inSocket.hasPendingDatagrams()) {
+ QMutexLocker foo(&mutex);
+ QByteArray datagram;
+ datagram.resize(sizeof(newHeadPose));
+ inSocket.readDatagram((char * ) newHeadPose, sizeof(double[6]));
+ }
+ usleep(10000);
+ }
+}
+
+void FTNoIR_Tracker::StartTracker(QFrame*)
+{
+ (void) inSocket.bind(QHostAddress::Any, (int) s.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
+ start();
+}
+
+void FTNoIR_Tracker::GetHeadPoseData(double *data)
+{
+ QMutexLocker foo(&mutex);
+ if (s.enable_x)
+ data[TX] = newHeadPose[TX];
+ if (s.enable_y)
+ data[TY] = newHeadPose[TY];
+ if (s.enable_z)
+ data[TZ] = newHeadPose[TZ];
+ if (s.enable_yaw)
+ data[Yaw] = newHeadPose[Yaw];
+ if (s.enable_pitch)
+ data[Pitch] = newHeadPose[Pitch];
+ if (s.enable_roll)
+ data[Roll] = newHeadPose[Roll];
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor()
+{
+ return new FTNoIR_Tracker;
+}
diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.h b/ftnoir_tracker_udp/ftnoir_tracker_udp.h
index c4c85372..62eb67df 100644
--- a/ftnoir_tracker_udp/ftnoir_tracker_udp.h
+++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.h
@@ -1,97 +1,77 @@
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include "ui_ftnoir_ftnclientcontrols.h"
-#include <QThread>
-#include <QUdpSocket>
-#include <QMessageBox>
-#include <QSettings>
-#include <QMutex>
-#include <QWaitCondition>
-#include <math.h>
-#include "facetracknoir/global-settings.h"
-
-class FTNoIR_Tracker : public ITracker, public QThread
-{
-public:
- FTNoIR_Tracker();
- ~FTNoIR_Tracker();
-
- void StartTracker( QFrame *videoframe );
- bool GiveHeadPoseData(double *data);
- void loadSettings();
- volatile bool should_quit;
- void WaitForExit() {
- should_quit = true;
- wait();
- }
-
-protected:
- void run(); // qthread override run method
-
-private:
- // UDP socket-variables
- QUdpSocket *inSocket; // Receive from ...
- QUdpSocket *outSocket; // Send to ...
- QHostAddress destIP; // Destination IP-address
- QHostAddress srcIP; // Source IP-address
-
- double newHeadPose[6]; // Structure with new headpose
-
- float portAddress; // Port-number
- bool bEnableRoll;
- bool bEnablePitch;
- bool bEnableYaw;
- bool bEnableX;
- bool bEnableY;
- bool bEnableZ;
- QMutex mutex;
-};
-
-// Widget that has controls for FTNoIR protocol client-settings.
-class TrackerControls: public QWidget, public ITrackerDialog
-{
- Q_OBJECT
-public:
-
- explicit TrackerControls();
- ~TrackerControls();
- void showEvent ( QShowEvent * event );
-
- void Initialize(QWidget *parent);
- void registerTracker(ITracker *tracker) {};
- void unRegisterTracker() {};
-
-private:
- Ui::UICFTNClientControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
-
-private slots:
- void doOK();
- void doCancel();
- void settingChanged() { settingsDirty = true; };
- void settingChanged(int) { settingsDirty = true; };
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker
-//*******************************************************************************************************
-class FTNoIR_TrackerDll : public Metadata
-{
-public:
- FTNoIR_TrackerDll();
- ~FTNoIR_TrackerDll();
-
- void getFullName(QString *strToBeFilled);
- void getShortName(QString *strToBeFilled);
- void getDescription(QString *strToBeFilled);
- void getIcon(QIcon *icon);
-
-private:
- QString trackerFullName; // Trackers' name and description
- QString trackerShortName;
- QString trackerDescription;
-};
-
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "ui_ftnoir_ftnclientcontrols.h"
+#include <QThread>
+#include <QUdpSocket>
+#include <QMessageBox>
+#include <QMutex>
+#include <QWaitCondition>
+#include <math.h>
+#include "facetracknoir/global-settings.h"
+#include "facetracknoir/options.h"
+using namespace options;
+
+struct settings {
+ pbundle b;
+ value<int> port;
+ value<bool> enable_roll, enable_pitch, enable_yaw,
+ enable_x, enable_y, enable_z;
+ settings() :
+ b(bundle("udp-tracker")),
+ port(b, "port", 4242),
+ enable_roll(b, "enable-roll", true),
+ enable_pitch(b, "enable-pitch", true),
+ enable_yaw(b, "enable-yaw", true),
+ enable_x(b, "enable-x", true),
+ enable_y(b, "enable-y", true),
+ enable_z(b, "enable-y", true)
+ {}
+};
+
+class FTNoIR_Tracker : public ITracker, public QThread
+{
+public:
+ FTNoIR_Tracker();
+ ~FTNoIR_Tracker();
+ void StartTracker(QFrame *);
+ void GetHeadPoseData(double *data);
+ volatile bool should_quit;
+protected:
+ void run(); // qthread override run method
+private:
+ QUdpSocket inSocket;
+ QHostAddress destIP;
+ QHostAddress srcIP;
+ double newHeadPose[6];
+ QMutex mutex;
+ settings s;
+};
+
+// Widget that has controls for FTNoIR protocol client-settings.
+class TrackerControls: public QWidget, public ITrackerDialog
+{
+ Q_OBJECT
+public:
+
+ explicit TrackerControls();
+ void registerTracker(ITracker *) {}
+ void unRegisterTracker() {}
+private:
+ Ui::UICFTNClientControls ui;
+ settings s;
+private slots:
+ void doOK();
+ void doCancel();
+};
+
+//*******************************************************************************************************
+// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker
+//*******************************************************************************************************
+class FTNoIR_TrackerDll : public Metadata
+{
+public:
+ void getFullName(QString *strToBeFilled);
+ void getShortName(QString *strToBeFilled);
+ void getDescription(QString *strToBeFilled);
+ void getIcon(QIcon *icon);
+};
+
diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp
index 4fe0d8c8..8d1b99f2 100644
--- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp
+++ b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp
@@ -1,182 +1,58 @@
-/********************************************************************************
-* 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 *
-* *
-* 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_udp.h"
-#include "facetracknoir/global-settings.h"
-
-//*******************************************************************************************************
-// FaceTrackNoIR Client Settings-dialog.
-//*******************************************************************************************************
-
-//
-// Constructor for server-settings-dialog
-//
-TrackerControls::TrackerControls() :
-QWidget()
-{
- ui.setupUi( this );
-
- // Connect Qt signals to member-functions
- connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
- connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
- connect(ui.spinPortNumber, SIGNAL(valueChanged(int)), this, SLOT(settingChanged()));
-
- connect(ui.chkEnableRoll, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnablePitch, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableYaw, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableX, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableY, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.chkEnableZ, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int)));
-
- // Load the settings from the current .INI-file
- loadSettings();
-}
-
-//
-// Destructor for server-dialog
-//
-TrackerControls::~TrackerControls() {
- qDebug() << "~TrackerControls() says: started";
-}
-
-//
-// Initialize tracker-client-dialog
-//
-void TrackerControls::Initialize(QWidget *parent) {
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-//
-// OK clicked on server-dialog
-//
-void TrackerControls::doOK() {
- save();
- this->close();
-}
-
-// override show event
-void TrackerControls::showEvent ( QShowEvent * event ) {
- loadSettings();
-}
-
-//
-// 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 );
-
- qDebug() << "doCancel says: answer =" << ret;
-
- switch (ret) {
- case QMessageBox::Save:
- save();
- this->close();
- break;
- case QMessageBox::Discard:
- this->close();
- break;
- case QMessageBox::Cancel:
- // Cancel was clicked
- break;
- default:
- // should never be reached
- break;
- }
- }
- else {
- this->close();
- }
-}
-
-
-//
-// Load the current Settings from the currently 'active' INI-file.
-//
-void TrackerControls::loadSettings() {
-
-// qDebug() << "loadSettings says: Starting ";
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
-// qDebug() << "loadSettings says: iniFile = " << currentFile;
-
- iniFile.beginGroup ( "FTNClient" );
- ui.chkEnableRoll->setChecked(iniFile.value ( "EnableRoll", 1 ).toBool());
- ui.chkEnablePitch->setChecked(iniFile.value ( "EnablePitch", 1 ).toBool());
- ui.chkEnableYaw->setChecked(iniFile.value ( "EnableYaw", 1 ).toBool());
- ui.chkEnableX->setChecked(iniFile.value ( "EnableX", 1 ).toBool());
- ui.chkEnableY->setChecked(iniFile.value ( "EnableY", 1 ).toBool());
- ui.chkEnableZ->setChecked(iniFile.value ( "EnableZ", 1 ).toBool());
-
- ui.spinPortNumber->setValue( iniFile.value ( "PortNumber", 5550 ).toInt() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-
-//
-// Save the current Settings to the currently 'active' INI-file.
-//
-void TrackerControls::save() {
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
-
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-
- iniFile.beginGroup ( "FTNClient" );
- iniFile.setValue ( "EnableRoll", ui.chkEnableRoll->isChecked() );
- iniFile.setValue ( "EnablePitch", ui.chkEnablePitch->isChecked() );
- iniFile.setValue ( "EnableYaw", ui.chkEnableYaw->isChecked() );
- iniFile.setValue ( "EnableX", ui.chkEnableX->isChecked() );
- iniFile.setValue ( "EnableY", ui.chkEnableY->isChecked() );
- iniFile.setValue ( "EnableZ", ui.chkEnableZ->isChecked() );
- iniFile.setValue ( "PortNumber", ui.spinPortNumber->value() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-}
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
-{
- return new TrackerControls;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_udp.h"
+#include "facetracknoir/global-settings.h"
+
+TrackerControls::TrackerControls() :
+QWidget()
+{
+ ui.setupUi( this );
+
+ connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK()));
+ connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel()));
+
+ tie_setting(s.enable_x, ui.chkEnableX);
+ tie_setting(s.enable_y, ui.chkEnableY);
+ tie_setting(s.enable_z, ui.chkEnableZ);
+ tie_setting(s.enable_yaw, ui.chkEnableYaw);
+ tie_setting(s.enable_pitch, ui.chkEnablePitch);
+ tie_setting(s.enable_roll, ui.chkEnableRoll);
+ tie_setting(s.port, ui.spinPortNumber);
+}
+
+void TrackerControls::doOK() {
+ s.b->save();
+ this->close();
+}
+
+void TrackerControls::doCancel() {
+ s.b->revert();
+ this->close();
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( )
+{
+ return new TrackerControls;
+}
diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp
index 0e794842..22dc7daa 100644
--- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp
+++ b/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp
@@ -1,81 +1,52 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: The Dialog class was used to get general info on the DLL. This
- had a big disadvantage: the complete dialog was loaded, just to get
- some data and then it was deleted again (without ever showing the dialog).
- The TrackerDll class solves this.
- The functions to get the name(s) and icon were removed from the two other classes.
-*/
-#include "ftnoir_tracker_udp.h"
-#include <QDebug>
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_TrackerDll::FTNoIR_TrackerDll() {
- //populate the description strings
- trackerFullName = "FaceTrackNoIR UDP";
- trackerShortName = "UDP";
- trackerDescription = "FaceTrackNoIR UDP";
-}
-
-FTNoIR_TrackerDll::~FTNoIR_TrackerDll()
-{
-
-}
-
-void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled)
-{
- *strToBeFilled = trackerFullName;
-}
-
-void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled)
-{
- *strToBeFilled = trackerShortName;
-}
-
-void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled)
-{
- *strToBeFilled = trackerDescription;
-}
-
-void FTNoIR_TrackerDll::getIcon(QIcon *icon)
-{
- *icon = QIcon(":/images/facetracknoir.png");
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new FTNoIR_TrackerDll;
-}
+/********************************************************************************
+* 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 *
+* *
+* 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_udp.h"
+#include <QDebug>
+#include "facetracknoir/global-settings.h"
+
+void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled)
+{
+ *strToBeFilled = "UDP";
+}
+
+void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled)
+{
+ *strToBeFilled = "UDP";
+}
+
+void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled)
+{
+ *strToBeFilled = "UDP";
+}
+
+void FTNoIR_TrackerDll::getIcon(QIcon *icon)
+{
+ *icon = QIcon(":/images/facetracknoir.png");
+}
+
+extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
+{
+ return new FTNoIR_TrackerDll;
+}
diff --git a/install-fail-tool b/install-fail-tool
new file mode 100755
index 00000000..99f8fbdf
--- /dev/null
+++ b/install-fail-tool
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+test -n "$1" || exit 1
+
+dir="$1"
+
+for i in "$dir"/* "$dir"/*/*; do
+ { test -x "$i" && test -f "$i"; } || continue
+ echo ---- $i ----
+ install_name_tool -id "@executable_path/$(basename -- "$i")" "$i"
+
+ otool -L "$i" | awk '{ print $1 }' |
+ while read l; do
+ j="$(basename -- "$l")"
+ if test -e "$dir/$j"; then
+ install_name_tool -change "$l" "@executable_path/$j" "$i"
+ fi
+ done
+done
diff --git a/installer/opentrack-installer.iss b/installer/opentrack-installer.iss
new file mode 100644
index 00000000..cf0ebec6
--- /dev/null
+++ b/installer/opentrack-installer.iss
@@ -0,0 +1,52 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#include "../build-mingw-w64/opentrack-version.h"
+#define MyAppName "opentrack"
+#define MyAppVersion OPENTRACK_VERSION
+#define MyAppPublisher "opentrack"
+#define MyAppURL "http://github.com/opentrack/opentrack"
+#define MyAppExeName "opentrack.exe"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{E454805B-11A6-469F-9FA9-865BEAD787D0}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+;AppVerName={#MyAppName} {#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+DefaultDirName={pf}\{#MyAppName}
+DefaultGroupName={#MyAppName}
+AllowNoIcons=yes
+OutputBaseFilename={#MyAppVersion}-win32-setup
+SetupIconFile=..\facetracknoir\facetracknoir.ico
+Compression=lzma2/ultra64
+SolidCompression=yes
+DisableWelcomePage=True
+DisableReadyPage=True
+DisableReadyMemo=True
+RestartIfNeededByRun=False
+InternalCompressLevel=ultra
+CompressionThreads=2
+MinVersion=0,5.01sp2
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+Source: "..\build-mingw-w64\install\*"; DestDir: "{app}"; Flags: ignoreversion createallsubdirs recursesubdirs
+
+[Icons]
+Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+
+[Run]
+Filename: "{app}\{#MyAppExeName}"; Flags: nowait postinstall skipifsilent; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"
diff --git a/opentrack-api/context.cpp b/opentrack-api/context.cpp
new file mode 100644
index 00000000..04fa5ac2
--- /dev/null
+++ b/opentrack-api/context.cpp
@@ -0,0 +1,112 @@
+#include "opentrack-guts.h"
+#include "opentrack.h"
+
+#if defined(__APPLE__)
+# define SONAME "dylib"
+#elif defined(_WIN32)
+# define SONAME "dll"
+#else
+# define SONAME "so"
+#endif
+
+#include <iostream>
+
+#ifdef _MSC_VER
+# define LIB_PREFIX ""
+#else
+# define LIB_PREFIX "lib"
+#endif
+
+static Metadata* get_metadata(DynamicLibrary* lib, QString& longName, QIcon& icon)
+{
+ Metadata* meta;
+ if (!lib->Metadata || ((meta = lib->Metadata()), !meta))
+ return NULL;
+ meta->getFullName(&longName);
+ meta->getIcon(&icon);
+ return meta;
+}
+
+static QList<opentrack_meta> list_files(QString filter)
+{
+ QList<opentrack_meta> ret;
+ QStringList filenames = QDir((qApp->applicationDirPath())).entryList(
+ QStringList() << (LIB_PREFIX + filter + ("*." SONAME)),
+ QDir::Files, QDir::Name );
+ for ( int i = 0; i < filenames.size(); i++) {
+ QIcon icon;
+ QString long_name;
+ QString str = filenames.at(i);
+ DynamicLibrary* lib = new DynamicLibrary(str);
+ qDebug() << "Loading" << str;
+ std::cout.flush();
+ Metadata* meta;
+ if (!(meta = get_metadata(lib, long_name, icon)))
+ {
+ delete lib;
+ continue;
+ }
+ /* TODO perhaps return full name and somesuch */
+ delete meta;
+ QString prefix(LIB_PREFIX + filter);
+ QString suffix("." SONAME);
+ if (str.size() > prefix.size() + suffix.size() && str.startsWith(prefix) && str.endsWith(suffix))
+ {
+ auto str2 = str.mid(prefix.size(), str.size() - prefix.size() - suffix.size());
+ opentrack_meta item(str2, lib);
+ ret.push_back(item);
+ }
+ }
+
+ return ret;
+}
+
+opentrack_ctx::opentrack_ctx(int argc, char** argv, void* window_parent) :
+ app(argc, argv),
+ meta_list(list_files("opentrack-tracker-")),
+ fake_frame(window_parent)
+{
+ const int count = meta_list.size();
+ list = new char*[count + 1];
+ for (int i = 0; i < count; i++)
+ {
+ QByteArray tmp = meta_list.at(i).path.toUtf8();
+ int len = tmp.size();
+ auto foo = new char[len+1];
+ for (int j = 0; j < len; j++)
+ foo[j] = tmp.at(j);
+ foo[len] = '\0';
+ list[i] = foo;
+ }
+ list[count] = NULL;
+}
+
+opentrack_ctx::~opentrack_ctx()
+{
+ for (int i = 0; list[i]; i++)
+ {
+ delete[] list[i];
+ }
+ delete[] list;
+}
+
+extern "C"
+{
+
+OPENTRACK_EXPORT const char** opentrack_enum_trackers(opentrack ctx)
+{
+ return const_cast<const char**>(ctx->list);
+}
+
+OPENTRACK_EXPORT opentrack opentrack_make_ctx(int argc, char** argv, void* window_parent)
+{
+ return new opentrack_ctx(argc, argv, window_parent);
+}
+
+OPENTRACK_EXPORT void opentrack_finalize_ctx(opentrack foo)
+{
+ delete foo;
+}
+
+}
+
diff --git a/opentrack-api/gnuc-version-script.txt b/opentrack-api/gnuc-version-script.txt
new file mode 100644
index 00000000..cd3a568d
--- /dev/null
+++ b/opentrack-api/gnuc-version-script.txt
@@ -0,0 +1,12 @@
+{
+ global:
+ opentrack_make_ctx;
+ opentrack_finalize_ctx;
+ opentrack_enum_trackers;
+ opentrack_make_tracker;
+ opentrack_tracker_start;
+ opentrack_tracker_tick;
+ opentrack_finalize_tracker;
+ local:
+ *;
+};
diff --git a/opentrack-api/opentrack-guts.h b/opentrack-api/opentrack-guts.h
new file mode 100644
index 00000000..c8e3309a
--- /dev/null
+++ b/opentrack-api/opentrack-guts.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include <QFrame>
+#include <QDir>
+#include <QList>
+#include <QStringList>
+#include <QDebug>
+#include <QIcon>
+#include <QShowEvent>
+#include <iostream>
+#include <cstring>
+#include <QString>
+#include <QApplication>
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+#include "facetracknoir/global-settings.h"
+#include <memory>
+
+typedef ITracker* opentrack_tracker;
+
+class opentrack_meta {
+public:
+ QString path;
+ std::shared_ptr<DynamicLibrary> lib;
+
+ opentrack_meta(QString& path, DynamicLibrary* lib) :
+ path(path), lib(lib)
+ {}
+};
+
+class MyFrame : public QFrame {
+ Q_OBJECT
+public:
+ MyFrame(void* parent)
+ {
+ if (parent == (void*) -1)
+ {
+ show();
+ setVisible(false);
+ hide();
+ }
+ else
+ {
+ create((WId) parent);
+ }
+ }
+ explicit MyFrame() {}
+};
+
+typedef class opentrack_ctx {
+public:
+ QApplication app;
+ char** list;
+ QList<opentrack_meta> meta_list;
+ MyFrame fake_frame;
+ opentrack_ctx(int argc, char** argv, void* window_parent);
+ ~opentrack_ctx();
+} *opentrack;
diff --git a/opentrack-api/opentrack.h b/opentrack-api/opentrack.h
new file mode 100644
index 00000000..88ba6cf0
--- /dev/null
+++ b/opentrack-api/opentrack.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifndef IN_OPENTRACK
+/* opaque pointers, forward definitions */
+struct opentrack_opaque_ctx;
+typedef struct opentrack_opaque_ctx* opentrack;
+struct opentrack_opaque_tracker;
+typedef struct opentrack_opaque_tracker* opentrack_tracker;
+#endif
+
+#ifdef IN_OPENTRACK
+# ifdef _WIN32
+# define OPENTRACK_EXPORT __declspec(dllexport)
+# else
+# define OPENTRACK_EXPORT
+# endif
+#else
+# ifdef _WIN32
+# define OPENTRACK_EXPORT __declspec(dllimport)
+# else
+# define OPENTRACK_EXPORT
+# endif
+#endif
+
+/* for `opentrack_tracker_tick', individual headpose elts */
+#ifndef IN_OPENTRACK
+enum opentrack_dof {
+ TX = 0,
+ TY,
+ TZ,
+ Yaw,
+ Pitch,
+ Roll,
+ DOF_count
+};
+#endif
+
+OPENTRACK_EXPORT opentrack opentrack_make_ctx(int argc, char** argv, void* window_parent);
+OPENTRACK_EXPORT void opentrack_finalize_ctx(opentrack self);
+
+/* no need to free the return value; invalid to modify it */
+OPENTRACK_EXPORT const char** opentrack_enum_trackers(opentrack self);
+
+/*
+ * don't `opentrack_tracker_tick an unstarted tracker, it's invalid to do so
+ * it's also invalid to start a finalized tracker
+ */
+OPENTRACK_EXPORT opentrack_tracker opentrack_make_tracker(opentrack ctx, const char* name);
+OPENTRACK_EXPORT void opentrack_tracker_start(opentrack self, opentrack_tracker tracker);
+OPENTRACK_EXPORT void opentrack_tracker_tick(opentrack_tracker tracker, double* headpose);
+OPENTRACK_EXPORT void opentrack_finalize_tracker(opentrack_tracker tracker);
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/opentrack-api/trackers.cpp b/opentrack-api/trackers.cpp
new file mode 100644
index 00000000..5027ec1d
--- /dev/null
+++ b/opentrack-api/trackers.cpp
@@ -0,0 +1,38 @@
+#include "opentrack-guts.h"
+#include "opentrack.h"
+
+extern "C" {
+
+opentrack_tracker OPENTRACK_EXPORT opentrack_make_tracker(opentrack ctx, const char* name)
+{
+ for (int i = 0; i < ctx->meta_list.size(); i++)
+ {
+ auto meta = ctx->meta_list.at(i);
+ if (ctx->meta_list.at(i).path == name)
+ {
+ ITracker* foo = static_cast<ITracker*>(meta.lib->Constructor());
+ return foo;
+ }
+ }
+ return NULL;
+}
+
+void OPENTRACK_EXPORT opentrack_finalize_tracker(opentrack_tracker tracker)
+{
+ delete tracker;
+}
+
+void OPENTRACK_EXPORT opentrack_tracker_start(opentrack self, opentrack_tracker tracker)
+{
+ // hot damn, this is problematic!
+ // need to pass QFrame from somewhere
+ return tracker->StartTracker(&self->fake_frame);
+}
+
+void OPENTRACK_EXPORT opentrack_tracker_tick(opentrack_tracker tracker, double* headpose)
+{
+ tracker->GetHeadPoseData(headpose);
+ QApplication::processEvents(0, 5);
+}
+
+}
diff --git a/opentrack-version.h b/opentrack-version.h
new file mode 100644
index 00000000..f31d5edf
--- /dev/null
+++ b/opentrack-version.h
@@ -0,0 +1,7 @@
+#ifndef OPENTRACK_VERSION
+# define OPENTRACK_VERSION @OPENTRACK_COMMIT_VERSION@
+#else
+# ifndef OPENTRACK_VERSION
+# define OPENTRACK_VERSION "Mourns-For-Trees"
+# endif
+#endif
diff --git a/qfunctionconfigurator/qfunctionconfiguratorplugin.cpp b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp
index 5e98eb39..1a9da10a 100644
--- a/qfunctionconfigurator/qfunctionconfiguratorplugin.cpp
+++ b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.cpp
@@ -1,37 +1,9 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-* The FunctionConfigurator was made by Stanislaw Halik, and adapted to *
-* FaceTrackNoIR. *
-* *
-* All credits for this nice piece of code should go to Stanislaw. *
-* *
-* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl> *
-* 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. *
-********************************************************************************/
+/* Copyright (c) 2011-2012 Stanislaw Halik <sthalik@misaki.pl>
+ * Adapted to FaceTrackNoIR by Wim Vriend.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
#include "qfunctionconfigurator.h"
#include <QtCore/QtPlugin>
@@ -110,13 +82,6 @@ QString QFunctionConfiguratorPlugin::domXml() const
" <blue>0</blue>\n"
" </color>\n"
" </property>\n"
- " <property name=\"colorBackground\">\n"
- " <color>\n"
- " <red>192</red>\n"
- " <green>192</green>\n"
- " <blue>192</blue>\n"
- " </color>\n"
- " </property>\n"
" <property name=\"stringInputEGU\" stdset=\"0\">\n"
" <string>Input Yaw (degr.)</string>\n"
" </property>\n"
diff --git a/qfunctionconfigurator/qfunctionconfiguratorplugin.h b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h
index c6b65fcc..bc637338 100644
--- a/qfunctionconfigurator/qfunctionconfiguratorplugin.h
+++ b/qfunctionconfigurator/broken/qfunctionconfiguratorplugin.h
@@ -1,3 +1,9 @@
+/* Copyright (c) 2011-2012 Stanislaw Halik <sthalik@misaki.pl>
+ * Adapted to FaceTrackNoIR by Wim Vriend.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
#ifndef QFUNCTIONCONFIGURATORPLUGIN_H
#define QFUNCTIONCONFIGURATORPLUGIN_H
@@ -6,7 +12,8 @@
class QFunctionConfiguratorPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
- Q_INTERFACES(QDesignerCustomWidgetInterface)
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "analogclock.json")
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
QFunctionConfiguratorPlugin(QObject *parent = 0);
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp
index 1b06bdc2..97a6db24 100644
--- a/qfunctionconfigurator/functionconfig.cpp
+++ b/qfunctionconfigurator/functionconfig.cpp
@@ -1,282 +1,281 @@
-/* Copyright (c) 2012, 2013 Stanisław Halik <sthalik@misaki.pl>
-
- * Permission to use, copy, modify, and/or distribute this
- * software for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice and this permission
- * notice appear in all copies.
- */
-
-#include <QMutexLocker>
-#include <QCoreApplication>
-#include <QPointF>
-#include <QList>
-#include "functionconfig.h"
-#include <QtAlgorithms>
-#include <QtAlgorithms>
-#include <QSettings>
-#include <math.h>
-#include <QPixmap>
-#include <QDebug>
-
-//
-// Constructor with List of Points in argument.
-//
-FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput)
-{
- _mutex = new QMutex(QMutex::Recursive);
- _title = title;
- _points = QList<QPointF>();
- _data = 0;
- _size = 0;
- lastValueTracked = QPointF(0,0);
- _tracking_active = false;
- _max_Input = intMaxInput; // Added WVR 20120805
- _max_Output = intMaxOutput;
- QSettings settings("opentrack"); // Registry settings (in HK_USER)
- QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString();
- QSettings iniFile( currentFile, QSettings::IniFormat );
- loadSettings(iniFile);
- reload();
-}
-
-FunctionConfig::FunctionConfig() :
- _tracking_active(false),
- _max_Input(0),
- _max_Output(0),
- _data(0),
- _mutex(0),
- _size(0)
-{
- _mutex = new QMutex();
-}
-
-//
-// Calculate the value of the function, given the input 'x'.
-// Used to draw the curve and, most importantly, to translate input to output.
-// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running.
-//
-float FunctionConfig::getValue(float x) {
- QMutexLocker foo(_mutex);
- int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
- float ret = getValueInternal(x2);
- lastValueTracked.setX(x);
- lastValueTracked.setY(ret);
- return ret;
-}
-
-//
-// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running.
-//
-bool FunctionConfig::getLastPoint(QPointF& point ) {
- QMutexLocker foo(_mutex);
- point = lastValueTracked;
- return _tracking_active;
-}
-
-float FunctionConfig::getValueInternal(int x) {
- float sign = x < 0 ? -1 : 1;
- x = x < 0 ? -x : x;
- float ret;
- if (!_data)
- ret = 0;
- else if (_size == 0)
- ret = 0;
- else if (x < 0)
- ret = 0;
- else if (x < _size && x >= 0)
- ret = _data[x];
- else
- ret = _data[_size - 1];
- return ret * sign;
-}
-
-static __inline QPointF ensureInBounds(QList<QPointF> points, int i) {
- int siz = points.size();
- if (siz == 0 || i < 0)
- return QPointF(0, 0);
- if (siz > i)
- return points[i];
- return points[siz - 1];
-}
-
-static bool sortFn(const QPointF& one, const QPointF& two) {
- return one.x() < two.x();
-}
-
-void FunctionConfig::reload() {
- _size = 0;
-
- if (_points.size())
- qStableSort(_points.begin(), _points.end(), sortFn);
-
- if (_data)
- delete[] _data;
- _data = NULL;
- if (_points.size()) {
- _data = new float[_size = MEMOIZE_PRECISION * _points[_points.size() - 1].x()];
-
- for (int i = 0; i < _size; i++)
- _data[i] = -1e6;
-
- for (int k = 0; k < _points[0].x() * MEMOIZE_PRECISION; k++) {
- if (k < _size)
- _data[k] = _points[0].y() * k / (_points[0].x() * MEMOIZE_PRECISION);
- }
-
- for (int i = 0; i < _points.size(); i++) {
- QPointF p0 = ensureInBounds(_points, i - 1);
- QPointF p1 = ensureInBounds(_points, i);
- QPointF p2 = ensureInBounds(_points, i + 1);
- QPointF p3 = ensureInBounds(_points, i + 2);
-
- int end = p2.x() * MEMOIZE_PRECISION;
- int start = p1.x() * MEMOIZE_PRECISION;
-
- for (int j = start; j < end && j < _size; j++) {
- float t = (j - start) / (float) (end - start);
- float t2 = t*t;
- float t3 = t*t*t;
-
- int x = .5 * ((2 * p1.x()) +
- (-p0.x() + p2.x()) * t +
- (2 * p0.x() - 5 * p1.x() + 4 * p2.x() - p3.x()) * t2 +
- (-p0.x() + 3 * p1.x() - 3 * p2.x() + p3.x()) * t3)
- * MEMOIZE_PRECISION;
-
- float y = .5 * ((2 * p1.y()) +
- (-p0.y() + p2.y()) * t +
- (2 * p0.y() - 5 * p1.y() + 4 * p2.y() - p3.y()) * t2 +
- (-p0.y() + 3 * p1.y() - 3 * p2.y() + p3.y()) * t3);
-
- if (x >= 0 && x < _size)
- _data[x] = y;
- }
- }
-
- float last = 0;
-
- for (int i = 0; i < _size; i++)
- {
- if (_data[i] == -1e6)
- _data[i] = last;
- last = _data[i];
- }
- }
-}
-
-FunctionConfig::~FunctionConfig() {
- if (_data)
- delete[] _data;
- if (_mutex)
- delete _mutex;
-}
-
-//
-// Remove a Point from the Function.
-// Used by the Widget.
-//
-void FunctionConfig::removePoint(int i) {
- QMutexLocker foo(_mutex);
- if (i >= 0 && i < _points.size())
- {
- _points.removeAt(i);
- reload();
- }
-}
-
-//
-// Add a Point to the Function.
-// Used by the Widget and by loadSettings.
-//
-void FunctionConfig::addPoint(QPointF pt) {
- QMutexLocker foo(_mutex);
- _points.append(pt);
- reload();
-}
-
-//
-// Move a Function Point.
-// Used by the Widget.
-//
-void FunctionConfig::movePoint(int idx, QPointF pt) {
- QMutexLocker foo(_mutex);
- if (idx >= 0 && idx < _points.size())
- {
- _points[idx] = pt;
- reload();
- }
-}
-
-//
-// Return the List of Points.
-// Used by the Widget.
-//
-QList<QPointF> FunctionConfig::getPoints() {
- QList<QPointF> ret;
- QMutexLocker foo(_mutex);
- for (int i = 0; i < _points.size(); i++) {
- ret.append(_points[i]);
- }
- return ret;
-}
-
-//
-// Load the Points for the Function from the INI-file designated by settings.
-// Settings for a specific Curve are loaded from their own Group in the INI-file.
-//
-void FunctionConfig::loadSettings(QSettings& settings) {
- QMutexLocker foo(_mutex);
- QPointF newPoint;
-
- QList<QPointF> points;
- settings.beginGroup(QString("Curves-%1").arg(_title));
-
- int max = settings.value("point-count", 0).toInt();
-
- qDebug() << _title << "count" << max;
-
- for (int i = 0; i < max; i++) {
- newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), (i + 1) * _max_Input/2).toFloat(),
- settings.value(QString("point-%1-y").arg(i), (i + 1) * _max_Output/2).toFloat());
- //
- // Make sure the new Point fits in the Function Range.
- // Maybe this can be improved?
- //
- if (newPoint.x() > _max_Input) {
- newPoint.setX(_max_Input);
- }
- if (newPoint.y() > _max_Output) {
- newPoint.setY(_max_Output);
- }
- points.append(newPoint);
- }
- settings.endGroup();
- _points = points;
- reload();
-}
-
-//
-// Save the Points for the Function to the INI-file designated by settings.
-// Settings for a specific Curve are saved in their own Group in the INI-file.
-// The number of Points is also saved, to make loading more convenient.
-//
-void FunctionConfig::saveSettings(QSettings& settings) {
- QMutexLocker foo(_mutex);
- settings.beginGroup(QString("Curves-%1").arg(_title));
- int max = _points.size();
- settings.setValue("point-count", max);
- for (int i = 0; i < max; i++) {
- settings.setValue(QString("point-%1-x").arg(i), _points[i].x());
- settings.setValue(QString("point-%1-y").arg(i), _points[i].y());
- }
-
- for (int i = max; true; i++)
- {
- QString x = QString("point-%1-x").arg(i);
- if (!settings.contains(x))
- break;
- settings.remove(x);
- settings.remove(QString("point-%1-y").arg(i));
- }
- settings.endGroup();
-}
+/* Copyright (c) 2012, 2013 Stanisław Halik <sthalik@misaki.pl>
+
+ * Permission to use, copy, modify, and/or distribute this
+ * software for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice and this permission
+ * notice appear in all copies.
+ */
+
+#include <QMutexLocker>
+#include <QCoreApplication>
+#include <QPointF>
+#include <QList>
+#include "functionconfig.h"
+#include <QtAlgorithms>
+#include <QtAlgorithms>
+#include <QSettings>
+#include <math.h>
+#include <QPixmap>
+
+//
+// Constructor with List of Points in argument.
+//
+FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput) :
+ _mutex(QMutex::Recursive)
+{
+ _title = title;
+ _points = QList<QPointF>();
+ _data = 0;
+ _size = 0;
+ lastValueTracked = QPointF(0,0);
+ _tracking_active = false;
+ _max_Input = intMaxInput; // Added WVR 20120805
+ _max_Output = intMaxOutput;
+ QSettings settings("opentrack"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat );
+ loadSettings(iniFile);
+ reload();
+}
+
+void FunctionConfig::setTrackingActive(bool blnActive)
+{
+ _tracking_active = blnActive;
+}
+
+FunctionConfig::FunctionConfig() :
+ _mutex(QMutex::Recursive),
+ _data(0),
+ _size(0),
+ _tracking_active(false),
+ _max_Input(0),
+ _max_Output(0)
+{
+}
+
+//
+// Calculate the value of the function, given the input 'x'.
+// Used to draw the curve and, most importantly, to translate input to output.
+// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running.
+//
+float FunctionConfig::getValue(float x) {
+ QMutexLocker foo(&_mutex);
+ int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION);
+ float ret = getValueInternal(x2);
+ lastValueTracked.setX(x);
+ lastValueTracked.setY(ret);
+ return ret;
+}
+
+//
+// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running.
+//
+bool FunctionConfig::getLastPoint(QPointF& point ) {
+ QMutexLocker foo(&_mutex);
+ point = lastValueTracked;
+ return _tracking_active;
+}
+
+float FunctionConfig::getValueInternal(int x) {
+ float sign = x < 0 ? -1 : 1;
+ x = x < 0 ? -x : x;
+ float ret;
+ if (!_data)
+ ret = 0;
+ else if (_size == 0)
+ ret = 0;
+ else if (x < 0)
+ ret = 0;
+ else if (x < _size && x >= 0)
+ ret = _data[x];
+ else
+ ret = _data[_size - 1];
+ return ret * sign;
+}
+
+static __inline QPointF ensureInBounds(QList<QPointF> points, int i) {
+ int siz = points.size();
+ if (siz == 0 || i < 0)
+ return QPointF(0, 0);
+ if (siz > i)
+ return points[i];
+ return points[siz - 1];
+}
+
+static bool sortFn(const QPointF& one, const QPointF& two) {
+ return one.x() < two.x();
+}
+
+void FunctionConfig::reload() {
+ _size = 0;
+
+ if (_points.size())
+ qStableSort(_points.begin(), _points.end(), sortFn);
+
+ if (_data)
+ delete[] _data;
+ _data = NULL;
+ if (_points.size()) {
+ _data = new float[_size = MEMOIZE_PRECISION * _points[_points.size() - 1].x()];
+
+ for (int i = 0; i < _size; i++)
+ _data[i] = -1e6;
+
+ for (int k = 0; k < _points[0].x() * MEMOIZE_PRECISION; k++) {
+ if (k < _size)
+ _data[k] = _points[0].y() * k / (_points[0].x() * MEMOIZE_PRECISION);
+ }
+
+ for (int i = 0; i < _points.size(); i++) {
+ QPointF p0 = ensureInBounds(_points, i - 1);
+ QPointF p1 = ensureInBounds(_points, i);
+ QPointF p2 = ensureInBounds(_points, i + 1);
+ QPointF p3 = ensureInBounds(_points, i + 2);
+
+ int end = p2.x() * MEMOIZE_PRECISION;
+ int start = p1.x() * MEMOIZE_PRECISION;
+
+ for (int j = start; j < end && j < _size; j++) {
+ double t = (j - start) / (double) (end - start);
+ double t2 = t*t;
+ double t3 = t*t*t;
+
+ int x = .5 * ((2. * p1.x()) +
+ (-p0.x() + p2.x()) * t +
+ (2. * p0.x() - 5. * p1.x() + 4. * p2.x() - p3.x()) * t2 +
+ (-p0.x() + 3. * p1.x() - 3. * p2.x() + p3.x()) * t3)
+ * MEMOIZE_PRECISION;
+
+ float y = .5 * ((2. * p1.y()) +
+ (-p0.y() + p2.y()) * t +
+ (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 +
+ (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3);
+
+ if (x >= 0 && x < _size)
+ _data[x] = y;
+ }
+ }
+
+ float last = 0;
+
+ for (int i = 0; i < _size; i++)
+ {
+ if (_data[i] == -1e6)
+ _data[i] = last;
+ last = _data[i];
+ }
+ }
+}
+
+FunctionConfig::~FunctionConfig() {
+ if (_data)
+ delete[] _data;
+}
+
+//
+// Remove a Point from the Function.
+// Used by the Widget.
+//
+void FunctionConfig::removePoint(int i) {
+ QMutexLocker foo(&_mutex);
+ if (i >= 0 && i < _points.size())
+ {
+ _points.removeAt(i);
+ reload();
+ }
+}
+
+//
+// Add a Point to the Function.
+// Used by the Widget and by loadSettings.
+//
+void FunctionConfig::addPoint(QPointF pt) {
+ QMutexLocker foo(&_mutex);
+ _points.append(pt);
+ reload();
+}
+
+//
+// Move a Function Point.
+// Used by the Widget.
+//
+void FunctionConfig::movePoint(int idx, QPointF pt) {
+ QMutexLocker foo(&_mutex);
+ if (idx >= 0 && idx < _points.size())
+ {
+ _points[idx] = pt;
+ reload();
+ }
+}
+
+//
+// Return the List of Points.
+// Used by the Widget.
+//
+QList<QPointF> FunctionConfig::getPoints() {
+ QList<QPointF> ret;
+ QMutexLocker foo(&_mutex);
+ for (int i = 0; i < _points.size(); i++) {
+ ret.append(_points[i]);
+ }
+ return ret;
+}
+
+//
+// Load the Points for the Function from the INI-file designated by settings.
+// Settings for a specific Curve are loaded from their own Group in the INI-file.
+//
+void FunctionConfig::loadSettings(QSettings& settings) {
+ QMutexLocker foo(&_mutex);
+ QPointF newPoint;
+
+ QList<QPointF> points;
+ settings.beginGroup(QString("Curves-%1").arg(_title));
+
+ int max = settings.value("point-count", 0).toInt();
+
+ for (int i = 0; i < max; i++) {
+ newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(),
+ settings.value(QString("point-%1-y").arg(i), 0).toFloat());
+ //
+ // Make sure the new Point fits in the Function Range.
+ // Maybe this can be improved?
+ //
+ if (newPoint.x() > _max_Input) {
+ newPoint.setX(_max_Input);
+ }
+ if (newPoint.y() > _max_Output) {
+ newPoint.setY(_max_Output);
+ }
+ points.append(newPoint);
+ }
+ settings.endGroup();
+ _points = points;
+ reload();
+}
+
+//
+// Save the Points for the Function to the INI-file designated by settings.
+// Settings for a specific Curve are saved in their own Group in the INI-file.
+// The number of Points is also saved, to make loading more convenient.
+//
+void FunctionConfig::saveSettings(QSettings& settings) {
+ QMutexLocker foo(&_mutex);
+ settings.beginGroup(QString("Curves-%1").arg(_title));
+ int max = _points.size();
+ settings.setValue("point-count", max);
+ for (int i = 0; i < max; i++) {
+ settings.setValue(QString("point-%1-x").arg(i), _points[i].x());
+ settings.setValue(QString("point-%1-y").arg(i), _points[i].y());
+ }
+
+ for (int i = max; true; i++)
+ {
+ QString x = QString("point-%1-x").arg(i);
+ if (!settings.contains(x))
+ break;
+ settings.remove(x);
+ settings.remove(QString("point-%1-y").arg(i));
+ }
+ settings.endGroup();
+}
diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h
index 0f60c979..4d771dfd 100644
--- a/qfunctionconfigurator/functionconfig.h
+++ b/qfunctionconfigurator/functionconfig.h
@@ -1,78 +1,75 @@
-/* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl>
-
- * Permission to use, copy, modify, and/or distribute this
- * software for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice and this permission
- * notice appear in all copies.
- */
-
-#include <QList>
-#include <QPointF>
-#include <QString>
-#include <QSettings>
-#include <QMutex>
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-
-#ifndef FUNCTION_CONFIG_H
-#define FUNCTION_CONFIG_H
-
-#define MEMOIZE_PRECISION 500
-
-class FTNOIR_TRACKER_BASE_EXPORT FunctionConfig {
-private:
- QMutex* _mutex;
- QList<QPointF> _points;
- void reload();
- float* _data;
- int _size;
- QString _title;
- float getValueInternal(int x);
- QPointF lastValueTracked; // The last input value requested by the Tracker, with it's output-value.
- volatile bool _tracking_active;
- int _max_Input;
- int _max_Output;
- FunctionConfig(const FunctionConfig&) {}
-public:
- //
- // Contructor(s) and destructor
- //
- FunctionConfig();
- FunctionConfig(QString title, int intMaxInput, int intMaxOutput);
- virtual ~FunctionConfig();
-
- float getValue(float x);
- bool getLastPoint(QPointF& point); // Get the last Point that was requested.
-
- //
- // Functions to manipulate the Function
- //
- void removePoint(int i);
- void removeAllPoints() {
- QMutexLocker foo(_mutex);
- _points.clear();
- reload();
- }
-
- void addPoint(QPointF pt);
- void movePoint(int idx, QPointF pt);
- QList<QPointF> getPoints();
- void setMaxInput(int MaxInput) {
- _max_Input = MaxInput;
- }
- void setMaxOutput(int MaxOutput) {
- _max_Output = MaxOutput;
- }
-
- //
- // Functions to load/save the Function-Points to an INI-file
- //
- void saveSettings(QSettings& settings);
- void loadSettings(QSettings& settings);
-
- void setTrackingActive(bool blnActive) {
- _tracking_active = blnActive;
- }
- QString getTitle() { return _title; }
-};
-
-#endif
+/* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl>
+
+ * 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 <QList>
+#include <QPointF>
+#include <QString>
+#include <QSettings>
+#include <QMutex>
+#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
+
+#define MEMOIZE_PRECISION 100
+
+class FTNOIR_TRACKER_BASE_EXPORT FunctionConfig {
+private:
+ QMutex _mutex;
+ QList<QPointF> _points;
+ void reload();
+ float* _data;
+ int _size;
+ QString _title;
+ float getValueInternal(int x);
+ QPointF lastValueTracked; // The last input value requested by the Tracker, with it's output-value.
+ volatile bool _tracking_active;
+ int _max_Input;
+ int _max_Output;
+ FunctionConfig(const FunctionConfig&) = delete;
+public:
+ int maxInput() const { return _max_Input; }
+ int maxOutput() const { return _max_Output; }
+ //
+ // Contructor(s) and destructor
+ //
+ FunctionConfig();
+ FunctionConfig(QString title, int intMaxInput, int intMaxOutput);
+ ~FunctionConfig();
+
+ float getValue(float x);
+ bool getLastPoint(QPointF& point); // Get the last Point that was requested.
+
+ //
+ // Functions to manipulate the Function
+ //
+ void removePoint(int i);
+ void removeAllPoints() {
+ QMutexLocker foo(&_mutex);
+ _points.clear();
+ reload();
+ }
+
+ void addPoint(QPointF pt);
+ void movePoint(int idx, QPointF pt);
+ QList<QPointF> getPoints();
+ void setMaxInput(int MaxInput) {
+ _max_Input = MaxInput;
+ }
+ void setMaxOutput(int MaxOutput) {
+ _max_Output = MaxOutput;
+ }
+
+ //
+ // Functions to load/save the Function-Points to an INI-file
+ //
+ void saveSettings(QSettings& settings);
+ void loadSettings(QSettings& settings);
+
+ void setTrackingActive(bool blnActive);
+ QString getTitle() { return _title; }
+};
diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp
index 304d252e..55d1e1bc 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.cpp
+++ b/qfunctionconfigurator/qfunctionconfigurator.cpp
@@ -1,45 +1,10 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-* The FunctionConfigurator was made by Stanislaw Halik, and adapted to *
-* FaceTrackNoIR. *
-* *
-* All credits for this nice piece of code should go to Stanislaw. *
-* *
-* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl> *
-* 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. *
-********************************************************************************/
-/*
- Modifications (last one on top):
- 20120830 - WVR: Changed functionality a bit. Now only draw the handles, when the function is drawn.
- Only check mouseMoves, when they occur 'in range'. Redraw the curve, when a resize occurs.
- Somehow, the curve was not drawn correctly, when this was not done (all points were too high).
- After a 'Reset' this would disappear...
- 20120828 - WVR: Removed bSkipText, which was used to not show a number below each vertical gridline.
-*/
+/* Copyright (c) 2011-2012 Stanislaw Halik <sthalik@misaki.pl>
+ * Adapted to FaceTrackNoIR by Wim Vriend.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
#include "qfunctionconfigurator/qfunctionconfigurator.h"
#include <QPainter>
#include <QPaintEvent>
@@ -52,323 +17,224 @@
#include <QImage>
#include <QPixmap>
#include <QTimer>
-
#include <QtDebug>
-
-#include <math.h>
+#include <cmath>
+#include <QTabWidget>
+#include <QTabBar>
+#include <QFontMetrics>
static const int pointSize = 5;
QFunctionConfigurator::QFunctionConfigurator(QWidget *parent)
: QWidget(parent)
{
-
- //
- // Defaults, for when the widget has no values different from the domXML()
- //
- MaxInput = 50; // Maximum input limit
- MaxOutput = 180; // Maximum output limit
- pPerEGU_Output = 1; // Number of pixels, per EGU
- pPerEGU_Input = 4; // Number of pixels, per EGU
- gDistEGU_Input = 5; // Distance of gridlines
- gDistEGU_Output = 10; // Distance of gridlines
-
-
- // Change compared to BezierConfigurator: X = horizontal (input), Y = vertical (output)
- // This will require the Curve-Dialog to be higher (which was the reason it was reversed in the first place..)
- range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output);
-
- setMouseTracking(true);
movingPoint = -1; // Index of that same point
-
- //
- // Variables for FunctionConfig
- //
- _config = 0;
- _points = QList<QPointF>();
- _draw_background = true;
- _draw_function = true;
-
-// qDebug() << "QFunctionConfigurator::QFunctionConfigurator object created.";
-
+ _config = 0;
+ _draw_background = true;
+ _draw_function = true;
+ update_range();
+ setMouseTracking(true);
}
-//
-// Attach an existing FunctionConfig to the Widget.
-//
-void QFunctionConfigurator::setConfig(FunctionConfig* config, QString settingsFile) {
-QPointF currentPoint;
-QPointF drawPoint;
-qreal x;
-
- _config = config;
- _points = config->getPoints();
- strSettingsFile = settingsFile; // Remember for Reset()
-
- qDebug() << "QFunctionConfigurator::setConfig" << config->getTitle();
- setCaption(config->getTitle());
-
- //
- // Get the Function Points, one for each pixel in the horizontal range.
- // If the curve does not change, there is no need to run this code every time (it slows down drawing).
- //
- for (int j = 0; j < MaxInput * pPerEGU_Input; j++) {
- //
- // Weird: not casting to float causes C++ to round the number...
- //
- x = (float) j / (float) pPerEGU_Input;
- currentPoint.setX ( x );
- currentPoint.setY (_config->getValue( x ));
- drawPoint = graphicalizePoint(currentPoint, "setConfig");
- //if (withinRect(drawPoint, range)) {
- //_draw_points.append(drawPoint);
-// qDebug() << "QFunctionConfigurator::setConfig _draw_Point to add = " << drawPoint;
- //}
- }
-
- _draw_function = true;
- this->update();
-}
+void QFunctionConfigurator::setConfig(FunctionConfig* config) {
+ QSettings settings("opentrack"); // Registry settings (in HK_USER)
+ QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString();
+ QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file)
-//
-// Load the FunctionConfig (points) from the INI-file.
-//
-void QFunctionConfigurator::loadSettings(QString settingsFile) {
-
- QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file)
- strSettingsFile = settingsFile; // Remember for Reset()
- qDebug() << "QFunctionConfigurator::loadSettings = " << settingsFile;
- if (_config) {
- _config->loadSettings(iniFile);
- setConfig(_config, settingsFile);
- }
+ config->loadSettings(iniFile);
+ _config = config;
+ _draw_function = _draw_background = true;
+ update_range();
+ update();
}
-//
-// Save the FunctionConfig (points) to the INI-file.
-//
void QFunctionConfigurator::saveSettings(QString settingsFile) {
- QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file)
- strSettingsFile = settingsFile; // Remember for Reset()
- qDebug() << "QFunctionConfigurator::saveSettings = " << settingsFile;
+ QSettings iniFile( settingsFile, QSettings::IniFormat ); // Application settings (in INI-file)
- if (_config) {
- _config->saveSettings(iniFile);
- }
+ if (_config) {
+ _config->saveSettings(iniFile);
+ }
}
-//
-// Draw the Background for the graph, the gridlines and the gridpoints.
-// The static objects are drawn on a Pixmap, so it does not have to be repeated every paintEvent. Hope this speeds things up...
-//
-void QFunctionConfigurator::drawBackground(const QRectF &fullRect)
+void QFunctionConfigurator::drawBackground()
{
-int i;
-QRect scale;
-
- qDebug() << "QFunctionConfigurator::drawBackground.";
-
- _background = QPixmap(fullRect.width(), fullRect.height());
- QPainter painter(&_background);
-
- painter.save();
- painter.setRenderHint(QPainter::Antialiasing);
- painter.fillRect(fullRect, colBackground);
- QColor bg_color(112, 154, 209);
- painter.fillRect(range, bg_color);
-
- QFont font("ComicSans", 4);
+ if (!_config)
+ return;
+ _background = QPixmap(width(), height());
+ QPainter painter(&_background);
+ painter.fillRect(rect(), QColor::fromRgb(204, 204, 204));
+ painter.setRenderHint(QPainter::Antialiasing);
+ QColor bg_color(112, 154, 209);
+ painter.fillRect(range, bg_color);
+
+ QFont font;
font.setPointSize(8);
painter.setFont(font);
+ QFontMetrics metrics(font);
QPen pen(QColor(55, 104, 170, 127), 1, Qt::SolidLine);
- //
- // Draw the Caption
- //
- if (_config) {
- strCaption = _config->getTitle();
- }
-
- scale.setCoords(range.left(), 0, range.right(), 20);
- painter.drawText(scale, Qt::AlignCenter, strCaption);
-
- //
- // Draw the horizontal grid
- //
- for (i = range.bottom() - gDistEGU_Output * pPerEGU_Output; i >= range.top(); i -= gDistEGU_Output * pPerEGU_Output) {
- drawLine(&painter, QPointF(40, i), QPointF(range.right(), i), pen);
- scale.setCoords(0, i - 5, range.left() - 5, i + 5);
- painter.drawText(scale, Qt::AlignRight, tr("%1").arg(((range.bottom() - i))/pPerEGU_Output));
- }
-
- //
- // Draw the vertical guidelines
- //
- for (i = range.left(); i <= range.right(); i += gDistEGU_Input * pPerEGU_Input) {
- drawLine(&painter, QPointF(i, range.top()), QPointF(i, range.bottom()), pen);
- scale.setCoords(i - 10, range.bottom() + 2, i + 10, range.bottom() + 15);
- painter.drawText(scale, Qt::AlignCenter, tr("%1").arg(abs(((range.left() - i))/pPerEGU_Input)));
- }
-
- scale.setCoords(range.left(), range.bottom() + 20, range.right(), range.bottom() + 35);
- painter.drawText(scale, Qt::AlignRight, strInputEGU);
-
- //
- // Draw the EGU of the vertical axis (vertically!)
- //
- font.setPointSize(10);
- painter.translate(range.topLeft().x() - 35, range.topLeft().y());
- painter.rotate(90);
- painter.drawText(0,0,strOutputEGU );
-
- //
- // Draw the two axis
- //
- pen.setWidth(2);
- pen.setColor( Qt::black );
- drawLine(&painter, range.topLeft() - QPointF(2,0), range.bottomLeft() - QPointF(2,0), pen);
- drawLine(&painter, range.bottomLeft(), range.bottomRight(), pen);
-
- painter.restore();
-}
+ const int xstep = 10, ystep = 10;
+ const int maxx = _config->maxInput();
+ const int maxy = _config->maxOutput();
+
+ // horizontal grid
+
+ for (int i = 0; i < maxy; i += xstep)
+ {
+ double y = range.height() - i * c.y() + range.y();
+ drawLine(&painter,
+ QPointF(range.x(), y),
+ QPointF(range.x() + range.width(), y),
+ pen);
+ painter.drawText(QRectF(10,
+ y - metrics.height()/2,
+ range.left(),
+ metrics.height()),
+ QString::number(i));
+ }
+ {
+ const int i = maxy;
+ double y = range.height() - i * c.y() + range.y();
+ drawLine(&painter,
+ QPointF(range.x(), y),
+ QPointF(range.x() + range.width(), y),
+ pen);
+ painter.drawText(QRectF(10,
+ y - metrics.height()/2,
+ range.x() - 10,
+ metrics.height()),
+ QString::number(i));
+ }
-//
-// Draw the Function for the graph, on a Pixmap.
-//
-void QFunctionConfigurator::drawFunction(const QRectF &fullRect)
+ // vertical grid
+
+ for (int i = 0; i < maxx; i += ystep)
+ {
+ double x = range.x() + i * c.x();
+ drawLine(&painter,
+ QPointF(x, range.y()),
+ QPointF(x, range.y() + range.height()),
+ pen);
+ const QString text = QString::number(i);
+ painter.drawText(QRectF(x - metrics.width(text)/2,
+ range.height() + 10 + metrics.height(),
+ metrics.width(text),
+ metrics.height()),
+ text);
+ }
+ {
+ const int i = maxx;
+ double x = range.x() + i * c.x();
+ drawLine(&painter,
+ QPointF(x, range.y()),
+ QPointF(x, range.y() + range.height()),
+ pen);
+ const QString text = QString::number(i);
+ painter.drawText(QRectF(x - metrics.width(text)/2,
+ range.height() + 10 + metrics.height(),
+ metrics.width(text),
+ metrics.height()),
+ text);
+ }
+}
+
+void QFunctionConfigurator::drawFunction()
{
- if (!_config)
- return;
-int i;
-QPointF prevPoint;
-QPointF currentPoint;
-
- //
- // Use the background picture to draw on.
- // ToDo: find out how to add Pixmaps, without getting it all green...
- //
- _function = QPixmap(_background);
- QPainter painter(&_function);
-
- painter.save();
+ if (!_config)
+ return;
+ int i;
+ QPointF prevPoint;
+ QPointF currentPoint;
+
+ _function = QPixmap(_background);
+ QPainter painter(&_function);
+
+ painter.save();
painter.setRenderHint(QPainter::Antialiasing, true);
- //
- // Draw the handles for the Points
- //
- for (i = 0; i < _points.size(); i++) {
- currentPoint = graphicalizePoint( _points[i], "drawFunction handles" ); // Get the next point and convert it to Widget measures
- drawPoint(&painter, currentPoint, QColor(200, 200, 210, 120));
- lastPoint = currentPoint; // Remember which point is the rightmost in the graph
-//qDebug() << "QFunctionConfigurator::paintEvent, drawing handle for " << currentPoint;
- }
+ QList<QPointF> points = _config->getPoints();
+
+ for (i = 0; i < points.size(); i++) {
+ currentPoint = point_to_pixel( points[i] ); // Get the next point and convert it to Widget measures
+ drawPoint(&painter, currentPoint, QColor(200, 200, 210, 120));
+ lastPoint = currentPoint; // Remember which point is the rightmost in the graph
+ }
QPen pen(colBezier, 1.2, Qt::SolidLine);
- prevPoint = graphicalizePoint( QPointF(0,0), "drawFunction lines" ); // Start at the Axis
- double max = maxInputEGU();
- QPointF prev = graphicalizePoint(QPointF(0, 0));
- double step = 1e-1 / (double) pixPerEGU_Input();
- for (double i = 0; i < max; i += step) {
- double val = _config->getValue(i);
- QPointF cur = graphicalizePoint(QPointF(i, val));
- drawLine(&painter, prev, cur, pen);
- prev = cur;
- }
- painter.restore();
+ prevPoint = point_to_pixel( QPointF(0,0) ); // Start at the Axis
+ double max = _config->maxInput();
+ QPointF prev = point_to_pixel(QPointF(0, 0));
+ const double step = 1.01;
+ for (double i = 0; i < max; i += step) {
+ double val = _config->getValue(i);
+ QPointF cur = point_to_pixel(QPointF(i, val));
+ drawLine(&painter, prev, cur, pen);
+ prev = cur;
+ }
+ painter.restore();
}
-//
-// The Widget paints the surface every x msecs.
-//
void QFunctionConfigurator::paintEvent(QPaintEvent *e)
{
-QPointF prevPoint;
-QPointF currentPoint;
-QPointF actualPos;
-int i;
+ QPointF prevPoint;
+ QPointF currentPoint;
+ QPointF actualPos;
+ int i;
-// qDebug() << "QFunctionConfigurator::paintEvent.";
-
- QPainter p(this);
+ QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
- p.setClipRect(e->rect());
-
- if (_draw_background) {
- drawBackground(e->rect()); // Draw the static parts on a Pixmap
- p.drawPixmap(0, 0, _background); // Paint the background
- _draw_background = false;
- }
-
- if (_draw_function) {
- drawFunction(e->rect()); // Draw the Function on a Pixmap
- _draw_function = false;
- }
- p.drawPixmap(0, 0, _function); // Always draw the background and the function
-
- QPen pen(Qt::white, 1, Qt::SolidLine);
-
- //
- // Draw the Points, that make up the Curve
- //
- if (_config) {
- //
- // When moving, also draw a sketched version of the Function.
- //
- if (movingPoint >= 0 && movingPoint < _points.size()) {
- prevPoint = graphicalizePoint( QPointF(0,0), "paintEvent moving" ); // Start at the Axis
- for (i = 0; i < _points.size(); i++) {
- currentPoint = graphicalizePoint( _points[i], "paintEvent moving" ); // Get the next point and convert it to Widget measures
- drawLine(&p, prevPoint, currentPoint, pen);
- prevPoint = currentPoint;
-// qDebug() << "QFunctionConfigurator::paintEvent, drawing while moving " << currentPoint;
- }
-
- //
- // When moving, also draw a few help-lines, so positioning the point gets easier.
- //
- pen.setWidth(1);
- pen.setColor( Qt::white );
- pen.setStyle( Qt::DashLine );
- actualPos = graphicalizePoint(_points[movingPoint], "paintEvent moving help line(s)");
- drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
- drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen);
- }
-
- //
- // If the Tracker is active, the 'Last Point' it requested is recorded.
- // Show that point on the graph, with some lines to assist.
- // This new feature is very handy for tweaking the curves!
- //
- if (_config->getLastPoint( currentPoint )) {
-
-// qDebug() << "QFunctionConfigurator::paintEvent, drawing tracked Point " << currentPoint;
-
- actualPos = graphicalizePoint( currentPoint, "paintEvent tracking" );
- drawPoint(&p, actualPos, QColor(255, 0, 0, 120));
-
- pen.setWidth(1);
- pen.setColor( Qt::black );
- pen.setStyle( Qt::SolidLine );
- drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
- drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.bottom()), pen);
- }
-
- }
-
- //
- // Draw the delimiters
- //
- pen.setWidth(1);
- pen.setColor( Qt::white );
- pen.setStyle( Qt::SolidLine );
- drawLine(&p, QPoint(lastPoint.x(), range.top()), QPoint(lastPoint.x(), range.bottom()), pen);
- drawLine(&p, QPoint(range.left(), lastPoint.y()), QPoint(range.right(), lastPoint.y()), pen);
-
- //QTimer::singleShot(50, this, SLOT(update()));
+
+ if (_draw_background) {
+ drawBackground();
+ _draw_background = false;
+ }
+ p.drawPixmap(e->rect(), _background);
+
+ if (_draw_function) {
+ drawFunction(); // Draw the Function on a Pixmap
+ _draw_function = false;
+ }
+ p.drawPixmap(e->rect(), _function); // Always draw the background and the function
+
+ if (_config) {
+ QPen pen(Qt::white, 1, Qt::SolidLine);
+ QList<QPointF> points = _config->getPoints();
+ if (movingPoint >= 0 && movingPoint < points.size()) {
+ prevPoint = point_to_pixel( QPointF(0,0) ); // Start at the Axis
+ for (i = 0; i < points.size(); i++) {
+ currentPoint = point_to_pixel( points[i] ); // Get the next point and convert it to Widget measures
+ drawLine(&p, prevPoint, currentPoint, pen);
+ prevPoint = currentPoint;
+ }
+ pen.setWidth(1);
+ pen.setColor( Qt::white );
+ pen.setStyle( Qt::DashLine );
+ actualPos = point_to_pixel(points[movingPoint]);
+ drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
+ drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.height() + range.top()), pen);
+ }
+
+ //
+ // If the Tracker is active, the 'Last Point' it requested is recorded.
+ // Show that point on the graph, with some lines to assist.
+ // This new feature is very handy for tweaking the curves!
+ //
+ if (_config->getLastPoint( currentPoint )) {
+ actualPos = point_to_pixel( QPointF(fabs(currentPoint.x()), fabs(currentPoint.y())) );
+ drawPoint(&p, actualPos, QColor(255, 0, 0, 120));
+
+ pen.setWidth(1);
+ pen.setColor( Qt::black );
+ pen.setStyle( Qt::SolidLine );
+ drawLine(&p, QPoint(range.left(), actualPos.y()), QPoint(actualPos.x(), actualPos.y()), pen);
+ drawLine(&p, QPoint(actualPos.x(), actualPos.y()), QPoint(actualPos.x(), range.width()), pen);
+ }
+
+ }
}
//
@@ -394,252 +260,144 @@ void QFunctionConfigurator::drawLine(QPainter *painter, const QPointF &start, co
painter->restore();
}
-//
-// If the mousebutton is pressed, check if it is inside one of the Points.
-// If so: start moving that Point, until mouse release.
-//
void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)
{
- //
- // First: check the left mouse-button
- //
- if (e->button() == Qt::LeftButton) {
-
- //
- // Check to see if the cursor is touching one of the points.
- //
- bool bTouchingPoint = false;
- movingPoint = -1;
- if (_config) {
-
- for (int i = 0; i < _points.size(); i++) {
- if ( markContains( graphicalizePoint( _points[i], "mousePressEvent markContains" ), e->pos() ) ) {
- bTouchingPoint = true;
- movingPoint = i;
+ if (!_config)
+ return;
+ QList<QPointF> points = _config->getPoints();
+ if (e->button() == Qt::LeftButton) {
+ bool bTouchingPoint = false;
+ movingPoint = -1;
+ if (_config) {
+ for (int i = 0; i < points.size(); i++) {
+ if ( point_within_pixel(points[i], e->pos() ) ) {
+ bTouchingPoint = true;
+ movingPoint = i;
+ timer.restart();
break;
- }
- }
-
- //
- // If the Left Mouse-button was clicked without touching a Point, add a new Point
- //
- if (!bTouchingPoint) {
- if (withinRect(e->pos(), range)) {
- _config->addPoint(normalizePoint(e->pos()));
- setConfig(_config, strSettingsFile);
- movingPoint = -1;
- emit CurveChanged( true );
- }
- }
- }
- }
-
- //
- // Then: check the right mouse-button
- //
- if (e->button() == Qt::RightButton) {
-
- //
- // Check to see if the cursor is touching one of the points.
- //
- if (_config) {
-
- for (int i = 0; i < _points.size(); i++) {
- if ( markContains( graphicalizePoint( _points[i], "mousePressEvent RightButton" ), e->pos() ) ) {
- movingPoint = i;
+ }
+ }
+ if (!bTouchingPoint) {
+ _config->addPoint(pixel_coord_to_point(e->pos()));
+ emit CurveChanged( true );
+ }
+ }
+ }
+
+ if (e->button() == Qt::RightButton) {
+ if (_config) {
+ int found_pt = -1;
+ for (int i = 0; i < points.size(); i++) {
+ if ( point_within_pixel(points[i], e->pos() ) ) {
+ found_pt = i;
break;
- }
- }
-
- //
- // If the Right Mouse-button was clicked while touching a Point, remove the Point
- //
- if (movingPoint >= 0 && movingPoint < _points.size()) {
- _config->removePoint(movingPoint);
- movingPoint = -1;
- setConfig(_config, strSettingsFile);
- emit CurveChanged( true );
- }
- else
- movingPoint = -1;
+ }
+ }
+
+ if (found_pt != -1) {
+ _config->removePoint(found_pt);
+ emit CurveChanged( true );
+ }
+ movingPoint = -1;
}
- }
+ }
+ _draw_function = true;
+ update();
}
-//
-// If the mouse if moving, make sure the Bezier moves along.
-// Of course, only when a Point is selected...
-//
void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)
{
+ if (!_config)
+ return;
+ QList<QPointF> points = _config->getPoints();
+ const int refresh_delay = 50;
+
+ if (movingPoint >= 0 && movingPoint < points.size()) {
+ setCursor(Qt::ClosedHandCursor);
+
+ if (timer.isValid() && timer.elapsed() > refresh_delay)
+ {
+ timer.restart();
+ QPointF new_pt = pixel_coord_to_point(e->pos());
+ points[movingPoint] = new_pt;
+ _config->movePoint(movingPoint, new_pt);
+ _draw_function = true;
+ update();
+ }
+ }
+ else {
+ bool bTouchingPoint = false;
+ if (_config) {
+ for (int i = 0; i < points.size(); i++) {
+ if ( point_within_pixel(points[i], e->pos() ) ) {
+ bTouchingPoint = true;
+ }
+ }
+ }
- if (movingPoint >= 0 && movingPoint < _points.size()) {
-
- setCursor(Qt::ClosedHandCursor);
-
- //
- // Change the currently moving Point.
- //
- _points[movingPoint] = normalizePoint(e->pos());
- update();
+ if ( bTouchingPoint ) {
+ setCursor(Qt::OpenHandCursor);
+ }
+ else {
+ setCursor(Qt::ArrowCursor);
+ }
}
- else {
-
- //
- // Check to see if the cursor is touching one of the points.
- //
- bool bTouchingPoint = false;
- if (_config) {
-
- for (int i = 0; i < _points.size(); i++) {
- if ( markContains( graphicalizePoint( _points[i], "mouseMoveEvent" ), e->pos() ) ) {
- bTouchingPoint = true;
- }
- }
- }
-
- if ( bTouchingPoint ) {
- setCursor(Qt::OpenHandCursor);
- }
- else {
- setCursor(Qt::ArrowCursor);
- }
-
- }
}
void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)
{
+ if (!_config)
+ return;
+ QList<QPointF> points = _config->getPoints();
+
if (e->button() == Qt::LeftButton) {
- //qDebug()<<"releasing";
- if (movingPoint >= 0 && movingPoint < _points.size()) {
+ timer.invalidate();
+ if (movingPoint >= 0 && movingPoint < points.size()) {
emit CurveChanged( true );
-
- //
- // Update the Point in the _config
- //
if (_config) {
- _config->movePoint(movingPoint, normalizePoint(e->pos()));
- setConfig(_config, strSettingsFile);
+ _config->movePoint(movingPoint, pixel_coord_to_point(e->pos()));
}
}
setCursor(Qt::ArrowCursor);
movingPoint = -1;
}
-}
-
-//
-// Determine if the mousebutton was pressed within the range of the Point.
-//
-bool QFunctionConfigurator::markContains(const QPointF &pos, const QPointF &coord) const
-{
- QRectF rect(pos.x() - pointSize,
- pos.y() - pointSize,
- pointSize*2, pointSize*2);
- QPainterPath path;
- path.addEllipse(rect);
- return path.contains(coord);
-}
-bool QFunctionConfigurator::withinRect( const QPointF &coord, const QRectF &rect ) const
-{
- QPainterPath path;
- path.addRect(rect);
- return path.contains(coord);
+ _draw_function = true;
+ update();
}
-//
-// Convert the Point in the graph, to the real-life Point.
-//
-QPointF QFunctionConfigurator::normalizePoint(QPointF point) const
+bool QFunctionConfigurator::point_within_pixel(QPointF pt, QPointF pixel) const
{
- QPointF norm;
-
- norm.setX( (point.x() - range.left()) / pPerEGU_Input );
- norm.setY( (range.bottom() - point.y()) / pPerEGU_Output );
-
- if (norm.x() > maxInputEGU())
- norm.setX(maxInputEGU());
- else if (norm.x() < 0)
- norm.setX(0);
- if (norm.y() > maxOutputEGU())
- norm.setY(maxOutputEGU());
- else if (norm.y() < 0)
- norm.setY(0);
-
- return norm;
+ QPointF pixel2(range.x() + pt.x() * c.x(), (range.y() + range.height() - pt.y() * c.y()));
+ return pixel2.x() >= pixel.x() - pointSize && pixel2.x() < pixel.x() + pointSize &&
+ pixel2.y() >= pixel.y() - pointSize && pixel2.y() < pixel.y() + pointSize;
}
-//
-// Convert the real-life Point into the graphical Point.
-//
-QPointF QFunctionConfigurator::graphicalizePoint(QPointF point, QString source) const
+QPointF QFunctionConfigurator::pixel_coord_to_point(QPointF point) const
{
-QPointF graph;
-
- graph.setX( range.left() + (fabs(point.x()) * pPerEGU_Input) );
- graph.setY( range.bottom() - (fabs(point.y()) * pPerEGU_Output) );
-
-// qDebug() << "QFunctionConfigurator::graphicalizePoint source = " << source << ", point = " << point << ", graph = " << graph;
-
- return graph;
-}
+ if (!_config)
+ return QPointF(-1, -1);
-void QFunctionConfigurator::setmaxInputEGU(int value)
-{
- MaxInput = value;
- setMinimumWidth(MaxInput * pPerEGU_Input + 55);
-// resetCurve();
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
-void QFunctionConfigurator::setmaxOutputEGU(int value)
-{
- MaxOutput = value;
- setMinimumHeight(MaxOutput * pPerEGU_Output + 60);
-// resetCurve();
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
+ double x = (point.x() - range.x()) / c.x();
+ double y = (range.height() - point.y() + range.y()) / c.y();
-//
-// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined.
-//
-void QFunctionConfigurator::setpixPerEGU_Input(int value)
-{
- pPerEGU_Input = value;
- setMinimumWidth(MaxInput * pPerEGU_Input + 55);
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
+ if (x < 0)
+ x = 0;
+ if (x > _config->maxInput())
+ x = _config->maxInput();
-//
-// To make configuration more visibly attractive, the number of pixels 'per EGU' can be defined.
-//
-void QFunctionConfigurator::setpixPerEGU_Output(int value)
-{
- pPerEGU_Output = value;
- setMinimumHeight(MaxOutput * pPerEGU_Output + 60);
- resize( MaxInput * pPerEGU_Input + 55, MaxOutput * pPerEGU_Output + 60 );
-}
+ if (y < 0)
+ y = 0;
+ if (y > _config->maxOutput())
+ y = _config->maxOutput();
-//
-// Define the distance of the grid 'in EGU' points.
-//
-void QFunctionConfigurator::setgridDistEGU_Input(int value)
-{
- gDistEGU_Input = value;
- _draw_background = true;
- _draw_function = true;
- repaint();
+ return QPointF(x, y);
}
-//
-// Define the distance of the grid 'in EGU' points.
-//
-void QFunctionConfigurator::setgridDistEGU_Output(int value)
+QPointF QFunctionConfigurator::point_to_pixel(QPointF point) const
{
- gDistEGU_Output = value;
- _draw_background = true;
- _draw_function = true;
- repaint();
+ return QPointF(range.x() + point.x() * c.x(),
+ range.y() + range.height() - point.y() * c.y());
}
void QFunctionConfigurator::setColorBezier(QColor color)
@@ -647,38 +405,9 @@ void QFunctionConfigurator::setColorBezier(QColor color)
colBezier = color;
update();
}
-void QFunctionConfigurator::setColorBackground(QColor color)
-{
- colBackground = color;
- update();
-}
-
-void QFunctionConfigurator::setInputEGU(QString egu)
-{
- strInputEGU = egu;
- update();
-}
-void QFunctionConfigurator::setOutputEGU(QString egu)
-{
- strOutputEGU = egu;
- update();
-}
-void QFunctionConfigurator::setCaption(QString cap)
-{
- strCaption = cap;
- update();
-}
-void QFunctionConfigurator::resizeEvent(QResizeEvent *e)
+void QFunctionConfigurator::resizeEvent(QResizeEvent *)
{
- range = QRectF(40, 20, MaxInput * pPerEGU_Input, MaxOutput * pPerEGU_Output);
-
- qDebug() << "QFunctionConfigurator::resizeEvent, name = " << strCaption << ",range = " << range;
-
- if (_config) {
- setConfig(_config, strSettingsFile);
- }
- _draw_background = true;
- _draw_function = true;
- repaint();
+ update_range();
+ repaint();
}
diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h
index 963f6b13..1f6b4f78 100644
--- a/qfunctionconfigurator/qfunctionconfigurator.h
+++ b/qfunctionconfigurator/qfunctionconfigurator.h
@@ -1,44 +1,16 @@
-/********************************************************************************
-* 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 *
-* *
-* 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/>. *
-* *
-* The FunctionConfigurator was made by Stanislaw Halik, and adapted to *
-* FaceTrackNoIR. *
-* *
-* All credits for this nice piece of code should go to Stanislaw. *
-* *
-* Copyright (c) 2011-2012, Stanislaw Halik <sthalik@misaki.pl> *
-* 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. *
-********************************************************************************/
+/* Copyright (c) 2011-2012 Stanislaw Halik <sthalik@misaki.pl>
+ * Adapted to FaceTrackNoIR by Wim Vriend.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
#ifndef QFUNCTIONCONFIGURATOR_H
#define QFUNCTIONCONFIGURATOR_H
#include <QWidget>
#include <QtGui>
-#include <QtDesigner/QDesignerExportWidget>
#include <QPointF>
+#include <QElapsedTimer>
#include "qfunctionconfigurator/functionconfig.h"
#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
@@ -49,104 +21,27 @@
// The Function is coded in a separate Class and can exists, without the Widget. When the widget is displayed (therefore 'created'), the Function can be attached to the
// Widget and the Widget used to change the Function.
//
+
class FTNOIR_TRACKER_BASE_EXPORT QFunctionConfigurator : public QWidget
{
Q_OBJECT
- Q_PROPERTY(int maxInputEGU READ maxInputEGU WRITE setmaxInputEGU);
- Q_PROPERTY(int maxOutputEGU READ maxOutputEGU WRITE setmaxOutputEGU);
- Q_PROPERTY(int pixPerEGU_Input READ pixPerEGU_Input WRITE setpixPerEGU_Input);
- Q_PROPERTY(int pixPerEGU_Output READ pixPerEGU_Output WRITE setpixPerEGU_Output);
- Q_PROPERTY(int gridDistEGU_Input READ gridDistEGU_Input WRITE setgridDistEGU_Input);
- Q_PROPERTY(int gridDistEGU_Output READ gridDistEGU_Output WRITE setgridDistEGU_Output);
-
- Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier);
- Q_PROPERTY(QColor colorBackground READ colorBackground WRITE setColorBackground);
- Q_PROPERTY(QString stringInputEGU READ stringInputEGU WRITE setInputEGU);
- Q_PROPERTY(QString stringOutputEGU READ stringOutputEGU WRITE setOutputEGU);
- Q_PROPERTY(QString stringCaption READ stringCaption WRITE setCaption);
-
- // Return the current value to Designer
- int maxInputEGU() const
- {
- return MaxInput;
- }
- int maxOutputEGU() const
- {
- return MaxOutput;
- }
- int pixPerEGU_Input() const
- {
- return pPerEGU_Input;
- }
- int pixPerEGU_Output() const
- {
- return pPerEGU_Output;
- }
- int gridDistEGU_Input() const
- {
- return gDistEGU_Input;
- }
- int gridDistEGU_Output() const
- {
- return gDistEGU_Output;
- }
-
- // Return the current color to Designer
- QColor colorBezier() const
+ Q_PROPERTY(QColor colorBezier READ colorBezier WRITE setColorBezier)
+ QColor colorBezier() const
{
return colBezier;
}
- // Return the current color to Designer
- QColor colorBackground() const
- {
- return colBackground;
- }
- // Return the current string to Designer
- QString stringInputEGU() const
- {
- return strInputEGU;
- }
- // Return the current string to Designer
- QString stringOutputEGU() const
- {
- return strOutputEGU;
- }
- // Return the current string to Designer
- QString stringCaption() const
- {
- return strCaption;
- }
-
public:
QFunctionConfigurator(QWidget *parent = 0);
FunctionConfig* config();
- void setConfig(FunctionConfig* config, QString settingsFile); // Connect the FunctionConfig to the Widget.
- void loadSettings(QString settingsFile); // Load the FunctionConfig (points) from the INI-file
- void saveSettings(QString settingsFile); // Save the FunctionConfig (points) to the INI-file
+ void setConfig(FunctionConfig* config);
+ void saveSettings(QString settingsFile);
signals:
void CurveChanged(bool);
public slots:
- void setmaxInputEGU(int);
- void setmaxOutputEGU(int);
- void setpixPerEGU_Input(int);
- void setpixPerEGU_Output(int);
- void setgridDistEGU_Input(int);
- void setgridDistEGU_Output(int);
-
void setColorBezier(QColor);
- void setColorBackground(QColor);
- void setInputEGU(QString);
- void setOutputEGU(QString);
- void setCaption(QString);
-
- void resetCurve() {
- qDebug() << "QFunctionConfigurator::resetCurve = " << strSettingsFile;
- loadSettings( strSettingsFile );
- }
-
protected slots:
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
@@ -154,50 +49,44 @@ protected slots:
void mouseReleaseEvent(QMouseEvent *e);
protected:
- void drawBackground(const QRectF &rect);
- void drawFunction(const QRectF &rect);
+ void drawBackground();
+ void drawFunction();
void drawPoint(QPainter *painter, const QPointF &pt, QColor colBG );
void drawLine(QPainter *painter, const QPointF &start, const QPointF &end, QPen pen);
- bool markContains(const QPointF &pt, const QPointF &coord) const;
-// bool withinRange( const QPointF &coord ) const;
- bool withinRect( const QPointF &coord, const QRectF &rect ) const;
+ bool point_within_pixel(QPointF pt, QPointF pixel) const;
protected:
virtual void resizeEvent(QResizeEvent *);
private:
+ void update_range() {
+ if (!_config)
+ return;
+ double w = width(), h = height();
+ const double mwl = 40, mhl = 20;
+ const double mwr = 15, mhr = 35;
+ range = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr));
+ c = QPointF(range.width() / _config->maxInput(), range.height() / _config->maxOutput());
+ _draw_function = _draw_background = true;
+ }
+
QRectF range; // The actual rectangle for the Bezier-curve
QPointF lastPoint; // The right-most point of the Function
- QPointF normalizePoint (QPointF point) const; // Convert the graphical Point to a real-life Point
- QPointF graphicalizePoint (QPointF point, QString source = "") const; // Convert the Point to a graphical Point
+ QPointF pixel_coord_to_point (QPointF point) const; // Convert the graphical Point to a real-life Point
+ QPointF point_to_pixel (QPointF point) const; // Convert the Point to a graphical Point
int movingPoint;
-
- int MaxInput; // Maximum input limit
- int MaxOutput; // Maximum output limit
- int pPerEGU_Input; // Number of pixels, per EGU of Input
- int pPerEGU_Output; // Number of pixels, per EGU of Output
- int gDistEGU_Input; // Distance of the grid, in EGU of Input
- int gDistEGU_Output; // Distance of the grid, in EGU of Output
+ QElapsedTimer timer;
+ QPointF c;
QColor colBezier; // Color of Bezier curve
- QColor colBackground; // Color of widget background
- QString strInputEGU; // Engineering Units input (vertical axis)
- QString strOutputEGU; // Engineering Units output (horizontal axis)
- QString strCaption; // Caption of the graph
- QString strSettingsFile; // Name of last read INI-file
bool _draw_background; // Flag to determine if the background should be (re-)drawn on the QPixmap
QPixmap _background; // Image of the static parts (axis, lines, etc.)
bool _draw_function; // Flag to determine if the function should be (re-)drawn on the QPixmap
QPixmap _function; // Image of the function (static unless edited by the user)
- //
- // Properties of the CurveConfigurator Widget
- //
- QString _title; // Title do display in Widget and to load Settings
FunctionConfig* _config;
- QList<QPointF> _points; // Function-points
};
#endif // QFUNCTIONCONFIGURATOR_H
diff --git a/qxt-mini/QxtGlobalShortcut b/qxt-mini/QxtGlobalShortcut
new file mode 100644
index 00000000..d673035b
--- /dev/null
+++ b/qxt-mini/QxtGlobalShortcut
@@ -0,0 +1,2 @@
+#include "qxtglobalshortcut.h"
+
diff --git a/qxt-mini/plat/qxtglobalshortcut_mac.cpp b/qxt-mini/plat/qxtglobalshortcut_mac.cpp
new file mode 100644
index 00000000..f43c773a
--- /dev/null
+++ b/qxt-mini/plat/qxtglobalshortcut_mac.cpp
@@ -0,0 +1,265 @@
+#include <Carbon/Carbon.h>
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#include "qxtglobalshortcut_p.h"
+#include <QMap>
+#include <QHash>
+#include <QtDebug>
+#include <QApplication>
+
+typedef QPair<uint, uint> Identifier;
+static QMap<quint32, EventHotKeyRef> keyRefs;
+static QHash<Identifier, quint32> keyIDs;
+static quint32 hotKeySerial = 0;
+static bool qxt_mac_handler_installed = false;
+
+OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data)
+{
+ Q_UNUSED(nextHandler);
+ Q_UNUSED(data);
+ if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
+ {
+ EventHotKeyID keyID;
+ GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID);
+ Identifier id = keyIDs.key(keyID.id);
+ if(id != Identifier())
+ QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first);
+ }
+ return noErr;
+}
+
+quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
+{
+ quint32 native = 0;
+ if (modifiers & Qt::ShiftModifier)
+ native |= shiftKey;
+ if (modifiers & Qt::ControlModifier)
+ native |= cmdKey;
+ if (modifiers & Qt::AltModifier)
+ native |= optionKey;
+ if (modifiers & Qt::MetaModifier)
+ native |= controlKey;
+ if (modifiers & Qt::KeypadModifier)
+ native |= kEventKeyModifierNumLockMask;
+ return native;
+}
+
+quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
+{
+ UTF16Char ch;
+ // Constants found in NSEvent.h from AppKit.framework
+ switch (key)
+ {
+ case Qt::Key_Return:
+ return kVK_Return;
+ case Qt::Key_Enter:
+ return kVK_ANSI_KeypadEnter;
+ case Qt::Key_Tab:
+ return kVK_Tab;
+ case Qt::Key_Space:
+ return kVK_Space;
+ case Qt::Key_Backspace:
+ return kVK_Delete;
+ case Qt::Key_Control:
+ return kVK_Command;
+ case Qt::Key_Shift:
+ return kVK_Shift;
+ case Qt::Key_CapsLock:
+ return kVK_CapsLock;
+ case Qt::Key_Option:
+ return kVK_Option;
+ case Qt::Key_Meta:
+ return kVK_Control;
+ case Qt::Key_F17:
+ return kVK_F17;
+ case Qt::Key_VolumeUp:
+ return kVK_VolumeUp;
+ case Qt::Key_VolumeDown:
+ return kVK_VolumeDown;
+ case Qt::Key_F18:
+ return kVK_F18;
+ case Qt::Key_F19:
+ return kVK_F19;
+ case Qt::Key_F20:
+ return kVK_F20;
+ case Qt::Key_F5:
+ return kVK_F5;
+ case Qt::Key_F6:
+ return kVK_F6;
+ case Qt::Key_F7:
+ return kVK_F7;
+ case Qt::Key_F3:
+ return kVK_F3;
+ case Qt::Key_F8:
+ return kVK_F8;
+ case Qt::Key_F9:
+ return kVK_F9;
+ case Qt::Key_F11:
+ return kVK_F11;
+ case Qt::Key_F13:
+ return kVK_F13;
+ case Qt::Key_F16:
+ return kVK_F16;
+ case Qt::Key_F14:
+ return kVK_F14;
+ case Qt::Key_F10:
+ return kVK_F10;
+ case Qt::Key_F12:
+ return kVK_F12;
+ case Qt::Key_F15:
+ return kVK_F15;
+ case Qt::Key_Help:
+ return kVK_Help;
+ case Qt::Key_Home:
+ return kVK_Home;
+ case Qt::Key_PageUp:
+ return kVK_PageUp;
+ case Qt::Key_Delete:
+ return kVK_ForwardDelete;
+ case Qt::Key_F4:
+ return kVK_F4;
+ case Qt::Key_End:
+ return kVK_End;
+ case Qt::Key_F2:
+ return kVK_F2;
+ case Qt::Key_PageDown:
+ return kVK_PageDown;
+ case Qt::Key_F1:
+ return kVK_F1;
+ case Qt::Key_Left:
+ return kVK_LeftArrow;
+ case Qt::Key_Right:
+ return kVK_RightArrow;
+ case Qt::Key_Down:
+ return kVK_DownArrow;
+ case Qt::Key_Up:
+ return kVK_UpArrow;
+ default:
+ ;
+ }
+
+ if (key == Qt::Key_Escape) ch = 27;
+ else if (key == Qt::Key_Return) ch = 13;
+ else if (key == Qt::Key_Enter) ch = 3;
+ else if (key == Qt::Key_Tab) ch = 9;
+ else ch = key;
+
+ CFDataRef currentLayoutData;
+ TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+
+ if (currentKeyboard == NULL)
+ return 0;
+
+ currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
+ CFRelease(currentKeyboard);
+ if (currentLayoutData == NULL)
+ return 0;
+
+ UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
+ UCKeyboardTypeHeader* table = header->keyboardTypeList;
+
+ uint8_t *data = (uint8_t*)header;
+ // God, would a little documentation for this shit kill you...
+ for (quint32 i=0; i < header->keyboardTypeCount; i++)
+ {
+ UCKeyStateRecordsIndex* stateRec = 0;
+ if (table[i].keyStateRecordsIndexOffset != 0)
+ {
+ stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset);
+ if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
+ }
+
+ UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset);
+ if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
+
+ for (quint32 j=0; j < charTable->keyToCharTableCount; j++)
+ {
+ UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]);
+ for (quint32 k=0; k < charTable->keyToCharTableSize; k++)
+ {
+ if (keyToChar[k] & kUCKeyOutputTestForIndexMask)
+ {
+ long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
+ if (stateRec && idx < stateRec->keyStateRecordCount)
+ {
+ UCKeyStateRecord* rec = reinterpret_cast<UCKeyStateRecord*>(data + stateRec->keyStateRecordOffsets[idx]);
+ if (rec->stateZeroCharData == ch) return k;
+ }
+ }
+ else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE)
+ {
+ if (keyToChar[k] == ch) return k;
+ }
+ } // for k
+ } // for j
+ } // for i
+ return 0;
+}
+
+bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
+{
+ if (!qxt_mac_handler_installed)
+ {
+ qxt_mac_handler_installed = true;
+ EventTypeSpec t;
+ t.eventClass = kEventClassKeyboard;
+ t.eventKind = kEventHotKeyPressed;
+ InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL);
+ }
+
+ EventHotKeyID keyID;
+ keyID.signature = 'cute';
+ keyID.id = ++hotKeySerial;
+
+ EventHotKeyRef ref = 0;
+ bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
+ if (rv)
+ {
+ keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id);
+ keyRefs.insert(keyID.id, ref);
+ }
+ return rv;
+}
+
+bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
+{
+ Identifier id(nativeMods, nativeKey);
+ if (!keyIDs.contains(id)) return false;
+
+ EventHotKeyRef ref = keyRefs.take(keyIDs[id]);
+ keyIDs.remove(id);
+ return !UnregisterEventHotKey(ref);
+}
+bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
+ void *message, long *result)
+{
+ return false;
+}
diff --git a/qxt-mini/plat/qxtglobalshortcut_x11.cpp b/qxt-mini/plat/qxtglobalshortcut_x11.cpp
new file mode 100644
index 00000000..0c203dd8
--- /dev/null
+++ b/qxt-mini/plat/qxtglobalshortcut_x11.cpp
@@ -0,0 +1,235 @@
+#include "../qxtglobalshortcut_p.h"
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#include <QVector>
+#include <QApplication>
+// include private header for great justice -sh 20131015
+#include <X11/Xlib.h>
+#include <xcb/xcb.h>
+#include "qplatformnativeinterface.h"
+
+namespace {
+
+const QVector<quint32> maskModifiers = QVector<quint32>()
+ << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
+
+typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event);
+
+class QxtX11ErrorHandler {
+public:
+ static bool error;
+
+ static int qxtX11ErrorHandler(Display *display, XErrorEvent *event)
+ {
+ Q_UNUSED(display);
+ switch (event->error_code)
+ {
+ case BadAccess:
+ case BadValue:
+ case BadWindow:
+ if (event->request_code == 33 /* X_GrabKey */ ||
+ event->request_code == 34 /* X_UngrabKey */)
+ {
+ error = true;
+ //TODO:
+ //char errstr[256];
+ //XGetErrorText(dpy, err->error_code, errstr, 256);
+ }
+ }
+ return 0;
+ }
+
+ QxtX11ErrorHandler()
+ {
+ error = false;
+ m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler);
+ }
+
+ ~QxtX11ErrorHandler()
+ {
+ XSetErrorHandler(m_previousErrorHandler);
+ }
+
+private:
+ X11ErrorHandler m_previousErrorHandler;
+};
+
+bool QxtX11ErrorHandler::error = false;
+
+class QxtX11Data {
+public:
+ QxtX11Data()
+ {
+#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+ m_display = QX11Info::display();
+#else
+ QPlatformNativeInterface *native = qApp->platformNativeInterface();
+ void *display = native->nativeResourceForScreen(QByteArray("display"),
+ QGuiApplication::primaryScreen());
+ m_display = reinterpret_cast<Display *>(display);
+#endif
+ }
+
+ bool isValid()
+ {
+ return m_display != 0;
+ }
+
+ Display *display()
+ {
+ Q_ASSERT(isValid());
+ return m_display;
+ }
+
+ Window rootWindow()
+ {
+ return DefaultRootWindow(display());
+ }
+
+ bool grabKey(quint32 keycode, quint32 modifiers, Window window)
+ {
+ QxtX11ErrorHandler errorHandler;
+
+ for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) {
+ XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True,
+ GrabModeAsync, GrabModeAsync);
+ }
+
+ if (errorHandler.error) {
+ ungrabKey(keycode, modifiers, window);
+ return false;
+ }
+
+ return true;
+ }
+
+ bool ungrabKey(quint32 keycode, quint32 modifiers, Window window)
+ {
+ QxtX11ErrorHandler errorHandler;
+
+ foreach (quint32 maskMods, maskModifiers) {
+ XUngrabKey(display(), keycode, modifiers | maskMods, window);
+ }
+
+ return !errorHandler.error;
+ }
+
+private:
+ Display *m_display;
+};
+
+} // namespace
+
+#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+bool QxtGlobalShortcutPrivate::eventFilter(void *message)
+{
+ XEvent *event = static_cast<XEvent *>(message);
+ if (event->type == KeyPress)
+ {
+ XKeyEvent *key = reinterpret_cast<XKeyEvent *>(event);
+ unsigned int keycode = key->keycode;
+ unsigned int keystate = key->state;
+#else
+bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
+ void *message, long *result)
+{
+ Q_UNUSED(result);
+
+ xcb_key_press_event_t *kev = 0;
+ if (eventType == "xcb_generic_event_t") {
+ xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
+ if ((ev->response_type & 127) == XCB_KEY_PRESS)
+ kev = static_cast<xcb_key_press_event_t *>(message);
+ }
+
+ if (kev != 0) {
+ unsigned int keycode = kev->detail;
+ unsigned int keystate = 0;
+ if(kev->state & XCB_MOD_MASK_1)
+ keystate |= Mod1Mask;
+ if(kev->state & XCB_MOD_MASK_CONTROL)
+ keystate |= ControlMask;
+ if(kev->state & XCB_MOD_MASK_4)
+ keystate |= Mod4Mask;
+ if(kev->state & XCB_MOD_MASK_SHIFT)
+ keystate |= ShiftMask;
+#endif
+ activateShortcut(keycode,
+ // Mod1Mask == Alt, Mod4Mask == Meta
+ keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
+ }
+ return false;
+}
+
+quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
+{
+ // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
+ quint32 native = 0;
+ if (modifiers & Qt::ShiftModifier)
+ native |= ShiftMask;
+ if (modifiers & Qt::ControlModifier)
+ native |= ControlMask;
+ if (modifiers & Qt::AltModifier)
+ native |= Mod1Mask;
+ if (modifiers & Qt::MetaModifier)
+ native |= Mod4Mask;
+
+ // TODO: resolve these?
+ //if (modifiers & Qt::MetaModifier)
+ //if (modifiers & Qt::KeypadModifier)
+ //if (modifiers & Qt::GroupSwitchModifier)
+ return native;
+}
+
+quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
+{
+ QxtX11Data x11;
+ if (!x11.isValid())
+ return 0;
+
+ KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
+ if (keysym == NoSymbol)
+ keysym = static_cast<ushort>(key);
+
+ return XKeysymToKeycode(x11.display(), keysym);
+}
+
+bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
+{
+ QxtX11Data x11;
+ return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow());
+}
+
+bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
+{
+ QxtX11Data x11;
+ return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow());
+}
diff --git a/qxt-mini/qplatformnativeinterface.h b/qxt-mini/qplatformnativeinterface.h
new file mode 100644
index 00000000..eaa24a9e
--- /dev/null
+++ b/qxt-mini/qplatformnativeinterface.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMNATIVEINTERFACE_H
+#define QPLATFORMNATIVEINTERFACE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the QPA API and is not meant to be used
+// in applications. Usage of this API may make your code
+// source and binary incompatible with future versions of Qt.
+//
+
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+
+class QOpenGLContext;
+class QScreen;
+class QWindow;
+class QPlatformWindow;
+class QBackingStore;
+
+class Q_GUI_EXPORT QPlatformNativeInterface : public QObject
+{
+ Q_OBJECT
+public:
+ virtual void *nativeResourceForIntegration(const QByteArray &resource);
+ virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
+ virtual void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
+ virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
+ virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore);
+
+ typedef void * (*NativeResourceForIntegrationFunction)();
+ typedef void * (*NativeResourceForContextFunction)(QOpenGLContext *context);
+ typedef void * (*NativeResourceForScreenFunction)(QScreen *screen);
+ typedef void * (*NativeResourceForWindowFunction)(QWindow *window);
+ typedef void * (*NativeResourceForBackingStoreFunction)(QBackingStore *backingStore);
+ virtual NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource);
+ virtual NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource);
+ virtual NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource);
+ virtual NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource);
+ virtual NativeResourceForBackingStoreFunction nativeResourceFunctionForBackingStore(const QByteArray &resource);
+
+ virtual QVariantMap windowProperties(QPlatformWindow *window) const;
+ virtual QVariant windowProperty(QPlatformWindow *window, const QString &name) const;
+ virtual QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
+ virtual void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
+
+Q_SIGNALS:
+ void windowPropertyChanged(QPlatformWindow *window, const QString &propertyName);
+};
+
+QT_END_NAMESPACE
+
+#endif // QPLATFORMNATIVEINTERFACE_H
diff --git a/qxt-mini/qxtglobal.h b/qxt-mini/qxtglobal.h
new file mode 100644
index 00000000..7d5abfbe
--- /dev/null
+++ b/qxt-mini/qxtglobal.h
@@ -0,0 +1,233 @@
+
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#ifndef QXTGLOBAL_H
+#define QXTGLOBAL_H
+
+#include <QtGlobal>
+
+#define QXT_VERSION 0x000700
+#define QXT_VERSION_STR "0.7.0"
+
+//--------------------------global macros------------------------------
+
+#ifndef QXT_NO_MACROS
+
+#ifndef _countof
+#define _countof(x) (sizeof(x)/sizeof(*x))
+#endif
+
+#endif // QXT_NO_MACROS
+
+//--------------------------export macros------------------------------
+
+#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_CORE)
+# define QXT_CORE_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_CORE_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_CORE_EXPORT
+#endif // BUILD_QXT_CORE
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_GUI)
+# define QXT_GUI_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_GUI_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_GUI_EXPORT
+#endif // BUILD_QXT_GUI
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_NETWORK)
+# define QXT_NETWORK_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_NETWORK_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_NETWORK_EXPORT
+#endif // BUILD_QXT_NETWORK
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_SQL)
+# define QXT_SQL_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_SQL_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_SQL_EXPORT
+#endif // BUILD_QXT_SQL
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_WEB)
+# define QXT_WEB_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_WEB_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_WEB_EXPORT
+#endif // BUILD_QXT_WEB
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_BERKELEY)
+# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_BERKELEY_EXPORT
+#endif // BUILD_QXT_BERKELEY
+
+#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
+# if defined(BUILD_QXT_ZEROCONF)
+# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT
+# else
+# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QXT_ZEROCONF_EXPORT
+#endif // QXT_ZEROCONF_EXPORT
+
+#if defined(BUILD_QXT_CORE) || defined(BUILD_QXT_GUI) || defined(BUILD_QXT_SQL) || defined(BUILD_QXT_NETWORK) || defined(BUILD_QXT_WEB) || defined(BUILD_QXT_BERKELEY) || defined(BUILD_QXT_ZEROCONF)
+# define BUILD_QXT
+#endif
+
+QXT_CORE_EXPORT const char* qxtVersion();
+
+#ifndef QT_BEGIN_NAMESPACE
+#define QT_BEGIN_NAMESPACE
+#endif
+
+#ifndef QT_END_NAMESPACE
+#define QT_END_NAMESPACE
+#endif
+
+#ifndef QT_FORWARD_DECLARE_CLASS
+#define QT_FORWARD_DECLARE_CLASS(Class) class Class;
+#endif
+
+/****************************************************************************
+** This file is derived from code bearing the following notice:
+** The sole author of this file, Adam Higerd, has explicitly disclaimed all
+** copyright interest and protection for the content within. This file has
+** been placed in the public domain according to United States copyright
+** statute and case law. In jurisdictions where this public domain dedication
+** is not legally recognized, anyone who receives a copy of this file is
+** permitted to use, modify, duplicate, and redistribute this file, in whole
+** or in part, with no restrictions or conditions. In these jurisdictions,
+** this file shall be copyright (C) 2006-2008 by Adam Higerd.
+****************************************************************************/
+
+#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
+#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
+#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
+#define QXT_D(PUB) PUB##Private& d = qxt_d()
+#define QXT_P(PUB) PUB& p = qxt_p()
+
+template <typename PUB>
+class QxtPrivate
+{
+public:
+ virtual ~QxtPrivate()
+ {}
+ inline void QXT_setPublic(PUB* pub)
+ {
+ qxt_p_ptr = pub;
+ }
+
+protected:
+ inline PUB& qxt_p()
+ {
+ return *qxt_p_ptr;
+ }
+ inline const PUB& qxt_p() const
+ {
+ return *qxt_p_ptr;
+ }
+ inline PUB* qxt_ptr()
+ {
+ return qxt_p_ptr;
+ }
+ inline const PUB* qxt_ptr() const
+ {
+ return qxt_p_ptr;
+ }
+
+private:
+ PUB* qxt_p_ptr;
+};
+
+template <typename PUB, typename PVT>
+class QxtPrivateInterface
+{
+ friend class QxtPrivate<PUB>;
+public:
+ QxtPrivateInterface()
+ {
+ pvt = new PVT;
+ }
+ ~QxtPrivateInterface()
+ {
+ delete pvt;
+ }
+
+ inline void setPublic(PUB* pub)
+ {
+ pvt->QXT_setPublic(pub);
+ }
+ inline PVT& operator()()
+ {
+ return *static_cast<PVT*>(pvt);
+ }
+ inline const PVT& operator()() const
+ {
+ return *static_cast<PVT*>(pvt);
+ }
+ inline PVT * operator->()
+ {
+ return static_cast<PVT*>(pvt);
+ }
+ inline const PVT * operator->() const
+ {
+ return static_cast<PVT*>(pvt);
+ }
+private:
+ QxtPrivateInterface(const QxtPrivateInterface&) { }
+ QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
+ QxtPrivate<PUB>* pvt;
+};
+
+#endif // QXT_GLOBAL
diff --git a/qxt-mini/qxtglobalshortcut.cpp b/qxt-mini/qxtglobalshortcut.cpp
new file mode 100644
index 00000000..8515a6b2
--- /dev/null
+++ b/qxt-mini/qxtglobalshortcut.cpp
@@ -0,0 +1,224 @@
+#include "qxtglobalshortcut.h"
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#include "qxtglobalshortcut_p.h"
+#include <QAbstractEventDispatcher>
+#include <QtDebug>
+
+#ifndef Q_OS_MAC
+int QxtGlobalShortcutPrivate::ref = 0;
+# if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0;
+# endif
+#endif // Q_OS_MAC
+QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts;
+
+QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier)
+{
+#ifndef Q_OS_MAC
+ if (ref == 0) {
+# if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+ prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter);
+# else
+ QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
+#endif
+ }
+ ++ref;
+#endif // Q_OS_MAC
+}
+
+QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate()
+{
+#ifndef Q_OS_MAC
+ --ref;
+ if (ref == 0) {
+ QAbstractEventDispatcher *ed = QAbstractEventDispatcher::instance();
+ if (ed != 0) {
+# if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+ ed->setEventFilter(prevEventFilter);
+# else
+ ed->removeNativeEventFilter(this);
+# endif
+ }
+ }
+#endif // Q_OS_MAC
+}
+
+bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut)
+{
+ if (shortcut.toString() == "") return false;
+ Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
+ key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]);
+ mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods);
+ const quint32 nativeKey = nativeKeycode(key);
+ const quint32 nativeMods = nativeModifiers(mods);
+ const bool res = registerShortcut(nativeKey, nativeMods);
+ if (res)
+ shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
+ else
+ qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString();
+ return res;
+}
+
+bool QxtGlobalShortcutPrivate::unsetShortcut()
+{
+ bool res = false;
+ const quint32 nativeKey = nativeKeycode(key);
+ const quint32 nativeMods = nativeModifiers(mods);
+ if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p())
+ res = unregisterShortcut(nativeKey, nativeMods);
+ if (res)
+ shortcuts.remove(qMakePair(nativeKey, nativeMods));
+ else
+ qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString();
+ key = Qt::Key(0);
+ mods = Qt::KeyboardModifiers(0);
+ return res;
+}
+
+void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods)
+{
+ QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
+ if (shortcut && shortcut->isEnabled())
+ emit shortcut->activated();
+}
+
+/*!
+ \class QxtGlobalShortcut
+ \inmodule QxtWidgets
+ \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey".
+
+ A global shortcut triggers even if the application is not active. This
+ makes it easy to implement applications that react to certain shortcuts
+ still if some other application is active or if the application is for
+ example minimized to the system tray.
+
+ Example usage:
+ \code
+ QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
+ connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
+ shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));
+ \endcode
+
+ \bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication.
+ */
+
+/*!
+ \fn QxtGlobalShortcut::activated()
+
+ This signal is emitted when the user types the shortcut's key sequence.
+
+ \sa shortcut
+ */
+
+/*!
+ Constructs a new QxtGlobalShortcut with \a parent.
+ */
+QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent)
+ : QObject(parent)
+{
+ QXT_INIT_PRIVATE(QxtGlobalShortcut);
+}
+
+/*!
+ Constructs a new QxtGlobalShortcut with \a shortcut and \a parent.
+ */
+QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent)
+ : QObject(parent)
+{
+ QXT_INIT_PRIVATE(QxtGlobalShortcut);
+ setShortcut(shortcut);
+}
+
+/*!
+ Destructs the QxtGlobalShortcut.
+ */
+QxtGlobalShortcut::~QxtGlobalShortcut()
+{
+ if (qxt_d().key != 0)
+ qxt_d().unsetShortcut();
+}
+
+/*!
+ \property QxtGlobalShortcut::shortcut
+ \brief the shortcut key sequence
+
+ \bold {Note:} Notice that corresponding key press and release events are not
+ delivered for registered global shortcuts even if they are disabled.
+ Also, comma separated key sequences are not supported.
+ Only the first part is used:
+
+ \code
+ qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B"));
+ Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A"));
+ \endcode
+ */
+QKeySequence QxtGlobalShortcut::shortcut() const
+{
+ return QKeySequence(qxt_d().key | qxt_d().mods);
+}
+
+bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut)
+{
+ if (qxt_d().key != 0)
+ qxt_d().unsetShortcut();
+ return qxt_d().setShortcut(shortcut);
+}
+
+/*!
+ \property QxtGlobalShortcut::enabled
+ \brief whether the shortcut is enabled
+
+ A disabled shortcut does not get activated.
+
+ The default value is \c true.
+
+ \sa setDisabled()
+ */
+bool QxtGlobalShortcut::isEnabled() const
+{
+ return qxt_d().enabled;
+}
+
+void QxtGlobalShortcut::setEnabled(bool enabled)
+{
+ qxt_d().enabled = enabled;
+}
+
+/*!
+ Sets the shortcut \a disabled.
+
+ \sa enabled
+ */
+void QxtGlobalShortcut::setDisabled(bool disabled)
+{
+ qxt_d().enabled = !disabled;
+}
diff --git a/qxt-mini/qxtglobalshortcut.h b/qxt-mini/qxtglobalshortcut.h
new file mode 100644
index 00000000..a81942d2
--- /dev/null
+++ b/qxt-mini/qxtglobalshortcut.h
@@ -0,0 +1,64 @@
+#ifndef QXTGLOBALSHORTCUT_H
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#define QXTGLOBALSHORTCUT_H
+
+#include "qxtglobal.h"
+#include <QObject>
+#include <QKeySequence>
+class QxtGlobalShortcutPrivate;
+
+class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject
+{
+ Q_OBJECT
+ QXT_DECLARE_PRIVATE(QxtGlobalShortcut)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
+
+public:
+ explicit QxtGlobalShortcut(QObject* parent = 0);
+ explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0);
+ virtual ~QxtGlobalShortcut();
+
+ QKeySequence shortcut() const;
+ bool setShortcut(const QKeySequence& shortcut);
+
+ bool isEnabled() const;
+
+public Q_SLOTS:
+ void setEnabled(bool enabled = true);
+ void setDisabled(bool disabled = true);
+
+Q_SIGNALS:
+ void activated();
+};
+
+#endif // QXTGLOBALSHORTCUT_H
diff --git a/qxt-mini/qxtglobalshortcut_p.h b/qxt-mini/qxtglobalshortcut_p.h
new file mode 100644
index 00000000..407f968e
--- /dev/null
+++ b/qxt-mini/qxtglobalshortcut_p.h
@@ -0,0 +1,81 @@
+#ifndef QXTGLOBALSHORTCUT_P_H
+/****************************************************************************
+** Copyright (c) 2006 - 2011, the LibQxt project.
+** See the Qxt AUTHORS file for a list of authors and copyright holders.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the LibQxt project nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** <http://libqxt.org> <foundation@libqxt.org>
+*****************************************************************************/
+
+#define QXTGLOBALSHORTCUT_P_H
+
+#include "qxtglobalshortcut.h"
+#include <QAbstractEventDispatcher>
+#include <QKeySequence>
+#include <QHash>
+
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+#include <QAbstractNativeEventFilter>
+#endif
+
+class QxtGlobalShortcutPrivate : public QxtPrivate<QxtGlobalShortcut>
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+ ,public QAbstractNativeEventFilter
+#endif
+{
+public:
+ QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
+ QxtGlobalShortcutPrivate();
+ ~QxtGlobalShortcutPrivate();
+
+ bool enabled;
+ Qt::Key key;
+ Qt::KeyboardModifiers mods;
+
+ bool setShortcut(const QKeySequence& shortcut);
+ bool unsetShortcut();
+
+ static bool error;
+ static int ref;
+# if QT_VERSION < QT_VERSION_CHECK(5,0,0)
+ static QAbstractEventDispatcher::EventFilter prevEventFilter;
+# else
+ static bool eventFilter(void* message);
+ virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
+# endif // QT_VERSION < QT_VERSION_CHECK(5,0,0)
+
+ static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
+
+private:
+ static quint32 nativeKeycode(Qt::Key keycode);
+ static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers);
+
+ static bool registerShortcut(quint32 nativeKey, quint32 nativeMods);
+ static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods);
+
+ static QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> shortcuts;
+};
+
+#endif // QXTGLOBALSHORTCUT_P_H
diff --git a/readme.txt b/readme.txt
deleted file mode 100644
index eb01d3c0..00000000
--- a/readme.txt
+++ /dev/null
@@ -1 +0,0 @@
-Windows binary builds are available at <http://ananke.laggy.pk/opentrack/> \ No newline at end of file
diff --git a/x-plane-plugin/plugin.c b/x-plane-plugin/plugin.c
index 18a01aa2..62c9d6f0 100644
--- a/x-plane-plugin/plugin.c
+++ b/x-plane-plugin/plugin.c
@@ -15,7 +15,11 @@
#include "ftnoir_tracker_base/ftnoir_tracker_types.h"
-// using Wine name to ease things
+#ifndef PLUGIN_API
+#define PLUGIN_API
+#endif
+
+/* using Wine name to ease things */
#define WINE_SHM_NAME "facetracknoir-wine-shm"
#define WINE_MTX_NAME "facetracknoir-wine-mtx"
@@ -36,27 +40,36 @@ static WineSHM* shm_posix = NULL;
static void *view_x, *view_y, *view_z, *view_heading, *view_pitch;
static float offset_x, offset_y, offset_z;
-PortableLockedShm* PortableLockedShm_init(const char *shmName, const char *mutexName, int mapSize)
+static void reinit_offset() {
+ offset_x = XPLMGetDataf(view_x);
+ offset_y = XPLMGetDataf(view_y);
+ offset_z = XPLMGetDataf(view_z);
+}
+
+#ifdef __GNUC__
+# define OT_UNUSED(varname) varname __attribute__((__unused__))
+#else
+# define OT_UNUSED(varname) varname
+#endif
+
+PortableLockedShm* PortableLockedShm_init(const char *shmName, const char *OT_UNUSED(mutexName), int mapSize)
{
PortableLockedShm* self = malloc(sizeof(PortableLockedShm));
char shm_filename[NAME_MAX];
shm_filename[0] = '/';
strncpy(shm_filename+1, shmName, NAME_MAX-2);
shm_filename[NAME_MAX-1] = '\0';
- sprintf(shm_filename + strlen(shm_filename), "%ld\n", (long) getuid());
- //(void) shm_unlink(shm_filename);
+ /* (void) shm_unlink(shm_filename); */
self->fd = shm_open(shm_filename, O_RDWR | O_CREAT, 0600);
- if (ftruncate(self->fd, mapSize) == 0)
- self->mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, self->fd, (off_t)0);
- else
- self->mem = (void*) -1;
+ (void) ftruncate(self->fd, mapSize);
+ self->mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, self->fd, (off_t)0);
return self;
}
void PortableLockedShm_free(PortableLockedShm* self)
{
- //(void) shm_unlink(shm_filename);
+ /*(void) shm_unlink(shm_filename);*/
(void) munmap(self->mem, self->size);
(void) close(self->fd);
free(self);
@@ -72,24 +85,18 @@ void PortableLockedShm_unlock(PortableLockedShm* self)
flock(self->fd, LOCK_UN);
}
-static void reinit_offset() {
- offset_x = XPLMGetDataf(view_x);
- offset_y = XPLMGetDataf(view_y);
- offset_z = XPLMGetDataf(view_z);
-}
-
int write_head_position(
- XPLMDrawingPhase inPhase,
- int inIsBefore,
- void * inRefcon)
+ XPLMDrawingPhase OT_UNUSED(inPhase),
+ int OT_UNUSED(inIsBefore),
+ void * OT_UNUSED(inRefcon))
{
if (lck_posix != NULL && shm_posix != NULL) {
PortableLockedShm_lock(lck_posix);
- XPLMSetDataf(view_x, shm_posix->data[TX] * 1e-2 + offset_x);
- XPLMSetDataf(view_y, shm_posix->data[TY] * 1e-2 + offset_y);
- XPLMSetDataf(view_z, shm_posix->data[TZ] * 1e-2 + offset_z);
- XPLMSetDataf(view_heading, shm_posix->data[Yaw]);
- XPLMSetDataf(view_pitch, shm_posix->data[Pitch]);
+ XPLMSetDataf(view_x, shm_posix->data[TX] * 1e-3 + offset_x);
+ XPLMSetDataf(view_y, shm_posix->data[TY] * 1e-3 + offset_y);
+ XPLMSetDataf(view_z, shm_posix->data[TZ] * 1e-3 + offset_z);
+ XPLMSetDataf(view_heading, shm_posix->data[Yaw] * 180 / 3.141592654);
+ XPLMSetDataf(view_pitch, shm_posix->data[Pitch] * 180 / 3.141592654);
PortableLockedShm_unlock(lck_posix);
}
return 1;
@@ -104,86 +111,41 @@ PLUGIN_API int XPluginStart ( char * outName, char * outSignature, char * outDes
if (view_x && view_y && view_z && view_heading && view_pitch) {
lck_posix = PortableLockedShm_init(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM));
if (lck_posix->mem == (void*)-1) {
- fprintf(stderr, "FTNOIR failed to init SHM #1!\n");
- return 0;
- }
- if (lck_posix->mem == NULL) {
- fprintf(stderr, "FTNOIR failed to init SHM #2!\n");
+ fprintf(stderr, "opentrack failed to init SHM!\n");
return 0;
}
shm_posix = (WineSHM*) lck_posix->mem;
memset(shm_posix, 0, sizeof(WineSHM));
- strcpy(outName, "FaceTrackNoIR");
- strcpy(outSignature, "FaceTrackNoIR - FreeTrack lives!");
- strcpy(outDescription, "Face tracking view control");
- fprintf(stderr, "FTNOIR init complete\n");
- return 1;
- }
- return 0;
-}
-
-#if 0
-static int camera_callback(XPLMCameraPosition_t* outCameraPosition, int inIsLosingControl, void* inRefCon) {
- if (!inIsLosingControl && XPLMGetCycleNumber() > 0) {
- //XPLMReadCameraPosition(outCameraPosition);
- PortableLockedShm_lock(lck_posix);
- outCameraPosition->heading = shm_posix->rx * 57.295781;
- outCameraPosition->pitch = shm_posix->ry * 57.295781;
- outCameraPosition->roll = shm_posix->rz * 57.295781;
- outCameraPosition->x = XPLMGetDataf(view_x);
- outCameraPosition->y = XPLMGetDataf(view_y);
- outCameraPosition->z = XPLMGetDataf(view_z);
- PortableLockedShm_unlock(lck_posix);
+ strcpy(outName, "opentrack");
+ strcpy(outSignature, "opentrack - freetrack lives!");
+ strcpy(outDescription, "head tracking view control");
+ fprintf(stderr, "opentrack init complete\n");
return 1;
}
return 0;
}
-static float flight_loop (
- float inElapsedSinceLastCall,
- float inElapsedTimeSinceLastFlightLoop,
- int inCounter,
- void * inRefcon)
-{
- XPLMControlCamera(xplm_ControlCameraForever, camera_callback, NULL);
- // don't want it called anymore
- return 0;
-}
-#endif
PLUGIN_API void XPluginStop ( void ) {
-#if 0
- // crashes due to race
if (lck_posix)
+ {
PortableLockedShm_free(lck_posix);
- lck_posix = NULL;
- shm_posix = NULL;
-#endif
+ lck_posix = NULL;
+ shm_posix = NULL;
+ }
}
PLUGIN_API void XPluginEnable ( void ) {
- reinit_offset();
XPLMRegisterDrawCallback(write_head_position, xplm_Phase_LastScene, 1, NULL);
-#if 0
- XPLMRegisterFlightLoopCallback(flight_loop, -1, NULL);
-#endif
}
PLUGIN_API void XPluginDisable ( void ) {
XPLMUnregisterDrawCallback(write_head_position, xplm_Phase_LastScene, 1, NULL);
- XPLMSetDataf(view_x, offset_x);
- XPLMSetDataf(view_y, offset_y);
- XPLMSetDataf(view_z, offset_z);
-#if 0
- XPLMUnregisterFlightLoopCallback(flight_loop, NULL);
- if (XPLMIsCameraBeingControlled(NULL))
- XPLMDontControlCamera();
-#endif
}
PLUGIN_API void XPluginReceiveMessage(
- XPLMPluginID inFromWho,
- int inMessage,
- void * inParam)
+ XPLMPluginID OT_UNUSED(inFromWho),
+ int OT_UNUSED(inMessage),
+ void * OT_UNUSED(inParam))
{
if (inMessage == XPLM_MSG_AIRPORT_LOADED)
reinit_offset();