diff --git a/Base/SceneElements/Objects/imstkRigidObject.cpp b/Base/SceneElements/Objects/imstkRigidObject.cpp index 6b35432aa6bc88ad64475e3ea7ea8f659e566db1..ef90fe46269a47a6972542cde7d5306d30127312 100644 --- a/Base/SceneElements/Objects/imstkRigidObject.cpp +++ b/Base/SceneElements/Objects/imstkRigidObject.cpp @@ -25,43 +25,105 @@ namespace imstk { +static dWorldID odeWorld; +static dJointGroupID odeContactgroup; +// dynamics and collision objects +static dSpaceID odeSpace; +static dBodyID odeBody; +static dGeomID odeGeom; +static dMass odeMass; -void RigidObject::setup() +void +RigidObject::odeNearCallback(void *data, dGeomID o1, dGeomID o2) { - // dynamics and collision objects - dWorldID world; - dSpaceID space; - dBodyID body; - dGeomID geom; - dMass m; - dJointGroupID contactgroup; + dBodyID b1 = dGeomGetBody(o1); + dBodyID b2 = dGeomGetBody(o2); + dContact contact; + contact.surface.mode = dContactBounce | dContactSoftCFM; + // friction parameter + contact.surface.mu = dInfinity; + // bounce is the amount of "bouncyness". + contact.surface.bounce = 0.9; + // bounce_vel is the minimum incoming velocity to cause a bounce + contact.surface.bounce_vel = 0.1; + // constraint force mixing parameter + contact.surface.soft_cfm = 0.001; + if (int numc = dCollide(o1, o2, 1, &contact.geom, sizeof(dContact))) + { + dJointID c = dJointCreateContact(odeWorld, odeContactgroup, &contact); + dJointAttach(c, b1, b2); + } +} + +void +RigidObject::simulationStep() +{ + // find collisions and add contact joints + dSpaceCollide(odeSpace, 0, &odeNearCallback); + // step the simulation + dWorldQuickStep(odeWorld, 0.01); + // remove all contact joints + dJointGroupEmpty(odeContactgroup); +} + +void +RigidObject::getGeometryConfig(imstk::Vec3d &p, imstk::Mat3d &orientation) +{ + const dReal *pos; + const dReal *R; + pos = dGeomGetPosition(odeGeom); + R = dGeomGetRotation(odeGeom); + + p[0] = (double)pos[0]; + p[1] = (double)pos[2]; + p[2] = (double)pos[1]; + + size_t rotPos = 0; + for (size_t r = 0; r < 3; r++) + { + for (size_t c = 0; c < 3; c++, rotPos++) + { + orientation(r, c) = (double)R[rotPos]; + } + } +} + +void +RigidObject::initOde() +{ dInitODE(); - // create world - world = dWorldCreate(); - space = dHashSpaceCreate(0); - dWorldSetGravity(world, 0, 0, -0.2); - dWorldSetCFM(world, 1e-5); - dCreatePlane(space, 0, 0, 1, 0); - contactgroup = dJointGroupCreate(0); - // create object - body = dBodyCreate(world); - geom = dCreateSphere(space, 0.5); - dMassSetSphere(&m, 1, 0.5); - dBodySetMass(body, &m); - dGeomSetBody(geom, body); - // set initial position - dBodySetPosition(body, 0, 0, 3); - // run simulation - char** filename; - filename = new char*; +} + +void +RigidObject::closeOde() +{ // clean up - dJointGroupDestroy(contactgroup); - dSpaceDestroy(space); - dWorldDestroy(world); + dJointGroupDestroy(odeContactgroup); + dSpaceDestroy(odeSpace); + dWorldDestroy(odeWorld); dCloseODE(); } +void +RigidObject::setup() +{ + // create world + odeWorld = dWorldCreate(); + odeSpace = dHashSpaceCreate(0); + dWorldSetGravity(odeWorld, 0, 0, -0.2); + dWorldSetCFM(odeWorld, 1e-5); + dCreatePlane(odeSpace, 0, 0, 1, 0); + odeContactgroup = dJointGroupCreate(0); + // create object + odeBody = dBodyCreate(odeWorld); + odeGeom = dCreateSphere(odeSpace, 0.5); + dMassSetSphere(&odeMass, 1, 0.5); + dBodySetMass(odeBody, &odeMass); + dGeomSetBody(odeGeom, odeBody); + // set initial position + dBodySetPosition(odeBody, 0, 0, 3); +} } // imstk #endif diff --git a/Base/SceneElements/Objects/imstkRigidObject.h b/Base/SceneElements/Objects/imstkRigidObject.h index fc3dc4e31635310ccfac68c10e08ca4725cfb1c9..cc2cad2e55a9ed79cfb27d43a0690e87b8986927 100644 --- a/Base/SceneElements/Objects/imstkRigidObject.h +++ b/Base/SceneElements/Objects/imstkRigidObject.h @@ -22,8 +22,10 @@ #ifndef imstkRigidObject_h #define imstkRigidObject_h +#ifdef iMSTK_USE_ODE // imstk #include "imstkDynamicObject.h" +#include "ode/ode.h" namespace imstk { @@ -47,8 +49,27 @@ public: m_type = Type::Rigid; } + //ode related functions + + // + // callback called at every loop + // + static void odeNearCallback(void *data, dGeomID o1, dGeomID o2); + + // initialize ode + static void initOde(); + + // close ode + static void closeOde(); + + // + static void simulationStep(); + + // + static void getGeometryConfig(imstk::Vec3d &p, imstk::Mat3d &orientation); + // This is just a simple function to test ODE - void setup(); + static void setup(); /// /// \brief Destructor @@ -58,5 +79,5 @@ public: protected: }; } // imstk - +#endif //imstk_USE_ODE #endif // ifndef imstkRigidObject_h diff --git a/Examples/Sandbox/main.cpp b/Examples/Sandbox/main.cpp index dfdec66f40cb8dcd498ba4b4d4013dc2e6c6e0f8..9acaf251d1fdc78758eb33cd16117c27c8a5061a 100644 --- a/Examples/Sandbox/main.cpp +++ b/Examples/Sandbox/main.cpp @@ -3231,23 +3231,59 @@ void testRigidBody() { // SDK and Scene auto sdk = std::make_shared<imstk::SimulationManager>(); - auto scene = sdk->createNewScene("RigidObjectPhysocs"); + auto scene = sdk->createNewScene("RigidObjectPhysics"); // Create a plane in the scene (visual) auto planeGeom = std::make_shared<imstk::Plane>(); planeGeom->setWidth(10); - planeGeom->setPosition(0.0, -50, 0.0); + planeGeom->setPosition(0.0, 2.5, 0.0); auto planeObj = std::make_shared<imstk::VisualObject>("Plane"); planeObj->setVisualGeometry(planeGeom); scene->addSceneObject(planeObj); -#ifdef iMSTK_USE_ODE - auto rgidibody = imstk::RigidObject("Rigid Object Yo!"); - rgidibody.setup(); + int counter = 1000; + +#ifdef iMSTK_USE_ODE + //Initialize rigid body + //Initialize imstk side of things. + auto sphereObj = apiutils::createVisualAnalyticalSceneObject( + imstk::Geometry::Type::Sphere, scene, "VisualSphere", 1.0, Vec3d(0., 3.0, 0.)); + + auto sceneManager = sdk->getSceneManager("RigidObjectPhysics"); + + sceneManager->setPreInitCallback([&](Module* module) + { + imstk::RigidObject::initOde(); + imstk::RigidObject::setup(); + }); + + sceneManager->setPreUpdateCallback([&](Module* module) + { + if (counter == 0) + { + imstk::RigidObject::simulationStep(); + counter = 1000; + } + else + { + counter--; + } + }); + sceneManager->setPostUpdateCallback([&](Module* module) + { + imstk::Vec3d pos; + imstk::Mat3d matrix; + imstk::RigidObject::getGeometryConfig(pos, matrix); + sphereObj->getVisualGeometry()->setTranslation(pos); + }); + sceneManager->setPostCleanUpCallback([&](Module* module) + { + imstk::RigidObject::closeOde(); + }); #endif // Move Camera auto cam = scene->getCamera(); - cam->setPosition(imstk::Vec3d(200, 200, 200)); + cam->setPosition(imstk::Vec3d(10, 10, 10)); cam->setFocalPoint(imstk::Vec3d(0, 0, 0)); //Run