Open main menu

CDOT Wiki β

Satijas

Joined 14 September 2009
Revision as of 13:43, 7 April 2011 by Satijas (talk | contribs)

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
In Input.h, 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:

   joystick->updateForce(design->getForceFactor(), design->getForceTime(), design->getForceDir());