/******************************************************************************* Main callback that calculates and sets the force. *******************************************************************************/ HDCallbackCode HDCALLBACK CoulombCallback(void *data) { HHD hHD = hdGetCurrentDevice(); hdBeginFrame(hHD); hduVector3Dd pos; hdGetDoublev(HD_CURRENT_POSITION,pos); hduVector3Dd forceVec; forceVec = forceField(pos); hdSetDoublev(HD_CURRENT_FORCE, forceVec); hdEndFrame(hHD); HDErrorInfo error; if (HD_DEVICE_ERROR(error = hdGetError())) { hduPrintError(stderr, &error, "Error during scheduler callback"); if (hduIsSchedulerError(&error)) { return HD_CALLBACK_DONE; } } return HD_CALLBACK_CONTINUE; }
// --- Parameters ---------------------------------------------------------- // const MmffAtomParameters* MmffAtom::parameters() const { const MmffParameters *mmffParameters = static_cast<const MmffForceField *>(forceField())->parameters(); if(!mmffParameters) return 0; return mmffParameters->atomParameters(this); }
/******************************************************************************* Graphics main loop function. *******************************************************************************/ void displayFunction(void) { // Setup model transformations. glMatrixMode(GL_MODELVIEW); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); setupGraphicsState(); drawAxes(sphereRadius*3.0); // Draw the fixed sphere. static const hduVector3Dd fixedSpherePosition(0, 0, 0); static const float fixedSphereColor[4] = {.2, .8, .8, .8}; GLUquadricObj* pQuadObj = gluNewQuadric(); drawSphere(pQuadObj, fixedSpherePosition, fixedSphereColor, sphereRadius); // Get the current position of end effector. DeviceDisplayState state; hdScheduleSynchronous(DeviceStateCallback, &state, HD_MIN_SCHEDULER_PRIORITY); // Draw a sphere to represent the haptic cursor and the dynamic // charge. static const float dynamicSphereColor[4] = { .8, .2, .2, .8 }; drawSphere(pQuadObj, state.position, dynamicSphereColor, sphereRadius); // Create the force vector. hduVector3Dd forceVector = 400.0 * forceField(state.position); drawForceVector(pQuadObj, state.position, forceVector, sphereRadius*.1); gluDeleteQuadric(pQuadObj); glPopMatrix(); glutSwapBuffers(); }
/*************************************************************************************** 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; } }
/// Returns the energy gradient for the atom. Vector3 ForceFieldAtom::gradient() const { return forceField()->gradient()[index()]; }