diff options
91 files changed, 12554 insertions, 12554 deletions
diff --git a/faceapi/build_options.h b/faceapi/build_options.h index 6bc6a44c..e298686e 100644 --- a/faceapi/build_options.h +++ b/faceapi/build_options.h @@ -1,8 +1,8 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Build Options
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-//controls whether or not FaceAPI should use the callback or poll
-#define USE_HEADPOSE_CALLBACK 1
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Build Options +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//controls whether or not FaceAPI should use the callback or poll +#define USE_HEADPOSE_CALLBACK 1 diff --git a/faceapi/lock.h b/faceapi/lock.h index efe38605..bb095675 100644 --- a/faceapi/lock.h +++ b/faceapi/lock.h @@ -1,35 +1,35 @@ -#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
+#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 index ce7d2a64..47b810fa 100644 --- a/faceapi/lockfree.h +++ b/faceapi/lockfree.h @@ -1,65 +1,65 @@ -//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
- }
-};
-
+//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 index 9fe0af95..8128ee97 100644 --- a/faceapi/main.cpp +++ b/faceapi/main.cpp @@ -1,529 +1,529 @@ -/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-
-//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;
-}
+/******************************************************************************** +* 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/>. * +*********************************************************************************/ + +//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 index a4f84705..b1a013e8 100644 --- a/faceapi/mutex.h +++ b/faceapi/mutex.h @@ -1,46 +1,46 @@ -#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
+#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 index b4263f59..981c9e33 100644 --- a/faceapi/stdafx.cpp +++ b/faceapi/stdafx.cpp @@ -1,8 +1,8 @@ -// 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
+// 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 index 1fdab0b1..92e24b3e 100644 --- a/faceapi/stdafx.h +++ b/faceapi/stdafx.h @@ -1,36 +1,36 @@ -#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>
+#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 index 5d25e9a7..80555d22 100644 --- a/faceapi/utils.h +++ b/faceapi/utils.h @@ -1,349 +1,349 @@ -#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,©_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
+#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,©_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/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp index f3ec8fce..fe8ce36b 100644 --- a/facetracknoir/facetracknoir.cpp +++ b/facetracknoir/facetracknoir.cpp @@ -1,1563 +1,1563 @@ -/********************************************************************************
-* 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 "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()));
- 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 ( true );
-
- //
- // 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() );
-
- //
- // Register the Tracker instance with the Tracker Dialog (if open)
- //
- if (pTrackerDialog && Libraries->pTracker) {
- pTrackerDialog->registerTracker( Libraries->pTracker );
- }
-
- if (pFilterDialog && Libraries->pFilter)
- pFilterDialog->registerFilter(Libraries->pFilter);
-
- tracker->start();
-
- 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);
-
- //
- // UnRegister the Tracker instance with the Tracker Dialog (if open)
- //
- if (pTrackerDialog) {
- pTrackerDialog->unRegisterTracker();
- }
- if (pProtocolDialog) {
- pProtocolDialog->unRegisterProtocol();
- }
- if (pFilterDialog)
- pFilterDialog->unregisterFilter();
-
- //
- // 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;
- }
- }
- 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));
-
- //
- // 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) {
- if (Libraries && Libraries->pTracker)
- pTrackerDialog->registerTracker(Libraries->pTracker);
- pTrackerDialog->Initialize(this);
- }
- }
-}
-
-// 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) {
- if (Libraries && Libraries->pSecondTracker)
- pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker);
- pSecondTrackerDialog->Initialize(this);
- }
- }
-}
-
-/** 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);
- if (Libraries && Libraries->pFilter)
- pFilterDialog->registerFilter(Libraries->pFilter);
- }
- }
-}
-/** 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);
-}
-
-static bool get_metadata(DynamicLibrary* lib, QString& longName, QIcon& icon)
-{
- Metadata* meta;
- if (!lib->Metadata || ((meta = lib->Metadata()), !meta))
- {
- delete lib;
- 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);
- }
-}
-
-//
-// Setup the icons for the comboBoxes
-//
-void FaceTrackNoIR::createIconGroupBox()
-{
- ui.cbxSecondTrackerSource->addItem(QIcon(), "None");
- dlopen_filters.push_back((DynamicLibrary*) NULL);
- ui.iconcomboFilter->addItem(QIcon(), "None");
-
- 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);
-
- 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()));
-
- // 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 ();
-
- if (tracker) /* running already */
- {
-#if defined(_WIN32) || defined(__WIN32)
- if (keybindingWorker)
- {
- keybindingWorker->should_quit = true;
- keybindingWorker->wait();
- delete keybindingWorker;
- keybindingWorker = NULL;
- }
- keybindingWorker = new KeybindingWorker(*this, keyCenter);
- keybindingWorker->start();
-#endif
- }
-}
-
-//
-// 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 "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())); + 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 ( true ); + + // + // 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() ); + + // + // Register the Tracker instance with the Tracker Dialog (if open) + // + if (pTrackerDialog && Libraries->pTracker) { + pTrackerDialog->registerTracker( Libraries->pTracker ); + } + + if (pFilterDialog && Libraries->pFilter) + pFilterDialog->registerFilter(Libraries->pFilter); + + tracker->start(); + + 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); + + // + // UnRegister the Tracker instance with the Tracker Dialog (if open) + // + if (pTrackerDialog) { + pTrackerDialog->unRegisterTracker(); + } + if (pProtocolDialog) { + pProtocolDialog->unRegisterProtocol(); + } + if (pFilterDialog) + pFilterDialog->unregisterFilter(); + + // + // 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; + } + } + 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)); + + // + // 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) { + if (Libraries && Libraries->pTracker) + pTrackerDialog->registerTracker(Libraries->pTracker); + pTrackerDialog->Initialize(this); + } + } +} + +// 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) { + if (Libraries && Libraries->pSecondTracker) + pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker); + pSecondTrackerDialog->Initialize(this); + } + } +} + +/** 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); + if (Libraries && Libraries->pFilter) + pFilterDialog->registerFilter(Libraries->pFilter); + } + } +} +/** 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); +} + +static bool get_metadata(DynamicLibrary* lib, QString& longName, QIcon& icon) +{ + Metadata* meta; + if (!lib->Metadata || ((meta = lib->Metadata()), !meta)) + { + delete lib; + 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); + } +} + +// +// Setup the icons for the comboBoxes +// +void FaceTrackNoIR::createIconGroupBox() +{ + ui.cbxSecondTrackerSource->addItem(QIcon(), "None"); + dlopen_filters.push_back((DynamicLibrary*) NULL); + ui.iconcomboFilter->addItem(QIcon(), "None"); + + 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); + + 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())); + + // 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 (); + + if (tracker) /* running already */ + { +#if defined(_WIN32) || defined(__WIN32) + if (keybindingWorker) + { + keybindingWorker->should_quit = true; + keybindingWorker->wait(); + delete keybindingWorker; + keybindingWorker = NULL; + } + keybindingWorker = new KeybindingWorker(*this, keyCenter); + keybindingWorker->start(); +#endif + } +} + +// +// 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; + } +} diff --git a/facetracknoir/facetracknoir.h b/facetracknoir/facetracknoir.h index ff0b3642..768f6107 100644 --- a/facetracknoir/facetracknoir.h +++ b/facetracknoir/facetracknoir.h @@ -1,295 +1,295 @@ -/********************************************************************************
-* 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();
-};
-
-// 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; }
-};
-
-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 + +#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(); +}; + +// 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; } +}; + +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(); + } +}; + #endif // FaceTrackNoIR_H
\ No newline at end of file diff --git a/facetracknoir/main.cpp b/facetracknoir/main.cpp index 7ff9f29f..bc0f973b 100644 --- a/facetracknoir/main.cpp +++ b/facetracknoir/main.cpp @@ -1,57 +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/>. *
-*********************************************************************************/
-
-#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 <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; +} + diff --git a/facetracknoir/rotation.h b/facetracknoir/rotation.h index dd70ca77..e97ec0f0 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 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 diff --git a/facetracknoir/tracker.cpp b/facetracknoir/tracker.cpp index f2b4845f..47daa697 100644 --- a/facetracknoir/tracker.cpp +++ b/facetracknoir/tracker.cpp @@ -1,218 +1,218 @@ -/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-#include "tracker.h"
-#include "facetracknoir.h"
-
-/** constructor **/
-Tracker::Tracker( FaceTrackNoIR *parent ) :
- should_quit(false),
- do_center(false)
-{
- // Retieve the pointer to the parent
- mainApp = parent;
- // Load the settings from the INI-file
- loadSettings();
-}
-
-Tracker::~Tracker()
-{
-}
-
-static void get_curve(double pos, double& out, THeadPoseDOF& axis) {
- bool altp = (pos < 0) && axis.altp;
- if (altp) {
- out = axis.invert * axis.curveAlt.getValue(pos);
- axis.curve.setTrackingActive( false );
- axis.curveAlt.setTrackingActive( true );
- }
- else {
- out = axis.invert * axis.curve.getValue(pos);
- axis.curve.setTrackingActive( true );
- axis.curveAlt.setTrackingActive( false );
- }
- out += axis.zero;
-}
-
-/** 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
- {
- 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);
- }
-
- if (Libraries->pTracker) {
- bTracker1Confid = Libraries->pTracker->GiveHeadPoseData(newpose);
- }
-
- {
- QMutexLocker foo(&mtx);
- const bool 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.
- //
- if (do_center) {
- //
- // Only copy valid values
- //
- 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();
-
- if (Libraries->pFilter)
- Libraries->pFilter->Initialize();
- }
-
- if (confid) {
- // get values
- 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
- }
- }
- }
-
- //for lower cpu load
- msleep(8);
- }
-
- for (int i = 0; i < 6; i++)
- {
- mainApp->axis(i).curve.setTrackingActive(false);
- mainApp->axis(i).curveAlt.setTrackingActive(false);
- }
-}
-
-//
-// Get the raw headpose, so it can be displayed.
-//
-void Tracker::getHeadPose( double *data ) {
- QMutexLocker foo(&mtx);
- for (int i = 0; i < 6; i++)
- {
- data[i] = mainApp->axis(i).headPos;
- }
-}
-
-//
-// 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; }
+/******************************************************************************** +* 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/>. * +*********************************************************************************/ +#include "tracker.h" +#include "facetracknoir.h" + +/** constructor **/ +Tracker::Tracker( FaceTrackNoIR *parent ) : + should_quit(false), + do_center(false) +{ + // Retieve the pointer to the parent + mainApp = parent; + // Load the settings from the INI-file + loadSettings(); +} + +Tracker::~Tracker() +{ +} + +static void get_curve(double pos, double& out, THeadPoseDOF& axis) { + bool altp = (pos < 0) && axis.altp; + if (altp) { + out = axis.invert * axis.curveAlt.getValue(pos); + axis.curve.setTrackingActive( false ); + axis.curveAlt.setTrackingActive( true ); + } + else { + out = axis.invert * axis.curve.getValue(pos); + axis.curve.setTrackingActive( true ); + axis.curveAlt.setTrackingActive( false ); + } + out += axis.zero; +} + +/** 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 + { + 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); + } + + if (Libraries->pTracker) { + bTracker1Confid = Libraries->pTracker->GiveHeadPoseData(newpose); + } + + { + QMutexLocker foo(&mtx); + const bool 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. + // + if (do_center) { + // + // Only copy valid values + // + 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(); + + if (Libraries->pFilter) + Libraries->pFilter->Initialize(); + } + + if (confid) { + // get values + 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 + } + } + } + + //for lower cpu load + msleep(8); + } + + for (int i = 0; i < 6; i++) + { + mainApp->axis(i).curve.setTrackingActive(false); + mainApp->axis(i).curveAlt.setTrackingActive(false); + } +} + +// +// Get the raw headpose, so it can be displayed. +// +void Tracker::getHeadPose( double *data ) { + QMutexLocker foo(&mtx); + for (int i = 0; i < 6; i++) + { + data[i] = mainApp->axis(i).headPos; + } +} + +// +// 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 7e2b84cd..eeb18dad 100644 --- a/facetracknoir/tracker.h +++ b/facetracknoir/tracker.h @@ -1,145 +1,145 @@ -/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-#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
-
- 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
-
- 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
+/******************************************************************************** +* 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/>. * +*********************************************************************************/ +#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 + + 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 + + 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 diff --git a/facetracknoir/tracker_types.cpp b/facetracknoir/tracker_types.cpp index 11adc985..da246722 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) +{ + 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; +} diff --git a/facetracknoir/tracker_types.h b/facetracknoir/tracker_types.h index ebd89e7c..54d1841e 100644 --- a/facetracknoir/tracker_types.h +++ b/facetracknoir/tracker_types.h @@ -1,41 +1,41 @@ -/********************************************************************************
-* 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/>. *
-*********************************************************************************/
-#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__
+/******************************************************************************** +* 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/>. * +*********************************************************************************/ +#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/freetrackclient/ftclient.h b/freetrackclient/ftclient.h index 406e1237..5e5d8747 100644 --- a/freetrackclient/ftclient.h +++ b/freetrackclient/ftclient.h @@ -1,30 +1,30 @@ -/** @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
+/** @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_filter_accela/ftnoir_filter_accela.cpp b/ftnoir_filter_accela/ftnoir_filter_accela.cpp index c2cda351..0b3d6518 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela.cpp @@ -1,90 +1,90 @@ -/* Copyright (c) 2012 Stanislaw Halik
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-#include "ftnoir_filter_accela/ftnoir_filter_accela.h"
-#include <cmath>
-#include <QDebug>
-#include <QMutexLocker>
-#include "facetracknoir/global-settings.h"
-
-using namespace std;
-
-FTNoIR_Filter::FTNoIR_Filter()
-{
- first_run = true;
- loadSettings();
-}
-
-FTNoIR_Filter::~FTNoIR_Filter()
-{
-
-}
-
-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)
-
- iniFile.beginGroup ( "Accela" );
- zoom_factor = iniFile.value("zoom-slowness", 0).toDouble();
- rotation_alpha = iniFile.value("rotation-alpha", ACCELA_SMOOTHING_ROTATION).toDouble();
- translation_alpha = iniFile.value("translation-alpha", ACCELA_SMOOTHING_TRANSLATION).toDouble();
- iniFile.endGroup ();
-}
-
-void FTNoIR_Filter::receiveSettings(double rot, double trans, double zoom_fac)
-{
- QMutexLocker foo(&mutex);
-
- rotation_alpha = rot;
- translation_alpha = trans;
- zoom_factor = zoom_fac;
-}
-
-static double parabola(const double a, const double x)
-{
- const double a1 = 1./a;
- return a1 * x * x;
-}
-
-void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position,
- double *target_camera_position,
- double *new_camera_position,
- double *last_post_filter_values)
-{
- if (first_run)
- {
- for (int i = 0; i < 6; i++)
- {
- new_camera_position[i] = target_camera_position[i];
- current_camera_position[i] = target_camera_position[i];
- }
-
- first_run = false;
- return;
- }
-
- QMutexLocker foo(&mutex);
-
- for (int i=0;i<6;i++)
- {
- const double vec = target_camera_position[i] - current_camera_position[i];
- const int sign = vec < 0 ? -1 : 1;
- const double x = fabs(vec);
- const double a = i >= 3 ? rotation_alpha : translation_alpha;
- const double reduction = 1. / std::max(1., 1. + zoom_factor * -last_post_filter_values[TZ] / 1000);
- const double velocity = parabola(a, x) * reduction;
- const double result = current_camera_position[i] + velocity * sign;
- const bool done = sign > 0 ? result >= target_camera_position[i] : result <= target_camera_position[i];
- new_camera_position[i] = current_camera_position[i] = done ? target_camera_position[i] : result;
- }
-}
-
-extern "C" FTNOIR_FILTER_BASE_EXPORT IFilter* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Filter;
-}
+/* Copyright (c) 2012 Stanislaw Halik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ +#include "ftnoir_filter_accela/ftnoir_filter_accela.h" +#include <cmath> +#include <QDebug> +#include <QMutexLocker> +#include "facetracknoir/global-settings.h" + +using namespace std; + +FTNoIR_Filter::FTNoIR_Filter() +{ + first_run = true; + loadSettings(); +} + +FTNoIR_Filter::~FTNoIR_Filter() +{ + +} + +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) + + iniFile.beginGroup ( "Accela" ); + zoom_factor = iniFile.value("zoom-slowness", 0).toDouble(); + rotation_alpha = iniFile.value("rotation-alpha", ACCELA_SMOOTHING_ROTATION).toDouble(); + translation_alpha = iniFile.value("translation-alpha", ACCELA_SMOOTHING_TRANSLATION).toDouble(); + iniFile.endGroup (); +} + +void FTNoIR_Filter::receiveSettings(double rot, double trans, double zoom_fac) +{ + QMutexLocker foo(&mutex); + + rotation_alpha = rot; + translation_alpha = trans; + zoom_factor = zoom_fac; +} + +static double parabola(const double a, const double x) +{ + const double a1 = 1./a; + return a1 * x * x; +} + +void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position, + double *target_camera_position, + double *new_camera_position, + double *last_post_filter_values) +{ + if (first_run) + { + for (int i = 0; i < 6; i++) + { + new_camera_position[i] = target_camera_position[i]; + current_camera_position[i] = target_camera_position[i]; + } + + first_run = false; + return; + } + + QMutexLocker foo(&mutex); + + for (int i=0;i<6;i++) + { + const double vec = target_camera_position[i] - current_camera_position[i]; + const int sign = vec < 0 ? -1 : 1; + const double x = fabs(vec); + const double a = i >= 3 ? rotation_alpha : translation_alpha; + const double reduction = 1. / std::max(1., 1. + zoom_factor * -last_post_filter_values[TZ] / 1000); + const double velocity = parabola(a, x) * reduction; + const double result = current_camera_position[i] + velocity * sign; + const bool done = sign > 0 ? result >= target_camera_position[i] : result <= target_camera_position[i]; + new_camera_position[i] = current_camera_position[i] = done ? target_camera_position[i] : result; + } +} + +extern "C" FTNOIR_FILTER_BASE_EXPORT IFilter* CALLING_CONVENTION GetConstructor() +{ + return new FTNoIR_Filter; +} diff --git a/ftnoir_filter_accela/ftnoir_filter_accela.h b/ftnoir_filter_accela/ftnoir_filter_accela.h index 0c13c0e8..49b551e7 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela.h +++ b/ftnoir_filter_accela/ftnoir_filter_accela.h @@ -1,107 +1,107 @@ -/********************************************************************************
-* 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 "facetracknoir/global-settings.h"
-#include <QMutex>
-
-#define ACCELA_SMOOTHING_ROTATION 6.0
-#define ACCELA_SMOOTHING_TRANSLATION 3.0
-
-//*******************************************************************************************************
-// FaceTrackNoIR Filter class.
-//*******************************************************************************************************
-class FTNOIR_FILTER_BASE_EXPORT 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() {
- first_run = true;
- }
- void receiveSettings(double rot, double trans, double zoom_fac);
-private:
- QMutex mutex;
- void loadSettings();
- bool first_run;
- double rotation_alpha, translation_alpha, zoom_factor;
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Filter Settings-dialog.
-//*******************************************************************************************************
-
-// Widget that has controls for FTNoIR protocol filter-settings.
-class FTNOIR_FILTER_BASE_EXPORT FilterControls: public QWidget, public IFilterDialog
-{
- Q_OBJECT
-public:
- explicit FilterControls();
- virtual ~FilterControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerFilter(IFilter* filter);
- void unregisterFilter();
-private:
- Ui::AccelaUICFilterControls ui;
- void loadSettings();
- void save();
- bool settingsDirty;
- FTNoIR_Filter* accela_filter;
-private slots:
- void doOK();
- void doCancel();
- void settingChanged(bool) { settingsDirty = true; }
- void settingChanged(int) { settingsDirty = true; }
-};
-
-//*******************************************************************************************************
-// 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 Mk3"); }
- void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Mk3"); }
- void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Accela filter Mk3"); }
-
- void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); }
-};
-
-
-#endif //INCLUDED_FTN_FILTER_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) 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 "facetracknoir/global-settings.h" +#include <QMutex> + +#define ACCELA_SMOOTHING_ROTATION 6.0 +#define ACCELA_SMOOTHING_TRANSLATION 3.0 + +//******************************************************************************************************* +// FaceTrackNoIR Filter class. +//******************************************************************************************************* +class FTNOIR_FILTER_BASE_EXPORT 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() { + first_run = true; + } + void receiveSettings(double rot, double trans, double zoom_fac); +private: + QMutex mutex; + void loadSettings(); + bool first_run; + double rotation_alpha, translation_alpha, zoom_factor; +}; + +//******************************************************************************************************* +// FaceTrackNoIR Filter Settings-dialog. +//******************************************************************************************************* + +// Widget that has controls for FTNoIR protocol filter-settings. +class FTNOIR_FILTER_BASE_EXPORT FilterControls: public QWidget, public IFilterDialog +{ + Q_OBJECT +public: + explicit FilterControls(); + virtual ~FilterControls(); + void showEvent ( QShowEvent * event ); + void Initialize(QWidget *parent); + void registerFilter(IFilter* filter); + void unregisterFilter(); +private: + Ui::AccelaUICFilterControls ui; + void loadSettings(); + void save(); + bool settingsDirty; + FTNoIR_Filter* accela_filter; +private slots: + void doOK(); + void doCancel(); + void settingChanged(bool) { settingsDirty = true; } + void settingChanged(int) { settingsDirty = true; } +}; + +//******************************************************************************************************* +// 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 Mk3"); } + void getShortName(QString *strToBeFilled) { *strToBeFilled = QString("Accela Mk3"); } + void getDescription(QString *strToBeFilled) { *strToBeFilled = QString("Accela filter Mk3"); } + + 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 8c7cd386..3e74ad81 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela_dialog.cpp @@ -1,190 +1,190 @@ -/********************************************************************************
-* 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/>. *
-* *
-********************************************************************************/
-#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(), accela_filter(NULL)
-{
- 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.rotation_alpha, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(int)));
- connect(ui.translation_alpha, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(int)));
-
- connect(ui.slideZoom, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int)));
- connect(ui.spinZoom, 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) {
- loadSettings();
-
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-void FilterControls::registerFilter(IFilter* filter)
-{
- accela_filter = (FTNoIR_Filter*) filter;
-}
-
-void FilterControls::unregisterFilter()
-{
- accela_filter = NULL;
-}
-
-//
-// 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);
-
- iniFile.beginGroup ( "Accela" );
- ui.slideZoom->setValue(iniFile.value("zoom-slowness", 0).toInt());
- ui.spinZoom->setValue(iniFile.value("zoom-slowness", 0).toInt());
- ui.rotation_alpha->setValue(iniFile.value("rotation-alpha", ACCELA_SMOOTHING_ROTATION).toDouble());
- ui.translation_alpha->setValue(iniFile.value("translation-alpha", ACCELA_SMOOTHING_TRANSLATION).toDouble());
- 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)
-
- qDebug() << "FTNoIR_Filter::save() says: iniFile = " << currentFile;
-
- double rot, trans, zoom;
-
- iniFile.beginGroup ( "Accela" );
- iniFile.setValue("zoom-slowness", zoom = ui.slideZoom->value());
- iniFile.setValue("rotation-alpha", rot = ui.rotation_alpha->value());
- iniFile.setValue("translation-alpha", trans = ui.translation_alpha->value());
- iniFile.endGroup ();
-
- settingsDirty = false;
-
- if (accela_filter)
- accela_filter->receiveSettings(rot, trans, zoom);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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) 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/>. * +* * +********************************************************************************/ +#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(), accela_filter(NULL) +{ + 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.rotation_alpha, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(int))); + connect(ui.translation_alpha, SIGNAL(valueChanged(double)), this, SLOT(settingChanged(int))); + + connect(ui.slideZoom, SIGNAL(valueChanged(int)), this, SLOT(settingChanged(int))); + connect(ui.spinZoom, 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) { + loadSettings(); + + QPoint offsetpos(100, 100); + if (parent) { + this->move(parent->pos() + offsetpos); + } + show(); +} + +void FilterControls::registerFilter(IFilter* filter) +{ + accela_filter = (FTNoIR_Filter*) filter; +} + +void FilterControls::unregisterFilter() +{ + accela_filter = NULL; +} + +// +// 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); + + iniFile.beginGroup ( "Accela" ); + ui.slideZoom->setValue(iniFile.value("zoom-slowness", 0).toInt()); + ui.spinZoom->setValue(iniFile.value("zoom-slowness", 0).toInt()); + ui.rotation_alpha->setValue(iniFile.value("rotation-alpha", ACCELA_SMOOTHING_ROTATION).toDouble()); + ui.translation_alpha->setValue(iniFile.value("translation-alpha", ACCELA_SMOOTHING_TRANSLATION).toDouble()); + 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) + + qDebug() << "FTNoIR_Filter::save() says: iniFile = " << currentFile; + + double rot, trans, zoom; + + iniFile.beginGroup ( "Accela" ); + iniFile.setValue("zoom-slowness", zoom = ui.slideZoom->value()); + iniFile.setValue("rotation-alpha", rot = ui.rotation_alpha->value()); + iniFile.setValue("translation-alpha", trans = ui.translation_alpha->value()); + iniFile.endGroup (); + + settingsDirty = false; + + if (accela_filter) + accela_filter->receiveSettings(rot, trans, zoom); +} + +//////////////////////////////////////////////////////////////////////////////// +// 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; +} diff --git a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp index 0235c067..d4a11028 100644 --- a/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp +++ b/ftnoir_filter_accela/ftnoir_filter_accela_dll.cpp @@ -1,39 +1,39 @@ -/********************************************************************************
-* 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_accela.h"
-#include "facetracknoir/global-settings.h"
-
-FTNoIR_FilterDll::FTNoIR_FilterDll() {
-}
-
-FTNoIR_FilterDll::~FTNoIR_FilterDll()
-{
-
-}
-
-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_accela.h" +#include "facetracknoir/global-settings.h" + +FTNoIR_FilterDll::FTNoIR_FilterDll() { +} + +FTNoIR_FilterDll::~FTNoIR_FilterDll() +{ + +} + +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 9ff286b1..49454a7e 100644 --- a/ftnoir_filter_base/ftnoir_filter_base.h +++ b/ftnoir_filter_base/ftnoir_filter_base.h @@ -1,41 +1,41 @@ -#ifndef FTNOIR_FILTER_BASE_H
-#define FTNOIR_FILTER_BASE_H
-
-#include "ftnoir_filter_base_global.h"
-#include "ftnoir_tracker_base/ftnoir_tracker_base.h"
-#include <QString>
-#include <QList>
-#include <QFile>
-#include <QCoreApplication>
-#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;
-};
-
-struct IFilterDialog
-{
- virtual ~IFilterDialog() {}
- virtual void Initialize(QWidget *parent) = 0;
- virtual void registerFilter(IFilter* tracker) = 0;
- virtual void unregisterFilter() = 0;
-};
-
-#endif // FTNOIR_FILTER_BASE_H
+#ifndef FTNOIR_FILTER_BASE_H +#define FTNOIR_FILTER_BASE_H + +#include "ftnoir_filter_base_global.h" +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include <QString> +#include <QList> +#include <QFile> +#include <QCoreApplication> +#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; +}; + +struct IFilterDialog +{ + virtual ~IFilterDialog() {} + virtual void Initialize(QWidget *parent) = 0; + 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..02733ace 100644 --- a/ftnoir_filter_base/ftnoir_filter_base_global.h +++ b/ftnoir_filter_base/ftnoir_filter_base_global.h @@ -1,12 +1,12 @@ -#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> + +#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 diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp index 43cfd102..b127c665 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.cpp @@ -1,173 +1,173 @@ -/********************************************************************************
-* 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 <QWidget>
-#include "facetracknoir/global-settings.h"
-#include <algorithm>
-#include <QMutexLocker>
-//#define LOG_OUTPUT
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// EWMA Filter: Exponentially Weighted Moving Average filter with dynamic smoothing parameter
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-FTNoIR_Filter::FTNoIR_Filter()
-{
- first_run = true;
- alpha_smoothing = 0.02f; // this is a constant for now, might be a parameter later
- loadSettings(); // Load the Settings
-}
-
-FTNoIR_Filter::~FTNoIR_Filter()
-{
-}
-
-void FTNoIR_Filter::receiveSettings(double smin, double smax, double sexpt)
-{
- QMutexLocker foo(&mutex);
-
- kMinSmoothing = smin;
- kMaxSmoothing = smax;
- kSmoothingScaleCurve = sexpt;
-}
-
-//
-// 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" );
- kMinSmoothing = iniFile.value ( "minSmooth", 15 ).toInt();
- kMaxSmoothing = iniFile.value ( "maxSmooth", 50 ).toInt();
- kSmoothingScaleCurve = iniFile.value ( "powCurve", 10 ).toInt();
- iniFile.endGroup ();
-}
-
-void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position,
- double *target_camera_position,
- double *new_camera_position,
- double *last_post_filter)
-{
- double delta;
- double new_alpha;
- double scale[]={0.025f,0.025f,0.025f,6.0f,6.0f,6.0f};
-
- //On the first run, initialize to output=target and return.
- if (first_run==true) {
- for (int i=0;i<6;i++) {
- new_camera_position[i] = target_camera_position[i];
- current_camera_position[i] = target_camera_position[i];
- alpha[i] = 0.0f;
- }
- first_run=false;
- return;
- }
-
- QMutexLocker foo(&mutex);
-
- for (int i=0;i<6;i++) {
- // Calculate the delta.
- delta=target_camera_position[i]-current_camera_position[i];
- // Normalise the delta.
- delta=std::min<double>(std::max<double>(fabs(delta)/scale[i],0.0),1.0);
- // Calculate the new alpha from the normalized delta.
- new_alpha=1.0/(kMinSmoothing+((1.0-pow(delta,kSmoothingScaleCurve))*(kMaxSmoothing-kMinSmoothing)));
- // Update the smoothed alpha.
- alpha[i]=(alpha_smoothing*new_alpha)+((1.0f-alpha_smoothing)*alpha[i]);
- }
-
- // Use the same (largest) smoothed alpha for each channel
- //NB: larger alpha = *less* lag (opposite to what you'd expect)
- float largest_alpha=0.0f;
- for (int i=0;i<6;i++) {
- largest_alpha=std::max<double>(largest_alpha, alpha[i]);
- }
-
- // Calculate the new camera position.
- for (int i=0;i<6;i++) {
- new_camera_position[i]=(largest_alpha*target_camera_position[i])+((1.0f-largest_alpha)*current_camera_position[i]);
- //new_camera_position[i]=(alpha[i]*target_camera_position[i])+((1.0f-alpha[i])*current_camera_position[i]);
- }
-
-#ifdef LOG_OUTPUT
- // Use this for some debug-output to file...
- QFile data(QCoreApplication::applicationDirPath() + "\\EWMA_output.txt");
- if (data.open(QFile::WriteOnly | QFile::Append)) {
- QTextStream out(&data);
- out << "current:\t" << current_camera_position[0]
- << "\t" << current_camera_position[1]
- << "\t" << current_camera_position[2]
- << "\t" << current_camera_position[3]
- << "\t" << current_camera_position[4]
- << "\t" << current_camera_position[5] << '\n';
- out << "target:\t" << target_camera_position[0]
- << "\t" << target_camera_position[1]
- << "\t" << target_camera_position[2]
- << "\t" << target_camera_position[3]
- << "\t" << target_camera_position[4]
- << "\t" << target_camera_position[5] << '\n';
- out << "output:\t" << new_camera_position[0]
- << "\t" << new_camera_position[1]
- << "\t" << new_camera_position[2]
- << "\t" << new_camera_position[3]
- << "\t" << new_camera_position[4]
- << "\t" << new_camera_position[5] << '\n';
- out << "largest_alpha:\t" << largest_alpha << '\n';
- }
-#endif
-
- // Update the current camera position to the new position.
- for (int i = 0; i < 6; i++) {
- current_camera_position[i] = new_camera_position[i];
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
-//#pragma comment(linker, "/export:GetFilter=_GetFilter@0")
-
-extern "C" FTNOIR_FILTER_BASE_EXPORT IFilter* CALLING_CONVENTION GetConstructor()
-{
- return new FTNoIR_Filter;
-}
+/******************************************************************************** +* 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 <QWidget> +#include "facetracknoir/global-settings.h" +#include <algorithm> +#include <QMutexLocker> +//#define LOG_OUTPUT + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// EWMA Filter: Exponentially Weighted Moving Average filter with dynamic smoothing parameter +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +FTNoIR_Filter::FTNoIR_Filter() +{ + first_run = true; + alpha_smoothing = 0.02f; // this is a constant for now, might be a parameter later + loadSettings(); // Load the Settings +} + +FTNoIR_Filter::~FTNoIR_Filter() +{ +} + +void FTNoIR_Filter::receiveSettings(double smin, double smax, double sexpt) +{ + QMutexLocker foo(&mutex); + + kMinSmoothing = smin; + kMaxSmoothing = smax; + kSmoothingScaleCurve = sexpt; +} + +// +// 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" ); + kMinSmoothing = iniFile.value ( "minSmooth", 15 ).toInt(); + kMaxSmoothing = iniFile.value ( "maxSmooth", 50 ).toInt(); + kSmoothingScaleCurve = iniFile.value ( "powCurve", 10 ).toInt(); + iniFile.endGroup (); +} + +void FTNoIR_Filter::FilterHeadPoseData(double *current_camera_position, + double *target_camera_position, + double *new_camera_position, + double *last_post_filter) +{ + double delta; + double new_alpha; + double scale[]={0.025f,0.025f,0.025f,6.0f,6.0f,6.0f}; + + //On the first run, initialize to output=target and return. + if (first_run==true) { + for (int i=0;i<6;i++) { + new_camera_position[i] = target_camera_position[i]; + current_camera_position[i] = target_camera_position[i]; + alpha[i] = 0.0f; + } + first_run=false; + return; + } + + QMutexLocker foo(&mutex); + + for (int i=0;i<6;i++) { + // Calculate the delta. + delta=target_camera_position[i]-current_camera_position[i]; + // Normalise the delta. + delta=std::min<double>(std::max<double>(fabs(delta)/scale[i],0.0),1.0); + // Calculate the new alpha from the normalized delta. + new_alpha=1.0/(kMinSmoothing+((1.0-pow(delta,kSmoothingScaleCurve))*(kMaxSmoothing-kMinSmoothing))); + // Update the smoothed alpha. + alpha[i]=(alpha_smoothing*new_alpha)+((1.0f-alpha_smoothing)*alpha[i]); + } + + // Use the same (largest) smoothed alpha for each channel + //NB: larger alpha = *less* lag (opposite to what you'd expect) + float largest_alpha=0.0f; + for (int i=0;i<6;i++) { + largest_alpha=std::max<double>(largest_alpha, alpha[i]); + } + + // Calculate the new camera position. + for (int i=0;i<6;i++) { + new_camera_position[i]=(largest_alpha*target_camera_position[i])+((1.0f-largest_alpha)*current_camera_position[i]); + //new_camera_position[i]=(alpha[i]*target_camera_position[i])+((1.0f-alpha[i])*current_camera_position[i]); + } + +#ifdef LOG_OUTPUT + // Use this for some debug-output to file... + QFile data(QCoreApplication::applicationDirPath() + "\\EWMA_output.txt"); + if (data.open(QFile::WriteOnly | QFile::Append)) { + QTextStream out(&data); + out << "current:\t" << current_camera_position[0] + << "\t" << current_camera_position[1] + << "\t" << current_camera_position[2] + << "\t" << current_camera_position[3] + << "\t" << current_camera_position[4] + << "\t" << current_camera_position[5] << '\n'; + out << "target:\t" << target_camera_position[0] + << "\t" << target_camera_position[1] + << "\t" << target_camera_position[2] + << "\t" << target_camera_position[3] + << "\t" << target_camera_position[4] + << "\t" << target_camera_position[5] << '\n'; + out << "output:\t" << new_camera_position[0] + << "\t" << new_camera_position[1] + << "\t" << new_camera_position[2] + << "\t" << new_camera_position[3] + << "\t" << new_camera_position[4] + << "\t" << new_camera_position[5] << '\n'; + out << "largest_alpha:\t" << largest_alpha << '\n'; + } +#endif + + // Update the current camera position to the new position. + for (int i = 0; i < 6; i++) { + current_camera_position[i] = new_camera_position[i]; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// 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. +//#pragma comment(linker, "/export:GetFilter=_GetFilter@0") + +extern "C" FTNOIR_FILTER_BASE_EXPORT IFilter* CALLING_CONVENTION GetConstructor() +{ + return new FTNoIR_Filter; +} diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h index 18fec8d4..91f32816 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2.h @@ -1,116 +1,116 @@ -/********************************************************************************
-* 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
-
-#include "ftnoir_filter_base/ftnoir_filter_base.h"
-#include "facetracknoir/global-settings.h"
-#include "ui_ftnoir_ewma_filtercontrols.h"
-#include <QWidget>
-#include <QMutex>
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// 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 receiveSettings(double smin, double smax, double sexpt);
-
-private:
- void loadSettings(); // Load the settings from the INI-file
- double newHeadPose; // Structure with new headpose
-
- bool first_run;
- double alpha_smoothing;
- double alpha[6];
-
- double kMinSmoothing;
- double kMaxSmoothing;
- double kSmoothingScaleCurve;
-
- QMutex mutex;
-};
-
-//*******************************************************************************************************
-// FaceTrackNoIR Filter Settings-dialog.
-//*******************************************************************************************************
-
-// Widget that has controls for FTNoIR protocol filter-settings.
-class FilterControls: public QWidget, public IFilterDialog
-{
- Q_OBJECT
-public:
- explicit FilterControls();
- virtual ~FilterControls();
- void showEvent ( QShowEvent * event );
- void Initialize(QWidget *parent);
- void registerFilter(IFilter* flt);
- void unregisterFilter();
-
-private:
- Ui::UICFilterControls ui;
- void loadSettings();
- void save();
-
- /** helper **/
- bool settingsDirty;
-
- FTNoIR_Filter* pFilter;
-
-private slots:
- void doOK();
- void doCancel();
- void settingChanged() { settingsDirty = true; }
- void settingChanged( int ) { settingsDirty = true; }
-};
-
-//*******************************************************************************************************
-// 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("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"); }
- void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); }
-};
-
-#endif //INCLUDED_FTN_FILTER_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) 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 + +#include "ftnoir_filter_base/ftnoir_filter_base.h" +#include "facetracknoir/global-settings.h" +#include "ui_ftnoir_ewma_filtercontrols.h" +#include <QWidget> +#include <QMutex> + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// 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 receiveSettings(double smin, double smax, double sexpt); + +private: + void loadSettings(); // Load the settings from the INI-file + double newHeadPose; // Structure with new headpose + + bool first_run; + double alpha_smoothing; + double alpha[6]; + + double kMinSmoothing; + double kMaxSmoothing; + double kSmoothingScaleCurve; + + QMutex mutex; +}; + +//******************************************************************************************************* +// FaceTrackNoIR Filter Settings-dialog. +//******************************************************************************************************* + +// Widget that has controls for FTNoIR protocol filter-settings. +class FilterControls: public QWidget, public IFilterDialog +{ + Q_OBJECT +public: + explicit FilterControls(); + virtual ~FilterControls(); + void showEvent ( QShowEvent * event ); + void Initialize(QWidget *parent); + void registerFilter(IFilter* flt); + void unregisterFilter(); + +private: + Ui::UICFilterControls ui; + void loadSettings(); + void save(); + + /** helper **/ + bool settingsDirty; + + FTNoIR_Filter* pFilter; + +private slots: + void doOK(); + void doCancel(); + void settingChanged() { settingsDirty = true; } + void settingChanged( int ) { settingsDirty = true; } +}; + +//******************************************************************************************************* +// 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("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"); } + void getIcon(QIcon *icon){ *icon = QIcon(":/images/filter-16.png"); } +}; + +#endif //INCLUDED_FTN_FILTER_H +//END diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp index ebcba5f1..91777213 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma2_dialog.cpp @@ -1,198 +1,198 @@ -/********************************************************************************
-* 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(), pFilter(NULL)
-{
- 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) {
- //
- //
- //
- QPoint offsetpos(100, 100);
- if (parent) {
- this->move(parent->pos() + offsetpos);
- }
- show();
-}
-
-void FilterControls::registerFilter(IFilter* flt)
-{
- pFilter = (FTNoIR_Filter*) flt;
-}
-
-void FilterControls::unregisterFilter()
-{
- pFilter = NULL;
-}
-
-//
-// 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)
-
- double smooth_min, smooth_max, smooth_expt;
-
- iniFile.beginGroup ( "Tracking" );
- iniFile.setValue ( "minSmooth", smooth_min = ui.minSmooth->value() );
- iniFile.setValue ( "powCurve", smooth_expt = ui.powCurve->value() );
- iniFile.setValue ( "maxSmooth", smooth_max = ui.maxSmooth->value() );
- iniFile.endGroup ();
-
- settingsDirty = false;
-
- if (pFilter)
- pFilter->receiveSettings(smooth_min, smooth_max, smooth_expt);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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" + +//******************************************************************************************************* +// FaceTrackNoIR Filter Settings-dialog. +//******************************************************************************************************* +// +// Constructor for server-settings-dialog +// +FilterControls::FilterControls() : + QWidget(), pFilter(NULL) +{ + 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) { + // + // + // + QPoint offsetpos(100, 100); + if (parent) { + this->move(parent->pos() + offsetpos); + } + show(); +} + +void FilterControls::registerFilter(IFilter* flt) +{ + pFilter = (FTNoIR_Filter*) flt; +} + +void FilterControls::unregisterFilter() +{ + pFilter = NULL; +} + +// +// 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) + + double smooth_min, smooth_max, smooth_expt; + + iniFile.beginGroup ( "Tracking" ); + iniFile.setValue ( "minSmooth", smooth_min = ui.minSmooth->value() ); + iniFile.setValue ( "powCurve", smooth_expt = ui.powCurve->value() ); + iniFile.setValue ( "maxSmooth", smooth_max = ui.maxSmooth->value() ); + iniFile.endGroup (); + + settingsDirty = false; + + if (pFilter) + pFilter->receiveSettings(smooth_min, smooth_max, smooth_expt); +} + +//////////////////////////////////////////////////////////////////////////////// +// 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; +} diff --git a/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp b/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp index 48c9d3be..087ede1b 100644 --- a/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp +++ b/ftnoir_filter_ewma2/ftnoir_filter_ewma_dll.cpp @@ -1,49 +1,49 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_posewidget/glwidget.cpp b/ftnoir_posewidget/glwidget.cpp index 671dd35d..9f495e0b 100644 --- a/ftnoir_posewidget/glwidget.cpp +++ b/ftnoir_posewidget/glwidget.cpp @@ -1,230 +1,230 @@ -/* 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);
+/* 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 diff --git a/ftnoir_posewidget/glwidget.h b/ftnoir_posewidget/glwidget.h index 9525f7d4..f46f3c9e 100644 --- a/ftnoir_posewidget/glwidget.h +++ b/ftnoir_posewidget/glwidget.h @@ -1,116 +1,116 @@ -/********************************************************************************
-* 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
+/******************************************************************************** +* 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 diff --git a/ftnoir_protocol_base/ftnoir_protocol_base.h b/ftnoir_protocol_base/ftnoir_protocol_base.h index 8533363d..1ebafdd5 100644 --- a/ftnoir_protocol_base/ftnoir_protocol_base.h +++ b/ftnoir_protocol_base/ftnoir_protocol_base.h @@ -1,75 +1,75 @@ -/********************************************************************************
-* 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;
-};
-
-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 <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; +}; + +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 diff --git a/ftnoir_protocol_base/ftnoir_protocol_base_global.h b/ftnoir_protocol_base/ftnoir_protocol_base_global.h index ca51e26d..9f66d67a 100644 --- a/ftnoir_protocol_base/ftnoir_protocol_base_global.h +++ b/ftnoir_protocol_base/ftnoir_protocol_base_global.h @@ -1,12 +1,12 @@ -#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> + +#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 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_protocol_fg.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp index abc401fa..d80791ce 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.cpp @@ -1,222 +1,222 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg.h b/ftnoir_protocol_fg/ftnoir_protocol_fg.h index 1c4484b8..5c2531be 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg.h +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg.h @@ -1,121 +1,121 @@ -/********************************************************************************
-* 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 +#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 diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp index b01f529b..2acd3f9c 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dialog.cpp @@ -1,215 +1,215 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp b/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp index 8d9dcf8f..6c7e7c52 100644 --- a/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp +++ b/ftnoir_protocol_fg/ftnoir_protocol_fg_dll.cpp @@ -1,49 +1,49 @@ -/********************************************************************************
-* 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"
-
-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" + +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; +} diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp index e4dbc614..ba053e11 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.cpp @@ -1,205 +1,205 @@ -/********************************************************************************
-* 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()
-{
- 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() +{ + 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; +} diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h index 5da1d2ca..99478a54 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc.h @@ -1,131 +1,131 @@ -/********************************************************************************
-* 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> + +#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 diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp index abe9329c..90ed22b2 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dialog.cpp @@ -1,185 +1,185 @@ -/********************************************************************************
-* 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"
-
-//*******************************************************************************************************
-// 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" + +//******************************************************************************************************* +// 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; +} diff --git a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp index c6ef3e38..b0ca2eee 100644 --- a/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp +++ b/ftnoir_protocol_fsuipc/ftnoir_protocol_fsuipc_dll.cpp @@ -1,49 +1,49 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp index 6e26c412..597f2a5f 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.cpp @@ -1,283 +1,283 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft.h b/ftnoir_protocol_ft/ftnoir_protocol_ft.h index f87c7300..05860907 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft.h +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft.h @@ -1,141 +1,141 @@ -/********************************************************************************
-* 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 +#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 diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp index 2442d6b2..810bef50 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft_dialog.cpp @@ -1,225 +1,225 @@ -/********************************************************************************
-* 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.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.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; +} diff --git a/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp b/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp index 5b6087b5..f4e4a40e 100644 --- a/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp +++ b/ftnoir_protocol_ft/ftnoir_protocol_ft_dll.cpp @@ -1,46 +1,46 @@ -/********************************************************************************
-* 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>
-
-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;
+/******************************************************************************** +* 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> + +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 diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp index 1fbc0b43..32d11c37 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.cpp @@ -1,118 +1,118 @@ -/********************************************************************************
-* 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()
-{
- 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() +{ + 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; +} diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h index 1c4b493e..31247d1e 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn.h @@ -1,104 +1,104 @@ -/********************************************************************************
-* 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 +#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 diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp index 328d866a..c902d6f8 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dialog.cpp @@ -1,180 +1,180 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp index c52d6c9e..acd3b990 100644 --- a/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp +++ b/ftnoir_protocol_ftn/ftnoir_protocol_ftn_dll.cpp @@ -1,49 +1,49 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp index 16a501b6..6b013d74 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.cpp @@ -1,101 +1,101 @@ -/********************************************************************************
-* 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"
-
-/** 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" + +/** 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; +} diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h index fd0058ea..b537fc4e 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse.h @@ -1,128 +1,128 @@ -/********************************************************************************
-* 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" + +#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 diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp index c2f68bd2..1e03a022 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dialog.cpp @@ -1,181 +1,181 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp index f2250735..d142934d 100644 --- a/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp +++ b/ftnoir_protocol_mouse/ftnoir_protocol_mouse_dll.cpp @@ -1,49 +1,49 @@ -/********************************************************************************
-* 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 <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 <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; +} diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp index cae11816..ca07fbf6 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.cpp @@ -1,356 +1,356 @@ -/********************************************************************************
-* 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;
-
-/** 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; + +/** 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; +} diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc.h b/ftnoir_protocol_sc/ftnoir_protocol_sc.h index c22c36c7..b3596722 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc.h +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc.h @@ -1,176 +1,176 @@ -/********************************************************************************
-* 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 +#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 diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp index 41e990dd..c2ddb72a 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc_dialog.cpp @@ -1,145 +1,145 @@ -/********************************************************************************
-* 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"
-
-//*******************************************************************************************************
-// 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" + +//******************************************************************************************************* +// 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; +} diff --git a/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp b/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp index 102c7c57..fce8753a 100644 --- a/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp +++ b/ftnoir_protocol_sc/ftnoir_protocol_sc_dll.cpp @@ -1,49 +1,49 @@ -/********************************************************************************
-* 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"
-
-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" + +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; +} diff --git a/ftnoir_tracker_base/ftnoir_tracker_base.h b/ftnoir_tracker_base/ftnoir_tracker_base.h index 7c2ab442..4d968e59 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_base.h +++ b/ftnoir_tracker_base/ftnoir_tracker_base.h @@ -1,81 +1,81 @@ -/********************************************************************************
-* 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;
-};
-
-#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 * +*********************************************************************************/ +/* + 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; +}; + +#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..af9899c5 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_base_global.h +++ b/ftnoir_tracker_base/ftnoir_tracker_base_global.h @@ -1,12 +1,12 @@ -#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> + +#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 diff --git a/ftnoir_tracker_base/ftnoir_tracker_sm_types.h b/ftnoir_tracker_base/ftnoir_tracker_sm_types.h index 1faf893f..526f8cdc 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_sm_types.h +++ b/ftnoir_tracker_base/ftnoir_tracker_sm_types.h @@ -1,36 +1,36 @@ -//
-// 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
-};
+// +// 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..591728a6 100644 --- a/ftnoir_tracker_base/ftnoir_tracker_types.h +++ b/ftnoir_tracker_base/ftnoir_tracker_types.h @@ -1,37 +1,37 @@ -/********************************************************************************
-* 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
+/******************************************************************************** +* 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 diff --git a/ftnoir_tracker_pt/camera.cpp b/ftnoir_tracker_pt/camera.cpp index fe39b436..46dd20c5 100644 --- a/ftnoir_tracker_pt/camera.cpp +++ b/ftnoir_tracker_pt/camera.cpp @@ -1,213 +1,213 @@ -/* 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
+/* 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 index 6fec12da..5f1f56b0 100644 --- a/ftnoir_tracker_pt/camera.h +++ b/ftnoir_tracker_pt/camera.h @@ -1,119 +1,119 @@ -/* 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
+/* 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 index 99b2f680..48702d19 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt.cpp @@ -1,261 +1,261 @@ -/* 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;
-}
+/* 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 index 0c45c6b6..3825fce7 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt.h @@ -1,96 +1,96 @@ -/* 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
+/* 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_dialog.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp index 4837f4a9..f222085e 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.cpp @@ -1,337 +1,337 @@ -/* 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;
-}
+/* 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 index ada331e5..f13fe13e 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dialog.h @@ -1,102 +1,102 @@ -/* 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
+/* 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_dll.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp index 22c4a33d..1c486382 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.cpp @@ -1,40 +1,40 @@ -/* 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_dll.h"
-#include <QIcon>
-#include "facetracknoir/global-settings.h"
-
-//-----------------------------------------------------------------------------
-void TrackerDll::getFullName(QString *strToBeFilled)
-{
- *strToBeFilled = "PointTracker 1.0";
-}
-
-void TrackerDll::getShortName(QString *strToBeFilled)
-{
- *strToBeFilled = "PointTracker";
-}
-
-void TrackerDll::getDescription(QString *strToBeFilled)
-{
- *strToBeFilled = "Tracks a 3-point model with know geometry like Freetrack / TrackIR";
-}
-
-void TrackerDll::getIcon(QIcon *icon)
-{
- *icon = QIcon(":/resources/icon.png");
-}
-
-
-//-----------------------------------------------------------------------------
-//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0")
-
-extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata()
-{
- return new TrackerDll;
-}
+/* 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_dll.h" +#include <QIcon> +#include "facetracknoir/global-settings.h" + +//----------------------------------------------------------------------------- +void TrackerDll::getFullName(QString *strToBeFilled) +{ + *strToBeFilled = "PointTracker 1.0"; +} + +void TrackerDll::getShortName(QString *strToBeFilled) +{ + *strToBeFilled = "PointTracker"; +} + +void TrackerDll::getDescription(QString *strToBeFilled) +{ + *strToBeFilled = "Tracks a 3-point model with know geometry like Freetrack / TrackIR"; +} + +void TrackerDll::getIcon(QIcon *icon) +{ + *icon = QIcon(":/resources/icon.png"); +} + + +//----------------------------------------------------------------------------- +//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") + +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() +{ + 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..4dc94173 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_dll.h @@ -1,18 +1,18 @@ -/* 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_base/ftnoir_tracker_base.h"
-#include "facetracknoir/global-settings.h"
-
-//-----------------------------------------------------------------------------
-class TrackerDll : public Metadata
-{
- void getFullName(QString *strToBeFilled);
- void getShortName(QString *strToBeFilled);
- void getDescription(QString *strToBeFilled);
- void getIcon(QIcon *icon);
-};
+/* 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_base/ftnoir_tracker_base.h" +#include "facetracknoir/global-settings.h" + +//----------------------------------------------------------------------------- +class TrackerDll : public Metadata +{ + void getFullName(QString *strToBeFilled); + void getShortName(QString *strToBeFilled); + void getDescription(QString *strToBeFilled); + void getIcon(QIcon *icon); +}; diff --git a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp index 3164b291..b0249813 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.cpp @@ -1,150 +1,150 @@ -/* 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);
+/* 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 index 88162c86..a1523898 100644 --- a/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h +++ b/ftnoir_tracker_pt/ftnoir_tracker_pt_settings.h @@ -1,84 +1,84 @@ -/* 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;
-};
-
+/* 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 index 61e86bec..09be967a 100644 --- a/ftnoir_tracker_pt/point_extractor.cpp +++ b/ftnoir_tracker_pt/point_extractor.cpp @@ -1,96 +1,96 @@ -/* 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;
-}
+/* 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/point_extractor.h b/ftnoir_tracker_pt/point_extractor.h index b142d2bb..9a6f7f2c 100644 --- a/ftnoir_tracker_pt/point_extractor.h +++ b/ftnoir_tracker_pt/point_extractor.h @@ -1,31 +1,31 @@ -/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef POINTEXTRACTOR_H
-#define POINTEXTRACTOR_H
-
-#include <opencv2/opencv.hpp>
-
-// ----------------------------------------------------------------------------
-// Extracts points from an opencv image
-class PointExtractor
-{
-public:
- // extracts points from frame and draws some processing info into frame, if draw_output is set
- // dt: time since last call in seconds
- // WARNING: returned reference is valid as long as object
- const std::vector<cv::Vec2f>& extract_points(cv::Mat frame, float dt, bool draw_output);
- const std::vector<cv::Vec2f>& get_points() { return points; }
-
- int threshold_val;
- int min_size, max_size;
-
-protected:
- std::vector<cv::Vec2f> points;
-};
-
-#endif //POINTEXTRACTOR_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 POINTEXTRACTOR_H +#define POINTEXTRACTOR_H + +#include <opencv2/opencv.hpp> + +// ---------------------------------------------------------------------------- +// Extracts points from an opencv image +class PointExtractor +{ +public: + // extracts points from frame and draws some processing info into frame, if draw_output is set + // dt: time since last call in seconds + // WARNING: returned reference is valid as long as object + const std::vector<cv::Vec2f>& extract_points(cv::Mat frame, float dt, bool draw_output); + const std::vector<cv::Vec2f>& get_points() { return points; } + + int threshold_val; + int min_size, max_size; + +protected: + std::vector<cv::Vec2f> points; +}; + +#endif //POINTEXTRACTOR_H diff --git a/ftnoir_tracker_pt/point_tracker.cpp b/ftnoir_tracker_pt/point_tracker.cpp index c08d6d83..210ed2eb 100644 --- a/ftnoir_tracker_pt/point_tracker.cpp +++ b/ftnoir_tracker_pt/point_tracker.cpp @@ -1,352 +1,352 @@ -/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include "point_tracker.h"
-
-#include <vector>
-#include <algorithm>
-#include <cmath>
-
-#include <QDebug>
-
-using namespace cv;
-using namespace std;
-
-const float PI = 3.14159265358979323846f;
-
-// ----------------------------------------------------------------------------
-static void get_row(const Matx33f& m, int i, Vec3f& v)
-{
- v[0] = m(i,0);
- v[1] = m(i,1);
- v[2] = m(i,2);
-}
-
-static void set_row(Matx33f& m, int i, const Vec3f& v)
-{
- m(i,0) = v[0];
- m(i,1) = v[1];
- m(i,2) = v[2];
-}
-
-// ----------------------------------------------------------------------------
-PointModel::PointModel(Vec3f M01, Vec3f M02)
- : M01(M01), M02(M02)
-{
- // calculate u
- u = M01.cross(M02);
- u /= norm(u);
-
- // calculate projection matrix on M01,M02 plane
- float s11 = M01.dot(M01);
- float s12 = M01.dot(M02);
- float s22 = M02.dot(M02);
- P = 1.0/(s11*s22-s12*s12) * Matx22f(s22, -s12,
- -s12, s11);
-
- // calculate d and d_order for simple freetrack-like point correspondence
- vector<Vec2f> points;
- points.push_back(Vec2f(0,0));
- points.push_back(Vec2f(M01[0], M01[1]));
- points.push_back(Vec2f(M02[0], M02[1]));
- // fit line to orthographically projected points
- // ERROR: yields wrong results with colinear points?!
- /*
- Vec4f line;
- fitLine(points, line, CV_DIST_L2, 0, 0.01, 0.01);
- d[0] = line[0]; d[1] = line[1];
- */
- // TODO: fix this
- d = Vec2f(M01[0]-M02[0], M01[1]-M02[1]);
-
- // sort model points
- get_d_order(points, d_order);
-}
-
-static bool d_vals_sort(const pair<float,int> a, const pair<float,int> b)
-{
- return a.first < b.first;
-}
-
-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)
- 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)
- 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)
-{
- X_CM.t[2] = 1000; // default position: 1 m away from cam;
-}
-
-void PointTracker::reset()
-{
- // enter init phase and reset velocities
- init_phase = true;
- dt_valid = 0;
- reset_velocities();
-}
-
-void PointTracker::reset_velocities()
-{
- v_t = Vec3f(0,0,0);
- v_r = Vec3f(0,0,0);
-}
-
-
-bool PointTracker::track(const vector<Vec2f>& points, float f, float dt)
-{
- if (!dynamic_pose_resolution) init_phase = true;
-
- dt_valid += dt;
- // if there was no valid tracking result for too long, do a reset
- if (dt_valid > dt_reset)
- {
- //qDebug()<<"dt_valid "<<dt_valid<<" > dt_reset "<<dt_reset;
- reset();
- }
-
- // if there is a pointtracking problem, reset the velocities
- if (!point_model.get() || (int) points.size() != PointModel::N_POINTS)
- {
- //qDebug()<<"Wrong number of points!";
- reset_velocities();
- return false;
- }
-
- X_CM_old = X_CM; // backup old transformation for velocity calculation
-
- if (!init_phase)
- predict(dt_valid);
-
- // if there is a point correspondence problem something has gone wrong, do a reset
- if (!find_correspondences(points, f))
- {
- //qDebug()<<"Error in finding point correspondences!";
- X_CM = X_CM_old; // undo prediction
- reset();
- return false;
- }
-
- (void) POSIT(f);
- //qDebug()<<"Number of POSIT iterations: "<<n_iter;
-
- if (!init_phase)
- update_velocities(dt_valid);
-
- // we have a valid tracking result, leave init phase and reset time since valid result
- init_phase = false;
- dt_valid = 0;
- return true;
-}
-
-void PointTracker::predict(float dt)
-{
- // predict with constant velocity
- Matx33f R;
- Rodrigues(dt*v_r, R);
- X_CM.R = R*X_CM.R;
- X_CM.t += dt * v_t;
-}
-
-void PointTracker::update_velocities(float dt)
-{
- // update velocities
- Rodrigues(X_CM.R*X_CM_old.R.t(), v_r);
- v_r /= dt;
- v_t = (X_CM.t - X_CM_old.t)/dt;
-}
-
-bool PointTracker::find_correspondences(const vector<Vec2f>& points, float f)
-{
- if (init_phase) {
- // We do a simple freetrack-like sorting in the init phase...
- // sort points
- int point_d_order[PointModel::N_POINTS];
- point_model->get_d_order(points, point_d_order);
-
- // set correspondences
- for (int i=0; i<PointModel::N_POINTS; ++i)
- {
- p[point_model->d_order[i]] = points[point_d_order[i]];
- }
- }
- else {
- // ... otherwise we look at the distance to the projection of the expected model points
- // project model points under current pose
- p_exp[0] = project(Vec3f(0,0,0), f);
- p_exp[1] = project(point_model->M01, f);
- p_exp[2] = project(point_model->M02, f);
-
- // set correspondences by minimum distance to projected model point
- bool point_taken[PointModel::N_POINTS];
- for (int i=0; i<PointModel::N_POINTS; ++i)
- point_taken[i] = false;
-
- float min_sdist = 0;
- int min_idx = 0;
-
- for (int i=0; i<PointModel::N_POINTS; ++i)
- {
- // find closest point to projected model point i
- for (int j=0; j<PointModel::N_POINTS; ++j)
- {
- Vec2f d = p_exp[i]-points[j];
- float sdist = d.dot(d);
- if (sdist < min_sdist || j==0)
- {
- min_idx = j;
- min_sdist = sdist;
- }
- }
- // if one point is closest to more than one model point, abort
- if (point_taken[min_idx]) return false;
- point_taken[min_idx] = true;
- p[i] = points[min_idx];
- }
- }
- return true;
-}
-
-
-
-int PointTracker::POSIT(float f)
-{
- // POSIT algorithm for coplanar points as presented in
- // [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
- // we use the same notation as in the paper here
-
- // The expected rotation used for resolving the ambiguity in POSIT:
- // In every iteration step the rotation closer to R_expected is taken
- Matx33f R_expected;
- if (init_phase)
- R_expected = Matx33f::eye(); // in the init phase, we want to be close to the default pose = no rotation
- else
- R_expected = X_CM.R; // later we want to be close to the last (predicted) rotation
-
- // initial pose = last (predicted) pose
- Vec3f k;
- get_row(X_CM.R, 2, k);
- float Z0 = X_CM.t[2];
-
- float old_epsilon_1 = 0;
- float old_epsilon_2 = 0;
- float epsilon_1 = 1;
- float epsilon_2 = 1;
-
- Vec3f I0, J0;
- Vec2f I0_coeff, J0_coeff;
-
- Vec3f I_1, J_1, I_2, J_2;
- Matx33f R_1, R_2;
- Matx33f* R_current;
-
- const int MAX_ITER = 100;
- const float EPS_THRESHOLD = 1e-4;
-
- int i=1;
- for (; i<MAX_ITER; ++i)
- {
- epsilon_1 = k.dot(point_model->M01)/Z0;
- epsilon_2 = k.dot(point_model->M02)/Z0;
-
- // vector of scalar products <I0, M0i> and <J0, M0i>
- Vec2f I0_M0i(p[1][0]*(1.0 + epsilon_1) - p[0][0],
- p[2][0]*(1.0 + epsilon_2) - p[0][0]);
- Vec2f J0_M0i(p[1][1]*(1.0 + epsilon_1) - p[0][1],
- p[2][1]*(1.0 + epsilon_2) - p[0][1]);
-
- // construct projection of I, J onto M0i plane: I0 and J0
- I0_coeff = point_model->P * I0_M0i;
- J0_coeff = point_model->P * J0_M0i;
- I0 = I0_coeff[0]*point_model->M01 + I0_coeff[1]*point_model->M02;
- J0 = J0_coeff[0]*point_model->M01 + J0_coeff[1]*point_model->M02;
-
- // calculate u component of I, J
- float II0 = I0.dot(I0);
- float IJ0 = I0.dot(J0);
- float JJ0 = J0.dot(J0);
- float rho, theta;
- if (JJ0 == II0) {
- rho = sqrt(abs(2*IJ0));
- theta = -PI/4;
- if (IJ0<0) theta *= -1;
- }
- else {
- rho = sqrt(sqrt( (JJ0-II0)*(JJ0-II0) + 4*IJ0*IJ0 ));
- theta = atan( -2*IJ0 / (JJ0-II0) );
- if (JJ0 - II0 < 0) theta += PI;
- theta /= 2;
- }
-
- // construct the two solutions
- I_1 = I0 + rho*cos(theta)*point_model->u;
- I_2 = I0 - rho*cos(theta)*point_model->u;
-
- J_1 = J0 + rho*sin(theta)*point_model->u;
- J_2 = J0 - rho*sin(theta)*point_model->u;
-
- float norm_const = 1.0/norm(I_1); // all have the same norm
-
- // create rotation matrices
- I_1 *= norm_const; J_1 *= norm_const;
- I_2 *= norm_const; J_2 *= norm_const;
-
- set_row(R_1, 0, I_1);
- set_row(R_1, 1, J_1);
- set_row(R_1, 2, I_1.cross(J_1));
-
- set_row(R_2, 0, I_2);
- set_row(R_2, 1, J_2);
- set_row(R_2, 2, I_2.cross(J_2));
-
- // the single translation solution
- Z0 = norm_const * f;
-
- // pick the rotation solution closer to the expected one
- // in simple metric d(A,B) = || I - A * B^T ||
- float R_1_deviation = norm(Matx33f::eye() - R_expected * R_1.t());
- float R_2_deviation = norm(Matx33f::eye() - R_expected * R_2.t());
-
- if (R_1_deviation < R_2_deviation)
- R_current = &R_1;
- else
- R_current = &R_2;
-
- get_row(*R_current, 2, k);
-
- // check for convergence condition
- if (abs(epsilon_1 - old_epsilon_1) + abs(epsilon_2 - old_epsilon_2) < EPS_THRESHOLD)
- break;
- old_epsilon_1 = epsilon_1;
- old_epsilon_2 = epsilon_2;
- }
-
- // apply results
- X_CM.R = *R_current;
- X_CM.t[0] = p[0][0] * Z0/f;
- X_CM.t[1] = p[0][1] * Z0/f;
- X_CM.t[2] = Z0;
-
- return i;
-
- //Rodrigues(X_CM.R, r);
- //qDebug()<<"iter: "<<i;
- //qDebug()<<"t: "<<X_CM.t[0]<<' '<<X_CM.t[1]<<' '<<X_CM.t[2];
- //Vec3f r;
- //
- //qDebug()<<"r: "<<r[0]<<' '<<r[1]<<' '<<r[2]<<'\n';
-}
+/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "point_tracker.h" + +#include <vector> +#include <algorithm> +#include <cmath> + +#include <QDebug> + +using namespace cv; +using namespace std; + +const float PI = 3.14159265358979323846f; + +// ---------------------------------------------------------------------------- +static void get_row(const Matx33f& m, int i, Vec3f& v) +{ + v[0] = m(i,0); + v[1] = m(i,1); + v[2] = m(i,2); +} + +static void set_row(Matx33f& m, int i, const Vec3f& v) +{ + m(i,0) = v[0]; + m(i,1) = v[1]; + m(i,2) = v[2]; +} + +// ---------------------------------------------------------------------------- +PointModel::PointModel(Vec3f M01, Vec3f M02) + : M01(M01), M02(M02) +{ + // calculate u + u = M01.cross(M02); + u /= norm(u); + + // calculate projection matrix on M01,M02 plane + float s11 = M01.dot(M01); + float s12 = M01.dot(M02); + float s22 = M02.dot(M02); + P = 1.0/(s11*s22-s12*s12) * Matx22f(s22, -s12, + -s12, s11); + + // calculate d and d_order for simple freetrack-like point correspondence + vector<Vec2f> points; + points.push_back(Vec2f(0,0)); + points.push_back(Vec2f(M01[0], M01[1])); + points.push_back(Vec2f(M02[0], M02[1])); + // fit line to orthographically projected points + // ERROR: yields wrong results with colinear points?! + /* + Vec4f line; + fitLine(points, line, CV_DIST_L2, 0, 0.01, 0.01); + d[0] = line[0]; d[1] = line[1]; + */ + // TODO: fix this + d = Vec2f(M01[0]-M02[0], M01[1]-M02[1]); + + // sort model points + get_d_order(points, d_order); +} + +static bool d_vals_sort(const pair<float,int> a, const pair<float,int> b) +{ + return a.first < b.first; +} + +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) + 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) + 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) +{ + X_CM.t[2] = 1000; // default position: 1 m away from cam; +} + +void PointTracker::reset() +{ + // enter init phase and reset velocities + init_phase = true; + dt_valid = 0; + reset_velocities(); +} + +void PointTracker::reset_velocities() +{ + v_t = Vec3f(0,0,0); + v_r = Vec3f(0,0,0); +} + + +bool PointTracker::track(const vector<Vec2f>& points, float f, float dt) +{ + if (!dynamic_pose_resolution) init_phase = true; + + dt_valid += dt; + // if there was no valid tracking result for too long, do a reset + if (dt_valid > dt_reset) + { + //qDebug()<<"dt_valid "<<dt_valid<<" > dt_reset "<<dt_reset; + reset(); + } + + // if there is a pointtracking problem, reset the velocities + if (!point_model.get() || (int) points.size() != PointModel::N_POINTS) + { + //qDebug()<<"Wrong number of points!"; + reset_velocities(); + return false; + } + + X_CM_old = X_CM; // backup old transformation for velocity calculation + + if (!init_phase) + predict(dt_valid); + + // if there is a point correspondence problem something has gone wrong, do a reset + if (!find_correspondences(points, f)) + { + //qDebug()<<"Error in finding point correspondences!"; + X_CM = X_CM_old; // undo prediction + reset(); + return false; + } + + (void) POSIT(f); + //qDebug()<<"Number of POSIT iterations: "<<n_iter; + + if (!init_phase) + update_velocities(dt_valid); + + // we have a valid tracking result, leave init phase and reset time since valid result + init_phase = false; + dt_valid = 0; + return true; +} + +void PointTracker::predict(float dt) +{ + // predict with constant velocity + Matx33f R; + Rodrigues(dt*v_r, R); + X_CM.R = R*X_CM.R; + X_CM.t += dt * v_t; +} + +void PointTracker::update_velocities(float dt) +{ + // update velocities + Rodrigues(X_CM.R*X_CM_old.R.t(), v_r); + v_r /= dt; + v_t = (X_CM.t - X_CM_old.t)/dt; +} + +bool PointTracker::find_correspondences(const vector<Vec2f>& points, float f) +{ + if (init_phase) { + // We do a simple freetrack-like sorting in the init phase... + // sort points + int point_d_order[PointModel::N_POINTS]; + point_model->get_d_order(points, point_d_order); + + // set correspondences + for (int i=0; i<PointModel::N_POINTS; ++i) + { + p[point_model->d_order[i]] = points[point_d_order[i]]; + } + } + else { + // ... otherwise we look at the distance to the projection of the expected model points + // project model points under current pose + p_exp[0] = project(Vec3f(0,0,0), f); + p_exp[1] = project(point_model->M01, f); + p_exp[2] = project(point_model->M02, f); + + // set correspondences by minimum distance to projected model point + bool point_taken[PointModel::N_POINTS]; + for (int i=0; i<PointModel::N_POINTS; ++i) + point_taken[i] = false; + + float min_sdist = 0; + int min_idx = 0; + + for (int i=0; i<PointModel::N_POINTS; ++i) + { + // find closest point to projected model point i + for (int j=0; j<PointModel::N_POINTS; ++j) + { + Vec2f d = p_exp[i]-points[j]; + float sdist = d.dot(d); + if (sdist < min_sdist || j==0) + { + min_idx = j; + min_sdist = sdist; + } + } + // if one point is closest to more than one model point, abort + if (point_taken[min_idx]) return false; + point_taken[min_idx] = true; + p[i] = points[min_idx]; + } + } + return true; +} + + + +int PointTracker::POSIT(float f) +{ + // POSIT algorithm for coplanar points as presented in + // [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] + // we use the same notation as in the paper here + + // The expected rotation used for resolving the ambiguity in POSIT: + // In every iteration step the rotation closer to R_expected is taken + Matx33f R_expected; + if (init_phase) + R_expected = Matx33f::eye(); // in the init phase, we want to be close to the default pose = no rotation + else + R_expected = X_CM.R; // later we want to be close to the last (predicted) rotation + + // initial pose = last (predicted) pose + Vec3f k; + get_row(X_CM.R, 2, k); + float Z0 = X_CM.t[2]; + + float old_epsilon_1 = 0; + float old_epsilon_2 = 0; + float epsilon_1 = 1; + float epsilon_2 = 1; + + Vec3f I0, J0; + Vec2f I0_coeff, J0_coeff; + + Vec3f I_1, J_1, I_2, J_2; + Matx33f R_1, R_2; + Matx33f* R_current; + + const int MAX_ITER = 100; + const float EPS_THRESHOLD = 1e-4; + + int i=1; + for (; i<MAX_ITER; ++i) + { + epsilon_1 = k.dot(point_model->M01)/Z0; + epsilon_2 = k.dot(point_model->M02)/Z0; + + // vector of scalar products <I0, M0i> and <J0, M0i> + Vec2f I0_M0i(p[1][0]*(1.0 + epsilon_1) - p[0][0], + p[2][0]*(1.0 + epsilon_2) - p[0][0]); + Vec2f J0_M0i(p[1][1]*(1.0 + epsilon_1) - p[0][1], + p[2][1]*(1.0 + epsilon_2) - p[0][1]); + + // construct projection of I, J onto M0i plane: I0 and J0 + I0_coeff = point_model->P * I0_M0i; + J0_coeff = point_model->P * J0_M0i; + I0 = I0_coeff[0]*point_model->M01 + I0_coeff[1]*point_model->M02; + J0 = J0_coeff[0]*point_model->M01 + J0_coeff[1]*point_model->M02; + + // calculate u component of I, J + float II0 = I0.dot(I0); + float IJ0 = I0.dot(J0); + float JJ0 = J0.dot(J0); + float rho, theta; + if (JJ0 == II0) { + rho = sqrt(abs(2*IJ0)); + theta = -PI/4; + if (IJ0<0) theta *= -1; + } + else { + rho = sqrt(sqrt( (JJ0-II0)*(JJ0-II0) + 4*IJ0*IJ0 )); + theta = atan( -2*IJ0 / (JJ0-II0) ); + if (JJ0 - II0 < 0) theta += PI; + theta /= 2; + } + + // construct the two solutions + I_1 = I0 + rho*cos(theta)*point_model->u; + I_2 = I0 - rho*cos(theta)*point_model->u; + + J_1 = J0 + rho*sin(theta)*point_model->u; + J_2 = J0 - rho*sin(theta)*point_model->u; + + float norm_const = 1.0/norm(I_1); // all have the same norm + + // create rotation matrices + I_1 *= norm_const; J_1 *= norm_const; + I_2 *= norm_const; J_2 *= norm_const; + + set_row(R_1, 0, I_1); + set_row(R_1, 1, J_1); + set_row(R_1, 2, I_1.cross(J_1)); + + set_row(R_2, 0, I_2); + set_row(R_2, 1, J_2); + set_row(R_2, 2, I_2.cross(J_2)); + + // the single translation solution + Z0 = norm_const * f; + + // pick the rotation solution closer to the expected one + // in simple metric d(A,B) = || I - A * B^T || + float R_1_deviation = norm(Matx33f::eye() - R_expected * R_1.t()); + float R_2_deviation = norm(Matx33f::eye() - R_expected * R_2.t()); + + if (R_1_deviation < R_2_deviation) + R_current = &R_1; + else + R_current = &R_2; + + get_row(*R_current, 2, k); + + // check for convergence condition + if (abs(epsilon_1 - old_epsilon_1) + abs(epsilon_2 - old_epsilon_2) < EPS_THRESHOLD) + break; + old_epsilon_1 = epsilon_1; + old_epsilon_2 = epsilon_2; + } + + // apply results + X_CM.R = *R_current; + X_CM.t[0] = p[0][0] * Z0/f; + X_CM.t[1] = p[0][1] * Z0/f; + X_CM.t[2] = Z0; + + return i; + + //Rodrigues(X_CM.R, r); + //qDebug()<<"iter: "<<i; + //qDebug()<<"t: "<<X_CM.t[0]<<' '<<X_CM.t[1]<<' '<<X_CM.t[2]; + //Vec3f r; + // + //qDebug()<<"r: "<<r[0]<<' '<<r[1]<<' '<<r[2]<<'\n'; +} diff --git a/ftnoir_tracker_pt/point_tracker.h b/ftnoir_tracker_pt/point_tracker.h index 7eee580d..8967f806 100644 --- a/ftnoir_tracker_pt/point_tracker.h +++ b/ftnoir_tracker_pt/point_tracker.h @@ -1,114 +1,114 @@ -/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef POINTTRACKER_H
-#define POINTTRACKER_H
-
-#include <memory>
-#include <opencv2/opencv.hpp>
-#include <list>
-
-// ----------------------------------------------------------------------------
-// Afine frame trafo
-class FrameTrafo
-{
-public:
- FrameTrafo() : R(cv::Matx33f::eye()), t(0,0,0) {}
- FrameTrafo(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {}
-
- cv::Matx33f R;
- cv::Vec3f t;
-};
-
-inline FrameTrafo operator*(const FrameTrafo& X, const FrameTrafo& Y)
-{
- return FrameTrafo(X.R*Y.R, X.R*Y.t + 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
-// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
-class PointModel
-{
- friend class PointTracker;
-public:
- static const int N_POINTS = 3;
-
- PointModel(cv::Vec3f M01, cv::Vec3f M02);
-
- const cv::Vec3f& get_M01() const { return M01; };
- const cv::Vec3f& get_M02() const { return M02; };
-
-protected:
- cv::Vec3f M01; // M01 in model frame
- cv::Vec3f M02; // M02 in model frame
-
- cv::Vec3f u; // unit vector perpendicular to M01,M02-plane
-
- cv::Matx22f P;
-
- cv::Vec2f d; // discrimant 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;
-};
-
-// ----------------------------------------------------------------------------
-// Tracks a 3-point model
-// implementing the POSIT algorithm for coplanar points as presented in
-// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"]
-class PointTracker
-{
-public:
- PointTracker();
-
- // track the pose using the set of normalized point coordinates (x pos in range -0.5:0.5)
- // f : (focal length)/(sensor width)
- // dt : time since last call
- bool track(const std::vector<cv::Vec2f>& points, float f, float dt);
- std::auto_ptr<PointModel> point_model;
-
- bool dynamic_pose_resolution;
- float dt_reset;
-
- FrameTrafo get_pose() const { return X_CM; }
- void reset();
-
-protected:
- inline cv::Vec2f project(const cv::Vec3f& v_M, float f)
- {
- cv::Vec3f v_C = X_CM * v_M;
- return cv::Vec2f(f*v_C[0]/v_C[2], f*v_C[1]/v_C[2]);
- }
-
- bool find_correspondences(const std::vector<cv::Vec2f>& points, float f);
-
- cv::Vec2f p[PointModel::N_POINTS]; // the points in model order
- cv::Vec2f p_exp[PointModel::N_POINTS]; // the expected point positions
-
- void predict(float dt);
- void update_velocities(float dt);
- void reset_velocities();
-
-
- int POSIT(float f); // The POSIT algorithm, returns the number of iterations
-
- bool init_phase;
- float dt_valid; // time since last valid tracking result
- cv::Vec3f v_t; // velocities
- cv::Vec3f v_r;
- FrameTrafo X_CM; // trafo from model to camera
- FrameTrafo X_CM_old;
-};
-
-#endif //POINTTRACKER_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 POINTTRACKER_H +#define POINTTRACKER_H + +#include <memory> +#include <opencv2/opencv.hpp> +#include <list> + +// ---------------------------------------------------------------------------- +// Afine frame trafo +class FrameTrafo +{ +public: + FrameTrafo() : R(cv::Matx33f::eye()), t(0,0,0) {} + FrameTrafo(const cv::Matx33f& R, const cv::Vec3f& t) : R(R),t(t) {} + + cv::Matx33f R; + cv::Vec3f t; +}; + +inline FrameTrafo operator*(const FrameTrafo& X, const FrameTrafo& Y) +{ + return FrameTrafo(X.R*Y.R, X.R*Y.t + 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 +// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] +class PointModel +{ + friend class PointTracker; +public: + static const int N_POINTS = 3; + + PointModel(cv::Vec3f M01, cv::Vec3f M02); + + const cv::Vec3f& get_M01() const { return M01; }; + const cv::Vec3f& get_M02() const { return M02; }; + +protected: + cv::Vec3f M01; // M01 in model frame + cv::Vec3f M02; // M02 in model frame + + cv::Vec3f u; // unit vector perpendicular to M01,M02-plane + + cv::Matx22f P; + + cv::Vec2f d; // discrimant 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; +}; + +// ---------------------------------------------------------------------------- +// Tracks a 3-point model +// implementing the POSIT algorithm for coplanar points as presented in +// [Denis Oberkampf, Daniel F. DeMenthon, Larry S. Davis: "Iterative Pose Estimation Using Coplanar Feature Points"] +class PointTracker +{ +public: + PointTracker(); + + // track the pose using the set of normalized point coordinates (x pos in range -0.5:0.5) + // f : (focal length)/(sensor width) + // dt : time since last call + bool track(const std::vector<cv::Vec2f>& points, float f, float dt); + std::auto_ptr<PointModel> point_model; + + bool dynamic_pose_resolution; + float dt_reset; + + FrameTrafo get_pose() const { return X_CM; } + void reset(); + +protected: + inline cv::Vec2f project(const cv::Vec3f& v_M, float f) + { + cv::Vec3f v_C = X_CM * v_M; + return cv::Vec2f(f*v_C[0]/v_C[2], f*v_C[1]/v_C[2]); + } + + bool find_correspondences(const std::vector<cv::Vec2f>& points, float f); + + cv::Vec2f p[PointModel::N_POINTS]; // the points in model order + cv::Vec2f p_exp[PointModel::N_POINTS]; // the expected point positions + + void predict(float dt); + void update_velocities(float dt); + void reset_velocities(); + + + int POSIT(float f); // The POSIT algorithm, returns the number of iterations + + bool init_phase; + float dt_valid; // time since last valid tracking result + cv::Vec3f v_t; // velocities + cv::Vec3f v_r; + FrameTrafo X_CM; // trafo from model to camera + FrameTrafo X_CM_old; +}; + +#endif //POINTTRACKER_H diff --git a/ftnoir_tracker_pt/resource.h b/ftnoir_tracker_pt/resource.h index c14e94ad..4ca527a3 100644 --- a/ftnoir_tracker_pt/resource.h +++ b/ftnoir_tracker_pt/resource.h @@ -1,14 +1,14 @@ -//{{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
+//{{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/timer.cpp b/ftnoir_tracker_pt/timer.cpp index 9e6ca8b8..07379853 100644 --- a/ftnoir_tracker_pt/timer.cpp +++ b/ftnoir_tracker_pt/timer.cpp @@ -1,65 +1,65 @@ -/* 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;
+/* 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 index 2aaf725a..1c2c3559 100644 --- a/ftnoir_tracker_pt/timer.h +++ b/ftnoir_tracker_pt/timer.h @@ -1,44 +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.
- */
-
-#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
-};
-
+/* 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/trans_calib.cpp b/ftnoir_tracker_pt/trans_calib.cpp index 9b75a1b6..729a0b7f 100644 --- a/ftnoir_tracker_pt/trans_calib.cpp +++ b/ftnoir_tracker_pt/trans_calib.cpp @@ -1,44 +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 "trans_calib.h"
-
-using namespace cv;
-
-//-----------------------------------------------------------------------------
-TranslationCalibrator::TranslationCalibrator()
-{
- reset();
-}
-
-void TranslationCalibrator::reset()
-{
- P = Matx66f::zeros();
- y = Vec6f(0,0,0, 0,0,0);
-}
-
-void TranslationCalibrator::update(const Matx33f& R_CM_k, const Vec3f& t_CM_k)
-{
- Matx<float, 6,3> H_k_T = Matx<float, 6,3>::zeros();
- for (int i=0; i<3; ++i) {
- for (int j=0; j<3; ++j) {
- H_k_T(i,j) = R_CM_k(j,i);
- }
- }
- for (int i=0; i<3; ++i)
- {
- H_k_T(3+i,i) = 1.0;
- }
- P += H_k_T * H_k_T.t();
- y += H_k_T * t_CM_k;
-}
-
-Vec3f TranslationCalibrator::get_estimate()
-{
- Vec6f x = P.inv() * y;
- return Vec3f(-x[0], -x[1], -x[2]);
+/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "trans_calib.h" + +using namespace cv; + +//----------------------------------------------------------------------------- +TranslationCalibrator::TranslationCalibrator() +{ + reset(); +} + +void TranslationCalibrator::reset() +{ + P = Matx66f::zeros(); + y = Vec6f(0,0,0, 0,0,0); +} + +void TranslationCalibrator::update(const Matx33f& R_CM_k, const Vec3f& t_CM_k) +{ + Matx<float, 6,3> H_k_T = Matx<float, 6,3>::zeros(); + for (int i=0; i<3; ++i) { + for (int j=0; j<3; ++j) { + H_k_T(i,j) = R_CM_k(j,i); + } + } + for (int i=0; i<3; ++i) + { + H_k_T(3+i,i) = 1.0; + } + P += H_k_T * H_k_T.t(); + y += H_k_T * t_CM_k; +} + +Vec3f TranslationCalibrator::get_estimate() +{ + Vec6f x = P.inv() * y; + return Vec3f(-x[0], -x[1], -x[2]); }
\ No newline at end of file diff --git a/ftnoir_tracker_pt/trans_calib.h b/ftnoir_tracker_pt/trans_calib.h index 4024d011..6288546a 100644 --- a/ftnoir_tracker_pt/trans_calib.h +++ b/ftnoir_tracker_pt/trans_calib.h @@ -1,39 +1,39 @@ -/* Copyright (c) 2012 Patrick Ruoff
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef TRANSCALIB_H
-#define TRANSCALIB_H
-
-#include <opencv2/opencv.hpp>
-
-//-----------------------------------------------------------------------------
-// calibrates the translation from head to model = t_MH
-// by recursive least squares /
-// kalman filter in information form with identity noise covariance
-// measurement equation when head position = t_CH is fixed:
-// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k
-
-class TranslationCalibrator
-{
-public:
- TranslationCalibrator();
-
- // reset the calibration process
- void reset();
-
- // update the current estimate
- void update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k);
-
- // get the current estimate for t_MH
- cv::Vec3f get_estimate();
-
-protected:
- cv::Matx66f P; // normalized precision matrix = inverse covariance
- cv::Vec6f y; // P*(-t_MH, t_CH)
-};
-
+/* Copyright (c) 2012 Patrick Ruoff + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#ifndef TRANSCALIB_H +#define TRANSCALIB_H + +#include <opencv2/opencv.hpp> + +//----------------------------------------------------------------------------- +// calibrates the translation from head to model = t_MH +// by recursive least squares / +// kalman filter in information form with identity noise covariance +// measurement equation when head position = t_CH is fixed: +// (R_CM_k , Id)*(-t_MH, t_CH) = t_CM_k + +class TranslationCalibrator +{ +public: + TranslationCalibrator(); + + // reset the calibration process + void reset(); + + // update the current estimate + void update(const cv::Matx33f& R_CM_k, const cv::Vec3f& t_CM_k); + + // get the current estimate for t_MH + cv::Vec3f get_estimate(); + +protected: + cv::Matx66f P; // normalized precision matrix = inverse covariance + cv::Vec6f y; // P*(-t_MH, t_CH) +}; + #endif //TRANSCALIB_H
\ No newline at end of file diff --git a/ftnoir_tracker_pt/video_widget.cpp b/ftnoir_tracker_pt/video_widget.cpp index a13542ba..2b554aba 100644 --- a/ftnoir_tracker_pt/video_widget.cpp +++ b/ftnoir_tracker_pt/video_widget.cpp @@ -1,52 +1,52 @@ -/* 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);
-}
+/* 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/video_widget.h b/ftnoir_tracker_pt/video_widget.h index 66959fde..3051919b 100644 --- a/ftnoir_tracker_pt/video_widget.h +++ b/ftnoir_tracker_pt/video_widget.h @@ -1,42 +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.
- */
-
-#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 <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 diff --git a/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp b/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp index 74e1d3d2..06c8b206 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp +++ b/ftnoir_tracker_sm/ftnoir_tracker_faceapi.cpp @@ -1,173 +1,173 @@ -/********************************************************************************
-* 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;
-}
+/******************************************************************************** +* 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 index f515dedc..332a619e 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp +++ b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dialog.cpp @@ -1,282 +1,282 @@ -/********************************************************************************
-* 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;
-}
+/******************************************************************************** +* 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 index a878a468..b1ab1d75 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp +++ b/ftnoir_tracker_sm/ftnoir_tracker_faceapi_dll.cpp @@ -1,72 +1,72 @@ -/********************************************************************************
-* 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_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;
-}
+/******************************************************************************** +* 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_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 index 33cfb9ef..5d692ea0 100644 --- a/ftnoir_tracker_sm/ftnoir_tracker_sm.h +++ b/ftnoir_tracker_sm/ftnoir_tracker_sm.h @@ -1,156 +1,156 @@ -/********************************************************************************
-* 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;
-};
+/******************************************************************************** +* 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_udp/ftnoir_tracker_udp.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp index 83f518fa..1364ee1c 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.cpp @@ -1,173 +1,173 @@ -/********************************************************************************
-* 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() +{ + 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; +} diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp.h b/ftnoir_tracker_udp/ftnoir_tracker_udp.h index c4c85372..76fcacf2 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp.h +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp.h @@ -1,97 +1,97 @@ -#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 <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; +}; + diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp index 4fe0d8c8..5c0d7b1c 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp_dialog.cpp @@ -1,182 +1,182 @@ -/********************************************************************************
-* 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" + +//******************************************************************************************************* +// 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; +} diff --git a/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp b/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp index d4afb410..dcdbe487 100644 --- a/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp +++ b/ftnoir_tracker_udp/ftnoir_tracker_udp_dll.cpp @@ -1,73 +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_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" + +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; +} diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp index 1b06bdc2..e0807859 100644 --- a/qfunctionconfigurator/functionconfig.cpp +++ b/qfunctionconfigurator/functionconfig.cpp @@ -1,282 +1,282 @@ -/* 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> +#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(); +} diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h index 0f60c979..21e9e43e 100644 --- a/qfunctionconfigurator/functionconfig.h +++ b/qfunctionconfigurator/functionconfig.h @@ -1,78 +1,78 @@ -/* 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. + */ + +#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 |