Bullet介绍
Bullet的主页 。最新版本在这里下载 。简单的中文介绍见百度百科 。一些也许可以促使你选择Bullet的小故事在以前的文章中有提及,参考这里 的开头--为什么选择Bullet。
主要特征:
* 代码用C++构建,遵守zlib开源协议,可免费用于各种商业目的。跨平台支持,包括PS3,XBox 360...
* 离散或是持续的碰撞检测。碰撞模型包括不规则物体和基本的图形;
* 快速而稳定的刚体动力学约束求解,滑块和较链的模拟;
* 衣服,绳子等柔软物体的模拟,支持约束 ;
* 丰富的插件支持,包括maya,Blender...
环境:ubuntu12.04 gcc4.6
安装
首先用git把代码clone下来
git clone svn checkout http://bullet.googlecode.com/svn/trunk/
然后终端cd到目录,还是那一套:
./configure
make
sudo make install
执行完之后Demos也编译好了,终端运行
./AllBulletDemos/AppAllBulletDemos
可以点击右边的next scene 来切换demo。
Hello World
参考官方wiki的helloworld教程,创建main.cpp
#include#include 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().getY() << 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 collisionConfiguration; delete dispatcher; delete broadphase; return 0; }
再创建CMakeLists.txt
cmake_minimum_required(VERSION 2.8) PROJECT (HELLO) SET(SRC_LIST main.cpp) INCLUDE_DIRECTORIES( /usr/local/include/bullet ) LINK_LIBRARIES( BulletDynamics BulletCollision LinearMath ) ADD_EXECUTABLE(hello ${SRC_LIST})
终端执行
cmake .
make
运行效果如下:
从wiki上看得出,这是模拟一个球体的抛物线。
这里需要注意一下,bullet只是负责计算!(据说最新的bullet已经使用OpenCL,将计算的任务放到了GPU),而图形渲染需要用到其他渲染引擎,比如OpenGL,Ogre等等。
术语表
下面的属于表也是来自bullet的官方wiki。
基础项
单量 - Scalar
单量其实就是数字,一个线性的值。比如1.0,1.23.单量可以用来构成其他的项。
比如,两点之间的距离就是一个单量,速度也是一个单量。
向量,3维向量,4维向量 - Vector
向量就是有方向的一段距离。
根据空间的维度,向量可分为2维,3维,4维。
三维向量的长度根据勾股定理可以用来计算,对应的就是向量的lengh方法,求根的算法非常消耗复杂,所以向量类有length2(),得到的就是没有开根的结果。
例如:
#define THRESHOLD 20 #define THRESHOLD_SQ THRESHOLD*THRESHOLD // Your compiler will optimise this out later Vector3 a(12,14,20); if(THRESHOLD > a.length()) { do_something; } // This one is much slower if(THRESHOLD_SQ > a.length2()) {do_something; } // Use this version if you can
欧拉坐标 - Euler co-ordinates
就是三维坐标,vector3(x,y,z)表示的就是三维空间中的一个点。
极坐标 - Polar co-ordinates
在 平面内取一个定点O, 叫极点,引一条射线Ox,叫做极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向)。对于平面内任何一点M,用ρ表示线段OM的长度,θ表示从Ox到OM的角度,ρ叫做点M的极径,θ叫做点M的极角,有序数对 (ρ,θ)就叫点M的极坐标,这样建立的坐标系叫做极坐标系。
平面中圆的极坐标表达式是:
x = ρ cos(θ) ; y = ρ sin(θ)
空间球体的极坐标表达式是:
欧拉角 - Euler Angle
欧拉角主要用于描述一个旋转,对空间中的一个点进行旋转通常可以描述为:先绕 x 旋转一个角,再绕 y 轴旋转一个角,再绕 z 轴旋转一个角,最后得到最终坐标。
由于电脑是一只只会线性计算的怪兽,嗷唔~ 在使用欧拉角进行旋转的时候可能会出现一种很蛋疼的情况 - 万圣节锁 youtube video explaining gimbal lock
为了避免万圣节锁,一个方法是设定好旋转轴的旋转顺序。
另一中方法是使用四元组。
四元组 - Quaternion
四元数一般定义如下:
q=w+xi+yj+zk
其中v=(x,y,z)是矢量,w是标量,虽然v是矢量,但不能简单的理解为3D空间的矢量,它是4维空间中的的矢量,也是非常不容易想像的。
通俗的讲,一个四元数(Quaternion)描述了一个旋转轴和一个旋转角度。这个旋转轴和这个角度可以通过 Quaternion::ToAngleAxis转换得到。当然也可以随意指定一个角度一个旋转轴来构造一个Quaternion。这个角度是相对于单位四元数而言的,也可以说是相对于物体的初始方向而言的。
当用一个四元数乘以一个向量时,实际上就是让该向量围绕着这个四元数所描述的旋转轴,转动这个四元数所描述的角度而得到的向量。
轴角 - AxisAngle
也是用来描述一个旋转。
旋转的轴角表示用两个值参数化了旋转: 一个轴或向量,和描述绕这个轴的旋转量的一个角。它也叫做旋转的指数坐标。
有时也叫做旋转向量表示,因为这两个参数(轴和角)可用在这个轴上的其模是旋转角的一个向量来表示。
合成项
变换 - Transform
变换就是一个位移加上一个旋转。
矩阵 - Matrix
所有的变换都可以用矩阵的运算来实现。但是要注意渲染系统的矩阵算法的实现和bullet中的是否是一样的。
物理项
刚体 - Rigid Body
刚体有着固定的质量、尺寸和其他的物理属性,它时物理模拟中最基础的项。
节点约束 - Joint,constraint
节点约束就是用于连接两个物体的地方,连接的方式又很多中,一种是简单的连接,连接的地方可以旋转,还有一种是绞接,只能单向运动。
世界 - World
所有的物体,所有的刚体,软体都在世界中,整个模拟系统就是一个世界。
参考
Bullet物理引擎不完全指南(Bullet Physics Engine not complete Guide) - http://blog.csdn.net/vagrxie/article/details/5952310
Bullet Tutorial Articles - http://bulletphysics.org/mediawiki-1.5.8/index.php/Tutorial_Articles