Bulletphysics and osg::Node

addict
Posts: 3
Joined: Mon Apr 04, 2011 7:43 pm

Bulletphysics and osg::Node

Post by addict »

Hi

I made a osg::Node (osg::Group) with Physics. This works great if i insert the node on position (0,0,0)
If i made a positionattitudeTransform with the physics-Node the node is on the new position but the physics-Node / Object is still at 0,0,0

here is the code:
h-File:

Code: Select all

class PhysicsCube :
			public osg::Group
		{
		public:
			PhysicsCube();
			~PhysicsCube(void);
			osg::MatrixTransform* createNode(double length, double mass, btDynamicsWorld* dynamicsWorld, osg::Vec3d position);
			void setColor(osg::Vec4d color);
			btRigidBody *getBody(void);

		private:
			void createGeometry(void);
			osg::ShapeDrawable* _boxDrawable;
			double _length;
			double _mass;
			btDynamicsWorld* _dynamicsWorld;
			btRigidBody* _body;
		};

		class BallUpdateCallback : public osg::NodeCallback
		{
		private:
			btRigidBody *_body;

		public:
			BallUpdateCallback(btRigidBody *body) :
			  _body(body)
			  {}

			  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
			  {
				  btScalar m[16];

				  btDefaultMotionState* myMotionState = ( btDefaultMotionState*)_body->getMotionState();
				  myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(m);

					double t = nv->getFrameStamp()->getReferenceTime();
					osg::Matrix mat = osg::computeLocalToWorld(nv->getNodePath());


				  //osg::Matrixf mat(m);

				  osg::PositionAttitudeTransform *pat = dynamic_cast<osg::PositionAttitudeTransform *>(node);
				  pat->setPosition(mat.getTrans());
				  pat->setAttitude(mat.getRotate());

				  I3D_LOG(notification) << mat.getTrans().x() << ", " << mat.getTrans().y() << ", " << mat.getTrans().z() << std::endl;

				  traverse(node, nv);
			  }
		};
cpp:

Code: Select all

osg::MatrixTransform* PhysicsCube::createNode(double length, double mass, btDynamicsWorld* dynamicsWorld, osg::Vec3d position)
{

	_length = length;
	_mass = mass;
	_dynamicsWorld = dynamicsWorld;

	position = osg::Vec3d(0,0,0);
	
	// OSG CODE
	osg::ref_ptr< osg::MatrixTransform > node = new osg::MatrixTransform;
	

	osg::Geode* geodeBox = new osg::Geode();

	osg::Box* box = new osg::Box(position, _length );
	_boxDrawable = new osg::ShapeDrawable(box);

	_boxDrawable->setColor(osg::Vec4d(0.5, 0.5, 1.0, 1.0));

	geodeBox->addDrawable(_boxDrawable);

	node->addChild(geodeBox);

	// OSGBBULLET CODE
	osgbBullet::MotionState * motion = new osgbBullet::MotionState;
	motion->setTransform( node.get() );
	btCollisionShape * collision = osgbBullet::btConvexTriMeshCollisionShapeFromOSG( node.get() );

	
	// BULLET CODE
	btTransform bodyTransform;
	bodyTransform.setIdentity();
	bodyTransform.setOrigin( btVector3( 0, 0, 0 ) );
	motion->setWorldTransform( bodyTransform );

	btScalar objectMass( mass );
	btVector3 inertia;
	collision->calculateLocalInertia( objectMass, inertia );
	btRigidBody::btRigidBodyConstructionInfo rbinfo( objectMass, motion, collision, inertia );
	 _body = new btRigidBody( rbinfo );
	//   body->setLinearVelocity( btVector3( -5, -1, 0 ) );
	//  body->setAngularVelocity( btVector3( 1, 0, 0 ) );
	dynamicsWorld->addRigidBody(_body );


	return( node.release() );
}

void PhysicsCube::createGeometry(void)
{
}

void PhysicsCube::setColor( osg::Vec4d color )
{
	_boxDrawable->setColor(color);
}

btRigidBody * PhysicsCube::getBody( void )
{
	return _body;
}
I use the physicsCube like this:

Code: Select all


_cNode = new I3DENGINE::Physics::PhysicsCube;
osg::PositionAttitudeTransform *temp = new osg::PositionAttitudeTransform;
temp->addChild(_cNode->createNode(length, mass, dynamicsWorld, position));
temp->addChild(_sNode);

temp->setPosition(osg::Vec3d(0,0,100)); // <- does not work correctly

temp->setUpdateCallback(new I3DENGINE::Physics::BallUpdateCallback(_cNode->getBody()));
return temp;
What has to be changed so that the node's position will be updated according to the physic's node location?
Sorry for my bad english!
Thanks!
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Bulletphysics and osg::Node

Post by Erwin Coumans »

It is best to update the body transform using body->setWorldTransform(trans), and not using the motionstate.

The motion state is only for initialization and for updates from body->motionstate (graphics), not the other way around (except for kinematic animated objects).

Thanks,
Erwin