void HLCALLBACK buttonCB(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata) { if (event == HL_EVENT_1BUTTONDOWN) { HLuint spring = *((HLuint *) userdata); HDdouble anchor[3]; hlCacheGetDoublev(cache, HL_PROXY_POSITION, anchor); hlEffectd(HL_EFFECT_PROPERTY_GAIN, 0.8); hlEffectd(HL_EFFECT_PROPERTY_MAGNITUDE, 1.0); hlEffectdv(HL_EFFECT_PROPERTY_POSITION, anchor); hlStartEffect(HL_EFFECT_SPRING, spring); } else if (event == HL_EVENT_1BUTTONUP) { HLuint spring = *((HLuint *) userdata); hlStopEffect(spring); } else if (event == HL_EVENT_2BUTTONDOWN) { static const HDdouble direction[3] = { 0, 0, 1 }; static const HDdouble duration = 100; /* ms */ /* Trigger an impulse by commanding a force with a direction and magnitude for a small duration. */ hlEffectd(HL_EFFECT_PROPERTY_DURATION, duration); hlEffectd(HL_EFFECT_PROPERTY_MAGNITUDE, 0.8); hlEffectdv(HL_EFFECT_PROPERTY_DIRECTION, direction); hlTriggerEffect(HL_EFFECT_CONSTANT); } }
/* Function: OnDragSurface --------------------------------------------------------------------------- Event callback function called when moving device while touching surface. */ void HLCALLBACK OnDragSurface(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata) { hduVector3Dd proxyPos; hlCacheGetDoublev(cache, HL_PROXY_POSITION, proxyPos); hduVector3Dd contactNormal; hlCacheGetDoublev(cache, HL_PROXY_TOUCH_NORMAL, contactNormal); hduVector3Dd reactionForce; hlCacheGetDoublev(cache, HL_DEVICE_FORCE, reactionForce); const double deviceToParticleForce = 5.0; hduVector3Dd particleForce = -deviceToParticleForce * contactNormal * reactionForce.magnitude(); mPS.HapticDeviceMove(proxyPos, particleForce); }
void HLCALLBACK touchShapeCallback(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata) { hduVector3Dd proxy; std::cout << "Touched ObjectID: " << object << " at point "; hlCacheGetDoublev(cache, HL_PROXY_POSITION, proxy); std::cout << proxy << " "; HLboolean buttDown; hlCacheGetBooleanv(cache, HL_BUTTON1_STATE, &buttDown); std::cout << "button 1 " << (buttDown ? "down" : "up") << std::endl; }
/*************************************************************************************** Servo loop thread callback. Computes a force effect. This callback defines the motion of the purple skull and calculates the force based on the "real-time" Proxy position in Device space. ****************************************************************************************/ void HLCALLBACK computeForceCB(HDdouble force[3], HLcache *cache, void *userdata) { DataTransportClass *localdataObject = (DataTransportClass *) userdata;//Typecast the pointer passed in appropriately hduVector3Dd skullPositionDS;//Position of the skull (Moving sphere) in Device Space. hduVector3Dd proxyPosition;//Position of the proxy in device space HDdouble instRate = 0.0; HDdouble deltaT = 0.0; static float counter = 0.0; float degInRad = 0.0; static int counter1 = 0; // Get the time delta since the last update. hdGetDoublev(HD_INSTANTANEOUS_UPDATE_RATE, &instRate); deltaT = 1.0 / instRate; counter+=deltaT; degInRad = counter*20*3.14159/180; hduVector3Dd ModelPos = localdataObject->Model->getTranslation(); localdataObject->Model->setTranslation(-ModelPos); localdataObject->Model->setTranslation(cos(degInRad)*64.0, sin(degInRad)*64.0,5.0);//Move the skull aroubnd in a circle WorldToDevice.multVecMatrix(localdataObject->Model->getTranslation(),skullPositionDS);//Convert the position of the sphere from world space to device space hlCacheGetDoublev(cache, HL_PROXY_POSITION, proxyPosition);//Get the position of the proxy in Device Coordinates (All HL commands in the servo loop callback fetch values in device coordinates) forceVec = forceField(proxyPosition, skullPositionDS, 40.0, 5.0);//Calculate the force counter1++; if(counter1>2000)//Make the force start after 2 seconds of program start. This is because the servo loop thread executes before the graphics thread. //Hence global variables set in the graphics thread will not be valid for sometime in the begining og the program { force[0] = forceVec[0]; force[1] = forceVec[1]; force[2] = forceVec[2]; counter1 = 2001; } else { force[0] = 0.0; force[1] = 0.0; force[2] = 0.0; } }
/******************************************************************************* Creates a spring upon button press. *******************************************************************************/ void HLCALLBACK buttonCB(HLenum event, HLuint object, HLenum thread, HLcache *cache, void *userdata) { if (event == HL_EVENT_1BUTTONDOWN) { HLuint spring = *((HLuint *) userdata); HDdouble anchor[3]; hlCacheGetDoublev(cache, HL_PROXY_POSITION, anchor); hlEffectd(HL_EFFECT_PROPERTY_GAIN, 0.8); hlEffectd(HL_EFFECT_PROPERTY_MAGNITUDE, 1.0); hlEffectdv(HL_EFFECT_PROPERTY_POSITION, anchor); hlStartEffect(HL_EFFECT_SPRING, spring); } else if (event == HL_EVENT_1BUTTONUP) { HLuint spring = *((HLuint *) userdata); hlStopEffect(spring); } }