osg+Bullet 自己写的代码,体现出Bullet的重力与碰撞

功能:

1.  显示牛与地板

2. 抄来Bullet的官方例子的代码,使之能正常运行

3. 用一个NodeCallback进行每帧运算

4. 把刚体运动的坐标作用于牛

#include "includes.h"
#include "btBulletDynamicsCommon.h"


class MyCallback:public osg::NodeCallback
{
public:
	MyCallback()
	{}
	MyCallback(osg::MatrixTransform* cow,btDiscreteDynamicsWorld* dynamicsWorld)
		:m_cow(cow),m_dynamicsWorld(dynamicsWorld)
	{}

	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
	{
		cout<<16<<endl;

			//for (i=0;i<100;i++)
	//{
		m_dynamicsWorld->stepSimulation(1.f/60.f,10);// 每秒60帧
		
		//print positions of all objects
		for (int j=m_dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--)
		{
			btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[j];
			btRigidBody* body = btRigidBody::upcast(obj);
			if (body && body->getMotionState())
			{
				btTransform trans;
				body->getMotionState()->getWorldTransform(trans);
				printf("world pos = %f\t%f\t%f\t(%d)\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()),j);

				if(1==j)
				{
					m_cow->setMatrix(osg::Matrix::translate(osg::Vec3( float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()) ) ) );
				}
			}
		}
	//}

		//继续遍历
		traverse(node,nv);
	}

private:
	osg::MatrixTransform* m_cow;
	btDiscreteDynamicsWorld* m_dynamicsWorld ;
};


int main()
{
	osgViewer::Viewer *viewer1 = new osgViewer::Viewer;
	osg::Node *cow = osgDB::readNodeFile("cow.osg");
	osg::Group *gScene = new osg::Group;

	// 把牛移上天:
	osg::MatrixTransform *mtCow= new osg::MatrixTransform;
	mtCow->addChild(cow);
	mtCow->setMatrix(osg::Matrix::translate(osg::Vec3(0,0,100) ));
	gScene->addChild(mtCow);// 加入场景

	// 建地面:
	osg::Geometry *geometry1 = new osg::Geometry;
	osg::Vec3Array *arrVertex = new osg::Vec3Array;
	geometry1->setVertexArray(arrVertex);
	arrVertex->push_back(osg::Vec3(-100,100,0) );
	arrVertex->push_back(osg::Vec3(100,100,0) );
	arrVertex->push_back(osg::Vec3(100,-100,0) );
	arrVertex->push_back(osg::Vec3(-100,-100,0) );
	geometry1->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
	//osg::Geode *geode1 = new osg::Geode;
	//geode1->addDrawable(geometry1);
	
	// 加入场景:
	gScene->addChild(geometry1);

	// 物理引擎:
	///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	btCollisionDispatcher* dispatcher = new	btCollisionDispatcher(collisionConfiguration);
	///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
	btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
	///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
	btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
	dynamicsWorld->setGravity(btVector3(0,0,-9.8));

	
	///create a few basic rigid bodies 地面
	btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(0.1)));
	//keep track of the shapes, we release memory at exit.
	//make sure to re-use collision shapes among rigid bodies whenever possible!
	btAlignedObjectArray<btCollisionShape*> collisionShapes;// 物理单位
	collisionShapes.push_back(groundShape);
	btTransform groundTransform;
	groundTransform.setIdentity();
	groundTransform.setOrigin(btVector3(0,0,0));

	{
		btScalar mass(0.);// 地板没有质量, 不受重力影响

		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(0,0,0);
		if (isDynamic)
		{
			groundShape->calculateLocalInertia(mass,localInertia);
			cout<<"0. != 0.f"<<endl;
		}

		//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
		btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
		btRigidBody* body = new btRigidBody(rbInfo);

		//add the body to the dynamics world
		dynamicsWorld->addRigidBody(body);
	}

	{
		//create a dynamic rigidbody

		//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
		btCollisionShape* colShape = new btSphereShape(btScalar(1.));
		collisionShapes.push_back(colShape);

		/// Create Dynamic Objects
		btTransform startTransform;
		startTransform.setIdentity();

		btScalar	mass(1.f);

		//rigidbody is dynamic if and only if mass is non zero, otherwise static
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(100,0,0);
		if (isDynamic)
		{
			colShape->calculateLocalInertia(mass,localInertia);
		}
		startTransform.setOrigin(btVector3(0,0,100));// 初始高度
		//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
		btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
		btRigidBody* body = new btRigidBody(rbInfo);

		dynamicsWorld->addRigidBody(body);
	}

	///-----stepsimulation_start-----
	//int i;
	//for (i=0;i<100;i++)
	//{
	//	dynamicsWorld->stepSimulation(1.f/60.f,10);// 每秒60帧
	//	
	//	//print positions of all objects
	//	for (int j=dynamicsWorld->getNumCollisionObjects()-1; j>=0 ;j--)
	//	{
	//		btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
	//		btRigidBody* body = btRigidBody::upcast(obj);
	//		if (body && body->getMotionState())
	//		{
	//			btTransform trans;
	//			body->getMotionState()->getWorldTransform(trans);
	//			printf("world pos = %f\t%f\t%f\t(%d)\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()),j);
	//		}
	//	}
	//}

	MyCallback *cb1= new MyCallback(mtCow,dynamicsWorld);
	gScene->addUpdateCallback(cb1);

	viewer1->setSceneData(gScene);
	viewer1->run();
	return 0;
}

由于osgBullet编译未能成功, 所以

猜你喜欢

转载自my.oschina.net/u/235558/blog/1647920