From a1126d63fe3068cc5651c8c3060647a33e4bb710 Mon Sep 17 00:00:00 2001 From: Wim Vriend Date: Sun, 23 Jan 2011 20:17:37 +0000 Subject: Start merging new filter git-svn-id: svn+ssh://svn.code.sf.net/p/facetracknoir/code@42 19e81ba0-9b1a-49c3-bd6c-561e1906d5fb --- FTNoIR_Filter_EWMA2/FTNoIR_Filter_EWMA2.vcproj | 235 ++++++++++++++++++++ FTNoIR_Filter_EWMA2/ftnoir_filter_base.h | 47 ++++ FTNoIR_Filter_EWMA2/ftnoir_filter_base_global.h | 12 ++ FTNoIR_Filter_EWMA2/ftnoir_filter_ewma2.cpp | 275 ++++++++++++++++++++++++ FTNoIR_Tracker_UDP/ftnoir_tracker_base.h | 1 - FTNoIR_Tracker_UDP/ftnoir_tracker_udp.cpp | 8 +- FaceTrackNoIR.sln | 6 + FaceTrackNoIR.suo | Bin 317440 -> 323072 bytes FaceTrackNoIR/FaceTrackNoIR.vcproj | 24 +-- FaceTrackNoIR/tracker.cpp | 190 ++++++++-------- FaceTrackNoIR/tracker.h | 4 + List of compatible webcams.xls | Bin 20480 -> 20480 bytes bin/FaceTrackNoIR.exe | Bin 741376 -> 741376 bytes bin/Settings/SimConnect.ini | 6 +- 14 files changed, 689 insertions(+), 119 deletions(-) create mode 100644 FTNoIR_Filter_EWMA2/FTNoIR_Filter_EWMA2.vcproj create mode 100644 FTNoIR_Filter_EWMA2/ftnoir_filter_base.h create mode 100644 FTNoIR_Filter_EWMA2/ftnoir_filter_base_global.h create mode 100644 FTNoIR_Filter_EWMA2/ftnoir_filter_ewma2.cpp diff --git a/FTNoIR_Filter_EWMA2/FTNoIR_Filter_EWMA2.vcproj b/FTNoIR_Filter_EWMA2/FTNoIR_Filter_EWMA2.vcproj new file mode 100644 index 00000000..4ff53df2 --- /dev/null +++ b/FTNoIR_Filter_EWMA2/FTNoIR_Filter_EWMA2.vcproj @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FTNoIR_Filter_EWMA2/ftnoir_filter_base.h b/FTNoIR_Filter_EWMA2/ftnoir_filter_base.h new file mode 100644 index 00000000..f05fe66a --- /dev/null +++ b/FTNoIR_Filter_EWMA2/ftnoir_filter_base.h @@ -0,0 +1,47 @@ +#ifndef FTNOIR_FILTER_BASE_H +#define FTNOIR_FILTER_BASE_H + +#include "ftnoir_filter_base_global.h" +#include "ftnoir_tracker_base.h" +#include +#include + +// 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 void Release() = 0; + virtual void Initialize() = 0; + virtual void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position) = 0; + + virtual void getFilterFullName(QString *strToBeFilled) = 0; + virtual void getFilterShortName(QString *strToBeFilled) = 0; + virtual void getFilterDescription(QString *strToBeFilled) = 0; + + //parameter value get/set - returns true if successful, false if not + virtual bool setParameterValue(const int index, const float newvalue) = 0; +}; + +// Handle type. In C++ language the iterface type is used. +typedef IFilter* FILTERHANDLE; + +//////////////////////////////////////////////////////////////////////////////// +// +#ifdef __cplusplus +# define EXTERN_C extern "C" +#else +# define EXTERN_C +#endif // __cplusplus + +// Factory function that creates instances of the Filter object. +EXTERN_C +FTNOIR_FILTER_BASE_EXPORT +FILTERHANDLE +__stdcall +GetFilter( + void); + +#endif // FTNOIR_FILTER_BASE_H diff --git a/FTNoIR_Filter_EWMA2/ftnoir_filter_base_global.h b/FTNoIR_Filter_EWMA2/ftnoir_filter_base_global.h new file mode 100644 index 00000000..aac4048e --- /dev/null +++ b/FTNoIR_Filter_EWMA2/ftnoir_filter_base_global.h @@ -0,0 +1,12 @@ +#ifndef FTNOIR_FILTER_BASE_GLOBAL_H +#define FTNOIR_FILTER_BASE_GLOBAL_H + +#include + +#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 new file mode 100644 index 00000000..059e2807 --- /dev/null +++ b/FTNoIR_Filter_EWMA2/ftnoir_filter_ewma2.cpp @@ -0,0 +1,275 @@ +#include "ftnoir_filter_base.h" +#include "math.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// EWMA Filter: Exponentially Weighted Moving Average filter with dynamic smoothing parameter +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class FTNoIR_Filter_EWMA2 : public IFilter +{ +public: + FTNoIR_Filter_EWMA2(); + ~FTNoIR_Filter_EWMA2(); + + void Release(); + void Initialize(); + void StartFilter(); + void FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position); + + void getFilterFullName(QString *strToBeFilled); + void getFilterShortName(QString *strToBeFilled); + void getFilterDescription(QString *strToBeFilled); + + bool setParameterValue(const int index, const float newvalue); + +private: + THeadPoseData newHeadPose; // Structure with new headpose + + bool first_run; + float smoothing_frames_range; + float alpha_smoothing; + float prev_alpha[6]; + + //parameter list for the filter-function(s) + enum + { + kMinSmoothing=0, + kMaxSmoothing, + kSmoothingScaleCurve, + kNumFilterParameters // Indicate number of parameters used + }; + + QString filterFullName; // Filters' name and description + QString filterShortName; + QString filterDescription; + + QList parameterValueAsFloat; + QList> parameterRange; + QList parameterSteps; + QList parameterNameAsString; + QList parameterValueAsString; + QList parameterUnitsAsString; +}; + +FTNoIR_Filter_EWMA2::FTNoIR_Filter_EWMA2() +{ + //populate the description strings + filterFullName = "EWMA Filter Mk2"; + filterShortName = "EWMA"; + filterDescription = "Exponentially Weighted Moving Average filter with dynamic smoothing parameter"; + + //allocate memory for the parameters + parameterValueAsFloat.clear(); + parameterRange.clear(); + parameterSteps.clear(); + parameterNameAsString.clear(); + parameterValueAsString.clear(); + parameterUnitsAsString.clear(); + + //set up parameters + parameterNameAsString.append("MinSmoothing"); + parameterUnitsAsString.append("Frames"); + parameterRange.append(std::pair(1.0f,100.0f)); + parameterSteps.append(1.0f); + parameterValueAsFloat.append(0.0f); + parameterValueAsString.append(""); + setParameterValue(kMinSmoothing,2.0f); + + parameterNameAsString.append("MaxSmoothing"); + parameterUnitsAsString.append("Frames"); + parameterRange.append(std::pair(1.0f,100.0f)); + parameterSteps.append(1.0f); + parameterValueAsFloat.append(0.0f); + parameterValueAsString.append(""); + setParameterValue(kMaxSmoothing,10.0f); + + parameterNameAsString.append("SmoothingScaleCurve"); + parameterUnitsAsString.append("Power"); + parameterRange.append(std::pair(0.25f,10.0f)); + parameterSteps.append(0.0f); + parameterValueAsFloat.append(0.0f); + parameterValueAsString.append(""); + setParameterValue(kSmoothingScaleCurve,10.0f); + + first_run = true; + alpha_smoothing = 0.1f; //this is a constant for now, might be a parameter later + +} + +FTNoIR_Filter_EWMA2::~FTNoIR_Filter_EWMA2() +{ + +} + +void FTNoIR_Filter_EWMA2::Release() +{ + delete this; +} + +void FTNoIR_Filter_EWMA2::Initialize() +{ + return; +} + +void FTNoIR_Filter_EWMA2::FilterHeadPoseData(THeadPoseData *current_camera_position, THeadPoseData *target_camera_position, THeadPoseData *new_camera_position) +{ + //non-optimised version for clarity + float prev_output[6]; + float target[6]; + float output_delta[6]; + float scale[]={0.25f,0.25f,0.25f,6.0f,6.0f,6.0f}; + float norm_output_delta[6]; + float alpha[6]; + float smoothed_alpha[6]; + float output[6]; + int i=0; + + #if PRE_FILTER_SCALING + //compensate for any prefilter scaling + scale[0]*=X_POS_SCALE; + scale[1]*=Y_POS_SCALE; + scale[2]*=Z_POS_SCALE; + scale[3]*=X_ROT_SCALE; + scale[4]*=Y_ROT_SCALE; + scale[5]*=Z_ROT_SCALE; + #endif + + //find out how far the head has moved + prev_output[0]=current_camera_position->x; + prev_output[1]=current_camera_position->y; + prev_output[2]=current_camera_position->z; + prev_output[3]=current_camera_position->yaw; + prev_output[4]=current_camera_position->pitch; + prev_output[5]=current_camera_position->roll; + + target[0]=target_camera_position->x; + target[1]=target_camera_position->y; + target[2]=target_camera_position->z; + target[3]=target_camera_position->yaw; + target[4]=target_camera_position->pitch; + target[5]=target_camera_position->roll; + + if (first_run==true) + { + //on the first run, output=target + for (i=0;i<6;i++) + { + output[i]=target[i]; + } + + new_camera_position->x=target[0]; + new_camera_position->y=target[1]; + new_camera_position->z=target[2]; + new_camera_position->yaw=target[3]; + new_camera_position->pitch=target[4]; + new_camera_position->roll=target[5]; + + first_run=false; + + //we can bail + return; + } + + //how far does the camera need to move to catch up? + for (i=0;i<6;i++) + { + output_delta[i]=(target[i]-prev_output[i]); + } + + //normalise the deltas + for (i=0;i<6;i++) + { + norm_output_delta[i]=std::min(std::max(fabs(output_delta[i])/scale[i],0.0f),1.0f); + } + + //calculate the alphas + //work out the dynamic smoothing factors + for (i=0;i<6;i++) + { + alpha[i]=1.0f/(parameterValueAsFloat[kMinSmoothing]+((1.0f-pow(norm_output_delta[i],parameterValueAsFloat[kSmoothingScaleCurve]))*smoothing_frames_range)); + smoothed_alpha[i]=(alpha_smoothing*alpha[i])+((1.0f-alpha_smoothing)*prev_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 (i=0;i<6;i++) + { + if (smoothed_alpha[i]>=largest_alpha) + { + largest_alpha=smoothed_alpha[i]; + } + } + + //move the camera + for (i=0;i<6;i++) + { + output[i]=(largest_alpha*target[i])+((1.0f-largest_alpha)*prev_output[i]); + } + + new_camera_position->x=output[0]; + new_camera_position->y=output[1]; + new_camera_position->z=output[2]; + new_camera_position->yaw=output[3]; + new_camera_position->pitch=output[4]; + new_camera_position->roll=output[5]; + + //update filter memories ready for next sample + for (i=0;i<6;i++) + { + prev_alpha[i]=smoothed_alpha[i]; + } + return; +} + +void FTNoIR_Filter_EWMA2::getFilterFullName(QString *strToBeFilled) +{ + *strToBeFilled = filterFullName; +}; + + +void FTNoIR_Filter_EWMA2::getFilterShortName(QString *strToBeFilled) +{ + *strToBeFilled = filterShortName; +}; + + +void FTNoIR_Filter_EWMA2::getFilterDescription(QString *strToBeFilled) +{ + *strToBeFilled = filterDescription; +}; + +bool FTNoIR_Filter_EWMA2::setParameterValue(const int index, const float newvalue) +{ + if ((index >= 0) && (index < parameterValueAsFloat.size())) + { + parameterValueAsFloat[index]=std::min(std::max(newvalue,parameterRange[index].first),parameterRange[index].second); +// updateParameterString(index); + + if (index==kMinSmoothing || index==kMaxSmoothing) + { + smoothing_frames_range=parameterValueAsFloat[kMaxSmoothing]-parameterValueAsFloat[kMinSmoothing]; + } + return true; + } + else + { + return false; + } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// 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") + +FTNOIR_FILTER_BASE_EXPORT FILTERHANDLE __stdcall GetFilter() +{ + return new FTNoIR_Filter_EWMA2; +} diff --git a/FTNoIR_Tracker_UDP/ftnoir_tracker_base.h b/FTNoIR_Tracker_UDP/ftnoir_tracker_base.h index 60c26ee1..ac4b2956 100644 --- a/FTNoIR_Tracker_UDP/ftnoir_tracker_base.h +++ b/FTNoIR_Tracker_UDP/ftnoir_tracker_base.h @@ -19,7 +19,6 @@ struct THeadPoseData { // Instances are obtained via factory function. struct ITracker { - virtual int Foo(int n) = 0; virtual void Release() = 0; virtual void Initialize() = 0; virtual void StartTracker() = 0; diff --git a/FTNoIR_Tracker_UDP/ftnoir_tracker_udp.cpp b/FTNoIR_Tracker_UDP/ftnoir_tracker_udp.cpp index 005671cb..eaa0b177 100644 --- a/FTNoIR_Tracker_UDP/ftnoir_tracker_udp.cpp +++ b/FTNoIR_Tracker_UDP/ftnoir_tracker_udp.cpp @@ -9,8 +9,7 @@ public: FTNoIR_Tracker_UDP(); ~FTNoIR_Tracker_UDP(); - int Foo(int n); - void Release(); + void Release(); void Initialize(); void StartTracker(); void GiveHeadPoseData(THeadPoseData *data); @@ -125,11 +124,6 @@ quint16 senderPort; } } -int FTNoIR_Tracker_UDP::Foo(int n) -{ - return n * n; -} - void FTNoIR_Tracker_UDP::Release() { delete this; diff --git a/FaceTrackNoIR.sln b/FaceTrackNoIR.sln index 1331f7ef..d125c314 100644 --- a/FaceTrackNoIR.sln +++ b/FaceTrackNoIR.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FTNoIR_ProtocolTester", "FT EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FTNoIR_Tracker_UDP", "FTNoIR_Tracker_UDP\FTNoIR_Tracker_UDP.vcproj", "{A42E7DE9-C1C5-48A2-8FEA-86D31CE3DA31}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FTNoIR_Filter_EWMA2", "FTNoIR_Filter_EWMA2\FTNoIR_Filter_EWMA2.vcproj", "{7DD9F1AA-B7C0-4056-AC4A-1501840E6438}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -28,6 +30,10 @@ Global {A42E7DE9-C1C5-48A2-8FEA-86D31CE3DA31}.Debug|Win32.Build.0 = Debug|Win32 {A42E7DE9-C1C5-48A2-8FEA-86D31CE3DA31}.Release|Win32.ActiveCfg = Release|Win32 {A42E7DE9-C1C5-48A2-8FEA-86D31CE3DA31}.Release|Win32.Build.0 = Release|Win32 + {7DD9F1AA-B7C0-4056-AC4A-1501840E6438}.Debug|Win32.ActiveCfg = Debug|Win32 + {7DD9F1AA-B7C0-4056-AC4A-1501840E6438}.Debug|Win32.Build.0 = Debug|Win32 + {7DD9F1AA-B7C0-4056-AC4A-1501840E6438}.Release|Win32.ActiveCfg = Release|Win32 + {7DD9F1AA-B7C0-4056-AC4A-1501840E6438}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FaceTrackNoIR.suo b/FaceTrackNoIR.suo index 48e0d28e..601e25f5 100644 Binary files a/FaceTrackNoIR.suo and b/FaceTrackNoIR.suo differ diff --git a/FaceTrackNoIR/FaceTrackNoIR.vcproj b/FaceTrackNoIR/FaceTrackNoIR.vcproj index 2ec885e4..e56d9e5c 100644 --- a/FaceTrackNoIR/FaceTrackNoIR.vcproj +++ b/FaceTrackNoIR/FaceTrackNoIR.vcproj @@ -47,7 +47,7 @@ OmitFramePointers="false" EnableFiberSafeOptimizations="false" WholeProgramOptimization="false" - AdditionalIncludeDirectories=".\GeneratedFiles;"$(QTDIR)\include";".\GeneratedFiles\$(ConfigurationName)";"$(QTDIR)\include\QtCore";"$(QTDIR)\include\QtNetwork";"$(QTDIR)\include\QtGui";"$(QTDIR)\include\QtOpenGL";"$(QTDIR)\include\QtWebKit";"$(QTDIR)\include\QtTest";"$(SM_API_PATH)\include";"$(SM_API_CPP_WRAPPERS)\include";"$(SM_API_QTDIR)\include";"$(SM_API_WIDGETS)\include";"$(SolutionDir)\FTNoIR_Tracker_UDP"" + AdditionalIncludeDirectories=".\GeneratedFiles;"$(QTDIR)\include";".\GeneratedFiles\$(ConfigurationName)";"$(QTDIR)\include\QtCore";"$(QTDIR)\include\QtNetwork";"$(QTDIR)\include\QtGui";"$(QTDIR)\include\QtOpenGL";"$(QTDIR)\include\QtWebKit";"$(QTDIR)\include\QtTest";"$(SM_API_PATH)\include";"$(SM_API_CPP_WRAPPERS)\include";"$(SM_API_QTDIR)\include";"$(SM_API_WIDGETS)\include";"$(SolutionDir)\FTNoIR_Tracker_UDP";"$(SolutionDir)\FTNoIR_Filter_EWMA2"" PreprocessorDefinitions="UNICODE;WIN32;QT_LARGEFILE_SUPPORT;QT_THREAD_SUPPORT;QT_NO_DEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_OPENGL_LIB;QT_NETWORK_LIB;QT_DLL" RuntimeLibrary="2" FloatingPointModel="2" @@ -258,7 +258,7 @@ @@ -284,7 +284,7 @@ @@ -310,7 +310,7 @@ @@ -336,7 +336,7 @@ @@ -366,7 +366,7 @@ @@ -392,7 +392,7 @@ @@ -422,7 +422,7 @@ @@ -448,7 +448,7 @@ @@ -482,7 +482,7 @@ @@ -512,7 +512,7 @@ @@ -538,7 +538,7 @@ diff --git a/FaceTrackNoIR/tracker.cpp b/FaceTrackNoIR/tracker.cpp index 73023b2f..ab2f3b86 100644 --- a/FaceTrackNoIR/tracker.cpp +++ b/FaceTrackNoIR/tracker.cpp @@ -53,7 +53,7 @@ // Definitions for testing purposes // #define USE_HEADPOSE_CALLBACK -//#define USE_DEBUG_CLIENT +#define USE_DEBUG_CLIENT using namespace sm::faceapi; using namespace sm::faceapi::qt; @@ -84,6 +84,9 @@ TShortKey Tracker::InhibitKey; // ShortKey to inhibit axis while tracking Tracker::Tracker( int clientID, int facetrackerID ) { importGetTracker getIT; QLibrary *trackerLib; +importGetFilter getFilter; +QLibrary *filterLib; + // Remember the selected client, from the ListBox // If the Tracker runs, this can NOT be changed... @@ -179,9 +182,28 @@ QLibrary *trackerLib; break; } -# ifdef USE_DEBUG_CLIENT - debug_Client = QSharedPointer(new ExcelServer ( this )); // Create Excel protocol-server -# endif +# ifdef USE_DEBUG_CLIENT + debug_Client = QSharedPointer(new ExcelServer ( this )); // Create Excel protocol-server +# endif + + // + // Load the DLL with the filter-logic and retrieve a pointer to the Filter-class. + // + filterLib = new QLibrary("FTNoIR_Filter_EWMA2.dll"); + + getFilter = (importGetFilter) filterLib->resolve("GetFilter"); + if (getFilter) { + IFilterPtr ptrXyz(getFilter()); + if (ptrXyz) + { + pFilter = ptrXyz; + qDebug() << "Filter::setup Function Resolved!"; + } + } + else { + QMessageBox::warning(0,"FaceTrackNoIR Error", "Filter-DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); + return; + } // Load the settings from the INI-file loadSettings(); @@ -245,8 +267,6 @@ void Tracker::setup(QWidget *head, FaceTrackNoIR *parent) { } if (selectedTracker == FT_FTNOIR) { - int fooResult = pTracker->Foo(42); - qDebug() << "Tracker::setup Foo gives: " << fooResult; pTracker->StartTracker(); } @@ -295,18 +315,38 @@ void Tracker::run() { float rawrotX, rawrotY, rawrotZ; // Locals... float rawposX, rawposY, rawposZ; - float rotX, rotY, rotZ; // Locals... - float posX, posY, posZ; + //float new_camera_position.pitch, new_camera_position.yaw, new_camera_position.roll; // Locals... + //float new_camera_position.x, new_camera_position.y, new_camera_position.z; SYSTEMTIME now; long newHeadPoseTime; float dT; + THeadPoseData current_camera_position; // Used for filtering + THeadPoseData target_camera_position; + THeadPoseData new_camera_position; + # ifndef USE_HEADPOSE_CALLBACK smEngineHeadPoseData head_pose; // headpose from faceAPI smEngineHeadPoseData temp_head_pose; // headpose from faceAPI # endif + new_camera_position.x = 0.0f; + new_camera_position.y = 0.0f; + new_camera_position.z = 0.0f; + new_camera_position.yaw = 0.0f; + new_camera_position.pitch = 0.0f; + new_camera_position.roll = 0.0f; + + // + // Test some Filter-stuff + // + if (pFilter) { + QString filterName; + pFilter->getFilterFullName(&filterName); + qDebug() << "Tracker::run() FilterName = " << filterName; + } + // // Setup the DirectInput for keyboard strokes // @@ -511,85 +551,43 @@ void Tracker::run() { if (Tracker::do_tracking && Tracker::confid) { - ////// 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'; - //// } - // Pitch - if (Tracker::useFilter) { - rotX = lowPassFilter ( getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos, -// rotX = lowPassFilter ( getSmoothFromList( &Pitch.rawList ), - &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; - } - 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); - - // 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 ); + current_camera_position = new_camera_position; // Remember the latest position + target_camera_position.x = X.headPos - X.offset_headPos - X.initial_headPos; + target_camera_position.y = Y.headPos - Y.offset_headPos - Y.initial_headPos; + target_camera_position.z = Z.headPos - Z.offset_headPos - Z.initial_headPos; + target_camera_position.pitch = Pitch.headPos - Pitch.offset_headPos - Pitch.initial_headPos; + target_camera_position.yaw = Yaw.headPos - Yaw.offset_headPos - Yaw.initial_headPos; + target_camera_position.roll = Roll.headPos - Roll.offset_headPos - Roll.initial_headPos; + + if (Tracker::useFilter && pFilter) { + pFilter->FilterHeadPoseData(¤t_camera_position, &target_camera_position, &new_camera_position); } else { - posZ = getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos; + new_camera_position.x = getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos; + new_camera_position.y = getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos; + new_camera_position.z = getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos; + new_camera_position.pitch = getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos; + new_camera_position.yaw = getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos; + new_camera_position.roll = getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos; } - posZ = Z.invert * getOutputFromCurve(&Z.curve, posZ, Z.NeutralZone, Z.MaxInput); + new_camera_position.x = X.invert * getOutputFromCurve(&X.curve, new_camera_position.x, X.NeutralZone, X.MaxInput); + new_camera_position.y = Y.invert * getOutputFromCurve(&Y.curve, new_camera_position.y, Y.NeutralZone, Y.MaxInput); + new_camera_position.z = Z.invert * getOutputFromCurve(&Z.curve, new_camera_position.z, Z.NeutralZone, Z.MaxInput); + new_camera_position.pitch = Pitch.invert * getOutputFromCurve(&Pitch.curve, new_camera_position.pitch, Pitch.NeutralZone, Pitch.MaxInput); + new_camera_position.yaw = Yaw.invert * getOutputFromCurve(&Yaw.curve, new_camera_position.yaw, Yaw.NeutralZone, Yaw.MaxInput); + new_camera_position.roll = Roll.invert * getOutputFromCurve(&Roll.curve, new_camera_position.roll, Roll.NeutralZone, Roll.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; + if (InhibitKey.doPitch) new_camera_position.pitch = 0.0f; + if (InhibitKey.doYaw) new_camera_position.yaw = 0.0f; + if (InhibitKey.doRoll) new_camera_position.roll = 0.0f; + if (InhibitKey.doX) new_camera_position.x = 0.0f; + if (InhibitKey.doY) new_camera_position.y = 0.0f; + if (InhibitKey.doZ) new_camera_position.z = 0.0f; } // @@ -597,23 +595,23 @@ void Tracker::run() { // // Free-track if (selectedClient == FREE_TRACK) { - server_Game->setHeadRotX( rotX ); // degrees - server_Game->setHeadRotY( rotY ); - server_Game->setHeadRotZ( rotZ ); + server_Game->setHeadRotX( new_camera_position.pitch ); // degrees + server_Game->setHeadRotY( new_camera_position.yaw ); + server_Game->setHeadRotZ( new_camera_position.roll ); - server_Game->setHeadPosX( posX ); // centimeters - server_Game->setHeadPosY( posY ); - server_Game->setHeadPosZ( posZ ); + server_Game->setHeadPosX( new_camera_position.x ); // centimeters + server_Game->setHeadPosY( new_camera_position.y ); + server_Game->setHeadPosZ( new_camera_position.z ); } // All Protocol server(s) 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 ); + server_Game->setVirtRotX ( new_camera_position.pitch ); // degrees + //server_Game->setVirtRotY ( new_camera_position.yaw ); + //server_Game->setVirtRotZ ( new_camera_position.roll ); + //server_Game->setVirtPosX ( new_camera_position.x ); // centimeters + //server_Game->setVirtPosY ( new_camera_position.y ); + //server_Game->setVirtPosZ ( new_camera_position.z ); } # ifdef USE_DEBUG_CLIENT @@ -625,12 +623,12 @@ void Tracker::run() { debug_Client->setHeadPosY( Tracker::Y.headPos ); debug_Client->setHeadPosZ( Tracker::Z.headPos ); - debug_Client->setVirtRotX ( rotX ); // degrees - debug_Client->setVirtRotY ( rotY ); - debug_Client->setVirtRotZ ( rotZ ); - debug_Client->setVirtPosX ( posX ); // centimeters - debug_Client->setVirtPosY ( posY ); - debug_Client->setVirtPosZ ( posZ ); + debug_Client->setVirtRotX ( new_camera_position.pitch ); // degrees + debug_Client->setVirtRotY ( new_camera_position.yaw ); + debug_Client->setVirtRotZ ( new_camera_position.roll ); + debug_Client->setVirtPosX ( new_camera_position.x ); // centimeters + debug_Client->setVirtPosY ( new_camera_position.y ); + debug_Client->setVirtPosZ ( new_camera_position.z ); # endif diff --git a/FaceTrackNoIR/tracker.h b/FaceTrackNoIR/tracker.h index ab14e06a..49310a23 100644 --- a/FaceTrackNoIR/tracker.h +++ b/FaceTrackNoIR/tracker.h @@ -46,6 +46,7 @@ #include "FTNoIR_cxx_protocolserver.h" #include "FTNoIR_Tracker_base.h" +#include "FTNoIR_Filter_base.h" #include "AutoClosePtr.h" // 1a. COM-Like usage with smart pointer. @@ -53,6 +54,8 @@ // be released automatically in destructor of the smart pointer. typedef AutoClosePtr ITrackerPtr; typedef ITracker *(WINAPI *importGetTracker)(void); +typedef AutoClosePtr IFilterPtr; +typedef IFilter *(WINAPI *importGetFilter)(void); // include the DirectX Library files #pragma comment (lib, "dinput8.lib") @@ -139,6 +142,7 @@ private: QSharedPointer _engine; smEngineHandle _engine_handle; ITrackerPtr pTracker; // Pointer to Tracker instance (in DLL) + IFilterPtr pFilter; // Pointer to Filter instance (in DLL) /** static callback method for the head pose tracking **/ static void STDCALL receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVideoFrame video_frame); diff --git a/List of compatible webcams.xls b/List of compatible webcams.xls index a3c7398e..c21e1bf8 100644 Binary files a/List of compatible webcams.xls and b/List of compatible webcams.xls differ diff --git a/bin/FaceTrackNoIR.exe b/bin/FaceTrackNoIR.exe index 438e6f3c..cf57f7f1 100644 Binary files a/bin/FaceTrackNoIR.exe and b/bin/FaceTrackNoIR.exe differ diff --git a/bin/Settings/SimConnect.ini b/bin/Settings/SimConnect.ini index 05f5d972..e9f0bc13 100644 --- a/bin/Settings/SimConnect.ini +++ b/bin/Settings/SimConnect.ini @@ -15,7 +15,7 @@ redY=90 redZ=90 [GameProtocol] -Selection=1 +Selection=5 [TrackerSource] Selection=0 @@ -28,11 +28,11 @@ Yaw_point4=@Variant(\0\0\0\x1a@d\x80\0\0\0\0\0@I\0\0\0\0\0\0) Pitch_point1=@Variant(\0\0\0\x1a\0\0\0\0\0\0\0\0@\x14\0\0\0\0\0\0) Pitch_point2=@Variant(\0\0\0\x1a@1\0\0\0\0\0\0@1\0\0\0\0\0\0) Pitch_point3=@Variant(\0\0\0\x1a@@\x80\0\0\0\0\0@@\x80\0\0\0\0\0) -Pitch_point4=@Variant(\0\0\0\x1a@c\xd0\0\0\0\0\0@I\0\0\0\0\0\0) +Pitch_point4=@Variant(\0\0\0\x1a@c\xe0\0\0\0\0\0@I\0\0\0\0\0\0) Roll_point1=@Variant(\0\0\0\x1a\0\0\0\0\0\0\0\0@\x14\0\0\0\0\0\0) Roll_point2=@Variant(\0\0\0\x1a@1\0\0\0\0\0\0@1\0\0\0\0\0\0) Roll_point3=@Variant(\0\0\0\x1a@@\x80\0\0\0\0\0@@\x80\0\0\0\0\0) -Roll_point4=@Variant(\0\0\0\x1a@d\x10\0\0\0\0\0@I\0\0\0\0\0\0) +Roll_point4=@Variant(\0\0\0\x1a@d \0\0\0\0\0@I\0\0\0\0\0\0) X_point1=@Variant(\0\0\0\x1a\0\0\0\0\0\0\0\0@\x14\0\0\0\0\0\0) X_point2=@Variant(\0\0\0\x1a@1\0\0\0\0\0\0@1\0\0\0\0\0\0) X_point3=@Variant(\0\0\0\x1a@@\x80\0\0\0\0\0@@\x80\0\0\0\0\0) -- cgit v1.2.3