00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00334 #include "../include/IPSA/SoPhysics.h"
00335 #include "../include/IPSA/SoWorldPhysics.h"
00336 #include "../include/IPSA/SoCollisionShape.h"
00337
00338 #include <Inventor/nodes/SoSeparator.h>
00339 #include <Inventor/nodes/SoResetTransform.h>
00340 #include <Inventor/nodes/SoNode.h>
00341 #include <Inventor/nodes/SoSphere.h>
00342 #include <Inventor/SbLinear.h>
00343 #include <cstdio>
00344
00345
00346 SO_KIT_SOURCE(SoPhysics);
00347
00350 void SoPhysics::initClass()
00351 {
00352 SO_KIT_INIT_CLASS(SoPhysics, SoBaseKit, "BaseKit");
00353 }
00354
00355
00362 SoPhysics::SoPhysics(const SbString& nodeName )
00363 : transform(NULL),
00364 CoinRefTransform(SbMatrix::identity()),
00365 isInitialised(FALSE),
00366 myWorld(NULL),
00367 body(NULL),
00368 geom(NULL)
00369 {
00370 SO_KIT_CONSTRUCTOR(SoPhysics);
00371 isBuiltIn = TRUE;
00372
00373 SO_KIT_ADD_CATALOG_ENTRY(separator,SoSeparator,FALSE,this,"",TRUE);
00374 SO_KIT_ADD_CATALOG_ENTRY(reset,SoResetTransform,FALSE,separator,collisionShape,TRUE);
00375 SO_KIT_ADD_CATALOG_ENTRY(collisionShape,SoCollisionShape,TRUE,separator,ODETransform,TRUE);
00376 SO_KIT_ADD_CATALOG_ENTRY(ODETransform,SoMatrixTransform,FALSE,separator,visualisationShape,TRUE);
00377 SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(visualisationShape,SoNode,SoSeparator,TRUE,separator,"",TRUE);
00378
00379 SO_KIT_ADD_FIELD(AUTO_UPDATE_COLLISION_SHAPE, (TRUE));
00380 SO_KIT_ADD_FIELD(mass,(1.0f));
00381 SO_KIT_ADD_FIELD(linVelocity,(0.0f ,0.0f, 0.0f));
00382 SO_KIT_ADD_FIELD(angVelocity,(0.0f, 0.0f, 0.0f));
00383 SO_KIT_ADD_FIELD(jointList, (NULL));
00384 SO_KIT_ADD_FIELD(torqueField,(0.0f, 0.0f, 0.0f));
00385 SO_KIT_ADD_FIELD(forceField,(0.0f, 0.0f, 0.0f));
00386 SO_KIT_ADD_FIELD(forcePos,(0.0f, 0.0f, 0.0f));
00387 SO_KIT_ADD_FIELD(inertia,(0.0f, 0.0f, 0.0f));
00388 SO_KIT_ADD_FIELD(scale,(1.0f, 1.0f, 1.0f));
00389 SO_KIT_ADD_FIELD(measureContactForces,(FALSE));
00390 SO_KIT_ADD_FIELD(drawCollisionShape,(FALSE));
00391
00392 SO_KIT_INIT_INSTANCE();
00393
00394 setName(nodeName);
00395
00396
00397 inertia.set1Value(0, 0.4f, 0.0f, 0.0f);
00398 inertia.set1Value(1, 0.0f, 0.4f, 0.0f);
00399 inertia.set1Value(2, 0.0f, 0.0f, 0.4f);
00400
00401 updateDependentObjectsSensor.setFunction(SoPhysics::UpdateDependentObjectsCB);
00402 updateDependentObjectsSensor.setData(this);
00403
00404 fieldUpdateSensor.setFunction(SoPhysics::FieldChangedCB);
00405 fieldUpdateSensor.setData(this);
00406 fieldUpdateTrigger.appendConnection(&mass);
00407 fieldUpdateTrigger.appendConnection(&linVelocity);
00408 fieldUpdateTrigger.appendConnection(&angVelocity);
00409 fieldUpdateTrigger.appendConnection(&drawCollisionShape);
00410 fieldUpdateTrigger.appendConnection(&inertia);
00411 fieldUpdateTrigger.appendConnection(&scale);
00412
00413
00414
00415
00416
00417
00418 }
00419
00420
00424 SoPhysics::~SoPhysics()
00425 {
00426
00427
00428
00429
00430 if (body != NULL)
00431 {
00432 dBodyDestroy(body);
00433 body = NULL;
00434 }
00435 }
00436
00437
00441 SoBaseKit* SoPhysics::copy(SbBool copyConnections) const
00442 {
00443
00444
00445 SoPhysics* newSoPhysics = dynamic_cast<SoPhysics*> (SoBaseKit::copy(copyConnections));
00446
00447 assert(isInitialised == false && "Can not copy initialised SoPhysics!\n");
00448
00449 newSoPhysics->myWorld = myWorld;
00450 newSoPhysics->CoinRefTransform = CoinRefTransform;
00451 newSoPhysics->body = body;
00452 newSoPhysics->geom = geom;
00453 newSoPhysics->transform = transform;
00454 newSoPhysics->isInitialised = isInitialised;
00455
00456 return newSoPhysics;
00457 }
00458
00459
00469 void SoPhysics::FieldChangedCB(void* data, SoSensor*)
00470 {
00471 SoPhysics* physicObj = static_cast<SoPhysics*> (data);
00472
00473 if (NULL == physicObj)
00474 return;
00475
00476 if (!physicObj->isInitialised)
00477 return;
00478
00479
00480
00481 dMass cm;
00482 dBodyGetMass(physicObj->body,&cm);
00483 cm.mass = physicObj->mass.getValue();
00484 dBodySetMass(physicObj->body,&cm);
00485
00486
00487 physicObj->setLinearVel(physicObj->linVelocity.getValue());
00488
00489
00490 SbVec3f ang = physicObj->angVelocity.getValue();
00491 dBodySetAngularVel(physicObj->body,ang[0],ang[1],ang[2]);
00492
00493
00494 SoCollisionShape* cshape = dynamic_cast<SoCollisionShape*> (physicObj->getPart("collisionShape", FALSE));
00495 cshape->setVisualisationStatus(physicObj->drawCollisionShape.getValue());
00496 }
00497
00498
00509 SbBool SoPhysics::setUpConnections(SbBool onOff, SbBool doItAlways)
00510 {
00511 if (!doItAlways && connectionsSetUp == onOff)
00512 return onOff;
00513 if (onOff)
00514 {
00515 SoBaseKit::setUpConnections(onOff, doItAlways);
00516
00517 SoPhysics::FieldChangedCB(this, NULL);
00518 SoPhysics::UpdateDependentObjectsCB(this, NULL);
00519
00520
00521 if (&fieldUpdateTrigger != fieldUpdateSensor.getAttachedField())
00522 fieldUpdateSensor.attach(&fieldUpdateTrigger);
00523 if (&updateDependentObjectsTrigger != updateDependentObjectsSensor.getAttachedField())
00524 updateDependentObjectsSensor.attach(&updateDependentObjectsTrigger);
00525 }
00526 else
00527 {
00528 if (NULL != fieldUpdateSensor.getAttachedField())
00529 fieldUpdateSensor.detach();
00530 if (NULL != updateDependentObjectsSensor.getAttachedField())
00531 updateDependentObjectsSensor.detach();
00532 SoBaseKit::setUpConnections(onOff, doItAlways);
00533 }
00534
00535 connectionsSetUp = onOff;
00536 return !connectionsSetUp;
00537 }
00538
00539
00544 dMass SoPhysics::getInitialMass() {
00545 dMass mass;
00546 SbVec3f i0 = this->inertia[0];
00547 SbVec3f i1 = this->inertia[1];
00548 SbVec3f i2 = this->inertia[2];
00549
00550 float m = this->mass.getValue();
00551 dMassSetParameters(&mass,m,0,0,0,i0[0],i1[1],i2[2],i0[1],i0[2],i1[2]);
00552
00553 return mass;
00554 }
00555
00556
00561 void SoPhysics::setWorld(dWorldID w)
00562 {
00563 myWorld = w;
00564 }
00565
00566
00570 dWorldID SoPhysics::getWorld()
00571 {
00572 return myWorld;
00573 }
00574
00575
00584 void SoPhysics::createOdeBody(SoCallbackAction *action)
00585 {
00586 if (isInitialised)
00587 return;
00588
00589
00590 assert(myWorld != NULL);
00591
00592 printf("creating ODE-Body <%s> (%s)\n", getTypeId().getName().getString(), getName().getString());
00593
00594
00595 body = dBodyCreate(myWorld);
00596 dBodySetData(body, this);
00597
00598
00599 SoCollisionShape *cshape = dynamic_cast<SoCollisionShape *> (getPart("collisionShape", TRUE));
00600 geom = cshape->getGeom();
00601 assert(geom != NULL);
00602 cshape->setVisualisationStatus(false);
00603 dGeomSetBody (geom, body);
00604
00605 SbVec3f lCOG;
00606 cshape->getCOG(lCOG);
00607
00608 SbVec3f ct,cs;
00609 SbRotation cr,cso;
00610 CoinRefTransform.getTransform(ct, cr, cs, cso);
00611 CoinRefTransform.setTransform(-lCOG, cr, cs);
00612
00613 init_linVelocity = this->linVelocity.getValue();
00614 init_angVelocity = this->angVelocity.getValue();
00615
00616
00617 transform = dynamic_cast<SoMatrixTransform*> (getPart("ODETransform", FALSE));
00618
00619 updateOdeBodyParameters(action->getModelMatrix());
00620
00621
00622 dMass bmass = getInitialMass();
00623 dBodySetMass(body, &bmass);
00624
00625 isInitialised = TRUE;
00626 }
00627
00628
00633 void SoPhysics::updateOIPosition()
00634 {
00635
00636 SbMatrix odet = this->getMatrixTransform();
00637
00638 SbMatrix ftrans = CoinRefTransform;
00639 ftrans.multRight(odet);
00640
00641
00642 assert(transform != NULL);
00643 transform->matrix.setValue(ftrans);
00644 }
00645
00646
00654 void SoPhysics::updateOdeBody(SoCallbackAction *action){
00655 if (!isInitialised)
00656 return;
00657
00658
00659 int numValues = forceField.getNum();
00660 for (int i = 0; i < numValues; i++)
00661 {
00662 this->setForceAtPosition(forceField[i], forcePos[i]);
00663 }
00664
00665 numValues = torqueField.getNum();
00666 for (int j = 0; j < numValues; j++)
00667 {
00668 this->setTorque(torqueField[j]);
00669 }
00670
00671
00672 updateOIPosition();
00673 }
00674
00682 void SoPhysics::resetOdeBody(SoCallbackAction* action)
00683 {
00684 if (!isInitialised)
00685 return;
00686
00687 this->linVelocity.setValue(init_linVelocity);
00688 this->angVelocity.setValue(init_angVelocity);
00689
00690 updateOdeBodyParameters(action->getModelMatrix());
00691 }
00692
00693
00698 void SoPhysics::updateOdeBodyParameters(const SbMatrix& actionModelMatrix)
00699 {
00700
00701
00702 SoCollisionShape *cshape = dynamic_cast<SoCollisionShape *> (getPart("collisionShape", FALSE));
00703 int alignment = cshape->alignment.getValue();
00704 SbMatrix mm;
00705 if (alignment == SoCollisionShape::STANDARD)
00706 {
00707 SbVec3f lCOG;
00708 cshape->getCOG(lCOG);
00709 mm.setTranslate(lCOG);
00710 }
00711 else if (alignment == SoCollisionShape::CENTERED)
00712 mm.setTranslate(SbVec3f(0.0, 0.0, 0.0));
00713
00714 mm = mm.multRight(actionModelMatrix);
00715 SbVec3f translation, scaling;
00716 SbRotation rotation, sr;
00717 mm.getTransform(translation, rotation, scaling, sr);
00718
00719
00720 scale.setValue(scaling);
00721
00722
00723 SbVec3f axis;
00724 float radians;
00725 rotation.getValue(axis, radians);
00726 const float* AXIS_VALUES = axis.getValue();
00727 dMatrix3 rot;
00728 dRFromAxisAndAngle(rot, AXIS_VALUES[0], AXIS_VALUES[1], AXIS_VALUES[2], radians);
00729
00730
00731 dBodySetRotation(body, rot);
00732
00733 dBodySetPosition(body, translation[0], translation[1], translation[2]);
00734
00735
00736 this->setLinearVel(init_linVelocity);
00737 dBodySetAngularVel(body, init_angVelocity[0], init_angVelocity[1], init_angVelocity[2]);
00738
00739
00740 updateOIPosition();
00741 }
00742
00743
00747 dBodyID SoPhysics::getBody()
00748 {
00749 return this->body;
00750 }
00751
00752
00757 SoSFVec3f SoPhysics::getCurrentForce()
00758 {
00759 SoSFVec3f ret;
00760 const dReal* FORCE = dBodyGetForce(this->body);
00761 ret.setValue(FORCE[0],FORCE[1],FORCE[2]);
00762 return ret;
00763 }
00764
00765
00769 SoSFVec3f SoPhysics::getCurrentTorque()
00770 {
00771 SoSFVec3f ret;
00772 const dReal* TORQUE;
00773 TORQUE = dBodyGetTorque(this->body);
00774 ret.setValue(TORQUE[0],TORQUE[1],TORQUE[2]);
00775 return ret;
00776 }
00777
00778
00782 SoSFVec3f SoPhysics::getCurrentLinearVel()
00783 {
00784 SoSFVec3f ret;
00785 const dReal* VELOCITY = dBodyGetLinearVel(this->body);
00786 ret.setValue(VELOCITY[0], VELOCITY[1], VELOCITY[2]);
00787 return ret;
00788 }
00789
00790
00799 SoSFVec3f SoPhysics::getCurrentPosition()
00800 {
00801 SoSFVec3f ret;
00802 dVector3 cppos;
00803 dBodyGetRelPointPos(body,0,0,0,cppos);
00804
00805 ret.setValue(cppos[0], cppos[1], cppos[2]);
00806 return ret;
00807 }
00808
00809
00813 SbMatrix SoPhysics::getMatrixTransform()
00814 {
00815 const dReal* TRANSLATION = dBodyGetPosition (body);
00816 const dReal* ROTATION = dBodyGetQuaternion (body);
00817 SbMatrix ret = SbMatrix::identity();
00818 ret.setTransform(SbVec3f(TRANSLATION[0],TRANSLATION[1],TRANSLATION[2]),
00819 SbRotation(ROTATION[1],ROTATION[2],ROTATION[3],ROTATION[0]),
00820 SbVec3f(1,1,1));
00821 return ret;
00822 }
00823
00824
00828 SbMatrix SoPhysics::getOIMatrixTransform()
00829 {
00830 return transform->matrix.getValue();
00831 }
00832
00833
00838 void SoPhysics::setForce(const SbVec3f& force)
00839 {
00840 dBodyAddForce(this->body, force[0], force[1], force[2]);
00841 }
00842
00843
00849 void SoPhysics::setForceAtPosition(const SbVec3f& force, const SbVec3f& position)
00850 {
00851 dBodyAddForceAtPos(this->body,
00852 force[0], force[1], force[2],
00853 position[0], position[1], position[2]);
00854 }
00855
00856
00862 void SoPhysics::setRelForceAtPosition(const SbVec3f& force, const SbVec3f& position)
00863 {
00864 dBodyAddRelForceAtRelPos(this->body,
00865 force[0], force[1], force[2],
00866 position[0], position[1], position[2]);
00867 }
00868
00869
00874 void SoPhysics::setRelForce(const SbVec3f& relForce)
00875 {
00876 dBodyAddRelForce(this->body, relForce[0], relForce[1], relForce[2]);
00877 }
00878
00879
00884 void SoPhysics::setLinearVel(const SbVec3f& vel)
00885 {
00886 dBodySetLinearVel(this->body, vel[0], vel[1], vel[2]);
00887 }
00888
00893 void SoPhysics::setTorque(const SbVec3f& torque)
00894 {
00895 dBodyAddTorque(this->body, torque[0], torque[1], torque[2]);
00896 }
00897
00898
00903 void SoPhysics::setCollisionShapeVisibility(SbBool visible)
00904 {
00905 this->drawCollisionShape.setValue(visible);
00906 }
00907
00908
00916 void SoPhysics::UpdateDependentObjectsCB(void* data, SoSensor* sensor)
00917 {
00918 SoPhysics* physicsBody = static_cast<SoPhysics*> (data);
00919 if (NULL == physicsBody)
00920 return;
00921
00922 physicsBody->updateDependentObjects();
00923 }
00924
00925
00936 SoCallbackAction::Response SoPhysics::InitialiseOdeBodiesCB(void* userdata, SoCallbackAction* action, const SoNode* node)
00937 {
00938 SoWorldPhysics* world = static_cast<SoWorldPhysics*> (userdata);
00939 SoPhysics* physicsBody = dynamic_cast<SoPhysics*> (const_cast<SoNode*> (node));
00940 if (NULL != world && NULL != physicsBody)
00941 {
00942 physicsBody->setUpConnections(TRUE, TRUE);
00943 physicsBody->setWorld(world->ownworld);
00944 physicsBody->createOdeBody(action);
00945 }
00946 return SoCallbackAction::CONTINUE;
00947 }
00948
00949
00957 SoCallbackAction::Response SoPhysics::UpdateOdeBodiesCB(void* userdata, SoCallbackAction* action, const SoNode* node)
00958 {
00959
00960 SoPhysics* physicsBody = dynamic_cast<SoPhysics*> (const_cast<SoNode*> (node));
00961 if (NULL != physicsBody)
00962 physicsBody->updateOdeBody(action);
00963 return SoCallbackAction::CONTINUE;
00964 }
00965
00966
00974 SoCallbackAction::Response SoPhysics::ResetOdeBodiesCB(void *userdata, SoCallbackAction* action, const SoNode* node)
00975 {
00976 SoPhysics* physicsBody = dynamic_cast<SoPhysics*> (const_cast<SoNode*> (node));
00977 if (NULL != physicsBody)
00978 physicsBody->resetOdeBody(action);
00979 return SoCallbackAction::CONTINUE;
00980 }