About Me
Hi, my name is Sasha. I'm in GAM670
Force Feedback
Add this to WindowSettings.h:
#define IDC_NOFF //number
Add this in typedef enum Integer in Configuration.h:
GF_CT_RMBL
In iInput.h:
add line 1 in the iJoystick class
In Input.h:
add line 2 in the Joystick class
add line 3 in the Joystick class
1. public: virtual void updateForce(float, double, int) = 0; 2. int feedBackOFF; LPDIRECTINPUTEFFECT centre; LPDIRECTINPUTEFFECT ffEffects;
3. public: void updateForce(float factor, double time, int direction);
In Input.cpp, add the following to the Joystick constructor
ffEffects = NULL; centre = NULL; feedBackOFF = 0;
add this in Joystick::interrogate function:
DIDEVCAPS didcaps; didcaps.dwSize = sizeof didcaps; if(SUCCEEDED(didInter->GetCapabilities(&didcaps)) && (didcaps.dwFlags && DIDC_FOREFEEDBACK){ EnableWindow(GetDlgItem((HWND)hwnd, IDC_NOFF), TRUE); } else{ EnableWindow(GetDlgItem((HWND)hwnd, IDC_NOFF), FALSE); }
add this in Joystick::setup function:
feedBackOFF = !!(flags & 8);
change the SetCooperativeLevel in setup to check for device exclusivity
else if (FAILED(joystick->SetCooperativeLevel((HWND)hwnd, (feedBackOFF ? DISCL_NONEXCLUSIVE : DISCL_EXCLUSIVE) | DISCL_FOREGROUND)))
add this line after (!zAxisOn)
if(feedBackOFF) centre = NULL;
add these in the restore function:
else{ if(ffEffects){ ffEffects->Download(); } if(centre){ centre->Download(); centre->Start(1,0); }
add this function in:
void Joystick::updateForce(float factor, double time, int direction){ if(joystick) { if (feedBackOFF == 0) { if(context->get(GF_CT_RMBL) == 1) { if(ffEffects){ ffEffects->Download(); } DIEFFECT dif; DWORD axes[2] = {DIJOFS_X, DIJOFS_Y}; LONG dir[2] = {1, 0}; ZeroMemory(&dif, sizeof dif); // set the size of the struct dif.dwSize = sizeof dif; // set axes and directions dif.rgdwAxes = axes; dif.rglDirection = dir; DIPERIODIC dip; DIENVELOPE die; // if both x & y have FF, make shake come at 45 degree angle // otherwise just shake the x axis. // if (axisIsActive[0] && axisIsActive[1]) { dif.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; dif.cAxes = 2; dir[0] = direction * DI_DEGREES; } else { // assume only x axis has FF dif.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; dif.cAxes = 1; } dif.dwGain = DI_FFNOMINALMAX; dif.dwDuration = time * DI_SECONDS / 2; // Timing in seconds of the force feedback, time is passed in here; dif.dwSamplePeriod = direction; dif.dwTriggerButton = DIEB_NOTRIGGER; dif.dwTriggerRepeatInterval = 0; dif.lpEnvelope = ¨ dif.cbTypeSpecificParams = sizeof dip; dif.lpvTypeSpecificParams = &dip; dif.dwStartDelay = 3 * DI_SECONDS; // 3 secs dip.dwMagnitude = 3 * DI_FFNOMINALMAX / 10; dip.lOffset = 0; dip.dwPhase = 0; dip.dwPeriod = DI_SECONDS / 10; // 1/10th second die.dwSize = sizeof die; die.dwAttackLevel = factor; die.dwAttackTime = factor * DI_SECONDS / 2; die.dwFadeLevel = factor; die.dwFadeTime = DI_SECONDS / 2; HRESULT hr = joystick->CreateEffect(GUID_Square, &dif, &ffEffects, NULL); // create a ramp force DIRAMPFORCE dirf; // if both x & y have FF, use the direction to change the angle of the shake // otherwise just shake the x axis. // if (axisIsActive[0] && axisIsActive[1]) { dif.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; dif.cAxes = 2; dir[0] = direction * DI_DEGREES; } else { // assume only x axis has FF dif.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; dif.cAxes = 1; } dif.dwGain = DI_FFNOMINALMAX; dif.dwDuration = time * DI_SECONDS / 2; // Timing in seconds for the force feedback, time is passed in here; dif.dwSamplePeriod = direction; dif.dwTriggerButton = DIEB_NOTRIGGER; dif.dwTriggerRepeatInterval = 0; dif.lpEnvelope = ¨ dif.cbTypeSpecificParams = sizeof dirf; dif.lpvTypeSpecificParams = &dirf; dif.dwStartDelay = 0.01 * DI_SECONDS; dirf.lStart = DI_FFNOMINALMAX / 2; dirf.lEnd = - DI_FFNOMINALMAX / 2; die.dwSize = sizeof die; die.dwAttackLevel = DI_FFNOMINALMAX / 50; die.dwAttackTime = time * DI_SECONDS / 2; die.dwFadeLevel = DI_FFNOMINALMAX / 10; die.dwFadeTime = time * DI_SECONDS / 2; if (SUCCEEDED(joystick->CreateEffect(GUID_RampForce, &dif, &ffEffects, NULL))){ ffEffects->Download();// download to driver ffEffects->Start(INFINITE,0); // infinite so it can be played as many times } } else if(context->get(GF_CT_RMBL) == 0) { if(ffEffects){ DWORD DIGFFS_STOPPED1 = 2; if(!joystick->GetForceFeedbackState(&DIGFFS_STOPPED1)) ffEffects->Stop(); } } } } }
Add this to release:
if(centre){ centre->Release(); centre = NULL; } if(ffEffects){ ffEffects->Release(); ffEffects = NULL; }
In UserDialog.cpp: In the saveUserChoices function, add another bool called ff:
bool y, z, ff, none;
Add this line after the y and z are retrieved
ff = SendDlgItemMessage(hwnd, IDC_NOFF, BM_GETCHECK, 0, 0) != BST_CHECKED;
Add this in the else statement after y = z = false;
ff = true;
Change the flags being set after:
flags = ((y ? 1 : 0) << 2) | ((z ? 1 : 0) << 1) | ((ff ? 0 : 1) << 3) | (none ? 1 : 0);
in iDesign.h, add these to the iDesign class:
virtual bool sendForce(bool) = 0; virtual void setForceTime(double) = 0; virtual double getForceTime() = 0; virtual void setForceDir(int) = 0; virtual int getForceDir() = 0; virtual void setForceFactor(float) = 0; virtual float getForceFactor() = 0;
in Design.h, add these to the Design class:
private: float fFactor; double fTime; int fDirection;
public: bool sendForce(bool); void setForceTime(double); double getForceTime(); void setForceDir(int); int getForceDir(); void setForceFactor(float); float getForceFactor();
In Design.cpp constructor, add these default values:
fTime = 0.1; fFactor = 1.0f; fDirection = 45;
You can then use these in Design::update function
setForceTime(double); setForceDir(int); setForceFactor(float); sendForce(bool); context->set(GF_CT_RMBL, int(0 or 1));
Add these functions in Design.cpp
bool Design::sendForce(bool force) { return force; }
void Design::setForceTime(double time) { fTime = time; }
double Design::getForceTime() { if(fTime != 0.0) return fTime; }
void Design::setForceDir(int fctr) { fDirection = fctr; }
int Design::getForceDir() { return fDirection; }
void Design::setForceFactor(float) { fFactor = 1.0f; }
float Design::getForceFactor() { return fFactor; }
In Engine.cpp, add this to run method:
joystick->updateForce(design->getForceFactor(), design->getForceTime(), design->getForceDir());