Difference between revisions of "User:Satijas"
(9 intermediate revisions by the same user not shown) | |||
Line 4: | Line 4: | ||
Hi, my name is Sasha. I'm in GAM670 | Hi, my name is Sasha. I'm in GAM670 | ||
− | [[ | + | == Force Feedback == |
+ | |||
+ | Add this to '''WindowSettings.h''': | ||
+ | <big> | ||
+ | |||
+ | #define IDC_NOFF //number | ||
+ | </big> | ||
+ | |||
+ | Add this in typedef enum Integer in '''Configuration.h''': | ||
+ | <big> | ||
+ | GF_CT_RMBL | ||
+ | </big> | ||
+ | |||
+ | In '''iInput.h''':<br /> | ||
+ | add line 1 in the iJoystick class<br /> | ||
+ | In '''Input.h''':<br /> | ||
+ | add line 2 in the Joystick class<br /> | ||
+ | add line 3 in the Joystick class<br /> | ||
+ | <big> | ||
+ | 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); | ||
+ | |||
+ | </big> | ||
+ | |||
+ | In '''Input.cpp''', add the following to the Joystick constructor | ||
+ | <big> | ||
+ | ffEffects = NULL; | ||
+ | centre = NULL; | ||
+ | feedBackOFF = 0; | ||
+ | </big> | ||
+ | |||
+ | add this in Joystick::interrogate function: | ||
+ | <big> | ||
+ | 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); | ||
+ | } | ||
+ | </big> | ||
+ | |||
+ | add this in Joystick::setup function: | ||
+ | <big> | ||
+ | feedBackOFF = !!(flags & 8); | ||
+ | </big> | ||
+ | |||
+ | change the SetCooperativeLevel in setup to check for device exclusivity | ||
+ | <big> | ||
+ | else if (FAILED(joystick->SetCooperativeLevel((HWND)hwnd, | ||
+ | (feedBackOFF ? DISCL_NONEXCLUSIVE : DISCL_EXCLUSIVE) | DISCL_FOREGROUND))) | ||
+ | </big> | ||
+ | |||
+ | add this line after (!zAxisOn) | ||
+ | <big> | ||
+ | if(feedBackOFF) | ||
+ | centre = NULL; | ||
+ | </big> | ||
+ | |||
+ | add these in the restore function: | ||
+ | <big> | ||
+ | else{ | ||
+ | if(ffEffects){ | ||
+ | ffEffects->Download(); | ||
+ | } | ||
+ | if(centre){ | ||
+ | centre->Download(); | ||
+ | centre->Start(1,0); | ||
+ | } | ||
+ | </big> | ||
+ | |||
+ | |||
+ | add this function in: | ||
+ | <big> | ||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </big> | ||
+ | |||
+ | Add this to release: | ||
+ | <big> | ||
+ | if(centre){ | ||
+ | centre->Release(); | ||
+ | centre = NULL; | ||
+ | } | ||
+ | if(ffEffects){ | ||
+ | ffEffects->Release(); | ||
+ | ffEffects = NULL; | ||
+ | } | ||
+ | </big> | ||
+ | |||
+ | In '''UserDialog.cpp''': | ||
+ | In the saveUserChoices function, add another bool called ff: | ||
+ | <big> | ||
+ | bool y, z, '''ff''', none; | ||
+ | </big> | ||
+ | |||
+ | Add this line after the y and z are retrieved | ||
+ | <big> | ||
+ | ff = SendDlgItemMessage(hwnd, IDC_NOFF, BM_GETCHECK, 0, 0) != BST_CHECKED; | ||
+ | </big> | ||
+ | |||
+ | Add this in the else statement after y = z = false; | ||
+ | <big> | ||
+ | ff = true; | ||
+ | </big> | ||
+ | |||
+ | Change the flags being set after: | ||
+ | <big> | ||
+ | flags = ((y ? 1 : 0) << 2) | ((z ? 1 : 0) << 1) '''| ((ff ? 0 : 1) << 3)''' | (none ? 1 : 0); | ||
+ | </big> | ||
+ | |||
+ | in '''iDesign.h''', add these to the iDesign class: | ||
+ | <big> | ||
+ | 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; | ||
+ | </big> | ||
+ | |||
+ | in '''Design.h''', add these to the Design class: | ||
+ | <big> | ||
+ | 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(); | ||
+ | </big> | ||
+ | |||
+ | In '''Design.cpp''' constructor, add these default values: | ||
+ | <big> | ||
+ | fTime = 0.1; | ||
+ | fFactor = 1.0f; | ||
+ | fDirection = 45; | ||
+ | </big> | ||
+ | |||
+ | You can then use these in Design::update function | ||
+ | <big> | ||
+ | setForceTime(double); | ||
+ | setForceDir(int); | ||
+ | setForceFactor(float); | ||
+ | sendForce(bool); | ||
+ | context->set(GF_CT_RMBL, int(0 or 1)); | ||
+ | </big> | ||
+ | |||
+ | Add these functions in '''Design.cpp''' | ||
+ | <big> | ||
+ | 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; | ||
+ | } | ||
+ | </big> | ||
− | + | In '''Engine.cpp''', add this to run method: | |
+ | <big> | ||
+ | joystick->updateForce(design->getForceFactor(), design->getForceTime(), design->getForceDir()); | ||
+ | </big> |
Latest revision as of 13:46, 7 April 2011
Contents
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());