/********************************************************************************
* FaceTrackNoIR This program is a private project of the some enthusiastic *
* gamers from Holland, who don't like to pay 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 . *
*********************************************************************************/
#ifndef __TRACKER_H__
#define __TRACKER_H__
#include
#include
#include
#include
#include
#include
#include
#include
#define DIRECTINPUT_VERSION 0x0800
#include
#include "FTServer.h" // Freetrack-server
#include "FGServer.h" // FlightGear-server
// include the DirectX Library files
#pragma comment (lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
using namespace sm::faceapi;
using namespace sm::faceapi::qt;
class FaceTrackNoIR; // pre-define parent-class to avoid circular includes
class Tracker : public QThread {
Q_OBJECT
private:
// Handles to neatly terminate thread...
HANDLE m_StopThread;
HANDLE m_WaitThread;
/** face api variables **/
APIScope *faceapi_scope;
QSharedPointer _engine;
QSharedPointer _headtracker;
smEngineHandle _engine_handle;
/** static callback method for the head pose tracking **/
static void STDCALL receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVideoFrame video_frame);
/** static member varables for saving the head pose **/
static float headPosX;
static float headPosY;
static float headPosZ; // Distance from camera
static float initial_headPosZ; // Initial distance when headpose is valid
static float headRotX;
static float headRotY;
static float headRotZ;
// Offsets, used to center view while tracking
static float offset_headPosX;
static float offset_headPosY;
static float offset_headPosZ; // Distance from camera
static float offset_headRotX;
static float offset_headRotY;
static float offset_headRotZ;
// Flags to start/stop/reset tracking
static bool confid;
static bool newdata;
static bool set_initial; // initial headpose is set
static bool do_tracking; // Start/stop tracking, using MINUS key on keyboard
static bool do_center; // Center head-position, using EQUALS key on keyboard
/** static member varables for calculating the virtual head pose **/
static float sensYaw;
static float sensPitch;
static float sensRoll;
static float sensX;
static float sensY;
static float sensZ;
static float invertYaw;
static float invertPitch;
static float invertRoll;
static float invertX;
static float invertY;
static float invertZ;
static bool useFilter;
/** Factors to remove jitter **/
static float redYaw;
static float redPitch;
static float redRoll;
static float redX;
static float redY;
static float redZ;
static float rotNeutralZone; // Neutral Zone for rotations (rad).
//
// The Raw FaceAPI-data may need smoothing.
// We implement smoothing, by taking the last 'x' raw samples and making an average of this.
// After 'x' samples, the oldest sample is removed and the fresh 'pre-pended' to the QList
//
QList rawYawList; // List of last 'x' values from FaceAPI
QList rawPitchList;
QList rawRollList;
QList rawXList;
QList rawYList;
QList rawZList;
int intMaxYawItems; // Max. number of items in QList: more = smoother (yet slower!)
int intMaxPitchItems;
int intMaxRollItems;
int intMaxXItems;
int intMaxYItems;
int intMaxZItems;
/** QT objects **/
QLineEdit *headXLine;
QLineEdit *headYLine;
QLineEdit *headZLine;
QLineEdit *headRotXLine;
QLineEdit *headRotYLine;
QLineEdit *headRotZLine;
QWidget *headPoseWidget;
FaceTrackNoIR *mainApp;
FTServer *server_FT; // Freetrack Server
FGServer *server_FG; // FlightGear Server
protected:
// qthread override run method
void run();
public:
Tracker();
~Tracker();
void setup(QWidget *head, FaceTrackNoIR *parent);
void registerHeadPoseCallback();
bool handleGameCommand ( int command );
QString getGameProgramName(); // Get the ProgramName from the game and display it.
QSharedPointer getEngine() { return _engine; };
// smEngineHandle getEngineHandle() { return _engine->handle(); };
static float getHeadPosX() {return headPosX;}
static float getHeadPosY() {return headPosY;}
static float getHeadPosZ() {return headPosZ;}
static void setHeadPosX(float x) { headPosX = x; }
static void setHeadPosY(float y) { headPosY = y; }
static void setHeadPosZ(float z) { headPosZ = z; }
static float getHeadRotX() {return headRotX;}
static float getHeadRotY() {return headRotY;}
static float getHeadRotZ() {return headRotZ;}
static void setHeadRotX(float x) { headRotX = x; }
static void setHeadRotY(float y) { headRotY = y; }
static void setHeadRotZ(float z) { headRotZ = z; }
static bool getConfid() { return confid; }
static void setSensYaw(int x) { sensYaw = x/100.0f; }
static void setSensPitch(int x) { sensPitch = x/100.0f; }
static void setSensRoll(int x) { sensRoll = x/100.0f; }
static void setSensX(int x) { sensX = x/100.0f; }
static void setSensY(int x) { sensY = x/100.0f; }
static void setSensZ(int x) { sensZ = x/100.0f; }
static void setInvertYaw(bool invert) { invertYaw = invert?-1.0f:+1.0f; }
static void setInvertPitch(bool invert) { invertPitch = invert?-1.0f:+1.0f; }
static void setInvertRoll(bool invert) { invertRoll = invert?-1.0f:+1.0f; }
static void setInvertX(bool invert) { invertX = invert?-1.0f:+1.0f; }
static void setInvertY(bool invert) { invertY = invert?-1.0f:+1.0f; }
static void setInvertZ(bool invert) { invertZ = invert?-1.0f:+1.0f; }
static void setUseFilter(bool set) { useFilter = set; }
static void setRedYaw(int x) { redYaw = x/100.0f; }
static void setRedPitch(int x) { redPitch = x/100.0f; }
static void setRedRoll(int x) { redRoll = x/100.0f; }
static void setRedX(int x) { redX = x/100.0f; }
static void setRedY(int x) { redY = x/100.0f; }
static void setRedZ(int x) { redZ = x/100.0f; }
static void setNeutralZone(int x) { rotNeutralZone = (x * 2.0f * 3.14159)/360.0f; }
void addRaw2List ( QList *rawList, float maxIndex, float raw );
float getSmoothFromList ( QList *rawList );
float getCorrectedNewRaw ( float NewRaw, float rotNeutral );
float lowPassFilter ( float newvalue, float *oldvalue, float dt, float coeff);
float getDegreesFromRads ( float rads ) { return ((rads * 360.0f)/ (2.0f * 3.14159)); }
// For now, use one slider for all
void setSmoothing(int x) {
intMaxYawItems = x;
intMaxPitchItems = x;
intMaxRollItems = x;
intMaxXItems = x;
intMaxYItems = x;
intMaxZItems = x;
}
};
#endif