summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--FaceTrackNoIR.suobin280064 -> 279040 bytes
-rw-r--r--FaceTrackNoIR/FGServer.cpp6
-rw-r--r--FaceTrackNoIR/FTIRServer.cpp149
-rw-r--r--FaceTrackNoIR/FTIRServer.h7
-rw-r--r--FaceTrackNoIR/FTServer.cpp137
-rw-r--r--FaceTrackNoIR/FTServer.h3
-rw-r--r--FaceTrackNoIR/FaceTrackNoIR.vcproj11
-rw-r--r--FaceTrackNoIR/PPJoyServer.cpp43
-rw-r--r--FaceTrackNoIR/PPJoyServer.h3
-rw-r--r--FaceTrackNoIR/SCServer.cpp59
-rw-r--r--FaceTrackNoIR/SCServer.h3
-rw-r--r--FaceTrackNoIR/tracker.cpp338
-rw-r--r--FaceTrackNoIR/tracker.h3
-rw-r--r--bin/FaceTrackNoIR.exebin716800 -> 716800 bytes
-rw-r--r--bin/Settings/ArmA.ini5
15 files changed, 355 insertions, 412 deletions
diff --git a/FaceTrackNoIR.suo b/FaceTrackNoIR.suo
index 658821a8..8826c353 100644
--- a/FaceTrackNoIR.suo
+++ b/FaceTrackNoIR.suo
Binary files differ
diff --git a/FaceTrackNoIR/FGServer.cpp b/FaceTrackNoIR/FGServer.cpp
index 6b96d249..47ca31ba 100644
--- a/FaceTrackNoIR/FGServer.cpp
+++ b/FaceTrackNoIR/FGServer.cpp
@@ -38,8 +38,8 @@ FGServer::FGServer( Tracker *parent ) {
headTracker = parent;
// Create events
- m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
- m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
+ //m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
+ //m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
loadSettings();
}
@@ -123,7 +123,7 @@ void FGServer::run() {
// Connect the inSocket to the member-function, to read FlightGear commands
connect(inSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()), Qt::DirectConnection);
- exec(); // Exec only returns, when the thread terminates...
+// exec(); // Exec only returns, when the thread terminates...
}
/** QThread terminate @override **/
diff --git a/FaceTrackNoIR/FTIRServer.cpp b/FaceTrackNoIR/FTIRServer.cpp
index 5ecd9622..54570fcd 100644
--- a/FaceTrackNoIR/FTIRServer.cpp
+++ b/FaceTrackNoIR/FTIRServer.cpp
@@ -21,17 +21,15 @@
********************************************************************************/
/*
Modifications (last one on top):
+ 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
+ is called from run() of Tracker.cpp
+ 20101127 - WVR: Added TrackIR.exe process for EZCA etc...
20101023 - WVR: Added TIRViews for FS2004, Combat FS3, etc...
*/
#include "FTIRServer.h"
/** constructor **/
FTIRServer::FTIRServer() {
-
- // Create events
- m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
- m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
-
loadSettings();
ProgramName = "";
}
@@ -39,16 +37,6 @@ FTIRServer::FTIRServer() {
/** destructor **/
FTIRServer::~FTIRServer() {
- // Trigger thread to stop
- ::SetEvent(m_StopThread);
-
- // Wait until thread finished
- ::WaitForSingleObject(m_WaitThread, INFINITE);
-
- // Close handles
- ::CloseHandle(m_StopThread);
- ::CloseHandle(m_WaitThread);
-
//
// Free the DLL's
//
@@ -62,88 +50,20 @@ FTIRServer::~FTIRServer() {
if (dummyTrackIR) {
dummyTrackIR->kill();
}
-
- //terminates the QThread and waits for finishing the QThread
- terminate();
- wait();
}
-/** QThread run @override **/
-void FTIRServer::run() {
- importSetPosition setposition; // Inside NPClient.dll
- importTIRViewsStart viewsStart = NULL; // Inside TIRViews.dll
- importTIRViewsStop viewsStop = NULL;
+//
+// Update Headpose in Game.
+//
+void FTIRServer::sendHeadposeToGame() {
//
- // Get the setposition function from the DLL and use it!
+ // Check if the pointer is OK and wait for the Mutex.
+ // Use the setposition in the (special) DLL, to write the headpose-data.
//
- setposition = (importSetPosition) FTIRClientLib.resolve("SetPosition");
- if (setposition == NULL) {
- qDebug() << "FTIRServer::run() says: SetPosition function not found in DLL!";
- return;
- }
- else {
- setposition (7.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f);
- }
-
- //
- // Load the Start function from TIRViews.dll and call it, to start compatibility with older games
- //
- if (useTIRViews) {
- viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart");
- if (viewsStart == NULL) {
- qDebug() << "FTIRServer::run() says: TIRViewsStart function not found in DLL!";
- }
- else {
- qDebug() << "FTIRServer::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() << "FTIRServer::run() says: TIRViewsStop function not found in DLL!";
- }
- }
-
- //
- // Run, until termination
- //
- forever
- {
- // Check event for stop thread
- if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0)
- {
- if (viewsStop != NULL) {
- viewsStop();
- }
-
- // Set event
- ::SetEvent(m_WaitThread);
- return;
- }
-
- if ( (pMemData != NULL) && (WaitForSingleObject(hFTIRMutex, 100) == WAIT_OBJECT_0) ) {
-
-// qDebug() << "FTIRServer says: virtRotX =" << virtRotX << " virtRotY =" << virtRotY;
- setposition (virtPosX, virtPosY, virtPosZ, virtRotZ, virtRotX, virtRotY );
-
- //// Use this for some debug-output to file...
- //QFile data("outputFTIR.txt");
- //if (data.open(QFile::WriteOnly | QFile::Append)) {
- // QTextStream out(&data);
- // out << virtPosX << " " << virtPosY << " " << virtPosZ << virtRotX << " " << virtRotY << " " << virtRotZ << '\n';
- //}
-
- //qDebug() << "FTIRServer says: pMemData.xRot =" << pMemData->data.xRot << " yRot =" << pMemData->data.yRot;
- ReleaseMutex(hFTIRMutex);
- }
-
- // just for lower cpu load
- msleep(15);
- yieldCurrentThread();
+ if ( (pMemData != NULL) && (WaitForSingleObject(hFTIRMutex, 100) == WAIT_OBJECT_0) ) {
+ setposition (virtPosX, virtPosY, virtPosZ, virtRotZ, virtRotX, virtRotY );
+ ReleaseMutex(hFTIRMutex);
}
}
@@ -282,7 +202,50 @@ bool FTIRServer::checkServerInstallationOK( HANDLE handle )
} catch(...) {
settings.~QSettings();
}
- return FTIRCreateMapping( handle );
+
+ //
+ // Create the File-mapping for Inter Process Communication
+ //
+ if (!FTIRCreateMapping( handle )){
+ return false;
+ }
+
+ //
+ // Find the functions in the DLL's
+ //
+ // Get the setposition function from the DLL and use it!
+ //
+ setposition = (importSetPosition) FTIRClientLib.resolve("SetPosition");
+ if (setposition == NULL) {
+ qDebug() << "FTIRServer::run() says: SetPosition function not found in DLL!";
+ return false;
+ }
+ else {
+ setposition (7.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f);
+ }
+
+ //
+ // Load the Start function from TIRViews.dll and call it, to start compatibility with older games
+ //
+ if (useTIRViews) {
+ viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart");
+ if (viewsStart == NULL) {
+ qDebug() << "FTIRServer::run() says: TIRViewsStart function not found in DLL!";
+ }
+ else {
+ qDebug() << "FTIRServer::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() << "FTIRServer::run() says: TIRViewsStop function not found in DLL!";
+ }
+ }
+ return true;
}
//
diff --git a/FaceTrackNoIR/FTIRServer.h b/FaceTrackNoIR/FTIRServer.h
index 98273bc5..c27a1ab5 100644
--- a/FaceTrackNoIR/FTIRServer.h
+++ b/FaceTrackNoIR/FTIRServer.h
@@ -56,13 +56,18 @@ public:
// protected member methods
protected:
- void run();
+// void run();
bool checkServerInstallationOK( HANDLE handle );
+ void sendHeadposeToGame();
private:
bool FTIRCreateMapping(HANDLE handle);
void FTIRDestroyMapping();
+ importSetPosition setposition; // Function inside NPClient.dll
+ importTIRViewsStart viewsStart; // Functions inside TIRViews.dll
+ importTIRViewsStop viewsStop;
+
HANDLE hFTIRMemMap;
FTIRMemMap *pMemData;
HANDLE hFTIRMutex;
diff --git a/FaceTrackNoIR/FTServer.cpp b/FaceTrackNoIR/FTServer.cpp
index 27808343..7814c2d3 100644
--- a/FaceTrackNoIR/FTServer.cpp
+++ b/FaceTrackNoIR/FTServer.cpp
@@ -41,110 +41,77 @@
//
/*
Modifications (last one on top):
- 20100601 - WVR: Added Mutex-bit in run(). Thought it wasn't so important (still do...).
- 20100523 - WVR: Implemented the Freetrack-protocol just like Freetrack does. Earlier
- FaceTrackNoIR only worked with an adapted DLL, with a putdata function.
- Now it works direcly in shared memory!
+ 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame
+ is called from run() of Tracker.cpp
+ 20100601 - WVR: Added Mutex-bit in run(). Thought it wasn't so important (still do...).
+ 20100523 - WVR: Implemented the Freetrack-protocol just like Freetrack does. Earlier
+ FaceTrackNoIR only worked with an adapted DLL, with a putdata function.
+ Now it works direcly in shared memory!
*/
#include "FTServer.h"
/** constructor **/
FTServer::FTServer() {
-
- // Create events
- m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
- m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
-
ProgramName = "";
}
/** destructor **/
FTServer::~FTServer() {
- // Trigger thread to stop
- ::SetEvent(m_StopThread);
-
- // Wait until thread finished
- ::WaitForSingleObject(m_WaitThread, INFINITE);
-
- // Close handles
- ::CloseHandle(m_StopThread);
- ::CloseHandle(m_WaitThread);
-
//
// Free the DLL
//
FTClientLib.unload();
- //if( aDLLHandle != INVALID_HANDLE_VALUE )
- // FreeLibrary( (HMODULE) aDLLHandle );
- //terminates the QThread and waits for finishing the QThread
- terminate();
- wait();
}
-/** QThread run @override **/
-void FTServer::run() {
-
- if (pMemData != NULL) {
- pMemData->data.DataID = 1;
- pMemData->data.CamWidth = 100;
- pMemData->data.CamHeight = 250;
- }
-
- forever
- {
- // Check event for stop thread
- if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0)
- {
- // Set event
- ::SetEvent(m_WaitThread);
- return;
- }
-
- if ( (pMemData != NULL) && (WaitForSingleObject(hFTMutex, 100) == WAIT_OBJECT_0) ) {
-
- //
- // Copy the Raw measurements directly to the client.
- //
- pMemData->data.RawX = headPosX;
- pMemData->data.RawY = headPosY;
- pMemData->data.RawZ = headPosZ;
- pMemData->data.RawPitch = headRotX;
- pMemData->data.RawYaw = headRotY;
- pMemData->data.RawRoll = headRotZ;
+//
+// Update Headpose in Game.
+//
+void FTServer::sendHeadposeToGame() {
- //
- // Multiply the FaceAPI value, with the sensitivity setting
- //
- pMemData->data.X = virtPosX;
- pMemData->data.Y = virtPosY;
- pMemData->data.Z = virtPosZ;
- pMemData->data.Pitch = virtRotX;
- pMemData->data.Yaw = virtRotY;
- pMemData->data.Roll = virtRotZ;
+ //
+ // Check if the pointer is OK and wait for the Mutex.
+ //
+ if ( (pMemData != NULL) && (WaitForSingleObject(hFTMutex, 100) == WAIT_OBJECT_0) ) {
- //
- // 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;
+ //
+ // Copy the Raw measurements directly to the client.
+ //
+ pMemData->data.RawX = headPosX;
+ pMemData->data.RawY = headPosY;
+ pMemData->data.RawZ = headPosZ;
+ pMemData->data.RawPitch = headRotX;
+ pMemData->data.RawYaw = headRotY;
+ pMemData->data.RawRoll = headRotZ;
- //qDebug() << "FTServer says: pMemData.DataID =" << pMemData->data.DataID;
- //qDebug() << "FTServer says: ProgramName =" << pMemData->ProgramName;
- ReleaseMutex(hFTMutex);
- }
+ //
+ // Multiply the FaceAPI value, with the sensitivity setting
+ //
+ pMemData->data.X = virtPosX;
+ pMemData->data.Y = virtPosY;
+ pMemData->data.Z = virtPosZ;
+ pMemData->data.Pitch = virtRotX;
+ pMemData->data.Yaw = virtRotY;
+ pMemData->data.Roll = virtRotZ;
- // just for lower cpu load
- msleep(15);
- yieldCurrentThread();
- pMemData->data.DataID += 1;
+ //
+ // 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;
+
+ //qDebug() << "FTServer says: pMemData.DataID =" << pMemData->data.DataID;
+ //qDebug() << "FTServer says: ProgramName =" << pMemData->ProgramName;
+ ReleaseMutex(hFTMutex);
}
+
+ pMemData->data.DataID += 1;
}
//
@@ -192,6 +159,12 @@ bool FTServer::FTCreateMapping(HANDLE handle)
return false;
}
+ if (pMemData != NULL) {
+ pMemData->data.DataID = 1;
+ pMemData->data.CamWidth = 100;
+ pMemData->data.CamHeight = 250;
+ }
+
return true;
}
diff --git a/FaceTrackNoIR/FTServer.h b/FaceTrackNoIR/FTServer.h
index 1d7907ed..ba1dfeb2 100644
--- a/FaceTrackNoIR/FTServer.h
+++ b/FaceTrackNoIR/FTServer.h
@@ -62,8 +62,9 @@ public:
// protected member methods
protected:
- void run();
+// void run();
bool checkServerInstallationOK( HANDLE handle );
+ void sendHeadposeToGame();
private:
bool FTCreateMapping(HANDLE handle);
diff --git a/FaceTrackNoIR/FaceTrackNoIR.vcproj b/FaceTrackNoIR/FaceTrackNoIR.vcproj
index f5c6e94e..4a98b8b3 100644
--- a/FaceTrackNoIR/FaceTrackNoIR.vcproj
+++ b/FaceTrackNoIR/FaceTrackNoIR.vcproj
@@ -1023,17 +1023,6 @@
>
<Tool
Name="VCCLCompilerTool"
- ObjectFile="$(IntDir)\$(InputName)1.obj"
- XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- ObjectFile="$(IntDir)\$(InputName)1.obj"
- XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
diff --git a/FaceTrackNoIR/PPJoyServer.cpp b/FaceTrackNoIR/PPJoyServer.cpp
index 812cd7cb..9a2301fd 100644
--- a/FaceTrackNoIR/PPJoyServer.cpp
+++ b/FaceTrackNoIR/PPJoyServer.cpp
@@ -42,8 +42,8 @@ char strDevName[100];
headTracker = parent;
// Create events
- m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
- m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
+ //m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
+ //m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
// Initialize arrays
for (int i = 0;i < 3;i++) {
@@ -72,33 +72,32 @@ PPJoyServer::~PPJoyServer() {
/* Make sure we could open the device! */
if (h == INVALID_HANDLE_VALUE) {
- terminate();
- wait();
+ //terminate();
+ //wait();
return;
}
- // Trigger thread to stop
- ::SetEvent(m_StopThread);
+ //// Trigger thread to stop
+ //::SetEvent(m_StopThread);
- // Wait until thread finished
- ::WaitForSingleObject(m_WaitThread, INFINITE);
+ //// Wait until thread finished
+ //::WaitForSingleObject(m_WaitThread, INFINITE);
- // Close handles
- ::CloseHandle(m_StopThread);
- ::CloseHandle(m_WaitThread);
+ //// Close handles
+ //::CloseHandle(m_StopThread);
+ //::CloseHandle(m_WaitThread);
//
// Free the Virtual Joystick
//
CloseHandle(h);
//terminates the QThread and waits for finishing the QThread
- terminate();
- wait();
+ //terminate();
+ //wait();
}
/** QThread run @override **/
-void PPJoyServer::run() {
-
+void PPJoyServer::sendHeadposeToGame() {
/* Initialise the IOCTL data structure */
JoyState.Signature= JOYSTICK_STATE_V1;
@@ -116,11 +115,11 @@ void PPJoyServer::run() {
forever
{
// Check event for stop thread
- if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) {
- // Set event
- ::SetEvent(m_WaitThread);
- return;
- }
+ //if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) {
+ // // Set event
+ // ::SetEvent(m_WaitThread);
+ // return;
+ //}
// The effective angle for faceTracking will be < 90 degrees, so we assume a smaller range here
Analog[0] = scale2AnalogLimits( virtRotX, -50.0f, 50.0f ); // Pitch
@@ -143,8 +142,8 @@ void PPJoyServer::run() {
return;
}
// just for lower cpu load
- msleep(15);
- yieldCurrentThread();
+ //msleep(15);
+ //yieldCurrentThread();
}
}
diff --git a/FaceTrackNoIR/PPJoyServer.h b/FaceTrackNoIR/PPJoyServer.h
index 31e7f97a..b5fdd012 100644
--- a/FaceTrackNoIR/PPJoyServer.h
+++ b/FaceTrackNoIR/PPJoyServer.h
@@ -72,7 +72,8 @@ public:
// protected member methods
protected:
- void run();
+// void run();
+ void sendHeadposeToGame();
private slots:
// void readPendingDatagrams();
diff --git a/FaceTrackNoIR/SCServer.cpp b/FaceTrackNoIR/SCServer.cpp
index c948b8a6..9ee52f8d 100644
--- a/FaceTrackNoIR/SCServer.cpp
+++ b/FaceTrackNoIR/SCServer.cpp
@@ -24,21 +24,12 @@
*/
#include "SCServer.h"
-
-//float SCServer::virtPosX = 0.0f;
-//float SCServer::virtPosY = 0.0f;
-//float SCServer::virtPosZ = 0.0f;
-//
-//float SCServer::virtRotX = 0.0f;
-//float SCServer::virtRotY = 0.0f;
-//float SCServer::virtRotZ = 0.0f;
-
/** constructor **/
SCServer::SCServer() {
// Create events
- m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
- m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
+ //m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
+ //m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
ProgramName = "";
}
@@ -47,16 +38,16 @@ SCServer::SCServer() {
SCServer::~SCServer() {
// Trigger thread to stop
- ::SetEvent(m_StopThread);
+ //::SetEvent(m_StopThread);
// Wait until thread finished
- if (isRunning()) {
- ::WaitForSingleObject(m_WaitThread, INFINITE);
- }
+ //if (isRunning()) {
+ // ::WaitForSingleObject(m_WaitThread, INFINITE);
+ //}
- // Close handles
- ::CloseHandle(m_StopThread);
- ::CloseHandle(m_WaitThread);
+ //// Close handles
+ //::CloseHandle(m_StopThread);
+ //::CloseHandle(m_WaitThread);
//
// Free the DLL
@@ -64,12 +55,12 @@ SCServer::~SCServer() {
SCClientLib.unload();
//terminates the QThread and waits for finishing the QThread
- terminate();
- wait();
+ //terminate();
+ //wait();
}
/** QThread run @override **/
-void SCServer::run() {
+void SCServer::sendHeadposeToGame() {
bool blnSimConnectActive = false;
HANDLE hSimConnect = NULL; // Handle to SimConnect
importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL
@@ -109,23 +100,23 @@ float prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ;
forever
{
// Check event for stop thread
- if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0)
- {
- // Set event
- simconnect_close( hSimConnect );
- ::SetEvent(m_WaitThread);
- return;
- }
+ //if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0)
+ //{
+ // // Set event
+// simconnect_close( hSimConnect );
+ // ::SetEvent(m_WaitThread);
+ // return;
+ //}
if (!blnSimConnectActive) {
if (SUCCEEDED(simconnect_open(&hSimConnect, "FaceTrackNoIR", NULL, 0, 0, 0))) {
qDebug() << "SCServer::run() says: SimConnect active!";
blnSimConnectActive = true;
}
- else {
- msleep(5000);
- yieldCurrentThread();
- }
+ //else {
+ // msleep(5000);
+ // yieldCurrentThread();
+ //}
}
else {
//
@@ -148,8 +139,8 @@ float prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ;
prevRotZ = virtRotZ;
// just for lower cpu load
- msleep(15);
- yieldCurrentThread();
+ //msleep(15);
+ //yieldCurrentThread();
}
}
}
diff --git a/FaceTrackNoIR/SCServer.h b/FaceTrackNoIR/SCServer.h
index 6df22b21..f107de55 100644
--- a/FaceTrackNoIR/SCServer.h
+++ b/FaceTrackNoIR/SCServer.h
@@ -62,8 +62,9 @@ public:
// protected member methods
protected:
- void run();
+// void run();
bool checkServerInstallationOK( HANDLE handle );
+ void sendHeadposeToGame();
private:
// Private properties
diff --git a/FaceTrackNoIR/tracker.cpp b/FaceTrackNoIR/tracker.cpp
index 1e3c17b4..a43acd9a 100644
--- a/FaceTrackNoIR/tracker.cpp
+++ b/FaceTrackNoIR/tracker.cpp
@@ -23,6 +23,8 @@
*********************************************************************************/
/*
Modifications (last one on top):
+ 20101224 - WVR: Removed the QThread inheritance of the Base Class for the protocol-servers.
+ Again, this drastically simplifies the code in the protocols.
20101217 - WVR: Created Base Class for the protocol-servers. This drastically simplifies
the code needed here.
20101024 - WVR: Added shortkey to disable/enable one or more axis during tracking.
@@ -55,6 +57,7 @@ bool Tracker::do_tracking = true;
bool Tracker::do_center = false;
bool Tracker::do_inhibit = false;
bool Tracker::useFilter = false;
+HANDLE Tracker::hTrackMutex = 0;
long Tracker::prevHeadPoseTime = 0;
THeadPoseDOF Tracker::Pitch; // One structure for each of 6DOF's
@@ -80,6 +83,8 @@ Tracker::Tracker( int clientID, int facetrackerID ) {
m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
+ Tracker::hTrackMutex = CreateMutexA(NULL, false, "HeadPose_mutex");
+
try {
// Initialize the faceAPI Qt library
sm::faceapi::qt::initialize();
@@ -157,6 +162,7 @@ Tracker::~Tracker() {
// Close handles
::CloseHandle(m_StopThread);
::CloseHandle(m_WaitThread);
+ ::CloseHandle( Tracker::hTrackMutex );
_engine->stop();
smAPIQuit();
@@ -196,10 +202,10 @@ void Tracker::setup(QWidget *head, FaceTrackNoIR *parent) {
if (server_Game) {
DLL_Ok = server_Game->checkServerInstallationOK( mainApp->winId() );
- if (DLL_Ok) {
- server_Game->start(); // Start the thread
- }
- else {
+ if (!DLL_Ok) {
+// server_Game->start(); // Start the thread
+ //}
+ //else {
QMessageBox::information(mainApp, "FaceTrackNoIR error", "Protocol is not (correctly) installed!");
}
@@ -342,186 +348,191 @@ void Tracker::run() {
}
}
- //
- // Get the System-time and substract the time from the previous call.
- // dT will be used for the EWMA-filter.
- //
- GetSystemTime ( &now );
- newHeadPoseTime = (((now.wHour * 3600) + (now.wMinute * 60) + now.wSecond) * 1000) + now.wMilliseconds;
- dT = (newHeadPoseTime - Tracker::prevHeadPoseTime) / 1000.0f;
-
- // Remember time for next call
- Tracker::prevHeadPoseTime = newHeadPoseTime;
-
- //if the confidence is good enough the headpose will be updated **/
- if (Tracker::confid) {
+ if (WaitForSingleObject(Tracker::hTrackMutex, 100) == WAIT_OBJECT_0) {
//
- // Most games need an offset to the initial position and NOT the
- // absolute distance to the camera: so remember the initial distance
- // to substract that later...
+ // Get the System-time and substract the time from the previous call.
+ // dT will be used for the EWMA-filter.
//
- if(Tracker::set_initial == false) {
- Tracker::Pitch.initial_headPos = Tracker::Pitch.headPos;
- Tracker::Yaw.initial_headPos = Tracker::Yaw.headPos;
- Tracker::Roll.initial_headPos = Tracker::Roll.headPos;
- Tracker::X.initial_headPos = Tracker::X.headPos;
- Tracker::Y.initial_headPos = Tracker::Y.headPos;
- Tracker::Z.initial_headPos = Tracker::Z.headPos;
- MessageBeep (MB_ICONASTERISK);
- Tracker::set_initial = true;
- }
+ GetSystemTime ( &now );
+ newHeadPoseTime = (((now.wHour * 3600) + (now.wMinute * 60) + now.wSecond) * 1000) + now.wMilliseconds;
+ dT = (newHeadPoseTime - Tracker::prevHeadPoseTime) / 1000.0f;
- rawrotX = Tracker::Pitch.headPos- Tracker::Pitch.initial_headPos; // degrees
- rawrotY = Tracker::Yaw.headPos- Tracker::Yaw.initial_headPos;
- rawrotZ = Tracker::Roll.headPos - Tracker::Roll.initial_headPos;
- rawposX = Tracker::X.headPos - Tracker::X.initial_headPos; // centimeters
- rawposY = Tracker::Y.headPos - Tracker::Y.initial_headPos;
- rawposZ = Tracker::Z.headPos - Tracker::Z.initial_headPos;
+ // Remember time for next call
+ Tracker::prevHeadPoseTime = newHeadPoseTime;
- headRotXLine->setText(QString("%1").arg( rawrotX, 0, 'f', 1)); // show degrees
- headRotYLine->setText(QString("%1").arg( rawrotY, 0, 'f', 1));
- headRotZLine->setText(QString("%1").arg( rawrotZ, 0, 'f', 1));
+ //if the confidence is good enough the headpose will be updated **/
+ if (Tracker::confid) {
- headXLine->setText(QString("%1").arg( rawposX, 0, 'f', 1)); // show centimeters
- headYLine->setText(QString("%1").arg( rawposY, 0, 'f', 1));
- headZLine->setText(QString("%1").arg( rawposZ, 0, 'f', 1));
-
- }
+ //
+ // Most games need an offset to the initial position and NOT the
+ // absolute distance to the camera: so remember the initial distance
+ // to substract that later...
+ //
+ if(Tracker::set_initial == false) {
+ Tracker::Pitch.initial_headPos = Tracker::Pitch.headPos;
+ Tracker::Yaw.initial_headPos = Tracker::Yaw.headPos;
+ Tracker::Roll.initial_headPos = Tracker::Roll.headPos;
+ Tracker::X.initial_headPos = Tracker::X.headPos;
+ Tracker::Y.initial_headPos = Tracker::Y.headPos;
+ Tracker::Z.initial_headPos = Tracker::Z.headPos;
+ MessageBeep (MB_ICONASTERISK);
+ Tracker::set_initial = true;
+ }
- //
- // If Center is pressed, copy the current values to the offsets.
- //
- if (Tracker::do_center && Tracker::set_initial) {
- Pitch.offset_headPos = getSmoothFromList( &Pitch.rawList )- Tracker::Pitch.initial_headPos;
- Yaw.offset_headPos = getSmoothFromList( &Yaw.rawList ) - Tracker::Yaw.initial_headPos;
- Roll.offset_headPos = getSmoothFromList( &Roll.rawList ) - Tracker::Roll.initial_headPos;
- X.offset_headPos = getSmoothFromList( &X.rawList ) - Tracker::X.initial_headPos;
- Y.offset_headPos = getSmoothFromList( &Y.rawList ) - Tracker::Y.initial_headPos;
- Z.offset_headPos = getSmoothFromList( &Z.rawList ) - Tracker::Z.initial_headPos;
-
- Tracker::do_center = false;
- }
+ rawrotX = Tracker::Pitch.headPos- Tracker::Pitch.initial_headPos; // degrees
+ rawrotY = Tracker::Yaw.headPos- Tracker::Yaw.initial_headPos;
+ rawrotZ = Tracker::Roll.headPos - Tracker::Roll.initial_headPos;
+ rawposX = Tracker::X.headPos - Tracker::X.initial_headPos; // centimeters
+ rawposY = Tracker::Y.headPos - Tracker::Y.initial_headPos;
+ rawposZ = Tracker::Z.headPos - Tracker::Z.initial_headPos;
- if (Tracker::do_tracking && Tracker::confid) {
+ headRotXLine->setText(QString("%1").arg( rawrotX, 0, 'f', 1)); // show degrees
+ headRotYLine->setText(QString("%1").arg( rawrotY, 0, 'f', 1));
+ headRotZLine->setText(QString("%1").arg( rawrotZ, 0, 'f', 1));
-////// Use this for some debug-output to file...
-//// QFile data("output.txt");
-//// if (data.open(QFile::WriteOnly | QFile::Append)) {
-//// QTextStream out(&data);
-//// out << Pitch.NeutralZone << " " << getDegreesFromRads(rotX) << " " << getOutputFromCurve(&Pitch.curve, getDegreesFromRads(rotX), Pitch.NeutralZone, Pitch.MaxInput) << '\n';
-////// out << dT << " " << getSmoothFromList( &Pitch.rawList ) << " " << Pitch.offset_headPos << '\n';
-//// }
+ headXLine->setText(QString("%1").arg( rawposX, 0, 'f', 1)); // show centimeters
+ headYLine->setText(QString("%1").arg( rawposY, 0, 'f', 1));
+ headZLine->setText(QString("%1").arg( rawposZ, 0, 'f', 1));
- // Pitch
- if (Tracker::useFilter) {
- rotX = lowPassFilter ( getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos,
- &Pitch.prevPos, dT, Tracker::Pitch.red );
- }
- else {
- rotX = getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos;
}
- rotX = Pitch.invert * getOutputFromCurve(&Pitch.curve, rotX, Pitch.NeutralZone, Pitch.MaxInput);
- // Yaw
- if (Tracker::useFilter) {
- rotY = lowPassFilter ( getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos,
- &Yaw.prevPos, dT, Tracker::Yaw.red );
- }
- else {
- rotY = getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos;
+ //
+ // If Center is pressed, copy the current values to the offsets.
+ //
+ if (Tracker::do_center && Tracker::set_initial) {
+ Pitch.offset_headPos = getSmoothFromList( &Pitch.rawList )- Tracker::Pitch.initial_headPos;
+ Yaw.offset_headPos = getSmoothFromList( &Yaw.rawList ) - Tracker::Yaw.initial_headPos;
+ Roll.offset_headPos = getSmoothFromList( &Roll.rawList ) - Tracker::Roll.initial_headPos;
+ X.offset_headPos = getSmoothFromList( &X.rawList ) - Tracker::X.initial_headPos;
+ Y.offset_headPos = getSmoothFromList( &Y.rawList ) - Tracker::Y.initial_headPos;
+ Z.offset_headPos = getSmoothFromList( &Z.rawList ) - Tracker::Z.initial_headPos;
+
+ Tracker::do_center = false;
}
- rotY = Yaw.invert * getOutputFromCurve(&Yaw.curve, rotY, Yaw.NeutralZone, Yaw.MaxInput);
- // Roll
- if (Tracker::useFilter) {
- rotZ = lowPassFilter ( getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos,
- &Roll.prevPos, dT, Tracker::Roll.red );
- }
- else {
- rotZ = getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos;
- }
- rotZ = Roll.invert * getOutputFromCurve(&Roll.curve, rotZ, Roll.NeutralZone, Roll.MaxInput);
+ if (Tracker::do_tracking && Tracker::confid) {
- // X
- if (Tracker::useFilter) {
- posX = lowPassFilter ( getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos,
- &X.prevPos, dT, Tracker::X.red );
- }
- else {
- posX = getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos;
- }
- posX = X.invert * getOutputFromCurve(&X.curve, posX, X.NeutralZone, X.MaxInput);
+ ////// Use this for some debug-output to file...
+ //// QFile data("output.txt");
+ //// if (data.open(QFile::WriteOnly | QFile::Append)) {
+ //// QTextStream out(&data);
+ //// out << Pitch.NeutralZone << " " << getDegreesFromRads(rotX) << " " << getOutputFromCurve(&Pitch.curve, getDegreesFromRads(rotX), Pitch.NeutralZone, Pitch.MaxInput) << '\n';
+ ////// out << dT << " " << getSmoothFromList( &Pitch.rawList ) << " " << Pitch.offset_headPos << '\n';
+ //// }
- // Y
- if (Tracker::useFilter) {
- posY = lowPassFilter ( getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos,
- &Y.prevPos, dT, Tracker::Y.red );
- }
- else {
- posY = getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos;
- }
- posY = Y.invert * getOutputFromCurve(&Y.curve, posY, Y.NeutralZone, Y.MaxInput);
+ // Pitch
+ if (Tracker::useFilter) {
+ rotX = lowPassFilter ( getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos,
+ &Pitch.prevPos, dT, Tracker::Pitch.red );
+ }
+ else {
+ rotX = getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos;
+ }
+ rotX = Pitch.invert * getOutputFromCurve(&Pitch.curve, rotX, Pitch.NeutralZone, Pitch.MaxInput);
- // Z
- if (Tracker::useFilter) {
- posZ = lowPassFilter ( getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos,
- &Z.prevPos, dT, Tracker::Z.red );
- }
- else {
- posZ = getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos;
- }
- posZ = Z.invert * getOutputFromCurve(&Z.curve, posZ, Z.NeutralZone, Z.MaxInput);
+ // Yaw
+ if (Tracker::useFilter) {
+ rotY = lowPassFilter ( getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos,
+ &Yaw.prevPos, dT, Tracker::Yaw.red );
+ }
+ else {
+ rotY = getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos;
+ }
+ rotY = Yaw.invert * getOutputFromCurve(&Yaw.curve, rotY, Yaw.NeutralZone, Yaw.MaxInput);
- //
- // Reset value for the selected axis, if inhibition is active
- //
- if (Tracker::do_inhibit) {
- if (InhibitKey.doPitch) rotX = 0.0f;
- if (InhibitKey.doYaw) rotY = 0.0f;
- if (InhibitKey.doRoll) rotZ = 0.0f;
- if (InhibitKey.doX) posX = 0.0f;
- if (InhibitKey.doY) posY = 0.0f;
- if (InhibitKey.doZ) posZ = 0.0f;
- }
+ // Roll
+ if (Tracker::useFilter) {
+ rotZ = lowPassFilter ( getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos,
+ &Roll.prevPos, dT, Tracker::Roll.red );
+ }
+ else {
+ rotZ = getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos;
+ }
+ rotZ = Roll.invert * getOutputFromCurve(&Roll.curve, rotZ, Roll.NeutralZone, Roll.MaxInput);
- //
- // Send the Virtual Pose to selected Protocol-Server
- //
- // Free-track
- if (selectedClient == FREE_TRACK) {
- server_Game->setHeadRotX( rotX ); // degrees
- server_Game->setHeadRotY( rotY );
- server_Game->setHeadRotZ( rotZ );
-
- server_Game->setHeadPosX( posX ); // centimeters
- server_Game->setHeadPosY( posY );
- server_Game->setHeadPosZ( posZ );
- }
+ // X
+ if (Tracker::useFilter) {
+ posX = lowPassFilter ( getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos,
+ &X.prevPos, dT, Tracker::X.red );
+ }
+ else {
+ posX = getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos;
+ }
+ posX = X.invert * getOutputFromCurve(&X.curve, posX, X.NeutralZone, X.MaxInput);
+
+ // Y
+ if (Tracker::useFilter) {
+ posY = lowPassFilter ( getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos,
+ &Y.prevPos, dT, Tracker::Y.red );
+ }
+ else {
+ posY = getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos;
+ }
+ posY = Y.invert * getOutputFromCurve(&Y.curve, posY, Y.NeutralZone, Y.MaxInput);
+
+ // Z
+ if (Tracker::useFilter) {
+ posZ = lowPassFilter ( getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos,
+ &Z.prevPos, dT, Tracker::Z.red );
+ }
+ else {
+ posZ = getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos;
+ }
+ posZ = Z.invert * getOutputFromCurve(&Z.curve, posZ, Z.NeutralZone, Z.MaxInput);
+
+ //
+ // Reset value for the selected axis, if inhibition is active
+ //
+ if (Tracker::do_inhibit) {
+ if (InhibitKey.doPitch) rotX = 0.0f;
+ if (InhibitKey.doYaw) rotY = 0.0f;
+ if (InhibitKey.doRoll) rotZ = 0.0f;
+ if (InhibitKey.doX) posX = 0.0f;
+ if (InhibitKey.doY) posY = 0.0f;
+ if (InhibitKey.doZ) posZ = 0.0f;
+ }
- // FlightGear
- if (server_Game) {
- server_Game->setVirtRotX ( rotX ); // degrees
- server_Game->setVirtRotY ( rotY );
- server_Game->setVirtRotZ ( rotZ );
- server_Game->setVirtPosX ( posX ); // centimeters
- server_Game->setVirtPosY ( posY );
- server_Game->setVirtPosZ ( posZ );
+ //
+ // Send the Virtual Pose to selected Protocol-Server
+ //
+ // Free-track
+ if (selectedClient == FREE_TRACK) {
+ server_Game->setHeadRotX( rotX ); // degrees
+ server_Game->setHeadRotY( rotY );
+ server_Game->setHeadRotZ( rotZ );
+
+ server_Game->setHeadPosX( posX ); // centimeters
+ server_Game->setHeadPosY( posY );
+ server_Game->setHeadPosZ( posZ );
+ }
+
+ // FlightGear
+ if (server_Game) {
+ server_Game->setVirtRotX ( rotX ); // degrees
+ server_Game->setVirtRotY ( rotY );
+ server_Game->setVirtRotZ ( rotZ );
+ server_Game->setVirtPosX ( posX ); // centimeters
+ server_Game->setVirtPosY ( posY );
+ server_Game->setVirtPosZ ( posZ );
+ }
}
- }
- else {
- //
- // Go to initial position
- //
- if (server_Game) {
- server_Game->setVirtRotX ( 0.0f );
- server_Game->setVirtRotY ( 0.0f );
- server_Game->setVirtRotZ ( 0.0f );
- server_Game->setVirtPosX ( 0.0f );
- server_Game->setVirtPosY ( 0.0f );
- server_Game->setVirtPosZ ( 0.0f );
+ else {
+ //
+ // Go to initial position
+ //
+ if (server_Game) {
+ server_Game->setVirtRotX ( 0.0f );
+ server_Game->setVirtRotY ( 0.0f );
+ server_Game->setVirtRotZ ( 0.0f );
+ server_Game->setVirtPosX ( 0.0f );
+ server_Game->setVirtPosY ( 0.0f );
+ server_Game->setVirtPosZ ( 0.0f );
+ }
}
}
+ ReleaseMutex(Tracker::hTrackMutex);
+ server_Game->sendHeadposeToGame();
//for lower cpu load
msleep(10);
@@ -543,7 +554,8 @@ void Tracker::receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVid
// Perform actions, when valid data is received from faceAPI.
// Write the Raw headpose-data and add it to the RawList, for processing...
//
- if( head_pose.confidence > 0 ) {
+ if (( head_pose.confidence > 0 ) && (WaitForSingleObject(Tracker::hTrackMutex, 100) == WAIT_OBJECT_0) ) {
+
Tracker::confid = true;
// Pitch
@@ -574,6 +586,8 @@ void Tracker::receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVid
Tracker::confid = false;
}
+ ReleaseMutex(Tracker::hTrackMutex);
+
// for lower cpu load
msleep(10);
yieldCurrentThread();
diff --git a/FaceTrackNoIR/tracker.h b/FaceTrackNoIR/tracker.h
index b81cf636..6a3fca93 100644
--- a/FaceTrackNoIR/tracker.h
+++ b/FaceTrackNoIR/tracker.h
@@ -153,6 +153,9 @@ private:
static bool do_center; // Center head-position, using the shortkey
static bool do_inhibit; // Inhibit DOF-axis, using the shortkey
+ static HANDLE hTrackMutex; // Prevent reading/writing the headpose simultaneously
+
+
static bool useFilter;
static long prevHeadPoseTime; // Time from previous sample
diff --git a/bin/FaceTrackNoIR.exe b/bin/FaceTrackNoIR.exe
index c980d4cd..261c34e2 100644
--- a/bin/FaceTrackNoIR.exe
+++ b/bin/FaceTrackNoIR.exe
Binary files differ
diff --git a/bin/Settings/ArmA.ini b/bin/Settings/ArmA.ini
index acea8fbe..c60fcf0e 100644
--- a/bin/Settings/ArmA.ini
+++ b/bin/Settings/ArmA.ini
@@ -1,5 +1,5 @@
[Tracking]
-Smooth=5
+Smooth=3
NeutralZone=5
sensYaw=90
sensPitch=90
@@ -69,3 +69,6 @@ Inhibit_Roll=false
Inhibit_X=false
Inhibit_Y=false
Inhibit_Z=false
+
+[TrackerSource]
+Selection=0