Bullet学习教程 入门 配置方法及HelloWord示例

关于学习Bullet的初衷是想在我的试验中加入更可信的三维碰撞检测机制,在这么多物理库的选择的为什么选择Bullet的主要原因是它的开源性以及支持IOS,其实这是我的肤浅的认识,关于Bullet、Physx、Havok、Box2D等优缺点网上有许多较深入的理解的文章,这里就不列举了。

1、Bullet的下载与配置

参考文章:http://blog.csdn.net/dhull/article/details/20463563


1 Bullet安装指导

    1. 下载bullet-2.82-r2704.zip,解压(r后面的数字可能不同);
    2. 运行“../build/vs2010.bat”,生成VS2010工程;
    3. 用VS2010打开“../vs2010/0BulletSolution.sln”;
    4. LinearMathBulletCollisionBulletDynamicsBulletSoftBody,分别在DebugRelease配置下编译生成LIB;
    5. 将“../lib”下的8个.lib文件,以及“../src”下所有.h文件,都拷贝出来即构成安装包;其中,.lib文件放到lib文件夹先,.h文件放到inc文件夹下。
注:生成lib也可参考http://bulletphysics.org/mediawiki-1.5.8/index.php/Creating_a_project_from_scratch,这里有详细的图文讲解

Bullet工程配置(使用Bullet库)

要使用Bullet,需要:

    1. 添加包含目录,将上一节拷贝的.h文件所在目录添加到工程的包含目录(在所有配置下);
    2. 添加库目录,将上一节拷贝的.lib文件所在目录添加到工程库目录(在所有配置下);
    3. 引用库,添加对.lib文件的引用(根据使用层次添加所需.lib文件,Debug和Release分别设置);
    4. 包含头文件,在代码中包含“btBulletDynamicsCommon.h”。
    5. 接下来,就可以自己编辑代码了。

注:

添加包含目录的两种方法:

    1. “项目属性 >> 配置属性 >> VC++目录 >> 包含目录”
    2. “项目属性 >> 配置属性 >> C/C++ >> 常规 >> 附加包含目录”。

添加库目录的两种方法:

    1. “项目属性 >> 配置属性 >> VC++目录 >> 库目录”
    2. “项目属性 >> 配置属性 >> 链接器 >> 常规 >> 附加库目录”。

引用库的两种方法:

    1. 代码#pragma comment (lib, "xxx.lib")(用#ifdef _DLL和#ifdef _DEBUG);
    2. “项目属性 >> 配置属性 >> 链接器 >> 输入 >> 附加依赖项”。

2、Bullet的HelloWord示例
#include <iostream>
#include <btBulletDynamicsCommon.h>  

int main (void)  
{ 
	btBroadphaseInterface* broadphase = new btDbvtBroadphase();
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();  
	btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);  
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
	btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);  
	dynamicsWorld->setGravity(btVector3(0,-10,0)); 

 
	btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
	btCollisionShape* fallShape = new btSphereShape(1); 

	btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));  
	btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));  
	btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);  
	dynamicsWorld->addRigidBody(groundRigidBody);

	btDefaultMotionState* fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));  
	btScalar mass = 1;  
	btVector3 fallInertia(0,0,0);  
	fallShape->calculateLocalInertia(mass,fallInertia);  
	btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);  
	btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);  
	dynamicsWorld->addRigidBody(fallRigidBody);

	for (int i=0 ; i<300 ; i++) 
	{  
		dynamicsWorld->stepSimulation(1/60.f,10);
		btTransform trans;  
		fallRigidBody->getMotionState()->getWorldTransform(trans);  
		std::cout << "sphere height: " << trans.getOrigin().getX()<<" "
			<<trans.getOrigin().getY()<<" "<<trans.getOrigin().getZ() << std::endl;  
	}	

	dynamicsWorld->removeRigidBody(fallRigidBody);
	delete fallRigidBody->getMotionState();  
	delete fallRigidBody;  

	dynamicsWorld->removeRigidBody(groundRigidBody);  
	delete groundRigidBody->getMotionState();  
	delete groundRigidBody;  

	delete fallShape;  
	delete groundShape;  
 
	delete dynamicsWorld;  
	delete solver;  
	delete dispatcher;  
	delete collisionConfiguration;  
	delete broadphase;   

	return 0;  
}

上面的源代码是依照Bullet的示例代码改写的,力争代码数量最少。示例实现是的对一个刚体小球从50单位的地方自由落体下落到地面上的整个过程。代码只是输出了每个是个小球的高度而已,在dos界面输出。

为了更直观一点,将物理模拟的高度通过OSG中小球的来显示出来,给人一种直观的感受:
#include <iostream>
#include <btBulletDynamicsCommon.h>  

//-------------------  在OSG中显示-begin-  -----------------------
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/ShapeDrawable>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <osglib.h>
//-------------------  在OSG中显示-end-  -----------------------

int main (void)  
{ 
	btBroadphaseInterface* broadphase = new btDbvtBroadphase();
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();  
	btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);  
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
	btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);  
	dynamicsWorld->setGravity(btVector3(0,-10,0)); 

 
	btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
	btCollisionShape* fallShape = new btSphereShape(1); 

	btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));  
	btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));  
	btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);  
	dynamicsWorld->addRigidBody(groundRigidBody);

	btDefaultMotionState* fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));  
	btScalar mass = 1;  
	btVector3 fallInertia(0,0,0);  
	fallShape->calculateLocalInertia(mass,fallInertia);  
	btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);  
	btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);  
	dynamicsWorld->addRigidBody(fallRigidBody);

	/*for (int i=0 ; i<300 ; i++) 
	{  
		dynamicsWorld->stepSimulation(1/60.f,10);
		btTransform trans;  
		fallRigidBody->getMotionState()->getWorldTransform(trans);  
		std::cout << "sphere height: " << trans.getOrigin().getX()<<" "
			<<trans.getOrigin().getY()<<" "<<trans.getOrigin().getZ() << std::endl;  
	}  */

	//-------------------  在OSG中显示-begin-  -----------------------
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	osg::ref_ptr<osg::Group> root = new osg::Group;
	osg::ref_ptr<osg::Geode> geode = new osg::Geode;

	osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
	hints->setDetailRatio(0.5f);	

	for (int i=0 ; i<30 ; i++)
	{  
		dynamicsWorld->stepSimulation(1/60.f,10);
		btTransform trans;  
		fallRigidBody->getMotionState()->getWorldTransform(trans); 

		std::cout << "sphere height: " << trans.getOrigin().getX()<<" "
			<<trans.getOrigin().getY()<<" "<<trans.getOrigin().getZ() << std::endl;
		
		geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(trans.getOrigin().getX(),
			trans.getOrigin().getZ(),
			trans.getOrigin().getY()),0.01f),hints.get()));//bullet的坐标系与OpenGL相同,但是OSG与OpenGL不同,故有调整
	}
	root->addChild(geode.get());

	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());
	viewer->setSceneData(root.get());
	viewer->realize();
	viewer->run();
	//-------------------  在OSG中显示-end-  -----------------------


	dynamicsWorld->removeRigidBody(fallRigidBody);
	delete fallRigidBody->getMotionState();  
	delete fallRigidBody;  

	dynamicsWorld->removeRigidBody(groundRigidBody);  
	delete groundRigidBody->getMotionState();  
	delete groundRigidBody;  

	delete fallShape;  
	delete groundShape;  
 
	delete dynamicsWorld;  
	delete solver;  
	delete dispatcher;  
	delete collisionConfiguration;  
	delete broadphase;   

	return 0;  
}
相信大家看完Bullet的第一个示例代码后会有一个很直观的感受,就是在原来自己所学的渲染中可以加入这种客观的物理性的东西,那么你的作品将会更加真实有趣。下面就附上Bullet的官方源代码,供大家学习钻研:
#include "btBulletDynamicsCommon.h"
#include <stdio.h>

int main(int argc, char** argv)
{
	int i;

	///-----initialization_start-----

	///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.
	//btDbvtBroadphase是很好的通用broadphase。
	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,-10,0));

	///-----initialization_end-----

	///create a few basic rigid bodies
	//创建一些基本的刚体
	btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));

	//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,-56,0));

	{
		btScalar mass(0.);

		//rigid body is dynamic if and only if mass is non zero, otherwise static
		//刚体是动态的,当且仅当质量不为0时,否则都是静态的。
		bool isDynamic = (mass != 0.f);

		btVector3 localInertia(0,0,0);
		if (isDynamic)
			groundShape->calculateLocalInertia(mass,localInertia);

		//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
		//推荐使用motionstate,它提供插值功能,并且同步激活对象。
		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 rigid body

		//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);

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

		btVector3 localInertia(0,0,0);
		if (isDynamic)
			colShape->calculateLocalInertia(mass,localInertia);

		startTransform.setOrigin(btVector3(2,10,0));

		//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);
	}



	/// Do some simulation


	///-----stepsimulation_start-----
	for (i=0;i<100;i++)
	{
		dynamicsWorld->stepSimulation(1.f/60.f,10);

		//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,%f,%f\n",float(trans.getOrigin().getX()),float(trans.getOrigin().getY()),float(trans.getOrigin().getZ()));
			}
		}
	}

	///-----stepsimulation_end-----

	//cleanup in the reverse order of creation/initialization
	//逆向清除创建或者初始化

	///-----cleanup_start-----

	//remove the rigid bodies from the dynamics world and delete them
	for (i=dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
	{
		btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i];
		btRigidBody* body = btRigidBody::upcast(obj);
		if (body && body->getMotionState())
		{
			delete body->getMotionState();
		}
		dynamicsWorld->removeCollisionObject( obj );
		delete obj;
	}

	//delete collision shapes
	for (int j=0;j<collisionShapes.size();j++)
	{
		btCollisionShape* shape = collisionShapes[j];
		collisionShapes[j] = 0;
		delete shape;
	}

	//delete dynamics world
	delete dynamicsWorld;

	//delete solver
	delete solver;

	//delete broadphase
	delete overlappingPairCache;

	//delete dispatcher
	delete dispatcher;

	delete collisionConfiguration;

	//next line is optional: it will be cleared by the destructor when the array goes out of scope
	collisionShapes.clear();

	///-----cleanup_end-----
}

Bullet后续的学习心得将继续奉献给大家。



  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值